twrpinstall: create library for twrpinstall

This library will need to mirror AOSP for any changes to installing
packages. The library has been separated out in order to make importing
updates from AOSP into the TWRP project.

twinstall.cpp has been removed from the recovery binary and added to
this library. It has been refactored for libziparchive.

Sideload has been reworked to use the newer methods from AOSP on
flashing packages through adb sideload.

We are also removing old libraries for adb and verifier.

Lastly before flashing a zip or image, we want to unlock block devices
for writing so that when an OTA is flashed to the inactive slot,
the flash will succeed.

Change-Id: I6d8702fc9031ffaf9f666b4ba375dc7d9362e473
diff --git a/Android.mk b/Android.mk
index 86a53d3..bf38c04 100755
--- a/Android.mk
+++ b/Android.mk
@@ -69,7 +69,6 @@
     partitionmanager.cpp \
     progresstracking.cpp \
     startupArgs.cpp \
-    twinstall.cpp \
     twrp-functions.cpp \
     twrpDigestDriver.cpp \
     openrecoveryscript.cpp \
@@ -78,7 +77,7 @@
     twrpApex.cpp \
     twrpRepacker.cpp
 
-LOCAL_STATIC_LIBRARIES += libavb
+LOCAL_STATIC_LIBRARIES += libavb libtwrpinstall
 LOCAL_SHARED_LIBRARIES += libfs_mgr libinit
 LOCAL_C_INCLUDES += \
     system/core/fs_mgr/libfs_avb/include/ \
@@ -88,7 +87,8 @@
     system/core/fs_mgr/liblp/include/ \
     system/gsid/include/ \
     system/core/init/ \
-    system/extras/ext4_utils/include
+    system/extras/ext4_utils/include \
+    $(LOCAL_PATH)/twinstall/include
 
 ifneq ($(TARGET_RECOVERY_REBOOT_SRC),)
   LOCAL_SRC_FILES += $(TARGET_RECOVERY_REBOOT_SRC)
@@ -120,12 +120,11 @@
     $(LOCAL_PATH)/install/include \
     $(LOCAL_PATH)/fuse_sideload/include \
     $(LOCAL_PATH)/install/include \
-    $(LOCAL_PATH)/verifier28/
+    $(LOCAL_PATH)/twrpinstall/include
 
 LOCAL_STATIC_LIBRARIES += libguitwrp
 LOCAL_SHARED_LIBRARIES += libz libc libcutils libstdc++ libtar libblkid libminuitwrp libminadbd libmtdutils libtwadbbu libbootloader_message
 LOCAL_SHARED_LIBRARIES += libcrecovery libtwadbbu libtwrpdigest libc++ libaosprecovery libinit libcrypto libbase libziparchive libselinux
-LOCAL_CFLAGS += -DUSE_28_VERIFIER
 
 ifneq ($(wildcard system/core/libsparse/Android.mk),)
 LOCAL_SHARED_LIBRARIES += libsparse
@@ -398,7 +397,8 @@
     toolbox \
     mkshrc_twrp \
     plat_hwservice_contexts \
-    vendor_hwservice_contexts
+    vendor_hwservice_contexts \
+    minadbd
 
 ifneq ($(TW_INCLUDE_CRYPTO),)
 TWRP_REQUIRED_MODULES += \
@@ -575,9 +575,9 @@
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_SRC_FILES := install/adb_install.cpp install/asn1_decoder.cpp install/fuse_sdcard_install.cpp \
-    install/get_args.cpp install/install.cpp install/installcommand.cpp install/legacy_property_service.cpp \
-    install/package.cpp install/verifier.cpp install/wipe_data.cpp install/tw_atomic.cpp \
-    install/set_metadata.cpp verifier28/verifier.cpp install/zipwrap.cpp install/ZipUtil.cpp
+    install/get_args.cpp install/install.cpp install/legacy_property_service.cpp \
+    install/package.cpp install/verifier.cpp install/wipe_data.cpp \
+    install/set_metadata.cpp install/zipwrap.cpp install/ZipUtil.cpp
 LOCAL_SHARED_LIBRARIES += libbase libbootloader_message libcrypto libext4_utils \
     libfs_mgr libfusesideload libhidl-gen-utils libhidlbase \
     liblog libselinux libtinyxml2 libutils libz libziparchive libcutils
@@ -589,6 +589,7 @@
                     $(commands_TWRP_local_path)/otautil/include \
                     $(commands_TWRP_local_path)/minadbd \
                     $(commands_TWRP_local_path)/minzip \
+                    $(commands_TWRP_local_path)/twrpinstall/include \
                     system/libvintf/include
 LOCAL_STATIC_LIBRARIES += libotautil libvintf_recovery libvintf libhidl-gen-utils
 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
@@ -599,22 +600,6 @@
 
 include $(BUILD_SHARED_LIBRARY)
 
-# libverifier (static library)
-# ===============================
-include $(CLEAR_VARS)
-LOCAL_CLANG := true
-LOCAL_MODULE := libverifier
-LOCAL_SRC_FILES := \
-    asn1_decoder.cpp \
-    verifier.cpp
-LOCAL_STATIC_LIBRARIES := \
-    libotautil \
-    libcrypto_utils \
-    libcrypto \
-    libbase
-LOCAL_CFLAGS := -Wall -Werror
-include $(BUILD_STATIC_LIBRARY)
-
 commands_recovery_local_path := $(LOCAL_PATH)
 
 #    $(LOCAL_PATH)/edify/Android.mk
diff --git a/etc/init.recovery.service22.rc b/etc/init.recovery.service22.rc
index d9f661d..410efff 100755
--- a/etc/init.recovery.service22.rc
+++ b/etc/init.recovery.service22.rc
@@ -2,6 +2,7 @@
 
 # For starting recovery on 5.0 and newer
 service recovery /system/bin/recovery
+    socket recovery stream 422 system system
     seclabel u:r:recovery:s0
 
 on early-init
diff --git a/gui/Android.mk b/gui/Android.mk
index e3ce1ab..b49b94d 100755
--- a/gui/Android.mk
+++ b/gui/Android.mk
@@ -44,9 +44,10 @@
 
 LOCAL_SHARED_LIBRARIES += libminuitwrp libc libstdc++ libaosprecovery libselinux
 LOCAL_C_INCLUDES += $(LOCAL_PATH)/../otautil/include
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../twrpinstall/include
 ifeq ($(shell test $(PLATFORM_SDK_VERSION) -ge 26; echo $$?),0)
-    LOCAL_SHARED_LIBRARIES += libziparchive 
-    LOCAL_STATIC_LIBRARIES += libotautil
+    LOCAL_SHARED_LIBRARIES += libziparchive
+    LOCAL_STATIC_LIBRARIES += libotautil libtwrpinstall
     ifneq ($(TW_INCLUDE_CRYPTO),)
         LOCAL_C_INCLUDES += bootable/recovery/crypto/fscrypt
     endif
diff --git a/gui/action.cpp b/gui/action.cpp
index 3d94393..b0f0027 100755
--- a/gui/action.cpp
+++ b/gui/action.cpp
@@ -42,11 +42,11 @@
 #include "../twrpRepacker.hpp"
 #include "../openrecoveryscript.hpp"
 
-#include "install/adb_install.h"
+#include "twinstall/adb_install.h"
 
 #include "fuse_sideload.h"
 #include "blanktimer.hpp"
-#include "../twinstall.h"
+#include "twinstall.h"
 
 extern "C" {
 #include "../twcommon.h"
@@ -398,6 +398,7 @@
 		simulate_progress_bar();
 	} else {
 		ret_val = TWinstall_zip(filename.c_str(), wipe_cache);
+		PartitionManager.Unlock_Block_Partitions();
 
 		// Now, check if we need to ensure TWRP remains installed...
 		struct stat st;
@@ -1589,9 +1590,9 @@
 		bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
 
 		// wait for the adb connection
-		// int ret = apply_from_adb("/", &sideload_child_pid);
 		Device::BuiltinAction reboot_action = Device::REBOOT_BOOTLOADER;
-		int ret = ApplyFromAdb("/", &reboot_action);
+		int ret = twrp_sideload("/", &reboot_action);
+		sideload_child_pid = GetMiniAdbdPid();
 		DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start
 
 		if (ret != 0) {
@@ -1602,27 +1603,11 @@
 			int wipe_cache = 0;
 			int wipe_dalvik = 0;
 			DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik);
-
-			if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) {
-				if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
-					PartitionManager.Wipe_By_Path("/cache");
-				if (wipe_dalvik)
-					PartitionManager.Wipe_Dalvik_Cache();
-			} else {
-				ret = 1; // failure
-			}
+			if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
+				PartitionManager.Wipe_By_Path("/cache");
+			if (wipe_dalvik)
+				PartitionManager.Wipe_Dalvik_Cache();
 		}
-		if (sideload_child_pid) {
-			LOGINFO("Signaling child sideload process to exit.\n");
-			struct stat st;
-			// Calling stat() on this magic filename signals the minadbd
-			// subprocess to shut down.
-			stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
-			int status;
-			LOGINFO("Waiting for child sideload process to exit.\n");
-			waitpid(sideload_child_pid, &status, 0);
-		}
-		property_set("ctl.start", "adbd");
 		TWFunc::Toggle_MTP(mtp_was_enabled);
 		reinject_after_flash();
 		operation_end(ret);
@@ -1639,6 +1624,7 @@
 	// Calling stat() on this magic filename signals the minadbd
 	// subprocess to shut down.
 	stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
+	sideload_child_pid = GetMiniAdbdPid();
 	if (!sideload_child_pid) {
 		LOGERR("Unable to get child ID\n");
 		return 0;
diff --git a/gui/hardwarekeyboard.cpp b/gui/hardwarekeyboard.cpp
index 68be906..12c4737 100644
--- a/gui/hardwarekeyboard.cpp
+++ b/gui/hardwarekeyboard.cpp
@@ -34,7 +34,7 @@
 #include <string>
 
 extern "C" {
-#include "../common.h"
+#include "common.h"
 }
 
 #include "../twcommon.h"
diff --git a/install/get_args.cpp b/install/get_args.cpp
index 116602e..c1fcc96 100755
--- a/install/get_args.cpp
+++ b/install/get_args.cpp
@@ -1,4 +1,4 @@
-#include "install/get_args.h"
+#include "twinstall/get_args.h"
 
 std::string stage;
 bool has_cache = false;
diff --git a/install/include/install/install.h b/install/include/install/install.h
index 9e6787f..fcbfc99 100755
--- a/install/include/install/install.h
+++ b/install/include/install/install.h
@@ -44,6 +44,9 @@
   BRICK,
 };
 
+static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
+static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
+
 // Installs the given update package. This function should also wipe the cache partition after a
 // successful installation if |should_wipe_cache| is true or an updater command asks to wipe the
 // cache.
diff --git a/minadbd21/Android.mk b/minadbd21/Android.mk
deleted file mode 100644
index 40ed9f7..0000000
--- a/minadbd21/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-#
-# Android.mk for adb
-#
-
-LOCAL_PATH:= $(call my-dir)
-
-# minadbd library
-# =========================================================
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-	adb.c \
-	fdevent.c \
-	fuse_adb_provider.c \
-	transport.c \
-	transport_usb.c \
-	sockets.c \
-	services.c \
-	usb_linux_client.c \
-	utils.c
-
-LOCAL_CFLAGS := -O2 -g -DADB_HOST=0 -Wall -Wno-unused-parameter
-LOCAL_CFLAGS += -D_XOPEN_SOURCE -D_GNU_SOURCE
-LOCAL_CFLAGS += -DUSE_FUSE_SIDELOAD22
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libminadbd
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/../
-LOCAL_SHARED_LIBRARIES := libfusesideload libcutils libc
-include $(BUILD_SHARED_LIBRARY)
diff --git a/minadbd21/README.txt b/minadbd21/README.txt
deleted file mode 100644
index c9df484..0000000
--- a/minadbd21/README.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-The contents of this directory are copied from system/core/adb, with
-the following changes:
-
-adb.c
-  - much support for host mode and non-linux OS's stripped out; this
-    version only runs as adbd on the device.
-  - always setuid/setgid's itself to the shell user
-  - only uses USB transport
-  - references to JDWP removed
-  - main() removed
-  - all ADB_HOST and win32 code removed
-  - removed listeners, logging code, background server (for host)
-
-adb.h
-  - minor changes to match adb.c changes
-
-sockets.c
-  - references to JDWP removed
-  - ADB_HOST code removed
-
-services.c
-  - all services except echo_service (which is commented out) removed
-  - all host mode support removed
-  - sideload_service() added; this is the only service supported.  It
-    receives a single blob of data, writes it to a fixed filename, and
-    makes the process exit.
-
-Android.mk
-  - only builds in adbd mode; builds as static library instead of a
-    standalone executable.
-
-sysdeps.h
-  - changes adb_creat() to use O_NOFOLLOW
-
-transport.c
-  - removed ADB_HOST code
-
-transport_usb.c
-  - removed ADB_HOST code
diff --git a/minadbd21/adb.c b/minadbd21/adb.c
deleted file mode 100644
index c35e830..0000000
--- a/minadbd21/adb.c
+++ /dev/null
@@ -1,418 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define  TRACE_TAG   TRACE_ADB
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <string.h>
-#include <time.h>
-#include <sys/time.h>
-
-#include "sysdeps.h"
-#include "adb.h"
-
-#include <private/android_filesystem_config.h>
-
-#if ADB_TRACE
-ADB_MUTEX_DEFINE( D_lock );
-#endif
-
-int HOST = 0;
-
-static const char *adb_device_banner = "sideload";
-
-char ADB_SIDELOAD_FILENAME[255];
-
-void fatal(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    fprintf(stderr, "error: ");
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    va_end(ap);
-    exit(-1);
-}
-
-void fatal_errno(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    fprintf(stderr, "error: %s: ", strerror(errno));
-    vfprintf(stderr, fmt, ap);
-    fprintf(stderr, "\n");
-    va_end(ap);
-    exit(-1);
-}
-
-int   adb_trace_mask;
-
-/* read a comma/space/colum/semi-column separated list of tags
- * from the ADB_TRACE environment variable and build the trace
- * mask from it. note that '1' and 'all' are special cases to
- * enable all tracing
- */
-void  adb_trace_init(void)
-{
-    const char*  p = getenv("ADB_TRACE");
-    const char*  q;
-
-    static const struct {
-        const char*  tag;
-        int           flag;
-    } tags[] = {
-        { "1", 0 },
-        { "all", 0 },
-        { "adb", TRACE_ADB },
-        { "sockets", TRACE_SOCKETS },
-        { "packets", TRACE_PACKETS },
-        { "rwx", TRACE_RWX },
-        { "usb", TRACE_USB },
-        { "sync", TRACE_SYNC },
-        { "sysdeps", TRACE_SYSDEPS },
-        { "transport", TRACE_TRANSPORT },
-        { "jdwp", TRACE_JDWP },
-        { "services", TRACE_SERVICES },
-        { NULL, 0 }
-    };
-
-    if (p == NULL)
-            return;
-
-    /* use a comma/column/semi-colum/space separated list */
-    while (*p) {
-        int  len, tagn;
-
-        q = strpbrk(p, " ,:;");
-        if (q == NULL) {
-            q = p + strlen(p);
-        }
-        len = q - p;
-
-        for (tagn = 0; tags[tagn].tag != NULL; tagn++)
-        {
-            int  taglen = strlen(tags[tagn].tag);
-
-            if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
-            {
-                int  flag = tags[tagn].flag;
-                if (flag == 0) {
-                    adb_trace_mask = ~0;
-                    return;
-                }
-                adb_trace_mask |= (1 << flag);
-                break;
-            }
-        }
-        p = q;
-        if (*p)
-            p++;
-    }
-}
-
-
-apacket *get_apacket(void)
-{
-    apacket *p = malloc(sizeof(apacket));
-    if(p == 0) fatal("failed to allocate an apacket");
-    memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
-    return p;
-}
-
-void put_apacket(apacket *p)
-{
-    free(p);
-}
-
-void handle_online(void)
-{
-    D("adb: online\n");
-}
-
-void handle_offline(atransport *t)
-{
-    D("adb: offline\n");
-    //Close the associated usb
-    run_transport_disconnects(t);
-}
-
-#if TRACE_PACKETS
-#define DUMPMAX 32
-void print_packet(const char *label, apacket *p)
-{
-    char *tag;
-    char *x;
-    unsigned count;
-
-    switch(p->msg.command){
-    case A_SYNC: tag = "SYNC"; break;
-    case A_CNXN: tag = "CNXN" ; break;
-    case A_OPEN: tag = "OPEN"; break;
-    case A_OKAY: tag = "OKAY"; break;
-    case A_CLSE: tag = "CLSE"; break;
-    case A_WRTE: tag = "WRTE"; break;
-    default: tag = "????"; break;
-    }
-
-    fprintf(stderr, "%s: %s %08x %08x %04x \"",
-            label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
-    count = p->msg.data_length;
-    x = (char*) p->data;
-    if(count > DUMPMAX) {
-        count = DUMPMAX;
-        tag = "\n";
-    } else {
-        tag = "\"\n";
-    }
-    while(count-- > 0){
-        if((*x >= ' ') && (*x < 127)) {
-            fputc(*x, stderr);
-        } else {
-            fputc('.', stderr);
-        }
-        x++;
-    }
-    fprintf(stderr, tag);
-}
-#endif
-
-static void send_ready(unsigned local, unsigned remote, atransport *t)
-{
-    D("Calling send_ready \n");
-    apacket *p = get_apacket();
-    p->msg.command = A_OKAY;
-    p->msg.arg0 = local;
-    p->msg.arg1 = remote;
-    send_packet(p, t);
-}
-
-static void send_close(unsigned local, unsigned remote, atransport *t)
-{
-    D("Calling send_close \n");
-    apacket *p = get_apacket();
-    p->msg.command = A_CLSE;
-    p->msg.arg0 = local;
-    p->msg.arg1 = remote;
-    send_packet(p, t);
-}
-
-static void send_connect(atransport *t)
-{
-    D("Calling send_connect \n");
-    apacket *cp = get_apacket();
-    cp->msg.command = A_CNXN;
-    cp->msg.arg0 = A_VERSION;
-    cp->msg.arg1 = MAX_PAYLOAD;
-    snprintf((char*) cp->data, sizeof cp->data, "%s::",
-            HOST ? "host" : adb_device_banner);
-    cp->msg.data_length = strlen((char*) cp->data) + 1;
-    send_packet(cp, t);
-}
-
-void parse_banner(char *banner, atransport *t)
-{
-    char *type, *product, *end;
-
-    D("parse_banner: %s\n", banner);
-    type = banner;
-    product = strchr(type, ':');
-    if(product) {
-        *product++ = 0;
-    } else {
-        product = "";
-    }
-
-        /* remove trailing ':' */
-    end = strchr(product, ':');
-    if(end) *end = 0;
-
-        /* save product name in device structure */
-    if (t->product == NULL) {
-        t->product = strdup(product);
-    } else if (strcmp(product, t->product) != 0) {
-        free(t->product);
-        t->product = strdup(product);
-    }
-
-    if(!strcmp(type, "bootloader")){
-        D("setting connection_state to CS_BOOTLOADER\n");
-        t->connection_state = CS_BOOTLOADER;
-        update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "device")) {
-        D("setting connection_state to CS_DEVICE\n");
-        t->connection_state = CS_DEVICE;
-        update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "recovery")) {
-        D("setting connection_state to CS_RECOVERY\n");
-        t->connection_state = CS_RECOVERY;
-        update_transports();
-        return;
-    }
-
-    if(!strcmp(type, "sideload")) {
-        D("setting connection_state to CS_SIDELOAD\n");
-        t->connection_state = CS_SIDELOAD;
-        update_transports();
-        return;
-    }
-
-    t->connection_state = CS_HOST;
-}
-
-void handle_packet(apacket *p, atransport *t)
-{
-    asocket *s;
-
-    D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
-            ((char*) (&(p->msg.command)))[1],
-            ((char*) (&(p->msg.command)))[2],
-            ((char*) (&(p->msg.command)))[3]);
-    print_packet("recv", p);
-
-    switch(p->msg.command){
-    case A_SYNC:
-        if(p->msg.arg0){
-            send_packet(p, t);
-            if(HOST) send_connect(t);
-        } else {
-            t->connection_state = CS_OFFLINE;
-            handle_offline(t);
-            send_packet(p, t);
-        }
-        return;
-
-    case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
-            /* XXX verify version, etc */
-        if(t->connection_state != CS_OFFLINE) {
-            t->connection_state = CS_OFFLINE;
-            handle_offline(t);
-        }
-        parse_banner((char*) p->data, t);
-        handle_online();
-        if(!HOST) send_connect(t);
-        break;
-
-    case A_OPEN: /* OPEN(local-id, 0, "destination") */
-        if(t->connection_state != CS_OFFLINE) {
-            char *name = (char*) p->data;
-            name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
-            s = create_local_service_socket(name);
-            if(s == 0) {
-                send_close(0, p->msg.arg0, t);
-            } else {
-                s->peer = create_remote_socket(p->msg.arg0, t);
-                s->peer->peer = s;
-                send_ready(s->id, s->peer->id, t);
-                s->ready(s);
-            }
-        }
-        break;
-
-    case A_OKAY: /* READY(local-id, remote-id, "") */
-        if(t->connection_state != CS_OFFLINE) {
-            if((s = find_local_socket(p->msg.arg1))) {
-                if(s->peer == 0) {
-                    s->peer = create_remote_socket(p->msg.arg0, t);
-                    s->peer->peer = s;
-                }
-                s->ready(s);
-            }
-        }
-        break;
-
-    case A_CLSE: /* CLOSE(local-id, remote-id, "") */
-        if(t->connection_state != CS_OFFLINE) {
-            if((s = find_local_socket(p->msg.arg1))) {
-                s->close(s);
-            }
-        }
-        break;
-
-    case A_WRTE:
-        if(t->connection_state != CS_OFFLINE) {
-            if((s = find_local_socket(p->msg.arg1))) {
-                unsigned rid = p->msg.arg0;
-                p->len = p->msg.data_length;
-
-                if(s->enqueue(s, p) == 0) {
-                    D("Enqueue the socket\n");
-                    send_ready(s->id, rid, t);
-                }
-                return;
-            }
-        }
-        break;
-
-    default:
-        printf("handle_packet: what is %08x?!\n", p->msg.command);
-    }
-
-    put_apacket(p);
-}
-
-static void adb_cleanup(void)
-{
-    usb_cleanup();
-}
-
-int adb_main(const char* path)
-{
-	strcpy(ADB_SIDELOAD_FILENAME, path);
-    atexit(adb_cleanup);
-#if defined(HAVE_FORKEXEC)
-    // No SIGCHLD. Let the service subproc handle its children.
-    signal(SIGPIPE, SIG_IGN);
-#endif
-
-    init_transport_registration();
-
-    // The minimal version of adbd only uses USB.
-    if (access(USB_ADB_PATH, F_OK) == 0 || access(USB_FFS_ADB_EP0, F_OK) == 0) {
-        // listen on USB
-        usb_init();
-    }
-
-/* Remove this so that perms work properly
-    if (setgid(AID_SHELL) != 0) {
-        fprintf(stderr, "failed to setgid to shell\n");
-        exit(1);
-    }
-    if (setuid(AID_SHELL) != 0) {
-        fprintf(stderr, "failed to setuid to shell\n");
-        exit(1);
-    }
-
-    fprintf(stderr, "userid is %d\n", getuid());
-*/
-
-    D("Event loop starting\n");
-
-    fdevent_loop();
-
-    usb_cleanup();
-
-    return 0;
-}
diff --git a/minadbd21/adb.h b/minadbd21/adb.h
deleted file mode 100644
index 08ee989..0000000
--- a/minadbd21/adb.h
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __ADB_H
-#define __ADB_H
-
-#include <limits.h>
-
-#include "transport.h"  /* readx(), writex() */
-#include "fdevent.h"
-
-#define MAX_PAYLOAD 4096
-
-#define A_SYNC 0x434e5953
-#define A_CNXN 0x4e584e43
-#define A_OPEN 0x4e45504f
-#define A_OKAY 0x59414b4f
-#define A_CLSE 0x45534c43
-#define A_WRTE 0x45545257
-
-#define A_VERSION 0x01000000        // ADB protocol version
-
-#define ADB_VERSION_MAJOR 1         // Used for help/version information
-#define ADB_VERSION_MINOR 0         // Used for help/version information
-
-#define ADB_SERVER_VERSION    29    // Increment this when we want to force users to start a new adb server
-
-typedef struct amessage amessage;
-typedef struct apacket apacket;
-typedef struct asocket asocket;
-typedef struct aservice aservice;
-typedef struct atransport atransport;
-typedef struct adisconnect  adisconnect;
-typedef struct usb_handle usb_handle;
-
-struct amessage {
-    unsigned command;       /* command identifier constant      */
-    unsigned arg0;          /* first argument                   */
-    unsigned arg1;          /* second argument                  */
-    unsigned data_length;   /* length of payload (0 is allowed) */
-    unsigned data_check;    /* checksum of data payload         */
-    unsigned magic;         /* command ^ 0xffffffff             */
-};
-
-struct apacket
-{
-    apacket *next;
-
-    unsigned len;
-    unsigned char *ptr;
-
-    amessage msg;
-    unsigned char data[MAX_PAYLOAD];
-};
-
-/* An asocket represents one half of a connection between a local and
-** remote entity.  A local asocket is bound to a file descriptor.  A
-** remote asocket is bound to the protocol engine.
-*/
-struct asocket {
-        /* chain pointers for the local/remote list of
-        ** asockets that this asocket lives in
-        */
-    asocket *next;
-    asocket *prev;
-
-        /* the unique identifier for this asocket
-        */
-    unsigned id;
-
-        /* flag: set when the socket's peer has closed
-        ** but packets are still queued for delivery
-        */
-    int    closing;
-
-        /* the asocket we are connected to
-        */
-
-    asocket *peer;
-
-        /* For local asockets, the fde is used to bind
-        ** us to our fd event system.  For remote asockets
-        ** these fields are not used.
-        */
-    fdevent fde;
-    int fd;
-
-        /* queue of apackets waiting to be written
-        */
-    apacket *pkt_first;
-    apacket *pkt_last;
-
-        /* enqueue is called by our peer when it has data
-        ** for us.  It should return 0 if we can accept more
-        ** data or 1 if not.  If we return 1, we must call
-        ** peer->ready() when we once again are ready to
-        ** receive data.
-        */
-    int (*enqueue)(asocket *s, apacket *pkt);
-
-        /* ready is called by the peer when it is ready for
-        ** us to send data via enqueue again
-        */
-    void (*ready)(asocket *s);
-
-        /* close is called by the peer when it has gone away.
-        ** we are not allowed to make any further calls on the
-        ** peer once our close method is called.
-        */
-    void (*close)(asocket *s);
-
-        /* socket-type-specific extradata */
-    void *extra;
-
-    	/* A socket is bound to atransport */
-    atransport *transport;
-};
-
-
-/* the adisconnect structure is used to record a callback that
-** will be called whenever a transport is disconnected (e.g. by the user)
-** this should be used to cleanup objects that depend on the
-** transport (e.g. remote sockets, etc...)
-*/
-struct  adisconnect
-{
-    void        (*func)(void*  opaque, atransport*  t);
-    void*         opaque;
-    adisconnect*  next;
-    adisconnect*  prev;
-};
-
-
-/* a transport object models the connection to a remote device or emulator
-** there is one transport per connected device/emulator. a "local transport"
-** connects through TCP (for the emulator), while a "usb transport" through
-** USB (for real devices)
-**
-** note that kTransportHost doesn't really correspond to a real transport
-** object, it's a special value used to indicate that a client wants to
-** connect to a service implemented within the ADB server itself.
-*/
-typedef enum transport_type {
-        kTransportUsb,
-        kTransportLocal,
-        kTransportAny,
-        kTransportHost,
-} transport_type;
-
-struct atransport
-{
-    atransport *next;
-    atransport *prev;
-
-    int (*read_from_remote)(apacket *p, atransport *t);
-    int (*write_to_remote)(apacket *p, atransport *t);
-    void (*close)(atransport *t);
-    void (*kick)(atransport *t);
-
-    int fd;
-    int transport_socket;
-    fdevent transport_fde;
-    int ref_count;
-    unsigned sync_token;
-    int connection_state;
-    transport_type type;
-
-        /* usb handle or socket fd as needed */
-    usb_handle *usb;
-    int sfd;
-
-        /* used to identify transports for clients */
-    char *serial;
-    char *product;
-    int adb_port; // Use for emulators (local transport)
-
-        /* a list of adisconnect callbacks called when the transport is kicked */
-    int          kicked;
-    adisconnect  disconnects;
-};
-
-
-void print_packet(const char *label, apacket *p);
-
-asocket *find_local_socket(unsigned id);
-void install_local_socket(asocket *s);
-void remove_socket(asocket *s);
-void close_all_sockets(atransport *t);
-
-#define  LOCAL_CLIENT_PREFIX  "emulator-"
-
-asocket *create_local_socket(int fd);
-asocket *create_local_service_socket(const char *destination);
-
-asocket *create_remote_socket(unsigned id, atransport *t);
-void connect_to_remote(asocket *s, const char *destination);
-void connect_to_smartsocket(asocket *s);
-
-void fatal(const char *fmt, ...);
-void fatal_errno(const char *fmt, ...);
-
-void handle_packet(apacket *p, atransport *t);
-void send_packet(apacket *p, atransport *t);
-
-void get_my_path(char *s, size_t maxLen);
-int launch_server(int server_port);
-int adb_main(const char* path);
-
-
-/* transports are ref-counted
-** get_device_transport does an acquire on your behalf before returning
-*/
-void init_transport_registration(void);
-int  list_transports(char *buf, size_t  bufsize);
-void update_transports(void);
-
-asocket*  create_device_tracker(void);
-
-/* Obtain a transport from the available transports.
-** If state is != CS_ANY, only transports in that state are considered.
-** If serial is non-NULL then only the device with that serial will be chosen.
-** If no suitable transport is found, error is set.
-*/
-atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char **error_out);
-void   add_transport_disconnect( atransport*  t, adisconnect*  dis );
-void   remove_transport_disconnect( atransport*  t, adisconnect*  dis );
-void   run_transport_disconnects( atransport*  t );
-void   kick_transport( atransport*  t );
-
-/* initialize a transport object's func pointers and state */
-#if ADB_HOST
-int get_available_local_transport_index();
-#endif
-void init_usb_transport(atransport *t, usb_handle *usb, int state);
-
-/* for MacOS X cleanup */
-void close_usb_devices();
-
-/* these should only be used for the "adb disconnect" command */
-void unregister_transport(atransport *t);
-void unregister_all_tcp_transports();
-
-void register_usb_transport(usb_handle *h, const char *serial, unsigned writeable);
-
-/* this should only be used for transports with connection_state == CS_NOPERM */
-void unregister_usb_transport(usb_handle *usb);
-
-atransport *find_transport(const char *serial);
-#if ADB_HOST
-atransport* find_emulator_transport_by_adb_port(int adb_port);
-#endif
-
-int service_to_fd(const char *name);
-#if ADB_HOST
-asocket *host_service_to_socket(const char*  name, const char *serial);
-#endif
-
-#if !ADB_HOST
-typedef enum {
-    BACKUP,
-    RESTORE
-} BackupOperation;
-int backup_service(BackupOperation operation, char* args);
-void framebuffer_service(int fd, void *cookie);
-void log_service(int fd, void *cookie);
-void remount_service(int fd, void *cookie);
-char * get_log_file_path(const char * log_name);
-#endif
-
-/* packet allocator */
-apacket *get_apacket(void);
-void put_apacket(apacket *p);
-
-int check_header(apacket *p);
-int check_data(apacket *p);
-
-/* define ADB_TRACE to 1 to enable tracing support, or 0 to disable it */
-
-#define  ADB_TRACE    1
-
-/* IMPORTANT: if you change the following list, don't
- * forget to update the corresponding 'tags' table in
- * the adb_trace_init() function implemented in adb.c
- */
-typedef enum {
-    TRACE_ADB = 0,   /* 0x001 */
-    TRACE_SOCKETS,
-    TRACE_PACKETS,
-    TRACE_TRANSPORT,
-    TRACE_RWX,       /* 0x010 */
-    TRACE_USB,
-    TRACE_SYNC,
-    TRACE_SYSDEPS,
-    TRACE_JDWP,      /* 0x100 */
-    TRACE_SERVICES,
-} AdbTrace;
-
-#if ADB_TRACE
-
-  extern int     adb_trace_mask;
-  extern unsigned char    adb_trace_output_count;
-  void    adb_trace_init(void);
-
-#  define ADB_TRACING  ((adb_trace_mask & (1 << TRACE_TAG)) != 0)
-
-  /* you must define TRACE_TAG before using this macro */
-#  define  D(...)                                      \
-        do {                                           \
-            if (ADB_TRACING) {                         \
-                int save_errno = errno;                \
-                adb_mutex_lock(&D_lock);               \
-                fprintf(stderr, "%s::%s():",           \
-                        __FILE__, __FUNCTION__);       \
-                errno = save_errno;                    \
-                fprintf(stderr, __VA_ARGS__ );         \
-                fflush(stderr);                        \
-                adb_mutex_unlock(&D_lock);             \
-                errno = save_errno;                    \
-           }                                           \
-        } while (0)
-#  define  DR(...)                                     \
-        do {                                           \
-            if (ADB_TRACING) {                         \
-                int save_errno = errno;                \
-                adb_mutex_lock(&D_lock);               \
-                errno = save_errno;                    \
-                fprintf(stderr, __VA_ARGS__ );         \
-                fflush(stderr);                        \
-                adb_mutex_unlock(&D_lock);             \
-                errno = save_errno;                    \
-           }                                           \
-        } while (0)
-#else
-#  define  D(...)          ((void)0)
-#  define  DR(...)         ((void)0)
-#  define  ADB_TRACING     0
-#endif
-
-
-#if !TRACE_PACKETS
-#define print_packet(tag,p) do {} while (0)
-#endif
-
-#if ADB_HOST_ON_TARGET
-/* adb and adbd are coexisting on the target, so use 5038 for adb
- * to avoid conflicting with adbd's usage of 5037
- */
-#  define DEFAULT_ADB_PORT 5038
-#else
-#  define DEFAULT_ADB_PORT 5037
-#endif
-
-#define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555
-
-#define ADB_CLASS              0xff
-#define ADB_SUBCLASS           0x42
-#define ADB_PROTOCOL           0x1
-
-
-void local_init(int port);
-int  local_connect(int  port);
-int  local_connect_arbitrary_ports(int console_port, int adb_port);
-
-/* usb host/client interface */
-void usb_init();
-void usb_cleanup();
-int usb_write(usb_handle *h, const void *data, int len);
-int usb_read(usb_handle *h, void *data, int len);
-int usb_close(usb_handle *h);
-void usb_kick(usb_handle *h);
-
-/* used for USB device detection */
-#if ADB_HOST
-int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_protocol);
-#endif
-
-unsigned host_to_le32(unsigned n);
-int adb_commandline(int argc, char **argv);
-
-int connection_state(atransport *t);
-
-#define CS_ANY       -1
-#define CS_OFFLINE    0
-#define CS_BOOTLOADER 1
-#define CS_DEVICE     2
-#define CS_HOST       3
-#define CS_RECOVERY   4
-#define CS_NOPERM     5 /* Insufficient permissions to communicate with the device */
-#define CS_SIDELOAD   6
-#define CS_UNAUTHORIZED 7
-
-extern int HOST;
-extern int SHELL_EXIT_NOTIFY_FD;
-
-#define CHUNK_SIZE (64*1024)
-
-#if !ADB_HOST
-#define USB_ADB_PATH     "/dev/android_adb"
-
-#define USB_FFS_ADB_PATH  "/dev/usb-ffs/adb/"
-#define USB_FFS_ADB_EP(x) USB_FFS_ADB_PATH#x
-
-#define USB_FFS_ADB_EP0   USB_FFS_ADB_EP(ep0)
-#define USB_FFS_ADB_OUT   USB_FFS_ADB_EP(ep1)
-#define USB_FFS_ADB_IN    USB_FFS_ADB_EP(ep2)
-#endif
-
-int sendfailmsg(int fd, const char *reason);
-int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s);
-
-//#define ADB_SIDELOAD_FILENAME "/tmp/update.zip"
-extern char ADB_SIDELOAD_FILENAME[255];
-
-#endif
diff --git a/minadbd21/fdevent.c b/minadbd21/fdevent.c
deleted file mode 100644
index 5c374a7..0000000
--- a/minadbd21/fdevent.c
+++ /dev/null
@@ -1,695 +0,0 @@
-/* http://frotznet.googlecode.com/svn/trunk/utils/fdevent.c
-**
-** Copyright 2006, Brian Swetland <swetland@frotz.net>
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#include <sys/ioctl.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <fcntl.h>
-
-#include <stdarg.h>
-#include <stddef.h>
-
-#include "fdevent.h"
-#include "transport.h"
-#include "sysdeps.h"
-
-
-/* !!! Do not enable DEBUG for the adb that will run as the server:
-** both stdout and stderr are used to communicate between the client
-** and server. Any extra output will cause failures.
-*/
-#define DEBUG 0   /* non-0 will break adb server */
-
-// This socket is used when a subproc shell service exists.
-// It wakes up the fdevent_loop() and cause the correct handling
-// of the shell's pseudo-tty master. I.e. force close it.
-int SHELL_EXIT_NOTIFY_FD = -1;
-
-static void fatal(const char *fn, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    fprintf(stderr, "%s:", fn);
-    vfprintf(stderr, fmt, ap);
-    va_end(ap);
-    abort();
-}
-
-#define FATAL(x...) fatal(__FUNCTION__, x)
-
-#if DEBUG
-#define D(...) \
-    do { \
-        adb_mutex_lock(&D_lock);               \
-        int save_errno = errno;                \
-        fprintf(stderr, "%s::%s():", __FILE__, __FUNCTION__);  \
-        errno = save_errno;                    \
-        fprintf(stderr, __VA_ARGS__);          \
-        adb_mutex_unlock(&D_lock);             \
-        errno = save_errno;                    \
-    } while(0)
-static void dump_fde(fdevent *fde, const char *info)
-{
-    adb_mutex_lock(&D_lock);
-    fprintf(stderr,"FDE #%03d %c%c%c %s\n", fde->fd,
-            fde->state & FDE_READ ? 'R' : ' ',
-            fde->state & FDE_WRITE ? 'W' : ' ',
-            fde->state & FDE_ERROR ? 'E' : ' ',
-            info);
-    adb_mutex_unlock(&D_lock);
-}
-#else
-#define D(...) ((void)0)
-#define dump_fde(fde, info) do { } while(0)
-#endif
-
-#define FDE_EVENTMASK  0x00ff
-#define FDE_STATEMASK  0xff00
-
-#define FDE_ACTIVE     0x0100
-#define FDE_PENDING    0x0200
-#define FDE_CREATED    0x0400
-
-static void fdevent_plist_enqueue(fdevent *node);
-static void fdevent_plist_remove(fdevent *node);
-static fdevent *fdevent_plist_dequeue(void);
-static void fdevent_subproc_event_func(int fd, unsigned events, void *userdata);
-
-static fdevent list_pending = {
-    .next = &list_pending,
-    .prev = &list_pending,
-};
-
-static fdevent **fd_table = 0;
-static int fd_table_max = 0;
-
-#ifdef CRAPTASTIC
-//HAVE_EPOLL
-
-#include <sys/epoll.h>
-
-static int epoll_fd = -1;
-
-static void fdevent_init()
-{
-        /* XXX: what's a good size for the passed in hint? */
-    epoll_fd = epoll_create(256);
-
-    if(epoll_fd < 0) {
-        perror("epoll_create() failed");
-        exit(1);
-    }
-
-        /* mark for close-on-exec */
-    fcntl(epoll_fd, F_SETFD, FD_CLOEXEC);
-}
-
-static void fdevent_connect(fdevent *fde)
-{
-    struct epoll_event ev;
-
-    memset(&ev, 0, sizeof(ev));
-    ev.events = 0;
-    ev.data.ptr = fde;
-
-#if 0
-    if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
-        perror("epoll_ctl() failed\n");
-        exit(1);
-    }
-#endif
-}
-
-static void fdevent_disconnect(fdevent *fde)
-{
-    struct epoll_event ev;
-
-    memset(&ev, 0, sizeof(ev));
-    ev.events = 0;
-    ev.data.ptr = fde;
-
-        /* technically we only need to delete if we
-        ** were actively monitoring events, but let's
-        ** be aggressive and do it anyway, just in case
-        ** something's out of sync
-        */
-    epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev);
-}
-
-static void fdevent_update(fdevent *fde, unsigned events)
-{
-    struct epoll_event ev;
-    int active;
-
-    active = (fde->state & FDE_EVENTMASK) != 0;
-
-    memset(&ev, 0, sizeof(ev));
-    ev.events = 0;
-    ev.data.ptr = fde;
-
-    if(events & FDE_READ) ev.events |= EPOLLIN;
-    if(events & FDE_WRITE) ev.events |= EPOLLOUT;
-    if(events & FDE_ERROR) ev.events |= (EPOLLERR | EPOLLHUP);
-
-    fde->state = (fde->state & FDE_STATEMASK) | events;
-
-    if(active) {
-            /* we're already active. if we're changing to *no*
-            ** events being monitored, we need to delete, otherwise
-            ** we need to just modify
-            */
-        if(ev.events) {
-            if(epoll_ctl(epoll_fd, EPOLL_CTL_MOD, fde->fd, &ev)) {
-                perror("epoll_ctl() failed\n");
-                exit(1);
-            }
-        } else {
-            if(epoll_ctl(epoll_fd, EPOLL_CTL_DEL, fde->fd, &ev)) {
-                perror("epoll_ctl() failed\n");
-                exit(1);
-            }
-        }
-    } else {
-            /* we're not active.  if we're watching events, we need
-            ** to add, otherwise we can just do nothing
-            */
-        if(ev.events) {
-            if(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fde->fd, &ev)) {
-                perror("epoll_ctl() failed\n");
-                exit(1);
-            }
-        }
-    }
-}
-
-static void fdevent_process()
-{
-    struct epoll_event events[256];
-    fdevent *fde;
-    int i, n;
-
-    n = epoll_wait(epoll_fd, events, 256, -1);
-
-    if(n < 0) {
-        if(errno == EINTR) return;
-        perror("epoll_wait");
-        exit(1);
-    }
-
-    for(i = 0; i < n; i++) {
-        struct epoll_event *ev = events + i;
-        fde = ev->data.ptr;
-
-        if(ev->events & EPOLLIN) {
-            fde->events |= FDE_READ;
-        }
-        if(ev->events & EPOLLOUT) {
-            fde->events |= FDE_WRITE;
-        }
-        if(ev->events & (EPOLLERR | EPOLLHUP)) {
-            fde->events |= FDE_ERROR;
-        }
-        if(fde->events) {
-            if(fde->state & FDE_PENDING) continue;
-            fde->state |= FDE_PENDING;
-            fdevent_plist_enqueue(fde);
-        }
-    }
-}
-
-#else /* USE_SELECT */
-
-#ifdef HAVE_WINSOCK
-#include <winsock2.h>
-#else
-#include <sys/select.h>
-#endif
-
-static fd_set read_fds;
-static fd_set write_fds;
-static fd_set error_fds;
-
-static int select_n = 0;
-
-static void fdevent_init(void)
-{
-    FD_ZERO(&read_fds);
-    FD_ZERO(&write_fds);
-    FD_ZERO(&error_fds);
-}
-
-static void fdevent_connect(fdevent *fde)
-{
-    if(fde->fd >= select_n) {
-        select_n = fde->fd + 1;
-    }
-}
-
-static void fdevent_disconnect(fdevent *fde)
-{
-    int i, n;
-
-    FD_CLR(fde->fd, &read_fds);
-    FD_CLR(fde->fd, &write_fds);
-    FD_CLR(fde->fd, &error_fds);
-
-    for(n = 0, i = 0; i < select_n; i++) {
-        if(fd_table[i] != 0) n = i;
-    }
-    select_n = n + 1;
-}
-
-static void fdevent_update(fdevent *fde, unsigned events)
-{
-    if(events & FDE_READ) {
-        FD_SET(fde->fd, &read_fds);
-    } else {
-        FD_CLR(fde->fd, &read_fds);
-    }
-    if(events & FDE_WRITE) {
-        FD_SET(fde->fd, &write_fds);
-    } else {
-        FD_CLR(fde->fd, &write_fds);
-    }
-    if(events & FDE_ERROR) {
-        FD_SET(fde->fd, &error_fds);
-    } else {
-        FD_CLR(fde->fd, &error_fds);
-    }
-
-    fde->state = (fde->state & FDE_STATEMASK) | events;
-}
-
-/* Looks at fd_table[] for bad FDs and sets bit in fds.
-** Returns the number of bad FDs.
-*/
-static int fdevent_fd_check(fd_set *fds)
-{
-    int i, n = 0;
-    fdevent *fde;
-
-    for(i = 0; i < select_n; i++) {
-        fde = fd_table[i];
-        if(fde == 0) continue;
-        if(fcntl(i, F_GETFL, NULL) < 0) {
-            FD_SET(i, fds);
-            n++;
-            // fde->state |= FDE_DONT_CLOSE;
-
-        }
-    }
-    return n;
-}
-
-#if !DEBUG
-static inline void dump_all_fds(const char *extra_msg) {}
-#else
-static void dump_all_fds(const char *extra_msg)
-{
-int i;
-    fdevent *fde;
-    // per fd: 4 digits (but really: log10(FD_SETSIZE)), 1 staus, 1 blank
-    char msg_buff[FD_SETSIZE*6 + 1], *pb=msg_buff;
-    size_t max_chars = FD_SETSIZE * 6 + 1;
-    int printed_out;
-#define SAFE_SPRINTF(...)                                                    \
-    do {                                                                     \
-        printed_out = snprintf(pb, max_chars, __VA_ARGS__);                  \
-        if (printed_out <= 0) {                                              \
-            D("... snprintf failed.\n");                                     \
-            return;                                                          \
-        }                                                                    \
-        if (max_chars < (unsigned int)printed_out) {                         \
-            D("... snprintf out of space.\n");                               \
-            return;                                                          \
-        }                                                                    \
-        pb += printed_out;                                                   \
-        max_chars -= printed_out;                                            \
-    } while(0)
-
-    for(i = 0; i < select_n; i++) {
-        fde = fd_table[i];
-        SAFE_SPRINTF("%d", i);
-        if(fde == 0) {
-            SAFE_SPRINTF("? ");
-            continue;
-        }
-        if(fcntl(i, F_GETFL, NULL) < 0) {
-            SAFE_SPRINTF("b");
-        }
-        SAFE_SPRINTF(" ");
-    }
-    D("%s fd_table[]->fd = {%s}\n", extra_msg, msg_buff);
-}
-#endif
-
-static void fdevent_process()
-{
-    int i, n;
-    fdevent *fde;
-    unsigned events;
-    fd_set rfd, wfd, efd;
-
-    memcpy(&rfd, &read_fds, sizeof(fd_set));
-    memcpy(&wfd, &write_fds, sizeof(fd_set));
-    memcpy(&efd, &error_fds, sizeof(fd_set));
-
-    dump_all_fds("pre select()");
-
-    n = select(select_n, &rfd, &wfd, &efd, NULL);
-    int saved_errno = errno;
-    D("select() returned n=%d, errno=%d\n", n, n<0?saved_errno:0);
-
-    dump_all_fds("post select()");
-
-    if(n < 0) {
-        switch(saved_errno) {
-        case EINTR: return;
-        case EBADF:
-            // Can't trust the FD sets after an error.
-            FD_ZERO(&wfd);
-            FD_ZERO(&efd);
-            FD_ZERO(&rfd);
-            break;
-        default:
-            D("Unexpected select() error=%d\n", saved_errno);
-            return;
-        }
-    }
-    if(n <= 0) {
-        // We fake a read, as the rest of the code assumes
-        // that errors will be detected at that point.
-        n = fdevent_fd_check(&rfd);
-    }
-
-    for(i = 0; (i < select_n) && (n > 0); i++) {
-        events = 0;
-        if(FD_ISSET(i, &rfd)) { events |= FDE_READ; n--; }
-        if(FD_ISSET(i, &wfd)) { events |= FDE_WRITE; n--; }
-        if(FD_ISSET(i, &efd)) { events |= FDE_ERROR; n--; }
-
-        if(events) {
-            fde = fd_table[i];
-            if(fde == 0)
-              FATAL("missing fde for fd %d\n", i);
-
-            fde->events |= events;
-
-            D("got events fde->fd=%d events=%04x, state=%04x\n",
-                fde->fd, fde->events, fde->state);
-            if(fde->state & FDE_PENDING) continue;
-            fde->state |= FDE_PENDING;
-            fdevent_plist_enqueue(fde);
-        }
-    }
-}
-
-#endif
-
-static void fdevent_register(fdevent *fde)
-{
-    if(fde->fd < 0) {
-        FATAL("bogus negative fd (%d)\n", fde->fd);
-    }
-
-    if(fde->fd >= fd_table_max) {
-        int oldmax = fd_table_max;
-        if(fde->fd > 32000) {
-            FATAL("bogus huuuuge fd (%d)\n", fde->fd);
-        }
-        if(fd_table_max == 0) {
-            fdevent_init();
-            fd_table_max = 256;
-        }
-        while(fd_table_max <= fde->fd) {
-            fd_table_max *= 2;
-        }
-        fd_table = realloc(fd_table, sizeof(fdevent*) * fd_table_max);
-        if(fd_table == 0) {
-            FATAL("could not expand fd_table to %d entries\n", fd_table_max);
-        }
-        memset(fd_table + oldmax, 0, sizeof(int) * (fd_table_max - oldmax));
-    }
-
-    fd_table[fde->fd] = fde;
-}
-
-static void fdevent_unregister(fdevent *fde)
-{
-    if((fde->fd < 0) || (fde->fd >= fd_table_max)) {
-        FATAL("fd out of range (%d)\n", fde->fd);
-    }
-
-    if(fd_table[fde->fd] != fde) {
-        FATAL("fd_table out of sync [%d]\n", fde->fd);
-    }
-
-    fd_table[fde->fd] = 0;
-
-    if(!(fde->state & FDE_DONT_CLOSE)) {
-        dump_fde(fde, "close");
-        adb_close(fde->fd);
-    }
-}
-
-static void fdevent_plist_enqueue(fdevent *node)
-{
-    fdevent *list = &list_pending;
-
-    node->next = list;
-    node->prev = list->prev;
-    node->prev->next = node;
-    list->prev = node;
-}
-
-static void fdevent_plist_remove(fdevent *node)
-{
-    node->prev->next = node->next;
-    node->next->prev = node->prev;
-    node->next = 0;
-    node->prev = 0;
-}
-
-static fdevent *fdevent_plist_dequeue(void)
-{
-    fdevent *list = &list_pending;
-    fdevent *node = list->next;
-
-    if(node == list) return 0;
-
-    list->next = node->next;
-    list->next->prev = list;
-    node->next = 0;
-    node->prev = 0;
-
-    return node;
-}
-
-static void fdevent_call_fdfunc(fdevent* fde)
-{
-    unsigned events = fde->events;
-    fde->events = 0;
-    if(!(fde->state & FDE_PENDING)) return;
-    fde->state &= (~FDE_PENDING);
-    dump_fde(fde, "callback");
-    fde->func(fde->fd, events, fde->arg);
-}
-
-static void fdevent_subproc_event_func(int fd, unsigned ev, void *userdata)
-{
-
-    D("subproc handling on fd=%d ev=%04x\n", fd, ev);
-
-    // Hook oneself back into the fde's suitable for select() on read.
-    if((fd < 0) || (fd >= fd_table_max)) {
-        FATAL("fd %d out of range for fd_table \n", fd);
-    }
-    fdevent *fde = fd_table[fd];
-    fdevent_add(fde, FDE_READ);
-
-    if(ev & FDE_READ){
-      int subproc_fd;
-
-      if(readx(fd, &subproc_fd, sizeof(subproc_fd))) {
-          FATAL("Failed to read the subproc's fd from fd=%d\n", fd);
-      }
-      if((subproc_fd < 0) || (subproc_fd >= fd_table_max)) {
-          D("subproc_fd %d out of range 0, fd_table_max=%d\n",
-            subproc_fd, fd_table_max);
-          return;
-      }
-      fdevent *subproc_fde = fd_table[subproc_fd];
-      if(!subproc_fde) {
-          D("subproc_fd %d cleared from fd_table\n", subproc_fd);
-          return;
-      }
-      if(subproc_fde->fd != subproc_fd) {
-          // Already reallocated?
-          D("subproc_fd %d != fd_table[].fd %d\n", subproc_fd, subproc_fde->fd);
-          return;
-      }
-
-      subproc_fde->force_eof = 1;
-
-      int rcount = 0;
-      ioctl(subproc_fd, FIONREAD, &rcount);
-      D("subproc with fd=%d  has rcount=%d err=%d\n",
-        subproc_fd, rcount, errno);
-
-      if(rcount) {
-        // If there is data left, it will show up in the select().
-        // This works because there is no other thread reading that
-        // data when in this fd_func().
-        return;
-      }
-
-      D("subproc_fde.state=%04x\n", subproc_fde->state);
-      subproc_fde->events |= FDE_READ;
-      if(subproc_fde->state & FDE_PENDING) {
-        return;
-      }
-      subproc_fde->state |= FDE_PENDING;
-      fdevent_call_fdfunc(subproc_fde);
-    }
-}
-
-fdevent *fdevent_create(int fd, fd_func func, void *arg)
-{
-    fdevent *fde = (fdevent*) malloc(sizeof(fdevent));
-    if(fde == 0) return 0;
-    fdevent_install(fde, fd, func, arg);
-    fde->state |= FDE_CREATED;
-    return fde;
-}
-
-void fdevent_destroy(fdevent *fde)
-{
-    if(fde == 0) return;
-    if(!(fde->state & FDE_CREATED)) {
-        FATAL("fde %p not created by fdevent_create()\n", fde);
-    }
-    fdevent_remove(fde);
-}
-
-void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg)
-{
-    memset(fde, 0, sizeof(fdevent));
-    fde->state = FDE_ACTIVE;
-    fde->fd = fd;
-    fde->force_eof = 0;
-    fde->func = func;
-    fde->arg = arg;
-
-#ifndef HAVE_WINSOCK
-    fcntl(fd, F_SETFL, O_NONBLOCK);
-#endif
-    fdevent_register(fde);
-    dump_fde(fde, "connect");
-    fdevent_connect(fde);
-    fde->state |= FDE_ACTIVE;
-}
-
-void fdevent_remove(fdevent *fde)
-{
-    if(fde->state & FDE_PENDING) {
-        fdevent_plist_remove(fde);
-    }
-
-    if(fde->state & FDE_ACTIVE) {
-        fdevent_disconnect(fde);
-        dump_fde(fde, "disconnect");
-        fdevent_unregister(fde);
-    }
-
-    fde->state = 0;
-    fde->events = 0;
-}
-
-
-void fdevent_set(fdevent *fde, unsigned events)
-{
-    events &= FDE_EVENTMASK;
-
-    if((fde->state & FDE_EVENTMASK) == events) return;
-
-    if(fde->state & FDE_ACTIVE) {
-        fdevent_update(fde, events);
-        dump_fde(fde, "update");
-    }
-
-    fde->state = (fde->state & FDE_STATEMASK) | events;
-
-    if(fde->state & FDE_PENDING) {
-            /* if we're pending, make sure
-            ** we don't signal an event that
-            ** is no longer wanted.
-            */
-        fde->events &= (~events);
-        if(fde->events == 0) {
-            fdevent_plist_remove(fde);
-            fde->state &= (~FDE_PENDING);
-        }
-    }
-}
-
-void fdevent_add(fdevent *fde, unsigned events)
-{
-    fdevent_set(
-        fde, (fde->state & FDE_EVENTMASK) | (events & FDE_EVENTMASK));
-}
-
-void fdevent_del(fdevent *fde, unsigned events)
-{
-    fdevent_set(
-        fde, (fde->state & FDE_EVENTMASK) & (~(events & FDE_EVENTMASK)));
-}
-
-void fdevent_subproc_setup()
-{
-    int s[2];
-
-    if(adb_socketpair(s)) {
-        FATAL("cannot create shell-exit socket-pair\n");
-    }
-    SHELL_EXIT_NOTIFY_FD = s[0];
-    fdevent *fde;
-    fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
-    if(!fde)
-      FATAL("cannot create fdevent for shell-exit handler\n");
-    fdevent_add(fde, FDE_READ);
-}
-
-void fdevent_loop()
-{
-    fdevent *fde;
-    fdevent_subproc_setup();
-
-    for(;;) {
-        D("--- ---- waiting for events\n");
-
-        fdevent_process();
-
-        while((fde = fdevent_plist_dequeue())) {
-            fdevent_call_fdfunc(fde);
-        }
-    }
-}
diff --git a/minadbd21/fdevent.h b/minadbd21/fdevent.h
deleted file mode 100644
index a0ebe2a..0000000
--- a/minadbd21/fdevent.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __FDEVENT_H
-#define __FDEVENT_H
-
-#include <stdint.h>  /* for int64_t */
-
-/* events that may be observed */
-#define FDE_READ              0x0001
-#define FDE_WRITE             0x0002
-#define FDE_ERROR             0x0004
-#define FDE_TIMEOUT           0x0008
-
-/* features that may be set (via the events set/add/del interface) */
-#define FDE_DONT_CLOSE        0x0080
-
-typedef struct fdevent fdevent;
-
-typedef void (*fd_func)(int fd, unsigned events, void *userdata);
-
-/* Allocate and initialize a new fdevent object
- * Note: use FD_TIMER as 'fd' to create a fd-less object
- * (used to implement timers).
-*/
-fdevent *fdevent_create(int fd, fd_func func, void *arg);
-
-/* Uninitialize and deallocate an fdevent object that was
-** created by fdevent_create()
-*/
-void fdevent_destroy(fdevent *fde);
-
-/* Initialize an fdevent object that was externally allocated
-*/
-void fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
-
-/* Uninitialize an fdevent object that was initialized by
-** fdevent_install()
-*/
-void fdevent_remove(fdevent *item);
-
-/* Change which events should cause notifications
-*/
-void fdevent_set(fdevent *fde, unsigned events);
-void fdevent_add(fdevent *fde, unsigned events);
-void fdevent_del(fdevent *fde, unsigned events);
-
-void fdevent_set_timeout(fdevent *fde, int64_t  timeout_ms);
-
-/* loop forever, handling events.
-*/
-void fdevent_loop();
-
-struct fdevent 
-{
-    fdevent *next;
-    fdevent *prev;
-
-    int fd;
-    int force_eof;
-
-    unsigned short state;
-    unsigned short events;
-
-    fd_func func;
-    void *arg;
-};
-
-
-#endif
diff --git a/minadbd21/fuse_adb_provider.c b/minadbd21/fuse_adb_provider.c
deleted file mode 100644
index 18e9906..0000000
--- a/minadbd21/fuse_adb_provider.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "adb.h"
-#include "fuse_sideload.h"
-
-struct adb_data {
-    int sfd;  // file descriptor for the adb channel
-
-    uint64_t file_size;
-    uint32_t block_size;
-};
-
-static int read_block_adb(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size) {
-    struct adb_data* ad = (struct adb_data*)cookie;
-
-    char buf[10];
-    snprintf(buf, sizeof(buf), "%08u", block);
-    if (writex(ad->sfd, buf, 8) < 0) {
-        fprintf(stderr, "failed to write to adb host: %s\n", strerror(errno));
-        return -EIO;
-    }
-
-    if (readx(ad->sfd, buffer, fetch_size) < 0) {
-        fprintf(stderr, "failed to read from adb host: %s\n", strerror(errno));
-        return -EIO;
-    }
-
-    return 0;
-}
-
-static void close_adb(void* cookie) {
-    struct adb_data* ad = (struct adb_data*)cookie;
-
-    writex(ad->sfd, "DONEDONE", 8);
-}
-
-int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size) {
-    struct adb_data ad;
-    struct provider_vtab vtab;
-
-    ad.sfd = sfd;
-    ad.file_size = file_size;
-    ad.block_size = block_size;
-
-    vtab.read_block = read_block_adb;
-    vtab.close = close_adb;
-
-    return run_old_fuse_sideload(&vtab, &ad, file_size, block_size);
-}
diff --git a/minadbd21/mutex_list.h b/minadbd21/mutex_list.h
deleted file mode 100644
index 652dd73..0000000
--- a/minadbd21/mutex_list.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* the list of mutexes used by adb */
-/* #ifndef __MUTEX_LIST_H
- * Do not use an include-guard. This file is included once to declare the locks
- * and once in win32 to actually do the runtime initialization.
- */
-#ifndef ADB_MUTEX
-#error ADB_MUTEX not defined when including this file
-#endif
-ADB_MUTEX(dns_lock)
-ADB_MUTEX(socket_list_lock)
-ADB_MUTEX(transport_lock)
-#if ADB_HOST
-ADB_MUTEX(local_transports_lock)
-#endif
-ADB_MUTEX(usb_lock)
-
-// Sadly logging to /data/adb/adb-... is not thread safe.
-//  After modifying adb.h::D() to count invocations:
-//   DEBUG(jpa):0:Handling main()
-//   DEBUG(jpa):1:[ usb_init - starting thread ]
-// (Oopsies, no :2:, and matching message is also gone.)
-//   DEBUG(jpa):3:[ usb_thread - opening device ]
-//   DEBUG(jpa):4:jdwp control socket started (10)
-ADB_MUTEX(D_lock)
-
-#undef ADB_MUTEX
diff --git a/minadbd21/services.c b/minadbd21/services.c
deleted file mode 100644
index 218b84a..0000000
--- a/minadbd21/services.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "sysdeps.h"
-#include "fdevent.h"
-#include "fuse_adb_provider.h"
-
-#define  TRACE_TAG  TRACE_SERVICES
-#include "adb.h"
-
-typedef struct stinfo stinfo;
-
-struct stinfo {
-    void (*func)(int fd, void *cookie);
-    int fd;
-    void *cookie;
-};
-
-
-void *service_bootstrap_func(void *x)
-{
-    stinfo *sti = x;
-    sti->func(sti->fd, sti->cookie);
-    free(sti);
-    return 0;
-}
-
-static void sideload_host_service(int sfd, void* cookie)
-{
-    char* saveptr;
-    const char* s = strtok_r(cookie, ":", &saveptr);
-    uint64_t file_size = strtoull(s, NULL, 10);
-    s = strtok_r(NULL, ":", &saveptr);
-    uint32_t block_size = strtoul(s, NULL, 10);
-
-    printf("sideload-host file size %llu block size %lu\n", file_size, block_size);
-
-    int result = run_adb_fuse(sfd, file_size, block_size);
-
-    printf("sideload_host finished\n");
-    sleep(1);
-    exit(result == 0 ? 0 : 1);
-}
-
-#if 0
-static void echo_service(int fd, void *cookie)
-{
-    char buf[4096];
-    int r;
-    char *p;
-    int c;
-
-    for(;;) {
-        r = read(fd, buf, 4096);
-        if(r == 0) goto done;
-        if(r < 0) {
-            if(errno == EINTR) continue;
-            else goto done;
-        }
-
-        c = r;
-        p = buf;
-        while(c > 0) {
-            r = write(fd, p, c);
-            if(r > 0) {
-                c -= r;
-                p += r;
-                continue;
-            }
-            if((r < 0) && (errno == EINTR)) continue;
-            goto done;
-        }
-    }
-done:
-    close(fd);
-}
-#endif
-
-static int create_service_thread(void (*func)(int, void *), void *cookie)
-{
-    stinfo *sti;
-    adb_thread_t t;
-    int s[2];
-
-    if(adb_socketpair(s)) {
-        printf("cannot create service socket pair\n");
-        return -1;
-    }
-
-    sti = malloc(sizeof(stinfo));
-    if(sti == 0) fatal("cannot allocate stinfo");
-    sti->func = func;
-    sti->cookie = cookie;
-    sti->fd = s[1];
-
-    if(adb_thread_create( &t, service_bootstrap_func, sti)){
-        free(sti);
-        adb_close(s[0]);
-        adb_close(s[1]);
-        printf("cannot create service thread\n");
-        return -1;
-    }
-
-    D("service thread started, %d:%d\n",s[0], s[1]);
-    return s[0];
-}
-
-int service_to_fd(const char *name)
-{
-    int ret = -1;
-
-    if (!strncmp(name, "sideload:", 9)) {
-        // this exit status causes recovery to print a special error
-        // message saying to use a newer adb (that supports
-        // sideload-host).
-        exit(3);
-    } else if (!strncmp(name, "sideload-host:", 14)) {
-        ret = create_service_thread(sideload_host_service, (void*)(name + 14));
-#if 0
-    } else if(!strncmp(name, "echo:", 5)){
-        ret = create_service_thread(echo_service, 0);
-#endif
-    }
-    if (ret >= 0) {
-        close_on_exec(ret);
-    }
-    return ret;
-}
diff --git a/minadbd21/sockets.c b/minadbd21/sockets.c
deleted file mode 100644
index 817410d..0000000
--- a/minadbd21/sockets.c
+++ /dev/null
@@ -1,731 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "sysdeps.h"
-
-#define  TRACE_TAG  TRACE_SOCKETS
-#include "adb.h"
-
-ADB_MUTEX_DEFINE( socket_list_lock );
-
-static void local_socket_close_locked(asocket *s);
-
-int sendfailmsg(int fd, const char *reason)
-{
-    char buf[9];
-    int len;
-    len = strlen(reason);
-    if(len > 0xffff) len = 0xffff;
-    snprintf(buf, sizeof buf, "FAIL%04x", len);
-    if(writex(fd, buf, 8)) return -1;
-    return writex(fd, reason, len);
-}
-
-//extern int online;
-
-static unsigned local_socket_next_id = 1;
-
-static asocket local_socket_list = {
-    .next = &local_socket_list,
-    .prev = &local_socket_list,
-};
-
-/* the the list of currently closing local sockets.
-** these have no peer anymore, but still packets to
-** write to their fd.
-*/
-static asocket local_socket_closing_list = {
-    .next = &local_socket_closing_list,
-    .prev = &local_socket_closing_list,
-};
-
-asocket *find_local_socket(unsigned id)
-{
-    asocket *s;
-    asocket *result = NULL;
-
-    adb_mutex_lock(&socket_list_lock);
-    for (s = local_socket_list.next; s != &local_socket_list; s = s->next) {
-        if (s->id == id) {
-            result = s;
-            break;
-        }
-    }
-    adb_mutex_unlock(&socket_list_lock);
-
-    return result;
-}
-
-static void
-insert_local_socket(asocket*  s, asocket*  list)
-{
-    s->next       = list;
-    s->prev       = s->next->prev;
-    s->prev->next = s;
-    s->next->prev = s;
-}
-
-
-void install_local_socket(asocket *s)
-{
-    adb_mutex_lock(&socket_list_lock);
-
-    s->id = local_socket_next_id++;
-    insert_local_socket(s, &local_socket_list);
-
-    adb_mutex_unlock(&socket_list_lock);
-}
-
-void remove_socket(asocket *s)
-{
-    // socket_list_lock should already be held
-    if (s->prev && s->next)
-    {
-        s->prev->next = s->next;
-        s->next->prev = s->prev;
-        s->next = 0;
-        s->prev = 0;
-        s->id = 0;
-    }
-}
-
-void close_all_sockets(atransport *t)
-{
-    asocket *s;
-
-        /* this is a little gross, but since s->close() *will* modify
-        ** the list out from under you, your options are limited.
-        */
-    adb_mutex_lock(&socket_list_lock);
-restart:
-    for(s = local_socket_list.next; s != &local_socket_list; s = s->next){
-        if(s->transport == t || (s->peer && s->peer->transport == t)) {
-            local_socket_close_locked(s);
-            goto restart;
-        }
-    }
-    adb_mutex_unlock(&socket_list_lock);
-}
-
-static int local_socket_enqueue(asocket *s, apacket *p)
-{
-    D("LS(%d): enqueue %d\n", s->id, p->len);
-
-    p->ptr = p->data;
-
-        /* if there is already data queue'd, we will receive
-        ** events when it's time to write.  just add this to
-        ** the tail
-        */
-    if(s->pkt_first) {
-        goto enqueue;
-    }
-
-        /* write as much as we can, until we
-        ** would block or there is an error/eof
-        */
-    while(p->len > 0) {
-        int r = adb_write(s->fd, p->ptr, p->len);
-        if(r > 0) {
-            p->len -= r;
-            p->ptr += r;
-            continue;
-        }
-        if((r == 0) || (errno != EAGAIN)) {
-            D( "LS(%d): not ready, errno=%d: %s\n", s->id, errno, strerror(errno) );
-            s->close(s);
-            return 1; /* not ready (error) */
-        } else {
-            break;
-        }
-    }
-
-    if(p->len == 0) {
-        put_apacket(p);
-        return 0; /* ready for more data */
-    }
-
-enqueue:
-    p->next = 0;
-    if(s->pkt_first) {
-        s->pkt_last->next = p;
-    } else {
-        s->pkt_first = p;
-    }
-    s->pkt_last = p;
-
-        /* make sure we are notified when we can drain the queue */
-    fdevent_add(&s->fde, FDE_WRITE);
-
-    return 1; /* not ready (backlog) */
-}
-
-static void local_socket_ready(asocket *s)
-{
-        /* far side is ready for data, pay attention to
-           readable events */
-    fdevent_add(&s->fde, FDE_READ);
-//    D("LS(%d): ready()\n", s->id);
-}
-
-static void local_socket_close(asocket *s)
-{
-    adb_mutex_lock(&socket_list_lock);
-    local_socket_close_locked(s);
-    adb_mutex_unlock(&socket_list_lock);
-}
-
-// be sure to hold the socket list lock when calling this
-static void local_socket_destroy(asocket  *s)
-{
-    apacket *p, *n;
-    D("LS(%d): destroying fde.fd=%d\n", s->id, s->fde.fd);
-
-        /* IMPORTANT: the remove closes the fd
-        ** that belongs to this socket
-        */
-    fdevent_remove(&s->fde);
-
-        /* dispose of any unwritten data */
-    for(p = s->pkt_first; p; p = n) {
-        D("LS(%d): discarding %d bytes\n", s->id, p->len);
-        n = p->next;
-        put_apacket(p);
-    }
-    remove_socket(s);
-    free(s);
-}
-
-
-static void local_socket_close_locked(asocket *s)
-{
-    D("entered. LS(%d) fd=%d\n", s->id, s->fd);
-    if(s->peer) {
-        D("LS(%d): closing peer. peer->id=%d peer->fd=%d\n",
-          s->id, s->peer->id, s->peer->fd);
-        s->peer->peer = 0;
-        // tweak to avoid deadlock
-        if (s->peer->close == local_socket_close) {
-            local_socket_close_locked(s->peer);
-        } else {
-            s->peer->close(s->peer);
-        }
-        s->peer = 0;
-    }
-
-        /* If we are already closing, or if there are no
-        ** pending packets, destroy immediately
-        */
-    if (s->closing || s->pkt_first == NULL) {
-        int   id = s->id;
-        local_socket_destroy(s);
-        D("LS(%d): closed\n", id);
-        return;
-    }
-
-        /* otherwise, put on the closing list
-        */
-    D("LS(%d): closing\n", s->id);
-    s->closing = 1;
-    fdevent_del(&s->fde, FDE_READ);
-    remove_socket(s);
-    D("LS(%d): put on socket_closing_list fd=%d\n", s->id, s->fd);
-    insert_local_socket(s, &local_socket_closing_list);
-}
-
-static void local_socket_event_func(int fd, unsigned ev, void *_s)
-{
-    asocket *s = _s;
-
-    D("LS(%d): event_func(fd=%d(==%d), ev=%04x)\n", s->id, s->fd, fd, ev);
-
-    /* put the FDE_WRITE processing before the FDE_READ
-    ** in order to simplify the code.
-    */
-    if(ev & FDE_WRITE){
-        apacket *p;
-
-        while((p = s->pkt_first) != 0) {
-            while(p->len > 0) {
-                int r = adb_write(fd, p->ptr, p->len);
-                if(r > 0) {
-                    p->ptr += r;
-                    p->len -= r;
-                    continue;
-                }
-                if(r < 0) {
-                    /* returning here is ok because FDE_READ will
-                    ** be processed in the next iteration loop
-                    */
-                    if(errno == EAGAIN) return;
-                    if(errno == EINTR) continue;
-                }
-                D(" closing after write because r=%d and errno is %d\n", r, errno);
-                s->close(s);
-                return;
-            }
-
-            if(p->len == 0) {
-                s->pkt_first = p->next;
-                if(s->pkt_first == 0) s->pkt_last = 0;
-                put_apacket(p);
-            }
-        }
-
-            /* if we sent the last packet of a closing socket,
-            ** we can now destroy it.
-            */
-        if (s->closing) {
-            D(" closing because 'closing' is set after write\n");
-            s->close(s);
-            return;
-        }
-
-            /* no more packets queued, so we can ignore
-            ** writable events again and tell our peer
-            ** to resume writing
-            */
-        fdevent_del(&s->fde, FDE_WRITE);
-        s->peer->ready(s->peer);
-    }
-
-
-    if(ev & FDE_READ){
-        apacket *p = get_apacket();
-        unsigned char *x = p->data;
-        size_t avail = MAX_PAYLOAD;
-        int r;
-        int is_eof = 0;
-
-        while(avail > 0) {
-            r = adb_read(fd, x, avail);
-            D("LS(%d): post adb_read(fd=%d,...) r=%d (errno=%d) avail=%zu\n",
-              s->id, s->fd, r, r<0?errno:0, avail);
-            if(r > 0) {
-                avail -= r;
-                x += r;
-                continue;
-            }
-            if(r < 0) {
-                if(errno == EAGAIN) break;
-                if(errno == EINTR) continue;
-            }
-
-                /* r = 0 or unhandled error */
-            is_eof = 1;
-            break;
-        }
-        D("LS(%d): fd=%d post avail loop. r=%d is_eof=%d forced_eof=%d\n",
-          s->id, s->fd, r, is_eof, s->fde.force_eof);
-        if((avail == MAX_PAYLOAD) || (s->peer == 0)) {
-            put_apacket(p);
-        } else {
-            p->len = MAX_PAYLOAD - avail;
-
-            r = s->peer->enqueue(s->peer, p);
-            D("LS(%d): fd=%d post peer->enqueue(). r=%d\n", s->id, s->fd, r);
-
-            if(r < 0) {
-                    /* error return means they closed us as a side-effect
-                    ** and we must return immediately.
-                    **
-                    ** note that if we still have buffered packets, the
-                    ** socket will be placed on the closing socket list.
-                    ** this handler function will be called again
-                    ** to process FDE_WRITE events.
-                    */
-                return;
-            }
-
-            if(r > 0) {
-                    /* if the remote cannot accept further events,
-                    ** we disable notification of READs.  They'll
-                    ** be enabled again when we get a call to ready()
-                    */
-                fdevent_del(&s->fde, FDE_READ);
-            }
-        }
-        /* Don't allow a forced eof if data is still there */
-        if((s->fde.force_eof && !r) || is_eof) {
-            D(" closing because is_eof=%d r=%d s->fde.force_eof=%d\n", is_eof, r, s->fde.force_eof);
-            s->close(s);
-        }
-    }
-
-    if(ev & FDE_ERROR){
-            /* this should be caught be the next read or write
-            ** catching it here means we may skip the last few
-            ** bytes of readable data.
-            */
-//        s->close(s);
-        D("LS(%d): FDE_ERROR (fd=%d)\n", s->id, s->fd);
-
-        return;
-    }
-}
-
-asocket *create_local_socket(int fd)
-{
-    asocket *s = calloc(1, sizeof(asocket));
-    if (s == NULL) fatal("cannot allocate socket");
-    s->fd = fd;
-    s->enqueue = local_socket_enqueue;
-    s->ready = local_socket_ready;
-    s->close = local_socket_close;
-    install_local_socket(s);
-
-    fdevent_install(&s->fde, fd, local_socket_event_func, s);
-/*    fdevent_add(&s->fde, FDE_ERROR); */
-    //fprintf(stderr, "Created local socket in create_local_socket \n");
-    D("LS(%d): created (fd=%d)\n", s->id, s->fd);
-    return s;
-}
-
-asocket *create_local_service_socket(const char *name)
-{
-    asocket *s;
-    int fd;
-
-    fd = service_to_fd(name);
-    if(fd < 0) return 0;
-
-    s = create_local_socket(fd);
-    D("LS(%d): bound to '%s' via %d\n", s->id, name, fd);
-    return s;
-}
-
-/* a Remote socket is used to send/receive data to/from a given transport object
-** it needs to be closed when the transport is forcibly destroyed by the user
-*/
-typedef struct aremotesocket {
-    asocket      socket;
-    adisconnect  disconnect;
-} aremotesocket;
-
-static int remote_socket_enqueue(asocket *s, apacket *p)
-{
-    D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d\n",
-      s->id, s->fd, s->peer->fd);
-    p->msg.command = A_WRTE;
-    p->msg.arg0 = s->peer->id;
-    p->msg.arg1 = s->id;
-    p->msg.data_length = p->len;
-    send_packet(p, s->transport);
-    return 1;
-}
-
-static void remote_socket_ready(asocket *s)
-{
-    D("entered remote_socket_ready RS(%d) OKAY fd=%d peer.fd=%d\n",
-      s->id, s->fd, s->peer->fd);
-    apacket *p = get_apacket();
-    p->msg.command = A_OKAY;
-    p->msg.arg0 = s->peer->id;
-    p->msg.arg1 = s->id;
-    send_packet(p, s->transport);
-}
-
-static void remote_socket_close(asocket *s)
-{
-    D("entered remote_socket_close RS(%d) CLOSE fd=%d peer->fd=%d\n",
-      s->id, s->fd, s->peer?s->peer->fd:-1);
-    apacket *p = get_apacket();
-    p->msg.command = A_CLSE;
-    if(s->peer) {
-        p->msg.arg0 = s->peer->id;
-        s->peer->peer = 0;
-        D("RS(%d) peer->close()ing peer->id=%d peer->fd=%d\n",
-          s->id, s->peer->id, s->peer->fd);
-        s->peer->close(s->peer);
-    }
-    p->msg.arg1 = s->id;
-    send_packet(p, s->transport);
-    D("RS(%d): closed\n", s->id);
-    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
-    free(s);
-}
-
-static void remote_socket_disconnect(void*  _s, atransport*  t)
-{
-    asocket*  s    = _s;
-    asocket*  peer = s->peer;
-
-    D("remote_socket_disconnect RS(%d)\n", s->id);
-    if (peer) {
-        peer->peer = NULL;
-        peer->close(peer);
-    }
-    remove_transport_disconnect( s->transport, &((aremotesocket*)s)->disconnect );
-    free(s);
-}
-
-asocket *create_remote_socket(unsigned id, atransport *t)
-{
-    asocket *s = calloc(1, sizeof(aremotesocket));
-    adisconnect*  dis = &((aremotesocket*)s)->disconnect;
-
-    if (s == NULL) fatal("cannot allocate socket");
-    s->id = id;
-    s->enqueue = remote_socket_enqueue;
-    s->ready = remote_socket_ready;
-    s->close = remote_socket_close;
-    s->transport = t;
-
-    dis->func   = remote_socket_disconnect;
-    dis->opaque = s;
-    add_transport_disconnect( t, dis );
-    D("RS(%d): created\n", s->id);
-    return s;
-}
-
-void connect_to_remote(asocket *s, const char *destination)
-{
-    D("Connect_to_remote call RS(%d) fd=%d\n", s->id, s->fd);
-    apacket *p = get_apacket();
-    int len = strlen(destination) + 1;
-
-    if(len > (MAX_PAYLOAD-1)) {
-        fatal("destination oversized");
-    }
-
-    D("LS(%d): connect('%s')\n", s->id, destination);
-    p->msg.command = A_OPEN;
-    p->msg.arg0 = s->id;
-    p->msg.data_length = len;
-    strcpy((char*) p->data, destination);
-    send_packet(p, s->transport);
-}
-
-
-/* this is used by magic sockets to rig local sockets to
-   send the go-ahead message when they connect */
-static void local_socket_ready_notify(asocket *s)
-{
-    s->ready = local_socket_ready;
-    s->close = local_socket_close;
-    adb_write(s->fd, "OKAY", 4);
-    s->ready(s);
-}
-
-/* this is used by magic sockets to rig local sockets to
-   send the failure message if they are closed before
-   connected (to avoid closing them without a status message) */
-static void local_socket_close_notify(asocket *s)
-{
-    s->ready = local_socket_ready;
-    s->close = local_socket_close;
-    sendfailmsg(s->fd, "closed");
-    s->close(s);
-}
-
-unsigned unhex(unsigned char *s, int len)
-{
-    unsigned n = 0, c;
-
-    while(len-- > 0) {
-        switch((c = *s++)) {
-        case '0': case '1': case '2':
-        case '3': case '4': case '5':
-        case '6': case '7': case '8':
-        case '9':
-            c -= '0';
-            break;
-        case 'a': case 'b': case 'c':
-        case 'd': case 'e': case 'f':
-            c = c - 'a' + 10;
-            break;
-        case 'A': case 'B': case 'C':
-        case 'D': case 'E': case 'F':
-            c = c - 'A' + 10;
-            break;
-        default:
-            return 0xffffffff;
-        }
-
-        n = (n << 4) | c;
-    }
-
-    return n;
-}
-
-/* skip_host_serial return the position in a string
-   skipping over the 'serial' parameter in the ADB protocol,
-   where parameter string may be a host:port string containing
-   the protocol delimiter (colon). */
-char *skip_host_serial(char *service) {
-    char *first_colon, *serial_end;
-
-    first_colon = strchr(service, ':');
-    if (!first_colon) {
-        /* No colon in service string. */
-        return NULL;
-    }
-    serial_end = first_colon;
-    if (isdigit(serial_end[1])) {
-        serial_end++;
-        while ((*serial_end) && isdigit(*serial_end)) {
-            serial_end++;
-        }
-        if ((*serial_end) != ':') {
-            // Something other than numbers was found, reset the end.
-            serial_end = first_colon;
-        }
-    }
-    return serial_end;
-}
-
-static int smart_socket_enqueue(asocket *s, apacket *p)
-{
-    unsigned len;
-
-    D("SS(%d): enqueue %d\n", s->id, p->len);
-
-    if(s->pkt_first == 0) {
-        s->pkt_first = p;
-        s->pkt_last = p;
-    } else {
-        if((s->pkt_first->len + p->len) > MAX_PAYLOAD) {
-            D("SS(%d): overflow\n", s->id);
-            put_apacket(p);
-            goto fail;
-        }
-
-        memcpy(s->pkt_first->data + s->pkt_first->len,
-               p->data, p->len);
-        s->pkt_first->len += p->len;
-        put_apacket(p);
-
-        p = s->pkt_first;
-    }
-
-        /* don't bother if we can't decode the length */
-    if(p->len < 4) return 0;
-
-    len = unhex(p->data, 4);
-    if((len < 1) ||  (len > 1024)) {
-        D("SS(%d): bad size (%d)\n", s->id, len);
-        goto fail;
-    }
-
-    D("SS(%d): len is %d\n", s->id, len );
-        /* can't do anything until we have the full header */
-    if((len + 4) > p->len) {
-        D("SS(%d): waiting for %d more bytes\n", s->id, len+4 - p->len);
-        return 0;
-    }
-
-    p->data[len + 4] = 0;
-
-    D("SS(%d): '%s'\n", s->id, (char*) (p->data + 4));
-
-    if (s->transport == NULL) {
-        char* error_string = "unknown failure";
-        s->transport = acquire_one_transport (CS_ANY,
-                kTransportAny, NULL, &error_string);
-
-        if (s->transport == NULL) {
-            sendfailmsg(s->peer->fd, error_string);
-            goto fail;
-        }
-    }
-
-    if(!(s->transport) || (s->transport->connection_state == CS_OFFLINE)) {
-           /* if there's no remote we fail the connection
-            ** right here and terminate it
-            */
-        sendfailmsg(s->peer->fd, "device offline (x)");
-        goto fail;
-    }
-
-
-        /* instrument our peer to pass the success or fail
-        ** message back once it connects or closes, then
-        ** detach from it, request the connection, and
-        ** tear down
-        */
-    s->peer->ready = local_socket_ready_notify;
-    s->peer->close = local_socket_close_notify;
-    s->peer->peer = 0;
-        /* give him our transport and upref it */
-    s->peer->transport = s->transport;
-
-    connect_to_remote(s->peer, (char*) (p->data + 4));
-    s->peer = 0;
-    s->close(s);
-    return 1;
-
-fail:
-        /* we're going to close our peer as a side-effect, so
-        ** return -1 to signal that state to the local socket
-        ** who is enqueueing against us
-        */
-    s->close(s);
-    return -1;
-}
-
-static void smart_socket_ready(asocket *s)
-{
-    D("SS(%d): ready\n", s->id);
-}
-
-static void smart_socket_close(asocket *s)
-{
-    D("SS(%d): closed\n", s->id);
-    if(s->pkt_first){
-        put_apacket(s->pkt_first);
-    }
-    if(s->peer) {
-        s->peer->peer = 0;
-        s->peer->close(s->peer);
-        s->peer = 0;
-    }
-    free(s);
-}
-
-asocket *create_smart_socket(void (*action_cb)(asocket *s, const char *act))
-{
-    D("Creating smart socket \n");
-    asocket *s = calloc(1, sizeof(asocket));
-    if (s == NULL) fatal("cannot allocate socket");
-    s->enqueue = smart_socket_enqueue;
-    s->ready = smart_socket_ready;
-    s->close = smart_socket_close;
-    s->extra = action_cb;
-
-    D("SS(%d): created %p\n", s->id, action_cb);
-    return s;
-}
-
-void smart_socket_action(asocket *s, const char *act)
-{
-
-}
-
-void connect_to_smartsocket(asocket *s)
-{
-    D("Connecting to smart socket \n");
-    asocket *ss = create_smart_socket(smart_socket_action);
-    s->peer = ss;
-    ss->peer = s;
-    s->ready(s);
-}
diff --git a/minadbd21/sysdeps.h b/minadbd21/sysdeps.h
deleted file mode 100644
index 800ddb7..0000000
--- a/minadbd21/sysdeps.h
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* this file contains system-dependent definitions used by ADB
- * they're related to threads, sockets and file descriptors
- */
-#ifndef _ADB_SYSDEPS_H
-#define _ADB_SYSDEPS_H
-
-#ifdef __CYGWIN__
-#  undef _WIN32
-#endif
-
-#ifdef _WIN32
-
-#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <process.h>
-#include <fcntl.h>
-#include <io.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <ctype.h>
-
-#define OS_PATH_SEPARATOR '\\'
-#define OS_PATH_SEPARATOR_STR "\\"
-
-typedef CRITICAL_SECTION          adb_mutex_t;
-
-#define  ADB_MUTEX_DEFINE(x)     adb_mutex_t   x
-
-/* declare all mutexes */
-/* For win32, adb_sysdeps_init() will do the mutex runtime initialization. */
-#define  ADB_MUTEX(x)   extern adb_mutex_t  x;
-#include "mutex_list.h"
-
-extern void  adb_sysdeps_init(void);
-
-static __inline__ void adb_mutex_lock( adb_mutex_t*  lock )
-{
-    EnterCriticalSection( lock );
-}
-
-static __inline__ void  adb_mutex_unlock( adb_mutex_t*  lock )
-{
-    LeaveCriticalSection( lock );
-}
-
-typedef struct { unsigned  tid; }  adb_thread_t;
-
-typedef  void*  (*adb_thread_func_t)(void*  arg);
-
-typedef  void (*win_thread_func_t)(void*  arg);
-
-static __inline__ int  adb_thread_create( adb_thread_t  *thread, adb_thread_func_t  func, void*  arg)
-{
-    thread->tid = _beginthread( (win_thread_func_t)func, 0, arg );
-    if (thread->tid == (unsigned)-1L) {
-        return -1;
-    }
-    return 0;
-}
-
-static __inline__ void  close_on_exec(int  fd)
-{
-    /* nothing really */
-}
-
-extern void  disable_tcp_nagle(int  fd);
-
-#define  lstat    stat   /* no symlinks on Win32 */
-
-#define  S_ISLNK(m)   0   /* no symlinks on Win32 */
-
-static __inline__  int    adb_unlink(const char*  path)
-{
-    int  rc = unlink(path);
-
-    if (rc == -1 && errno == EACCES) {
-        /* unlink returns EACCES when the file is read-only, so we first */
-        /* try to make it writable, then unlink again...                  */
-        rc = chmod(path, _S_IREAD|_S_IWRITE );
-        if (rc == 0)
-            rc = unlink(path);
-    }
-    return rc;
-}
-#undef  unlink
-#define unlink  ___xxx_unlink
-
-static __inline__ int  adb_mkdir(const char*  path, int mode)
-{
-	return _mkdir(path);
-}
-#undef   mkdir
-#define  mkdir  ___xxx_mkdir
-
-extern int  adb_open(const char*  path, int  options);
-extern int  adb_creat(const char*  path, int  mode);
-extern int  adb_read(int  fd, void* buf, int len);
-extern int  adb_write(int  fd, const void*  buf, int  len);
-extern int  adb_lseek(int  fd, int  pos, int  where);
-extern int  adb_shutdown(int  fd);
-extern int  adb_close(int  fd);
-
-static __inline__ int  unix_close(int fd)
-{
-    return close(fd);
-}
-#undef   close
-#define  close   ____xxx_close
-
-static __inline__  int  unix_read(int  fd, void*  buf, size_t  len)
-{
-    return read(fd, buf, len);
-}
-#undef   read
-#define  read  ___xxx_read
-
-static __inline__  int  unix_write(int  fd, const void*  buf, size_t  len)
-{
-    return write(fd, buf, len);
-}
-#undef   write
-#define  write  ___xxx_write
-
-static __inline__ int  adb_open_mode(const char* path, int options, int mode)
-{
-    return adb_open(path, options);
-}
-
-static __inline__ int  unix_open(const char*  path, int options,...)
-{
-    if ((options & O_CREAT) == 0)
-    {
-        return  open(path, options);
-    }
-    else
-    {
-        int      mode;
-        va_list  args;
-        va_start( args, options );
-        mode = va_arg( args, int );
-        va_end( args );
-        return open(path, options, mode);
-    }
-}
-#define  open    ___xxx_unix_open
-
-
-/* normally provided by <cutils/misc.h> */
-extern void*  load_file(const char*  pathname, unsigned*  psize);
-
-/* normally provided by <cutils/sockets.h> */
-extern int socket_loopback_client(int port, int type);
-extern int socket_network_client(const char *host, int port, int type);
-extern int socket_loopback_server(int port, int type);
-extern int socket_inaddr_any_server(int port, int type);
-
-/* normally provided by "fdevent.h" */
-
-#define FDE_READ              0x0001
-#define FDE_WRITE             0x0002
-#define FDE_ERROR             0x0004
-#define FDE_DONT_CLOSE        0x0080
-
-typedef struct fdevent fdevent;
-
-typedef void (*fd_func)(int fd, unsigned events, void *userdata);
-
-fdevent *fdevent_create(int fd, fd_func func, void *arg);
-void     fdevent_destroy(fdevent *fde);
-void     fdevent_install(fdevent *fde, int fd, fd_func func, void *arg);
-void     fdevent_remove(fdevent *item);
-void     fdevent_set(fdevent *fde, unsigned events);
-void     fdevent_add(fdevent *fde, unsigned events);
-void     fdevent_del(fdevent *fde, unsigned events);
-void     fdevent_loop();
-
-struct fdevent {
-    fdevent *next;
-    fdevent *prev;
-
-    int fd;
-    int force_eof;
-
-    unsigned short state;
-    unsigned short events;
-
-    fd_func func;
-    void *arg;
-};
-
-static __inline__ void  adb_sleep_ms( int  mseconds )
-{
-    Sleep( mseconds );
-}
-
-extern int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen);
-
-#undef   accept
-#define  accept  ___xxx_accept
-
-static __inline__  int  adb_socket_setbufsize( int   fd, int  bufsize )
-{
-    int opt = bufsize;
-    return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (const char*)&opt, sizeof(opt));
-}
-
-extern int  adb_socketpair( int  sv[2] );
-
-static __inline__  char*  adb_dirstart( const char*  path )
-{
-    char*  p  = strchr(path, '/');
-    char*  p2 = strchr(path, '\\');
-
-    if ( !p )
-        p = p2;
-    else if ( p2 && p2 > p )
-        p = p2;
-
-    return p;
-}
-
-static __inline__  char*  adb_dirstop( const char*  path )
-{
-    char*  p  = strrchr(path, '/');
-    char*  p2 = strrchr(path, '\\');
-
-    if ( !p )
-        p = p2;
-    else if ( p2 && p2 > p )
-        p = p2;
-
-    return p;
-}
-
-static __inline__  int  adb_is_absolute_host_path( const char*  path )
-{
-    return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
-}
-
-#else /* !_WIN32 a.k.a. Unix */
-
-#include "fdevent.h"
-#include <cutils/sockets.h>
-#include <cutils/properties.h>
-#include <cutils/misc.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include <pthread.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <string.h>
-
-#define OS_PATH_SEPARATOR '/'
-#define OS_PATH_SEPARATOR_STR "/"
-
-typedef  pthread_mutex_t          adb_mutex_t;
-
-#define  ADB_MUTEX_INITIALIZER    PTHREAD_MUTEX_INITIALIZER
-#define  adb_mutex_init           pthread_mutex_init
-#define  adb_mutex_lock           pthread_mutex_lock
-#define  adb_mutex_unlock         pthread_mutex_unlock
-#define  adb_mutex_destroy        pthread_mutex_destroy
-
-#define  ADB_MUTEX_DEFINE(m)      adb_mutex_t   m = PTHREAD_MUTEX_INITIALIZER
-
-#define  adb_cond_t               pthread_cond_t
-#define  adb_cond_init            pthread_cond_init
-#define  adb_cond_wait            pthread_cond_wait
-#define  adb_cond_broadcast       pthread_cond_broadcast
-#define  adb_cond_signal          pthread_cond_signal
-#define  adb_cond_destroy         pthread_cond_destroy
-
-/* declare all mutexes */
-#define  ADB_MUTEX(x)   extern adb_mutex_t  x;
-#include "mutex_list.h"
-
-static __inline__ void  close_on_exec(int  fd)
-{
-    fcntl( fd, F_SETFD, FD_CLOEXEC );
-}
-
-static __inline__ int  unix_open(const char*  path, int options,...)
-{
-    if ((options & O_CREAT) == 0)
-    {
-        return  open(path, options);
-    }
-    else
-    {
-        int      mode;
-        va_list  args;
-        va_start( args, options );
-        mode = va_arg( args, int );
-        va_end( args );
-        return open(path, options, mode);
-    }
-}
-
-static __inline__ int  adb_open_mode( const char*  pathname, int  options, int  mode )
-{
-    return open( pathname, options, mode );
-}
-
-static __inline__  int  adb_creat(const char*  path, int  mode)
-{
-    int  fd = open(path, O_CREAT|O_WRONLY|O_TRUNC|O_NOFOLLOW, mode);
-
-    if ( fd < 0 )
-        return -1;
-
-    close_on_exec(fd);
-    return fd;
-}
-#undef   creat
-#define  creat  ___xxx_creat
-
-static __inline__ int  adb_open( const char*  pathname, int  options )
-{
-    int  fd = open( pathname, options );
-    if (fd < 0)
-        return -1;
-    close_on_exec( fd );
-    return fd;
-}
-#undef   open
-#define  open    ___xxx_open
-
-static __inline__ int  adb_shutdown(int fd)
-{
-    return shutdown(fd, SHUT_RDWR);
-}
-#undef   shutdown
-#define  shutdown   ____xxx_shutdown
-
-static __inline__ int  adb_close(int fd)
-{
-    return close(fd);
-}
-#undef   close
-#define  close   ____xxx_close
-
-
-static __inline__  int  adb_read(int  fd, void*  buf, size_t  len)
-{
-    return read(fd, buf, len);
-}
-
-#undef   read
-#define  read  ___xxx_read
-
-static __inline__  int  adb_write(int  fd, const void*  buf, size_t  len)
-{
-    return write(fd, buf, len);
-}
-#undef   write
-#define  write  ___xxx_write
-
-static __inline__ int   adb_lseek(int  fd, int  pos, int  where)
-{
-    return lseek(fd, pos, where);
-}
-#undef   lseek
-#define  lseek   ___xxx_lseek
-
-static __inline__  int    adb_unlink(const char*  path)
-{
-    return  unlink(path);
-}
-#undef  unlink
-#define unlink  ___xxx_unlink
-
-static __inline__ int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
-{
-    int fd;
-
-    fd = accept(serverfd, addr, addrlen);
-    if (fd >= 0)
-        close_on_exec(fd);
-
-    return fd;
-}
-
-#undef   accept
-#define  accept  ___xxx_accept
-
-#define  unix_read   adb_read
-#define  unix_write  adb_write
-#define  unix_close  adb_close
-
-typedef  pthread_t                 adb_thread_t;
-
-typedef void*  (*adb_thread_func_t)( void*  arg );
-
-static __inline__ int  adb_thread_create( adb_thread_t  *pthread, adb_thread_func_t  start, void*  arg )
-{
-    pthread_attr_t   attr;
-
-    pthread_attr_init (&attr);
-    pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
-
-    return pthread_create( pthread, &attr, start, arg );
-}
-
-static __inline__  int  adb_socket_setbufsize( int   fd, int  bufsize )
-{
-    int opt = bufsize;
-    return setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt));
-}
-
-static __inline__ void  disable_tcp_nagle(int fd)
-{
-    int  on = 1;
-    setsockopt( fd, IPPROTO_TCP, TCP_NODELAY, (void*)&on, sizeof(on) );
-}
-
-
-static __inline__ int  unix_socketpair( int  d, int  type, int  protocol, int sv[2] )
-{
-    return socketpair( d, type, protocol, sv );
-}
-
-static __inline__ int  adb_socketpair( int  sv[2] )
-{
-    int  rc;
-
-    rc = unix_socketpair( AF_UNIX, SOCK_STREAM, 0, sv );
-    if (rc < 0)
-        return -1;
-
-    close_on_exec( sv[0] );
-    close_on_exec( sv[1] );
-    return 0;
-}
-
-#undef   socketpair
-#define  socketpair   ___xxx_socketpair
-
-static __inline__ void  adb_sleep_ms( int  mseconds )
-{
-    usleep( mseconds*1000 );
-}
-
-static __inline__ int  adb_mkdir(const char*  path, int mode)
-{
-    return mkdir(path, mode);
-}
-#undef   mkdir
-#define  mkdir  ___xxx_mkdir
-
-static __inline__ void  adb_sysdeps_init(void)
-{
-}
-
-static __inline__ char*  adb_dirstart(const char*  path)
-{
-    return strchr(path, '/');
-}
-
-static __inline__ char*  adb_dirstop(const char*  path)
-{
-    return strrchr(path, '/');
-}
-
-static __inline__  int  adb_is_absolute_host_path( const char*  path )
-{
-    return path[0] == '/';
-}
-
-#endif /* !_WIN32 */
-
-#endif /* _ADB_SYSDEPS_H */
diff --git a/minadbd21/transport.c b/minadbd21/transport.c
deleted file mode 100644
index 92679f5..0000000
--- a/minadbd21/transport.c
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-
-#include "sysdeps.h"
-
-#define   TRACE_TAG  TRACE_TRANSPORT
-#include "adb.h"
-
-static void transport_unref(atransport *t);
-
-static atransport transport_list = {
-    .next = &transport_list,
-    .prev = &transport_list,
-};
-
-ADB_MUTEX_DEFINE( transport_lock );
-
-#if ADB_TRACE
-#define MAX_DUMP_HEX_LEN 16
-static void  dump_hex( const unsigned char*  ptr, size_t  len )
-{
-    int  nn, len2 = len;
-    // Build a string instead of logging each character.
-    // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
-    char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
-
-    if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
-
-    for (nn = 0; nn < len2; nn++) {
-        sprintf(pb, "%02x", ptr[nn]);
-        pb += 2;
-    }
-    sprintf(pb++, " ");
-
-    for (nn = 0; nn < len2; nn++) {
-        int  c = ptr[nn];
-        if (c < 32 || c > 127)
-            c = '.';
-        *pb++ =  c;
-    }
-    *pb++ = '\0';
-    DR("%s\n", buffer);
-}
-#endif
-
-void
-kick_transport(atransport*  t)
-{
-    if (t && !t->kicked)
-    {
-        int  kicked;
-
-        adb_mutex_lock(&transport_lock);
-        kicked = t->kicked;
-        if (!kicked)
-            t->kicked = 1;
-        adb_mutex_unlock(&transport_lock);
-
-        if (!kicked)
-            t->kick(t);
-    }
-}
-
-void
-run_transport_disconnects(atransport*  t)
-{
-    adisconnect*  dis = t->disconnects.next;
-
-    D("%s: run_transport_disconnects\n", t->serial);
-    while (dis != &t->disconnects) {
-        adisconnect*  next = dis->next;
-        dis->func( dis->opaque, t );
-        dis = next;
-    }
-}
-
-#if ADB_TRACE
-static void
-dump_packet(const char* name, const char* func, apacket* p)
-{
-    unsigned  command = p->msg.command;
-    int       len     = p->msg.data_length;
-    char      cmd[9];
-    char      arg0[12], arg1[12];
-    int       n;
-
-    for (n = 0; n < 4; n++) {
-        int  b = (command >> (n*8)) & 255;
-        if (b < 32 || b >= 127)
-            break;
-        cmd[n] = (char)b;
-    }
-    if (n == 4) {
-        cmd[4] = 0;
-    } else {
-        /* There is some non-ASCII name in the command, so dump
-            * the hexadecimal value instead */
-        snprintf(cmd, sizeof cmd, "%08x", command);
-    }
-
-    if (p->msg.arg0 < 256U)
-        snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
-    else
-        snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
-
-    if (p->msg.arg1 < 256U)
-        snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
-    else
-        snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
-
-    D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
-        name, func, cmd, arg0, arg1, len);
-    dump_hex(p->data, len);
-}
-#endif /* ADB_TRACE */
-
-static int
-read_packet(int  fd, const char* name, apacket** ppacket)
-{
-    char *p = (char*)ppacket;  /* really read a packet address */
-    int   r;
-    int   len = sizeof(*ppacket);
-    char  buff[8];
-    if (!name) {
-        snprintf(buff, sizeof buff, "fd=%d", fd);
-        name = buff;
-    }
-    while(len > 0) {
-        r = adb_read(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p   += r;
-        } else {
-            D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
-            if((r < 0) && (errno == EINTR)) continue;
-            return -1;
-        }
-    }
-
-#if ADB_TRACE
-    if (ADB_TRACING) {
-        dump_packet(name, "from remote", *ppacket);
-    }
-#endif
-    return 0;
-}
-
-static int
-write_packet(int  fd, const char* name, apacket** ppacket)
-{
-    char *p = (char*) ppacket;  /* we really write the packet address */
-    int r, len = sizeof(ppacket);
-    char buff[8];
-    if (!name) {
-        snprintf(buff, sizeof buff, "fd=%d", fd);
-        name = buff;
-    }
-
-#if ADB_TRACE
-    if (ADB_TRACING) {
-        dump_packet(name, "to remote", *ppacket);
-    }
-#endif
-    len = sizeof(ppacket);
-    while(len > 0) {
-        r = adb_write(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p += r;
-        } else {
-            D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
-            if((r < 0) && (errno == EINTR)) continue;
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static void transport_socket_events(int fd, unsigned events, void *_t)
-{
-    atransport *t = _t;
-    D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
-    if(events & FDE_READ){
-        apacket *p = 0;
-        if(read_packet(fd, t->serial, &p)){
-            D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
-        } else {
-            handle_packet(p, (atransport *) _t);
-        }
-    }
-}
-
-void send_packet(apacket *p, atransport *t)
-{
-    unsigned char *x;
-    unsigned sum;
-    unsigned count;
-
-    p->msg.magic = p->msg.command ^ 0xffffffff;
-
-    count = p->msg.data_length;
-    x = (unsigned char *) p->data;
-    sum = 0;
-    while(count-- > 0){
-        sum += *x++;
-    }
-    p->msg.data_check = sum;
-
-    print_packet("send", p);
-
-    if (t == NULL) {
-        D("Transport is null \n");
-        // Zap errno because print_packet() and other stuff have errno effect.
-        errno = 0;
-        fatal_errno("Transport is null");
-    }
-
-    if(write_packet(t->transport_socket, t->serial, &p)){
-        fatal_errno("cannot enqueue packet on transport socket");
-    }
-}
-
-/* The transport is opened by transport_register_func before
-** the input and output threads are started.
-**
-** The output thread issues a SYNC(1, token) message to let
-** the input thread know to start things up.  In the event
-** of transport IO failure, the output thread will post a
-** SYNC(0,0) message to ensure shutdown.
-**
-** The transport will not actually be closed until both
-** threads exit, but the input thread will kick the transport
-** on its way out to disconnect the underlying device.
-*/
-
-static void *output_thread(void *_t)
-{
-    atransport *t = _t;
-    apacket *p;
-
-    D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
-       t->serial, t->fd, t->sync_token + 1);
-    p = get_apacket();
-    p->msg.command = A_SYNC;
-    p->msg.arg0 = 1;
-    p->msg.arg1 = ++(t->sync_token);
-    p->msg.magic = A_SYNC ^ 0xffffffff;
-    if(write_packet(t->fd, t->serial, &p)) {
-        put_apacket(p);
-        D("%s: failed to write SYNC packet\n", t->serial);
-        goto oops;
-    }
-
-    D("%s: data pump started\n", t->serial);
-    for(;;) {
-        p = get_apacket();
-
-        if(t->read_from_remote(p, t) == 0){
-            D("%s: received remote packet, sending to transport\n",
-              t->serial);
-            if(write_packet(t->fd, t->serial, &p)){
-                put_apacket(p);
-                D("%s: failed to write apacket to transport\n", t->serial);
-                goto oops;
-            }
-        } else {
-            D("%s: remote read failed for transport\n", t->serial);
-            put_apacket(p);
-            break;
-        }
-    }
-
-    D("%s: SYNC offline for transport\n", t->serial);
-    p = get_apacket();
-    p->msg.command = A_SYNC;
-    p->msg.arg0 = 0;
-    p->msg.arg1 = 0;
-    p->msg.magic = A_SYNC ^ 0xffffffff;
-    if(write_packet(t->fd, t->serial, &p)) {
-        put_apacket(p);
-        D("%s: failed to write SYNC apacket to transport", t->serial);
-    }
-
-oops:
-    D("%s: transport output thread is exiting\n", t->serial);
-    kick_transport(t);
-    transport_unref(t);
-    return 0;
-}
-
-static void *input_thread(void *_t)
-{
-    atransport *t = _t;
-    apacket *p;
-    int active = 0;
-
-    D("%s: starting transport input thread, reading from fd %d\n",
-       t->serial, t->fd);
-
-    for(;;){
-        if(read_packet(t->fd, t->serial, &p)) {
-            D("%s: failed to read apacket from transport on fd %d\n",
-               t->serial, t->fd );
-            break;
-        }
-        if(p->msg.command == A_SYNC){
-            if(p->msg.arg0 == 0) {
-                D("%s: transport SYNC offline\n", t->serial);
-                put_apacket(p);
-                break;
-            } else {
-                if(p->msg.arg1 == t->sync_token) {
-                    D("%s: transport SYNC online\n", t->serial);
-                    active = 1;
-                } else {
-                    D("%s: transport ignoring SYNC %d != %d\n",
-                      t->serial, p->msg.arg1, t->sync_token);
-                }
-            }
-        } else {
-            if(active) {
-                D("%s: transport got packet, sending to remote\n", t->serial);
-                t->write_to_remote(p, t);
-            } else {
-                D("%s: transport ignoring packet while offline\n", t->serial);
-            }
-        }
-
-        put_apacket(p);
-    }
-
-    // this is necessary to avoid a race condition that occured when a transport closes
-    // while a client socket is still active.
-    close_all_sockets(t);
-
-    D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
-    kick_transport(t);
-    transport_unref(t);
-    return 0;
-}
-
-
-static int transport_registration_send = -1;
-static int transport_registration_recv = -1;
-static fdevent transport_registration_fde;
-
-void  update_transports(void)
-{
-    // nothing to do on the device side
-}
-
-typedef struct tmsg tmsg;
-struct tmsg
-{
-    atransport *transport;
-    int         action;
-};
-
-static int
-transport_read_action(int  fd, struct tmsg*  m)
-{
-    char *p   = (char*)m;
-    int   len = sizeof(*m);
-    int   r;
-
-    while(len > 0) {
-        r = adb_read(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p   += r;
-        } else {
-            if((r < 0) && (errno == EINTR)) continue;
-            D("transport_read_action: on fd %d, error %d: %s\n",
-              fd, errno, strerror(errno));
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static int
-transport_write_action(int  fd, struct tmsg*  m)
-{
-    char *p   = (char*)m;
-    int   len = sizeof(*m);
-    int   r;
-
-    while(len > 0) {
-        r = adb_write(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p   += r;
-        } else {
-            if((r < 0) && (errno == EINTR)) continue;
-            D("transport_write_action: on fd %d, error %d: %s\n",
-              fd, errno, strerror(errno));
-            return -1;
-        }
-    }
-    return 0;
-}
-
-static void transport_registration_func(int _fd, unsigned ev, void *data)
-{
-    tmsg m;
-    adb_thread_t output_thread_ptr;
-    adb_thread_t input_thread_ptr;
-    int s[2];
-    atransport *t;
-
-    if(!(ev & FDE_READ)) {
-        return;
-    }
-
-    if(transport_read_action(_fd, &m)) {
-        fatal_errno("cannot read transport registration socket");
-    }
-
-    t = m.transport;
-
-    if(m.action == 0){
-        D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
-
-            /* IMPORTANT: the remove closes one half of the
-            ** socket pair.  The close closes the other half.
-            */
-        fdevent_remove(&(t->transport_fde));
-        adb_close(t->fd);
-
-        adb_mutex_lock(&transport_lock);
-        t->next->prev = t->prev;
-        t->prev->next = t->next;
-        adb_mutex_unlock(&transport_lock);
-
-        run_transport_disconnects(t);
-
-        if (t->product)
-            free(t->product);
-        if (t->serial)
-            free(t->serial);
-
-        memset(t,0xee,sizeof(atransport));
-        free(t);
-
-        update_transports();
-        return;
-    }
-
-    /* don't create transport threads for inaccessible devices */
-    if (t->connection_state != CS_NOPERM) {
-        /* initial references are the two threads */
-        t->ref_count = 2;
-
-        if(adb_socketpair(s)) {
-            fatal_errno("cannot open transport socketpair");
-        }
-
-        D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
-
-        t->transport_socket = s[0];
-        t->fd = s[1];
-
-        fdevent_install(&(t->transport_fde),
-                        t->transport_socket,
-                        transport_socket_events,
-                        t);
-
-        fdevent_set(&(t->transport_fde), FDE_READ);
-
-        if(adb_thread_create(&input_thread_ptr, input_thread, t)){
-            fatal_errno("cannot create input thread");
-        }
-
-        if(adb_thread_create(&output_thread_ptr, output_thread, t)){
-            fatal_errno("cannot create output thread");
-        }
-    }
-
-        /* put us on the master device list */
-    adb_mutex_lock(&transport_lock);
-    t->next = &transport_list;
-    t->prev = transport_list.prev;
-    t->next->prev = t;
-    t->prev->next = t;
-    adb_mutex_unlock(&transport_lock);
-
-    t->disconnects.next = t->disconnects.prev = &t->disconnects;
-
-    update_transports();
-}
-
-void init_transport_registration(void)
-{
-    int s[2];
-
-    if(adb_socketpair(s)){
-        fatal_errno("cannot open transport registration socketpair");
-    }
-
-    transport_registration_send = s[0];
-    transport_registration_recv = s[1];
-
-    fdevent_install(&transport_registration_fde,
-                    transport_registration_recv,
-                    transport_registration_func,
-                    0);
-
-    fdevent_set(&transport_registration_fde, FDE_READ);
-}
-
-/* the fdevent select pump is single threaded */
-static void register_transport(atransport *transport)
-{
-    tmsg m;
-    m.transport = transport;
-    m.action = 1;
-    D("transport: %s registered\n", transport->serial);
-    if(transport_write_action(transport_registration_send, &m)) {
-        fatal_errno("cannot write transport registration socket\n");
-    }
-}
-
-static void remove_transport(atransport *transport)
-{
-    tmsg m;
-    m.transport = transport;
-    m.action = 0;
-    D("transport: %s removed\n", transport->serial);
-    if(transport_write_action(transport_registration_send, &m)) {
-        fatal_errno("cannot write transport registration socket\n");
-    }
-}
-
-
-static void transport_unref_locked(atransport *t)
-{
-    t->ref_count--;
-    if (t->ref_count == 0) {
-        D("transport: %s unref (kicking and closing)\n", t->serial);
-        if (!t->kicked) {
-            t->kicked = 1;
-            t->kick(t);
-        }
-        t->close(t);
-        remove_transport(t);
-    } else {
-        D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
-    }
-}
-
-static void transport_unref(atransport *t)
-{
-    if (t) {
-        adb_mutex_lock(&transport_lock);
-        transport_unref_locked(t);
-        adb_mutex_unlock(&transport_lock);
-    }
-}
-
-void add_transport_disconnect(atransport*  t, adisconnect*  dis)
-{
-    adb_mutex_lock(&transport_lock);
-    dis->next       = &t->disconnects;
-    dis->prev       = dis->next->prev;
-    dis->prev->next = dis;
-    dis->next->prev = dis;
-    adb_mutex_unlock(&transport_lock);
-}
-
-void remove_transport_disconnect(atransport*  t, adisconnect*  dis)
-{
-    dis->prev->next = dis->next;
-    dis->next->prev = dis->prev;
-    dis->next = dis->prev = dis;
-}
-
-
-atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
-{
-    atransport *t;
-    atransport *result = NULL;
-    int ambiguous = 0;
-
-retry:
-    if (error_out)
-        *error_out = "device not found";
-
-    adb_mutex_lock(&transport_lock);
-    for (t = transport_list.next; t != &transport_list; t = t->next) {
-        if (t->connection_state == CS_NOPERM) {
-        if (error_out)
-            *error_out = "insufficient permissions for device";
-            continue;
-        }
-
-        /* check for matching serial number */
-        if (serial) {
-            if (t->serial && !strcmp(serial, t->serial)) {
-                result = t;
-                break;
-            }
-        } else {
-            if (ttype == kTransportUsb && t->type == kTransportUsb) {
-                if (result) {
-                    if (error_out)
-                        *error_out = "more than one device";
-                    ambiguous = 1;
-                    result = NULL;
-                    break;
-                }
-                result = t;
-            } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
-                if (result) {
-                    if (error_out)
-                        *error_out = "more than one emulator";
-                    ambiguous = 1;
-                    result = NULL;
-                    break;
-                }
-                result = t;
-            } else if (ttype == kTransportAny) {
-                if (result) {
-                    if (error_out)
-                        *error_out = "more than one device and emulator";
-                    ambiguous = 1;
-                    result = NULL;
-                    break;
-                }
-                result = t;
-            }
-        }
-    }
-    adb_mutex_unlock(&transport_lock);
-
-    if (result) {
-         /* offline devices are ignored -- they are either being born or dying */
-        if (result && result->connection_state == CS_OFFLINE) {
-            if (error_out)
-                *error_out = "device offline";
-            result = NULL;
-        }
-         /* check for required connection state */
-        if (result && state != CS_ANY && result->connection_state != state) {
-            if (error_out)
-                *error_out = "invalid device state";
-            result = NULL;
-        }
-    }
-
-    if (result) {
-        /* found one that we can take */
-        if (error_out)
-            *error_out = NULL;
-    } else if (state != CS_ANY && (serial || !ambiguous)) {
-        adb_sleep_ms(1000);
-        goto retry;
-    }
-
-    return result;
-}
-
-void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
-{
-    atransport *t = calloc(1, sizeof(atransport));
-    D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
-      serial ? serial : "");
-    init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
-    if(serial) {
-        t->serial = strdup(serial);
-    }
-    register_transport(t);
-}
-
-/* this should only be used for transports with connection_state == CS_NOPERM */
-void unregister_usb_transport(usb_handle *usb)
-{
-    atransport *t;
-    adb_mutex_lock(&transport_lock);
-    for(t = transport_list.next; t != &transport_list; t = t->next) {
-        if (t->usb == usb && t->connection_state == CS_NOPERM) {
-            t->next->prev = t->prev;
-            t->prev->next = t->next;
-            break;
-        }
-     }
-    adb_mutex_unlock(&transport_lock);
-}
-
-#undef TRACE_TAG
-#define TRACE_TAG  TRACE_RWX
-
-int readx(int fd, void *ptr, size_t len)
-{
-    char *p = ptr;
-    int r;
-#if ADB_TRACE
-    size_t len0 = len;
-#endif
-    D("readx: fd=%d wanted=%d\n", fd, (int)len);
-    while(len > 0) {
-        r = adb_read(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p += r;
-        } else {
-            if (r < 0) {
-                D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
-                if (errno == EINTR)
-                    continue;
-            } else {
-                D("readx: fd=%d disconnected\n", fd);
-            }
-            return -1;
-        }
-    }
-
-#if ADB_TRACE
-    D("readx: fd=%d wanted=%zu got=%zu\n", fd, len0, len0 - len);
-    dump_hex( ptr, len0 );
-#endif
-    return 0;
-}
-
-int writex(int fd, const void *ptr, size_t len)
-{
-    char *p = (char*) ptr;
-    int r;
-
-#if ADB_TRACE
-    D("writex: fd=%d len=%d: ", fd, (int)len);
-    dump_hex( ptr, len );
-#endif
-    while(len > 0) {
-        r = adb_write(fd, p, len);
-        if(r > 0) {
-            len -= r;
-            p += r;
-        } else {
-            if (r < 0) {
-                D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
-                if (errno == EINTR)
-                    continue;
-            } else {
-                D("writex: fd=%d disconnected\n", fd);
-            }
-            return -1;
-        }
-    }
-    return 0;
-}
-
-int check_header(apacket *p)
-{
-    if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
-        D("check_header(): invalid magic\n");
-        return -1;
-    }
-
-    if(p->msg.data_length > MAX_PAYLOAD) {
-        D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
-        return -1;
-    }
-
-    return 0;
-}
-
-int check_data(apacket *p)
-{
-    unsigned count, sum;
-    unsigned char *x;
-
-    count = p->msg.data_length;
-    x = p->data;
-    sum = 0;
-    while(count-- > 0) {
-        sum += *x++;
-    }
-
-    if(sum != p->msg.data_check) {
-        return -1;
-    } else {
-        return 0;
-    }
-}
diff --git a/minadbd21/transport.h b/minadbd21/transport.h
deleted file mode 100644
index 992e052..0000000
--- a/minadbd21/transport.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __TRANSPORT_H
-#define __TRANSPORT_H
-
-/* convenience wrappers around read/write that will retry on
-** EINTR and/or short read/write.  Returns 0 on success, -1
-** on error or EOF.
-*/
-int readx(int fd, void *ptr, size_t len);
-int writex(int fd, const void *ptr, size_t len);
-#endif   /* __TRANSPORT_H */
diff --git a/minadbd21/transport_usb.c b/minadbd21/transport_usb.c
deleted file mode 100644
index 91cbf61..0000000
--- a/minadbd21/transport_usb.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <sysdeps.h>
-
-#define  TRACE_TAG  TRACE_TRANSPORT
-#include "adb.h"
-
-#ifdef HAVE_BIG_ENDIAN
-#define H4(x)	(((x) & 0xFF000000) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | (((x) & 0x000000FF) << 24)
-static inline void fix_endians(apacket *p)
-{
-    p->msg.command     = H4(p->msg.command);
-    p->msg.arg0        = H4(p->msg.arg0);
-    p->msg.arg1        = H4(p->msg.arg1);
-    p->msg.data_length = H4(p->msg.data_length);
-    p->msg.data_check  = H4(p->msg.data_check);
-    p->msg.magic       = H4(p->msg.magic);
-}
-unsigned host_to_le32(unsigned n)
-{
-    return H4(n);
-}
-#else
-#define fix_endians(p) do {} while (0)
-unsigned host_to_le32(unsigned n)
-{
-    return n;
-}
-#endif
-
-static int remote_read(apacket *p, atransport *t)
-{
-    if(usb_read(t->usb, &p->msg, sizeof(amessage))){
-        D("remote usb: read terminated (message)\n");
-        return -1;
-    }
-
-    fix_endians(p);
-
-    if(check_header(p)) {
-        D("remote usb: check_header failed\n");
-        return -1;
-    }
-
-    if(p->msg.data_length) {
-        if(usb_read(t->usb, p->data, p->msg.data_length)){
-            D("remote usb: terminated (data)\n");
-            return -1;
-        }
-    }
-
-    if(check_data(p)) {
-        D("remote usb: check_data failed\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-static int remote_write(apacket *p, atransport *t)
-{
-    unsigned size = p->msg.data_length;
-
-    fix_endians(p);
-
-    if(usb_write(t->usb, &p->msg, sizeof(amessage))) {
-        D("remote usb: 1 - write terminated\n");
-        return -1;
-    }
-    if(p->msg.data_length == 0) return 0;
-    if(usb_write(t->usb, &p->data, size)) {
-        D("remote usb: 2 - write terminated\n");
-        return -1;
-    }
-
-    return 0;
-}
-
-static void remote_close(atransport *t)
-{
-    usb_close(t->usb);
-    t->usb = 0;
-}
-
-static void remote_kick(atransport *t)
-{
-    usb_kick(t->usb);
-}
-
-void init_usb_transport(atransport *t, usb_handle *h, int state)
-{
-    D("transport: usb\n");
-    t->close = remote_close;
-    t->kick = remote_kick;
-    t->read_from_remote = remote_read;
-    t->write_to_remote = remote_write;
-    t->sync_token = 1;
-    t->connection_state = state;
-    t->type = kTransportUsb;
-    t->usb = h;
-
-    HOST = 0;
-}
diff --git a/minadbd21/usb_linux_client.c b/minadbd21/usb_linux_client.c
deleted file mode 100644
index ec32bcf..0000000
--- a/minadbd21/usb_linux_client.c
+++ /dev/null
@@ -1,493 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <linux/usb/ch9.h>
-#include <linux/usb/functionfs.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <errno.h>
-
-#include "sysdeps.h"
-
-#define   TRACE_TAG  TRACE_USB
-#include "adb.h"
-
-#define MAX_PACKET_SIZE_FS	64
-#define MAX_PACKET_SIZE_HS	512
-
-#define cpu_to_le16(x)  htole16(x)
-#define cpu_to_le32(x)  htole32(x)
-
-struct usb_handle
-{
-    int fd;
-    adb_cond_t notify;
-    adb_mutex_t lock;
-
-    int (*write)(usb_handle *h, const void *data, int len);
-    int (*read)(usb_handle *h, void *data, int len);
-    void (*kick)(usb_handle *h);
-
-    int control;
-    int bulk_out; /* "out" from the host's perspective => source for adbd */
-    int bulk_in;  /* "in" from the host's perspective => sink for adbd */
-};
-
-static const struct {
-    struct usb_functionfs_descs_head header;
-    struct {
-        struct usb_interface_descriptor intf;
-        struct usb_endpoint_descriptor_no_audio source;
-        struct usb_endpoint_descriptor_no_audio sink;
-    } __attribute__((packed)) fs_descs, hs_descs;
-} __attribute__((packed)) descriptors = {
-    .header = {
-        .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
-        .length = cpu_to_le32(sizeof(descriptors)),
-        .fs_count = 3,
-        .hs_count = 3,
-    },
-    .fs_descs = {
-        .intf = {
-            .bLength = sizeof(descriptors.fs_descs.intf),
-            .bDescriptorType = USB_DT_INTERFACE,
-            .bInterfaceNumber = 0,
-            .bNumEndpoints = 2,
-            .bInterfaceClass = ADB_CLASS,
-            .bInterfaceSubClass = ADB_SUBCLASS,
-            .bInterfaceProtocol = ADB_PROTOCOL,
-            .iInterface = 1, /* first string from the provided table */
-        },
-        .source = {
-            .bLength = sizeof(descriptors.fs_descs.source),
-            .bDescriptorType = USB_DT_ENDPOINT,
-            .bEndpointAddress = 1 | USB_DIR_OUT,
-            .bmAttributes = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
-        },
-        .sink = {
-            .bLength = sizeof(descriptors.fs_descs.sink),
-            .bDescriptorType = USB_DT_ENDPOINT,
-            .bEndpointAddress = 2 | USB_DIR_IN,
-            .bmAttributes = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize = MAX_PACKET_SIZE_FS,
-        },
-    },
-    .hs_descs = {
-        .intf = {
-            .bLength = sizeof(descriptors.hs_descs.intf),
-            .bDescriptorType = USB_DT_INTERFACE,
-            .bInterfaceNumber = 0,
-            .bNumEndpoints = 2,
-            .bInterfaceClass = ADB_CLASS,
-            .bInterfaceSubClass = ADB_SUBCLASS,
-            .bInterfaceProtocol = ADB_PROTOCOL,
-            .iInterface = 1, /* first string from the provided table */
-        },
-        .source = {
-            .bLength = sizeof(descriptors.hs_descs.source),
-            .bDescriptorType = USB_DT_ENDPOINT,
-            .bEndpointAddress = 1 | USB_DIR_OUT,
-            .bmAttributes = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
-        },
-        .sink = {
-            .bLength = sizeof(descriptors.hs_descs.sink),
-            .bDescriptorType = USB_DT_ENDPOINT,
-            .bEndpointAddress = 2 | USB_DIR_IN,
-            .bmAttributes = USB_ENDPOINT_XFER_BULK,
-            .wMaxPacketSize = MAX_PACKET_SIZE_HS,
-        },
-    },
-};
-
-#define STR_INTERFACE_ "ADB Interface"
-
-static const struct {
-    struct usb_functionfs_strings_head header;
-    struct {
-        __le16 code;
-        const char str1[sizeof(STR_INTERFACE_)];
-    } __attribute__((packed)) lang0;
-} __attribute__((packed)) strings = {
-    .header = {
-        .magic = cpu_to_le32(FUNCTIONFS_STRINGS_MAGIC),
-        .length = cpu_to_le32(sizeof(strings)),
-        .str_count = cpu_to_le32(1),
-        .lang_count = cpu_to_le32(1),
-    },
-    .lang0 = {
-        cpu_to_le16(0x0409), /* en-us */
-        STR_INTERFACE_,
-    },
-};
-
-void usb_cleanup()
-{
-    // nothing to do here
-}
-
-static void *usb_adb_open_thread(void *x)
-{
-    struct usb_handle *usb = (struct usb_handle *)x;
-    int fd;
-
-    while (1) {
-        // wait until the USB device needs opening
-        adb_mutex_lock(&usb->lock);
-        while (usb->fd != -1)
-            adb_cond_wait(&usb->notify, &usb->lock);
-        adb_mutex_unlock(&usb->lock);
-
-        D("[ usb_thread - opening device ]\n");
-        do {
-            /* XXX use inotify? */
-            fd = unix_open("/dev/android_adb", O_RDWR);
-            if (fd < 0) {
-                // to support older kernels
-                fd = unix_open("/dev/android", O_RDWR);
-                fprintf(stderr, "usb_adb_open_thread: %d\n", fd );
-            }
-            if (fd < 0) {
-                adb_sleep_ms(1000);
-            }
-        } while (fd < 0);
-        D("[ opening device succeeded ]\n");
-
-        close_on_exec(fd);
-        usb->fd = fd;
-
-        D("[ usb_thread - registering device ]\n");
-        register_usb_transport(usb, 0, 1);
-    }
-
-    // never gets here
-    return 0;
-}
-
-static int usb_adb_write(usb_handle *h, const void *data, int len)
-{
-    int n;
-
-    D("about to write (fd=%d, len=%d)\n", h->fd, len);
-    n = adb_write(h->fd, data, len);
-    if(n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->fd, n, errno, strerror(errno));
-        return -1;
-    }
-    D("[ done fd=%d ]\n", h->fd);
-    return 0;
-}
-
-static int usb_adb_read(usb_handle *h, void *data, int len)
-{
-    int n;
-
-    D("about to read (fd=%d, len=%d)\n", h->fd, len);
-    n = adb_read(h->fd, data, len);
-    if(n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->fd, n, errno, strerror(errno));
-        return -1;
-    }
-    D("[ done fd=%d ]\n", h->fd);
-    return 0;
-}
-
-static void usb_adb_kick(usb_handle *h)
-{
-    D("usb_kick\n");
-    adb_mutex_lock(&h->lock);
-    adb_close(h->fd);
-    h->fd = -1;
-
-    // notify usb_adb_open_thread that we are disconnected
-    adb_cond_signal(&h->notify);
-    adb_mutex_unlock(&h->lock);
-}
-
-static void usb_adb_init()
-{
-    usb_handle *h;
-    adb_thread_t tid;
-    int fd;
-
-    h = calloc(1, sizeof(usb_handle));
-
-    h->write = usb_adb_write;
-    h->read = usb_adb_read;
-    h->kick = usb_adb_kick;
-    h->fd = -1;
-
-    adb_cond_init(&h->notify, 0);
-    adb_mutex_init(&h->lock, 0);
-
-    fprintf(stderr, "Starting to open usb_init()\n");
-    // Open the file /dev/android_adb_enable to trigger 
-    // the enabling of the adb USB function in the kernel.
-    // We never touch this file again - just leave it open
-    // indefinitely so the kernel will know when we are running
-    // and when we are not.
-    fd = unix_open("/dev/android_adb_enable", O_RDWR);
-    fprintf(stderr, "unix_open to open usb_init(): %d\n", fd);
-    if (fd < 0) {
-       D("failed to open /dev/android_adb_enable\n");
-    } else {
-        close_on_exec(fd);
-    }
-
-    printf("[ usb_init - starting thread ]\n");
-    if(adb_thread_create(&tid, usb_adb_open_thread, h)){
-        fatal_errno("cannot create usb thread");
-        fprintf(stderr, "cannot create the usb thread()\n");
-    }
-}
-
-
-static void init_functionfs(struct usb_handle *h)
-{
-    ssize_t ret;
-
-    D("OPENING %s\n", USB_FFS_ADB_EP0);
-    h->control = adb_open(USB_FFS_ADB_EP0, O_RDWR);
-    if (h->control < 0) {
-        D("[ %s: cannot open control endpoint: errno=%d]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
-
-    ret = adb_write(h->control, &descriptors, sizeof(descriptors));
-    if (ret < 0) {
-        D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
-
-    ret = adb_write(h->control, &strings, sizeof(strings));
-    if (ret < 0) {
-        D("[ %s: writing strings failed: errno=%d]\n", USB_FFS_ADB_EP0, errno);
-        goto err;
-    }
-
-    h->bulk_out = adb_open(USB_FFS_ADB_OUT, O_RDWR);
-    if (h->bulk_out < 0) {
-        D("[ %s: cannot open bulk-out ep: errno=%d ]\n", USB_FFS_ADB_OUT, errno);
-        goto err;
-    }
-
-    h->bulk_in = adb_open(USB_FFS_ADB_IN, O_RDWR);
-    if (h->bulk_in < 0) {
-        D("[ %s: cannot open bulk-in ep: errno=%d ]\n", USB_FFS_ADB_IN, errno);
-        goto err;
-    }
-
-    return;
-
-err:
-    if (h->bulk_in > 0) {
-        adb_close(h->bulk_in);
-        h->bulk_in = -1;
-    }
-    if (h->bulk_out > 0) {
-        adb_close(h->bulk_out);
-        h->bulk_out = -1;
-    }
-    if (h->control > 0) {
-        adb_close(h->control);
-        h->control = -1;
-    }
-    return;
-}
-
-static void *usb_ffs_open_thread(void *x)
-{
-    struct usb_handle *usb = (struct usb_handle *)x;
-
-    while (1) {
-        // wait until the USB device needs opening
-        adb_mutex_lock(&usb->lock);
-        while (usb->control != -1)
-            adb_cond_wait(&usb->notify, &usb->lock);
-        adb_mutex_unlock(&usb->lock);
-
-        while (1) {
-            init_functionfs(usb);
-
-            if (usb->control >= 0)
-                break;
-
-            adb_sleep_ms(1000);
-        }
-
-        D("[ usb_thread - registering device ]\n");
-        register_usb_transport(usb, 0, 1);
-    }
-
-    // never gets here
-    return 0;
-}
-
-static int bulk_write(int bulk_in, const char *buf, size_t length)
-{
-    size_t count = 0;
-    int ret;
-
-    do {
-        ret = adb_write(bulk_in, buf + count, length - count);
-        if (ret < 0) {
-            if (errno != EINTR)
-                return ret;
-        } else {
-            count += ret;
-        }
-    } while (count < length);
-
-    D("[ bulk_write done fd=%d ]\n", bulk_in);
-    return count;
-}
-
-static int usb_ffs_write(usb_handle *h, const void *data, int len)
-{
-    int n;
-
-    D("about to write (fd=%d, len=%d)\n", h->bulk_in, len);
-    n = bulk_write(h->bulk_in, data, len);
-    if (n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->bulk_in, n, errno, strerror(errno));
-        return -1;
-    }
-    D("[ done fd=%d ]\n", h->bulk_in);
-    return 0;
-}
-
-static int bulk_read(int bulk_out, char *buf, size_t length)
-{
-    size_t count = 0;
-    int ret;
-
-    do {
-        ret = adb_read(bulk_out, buf + count, length - count);
-        if (ret < 0) {
-            if (errno != EINTR) {
-                D("[ bulk_read failed fd=%d length=%zu count=%zu ]\n",
-                                           bulk_out, length, count);
-                return ret;
-            }
-        } else {
-            count += ret;
-        }
-    } while (count < length);
-
-    return count;
-}
-
-static int usb_ffs_read(usb_handle *h, void *data, int len)
-{
-    int n;
-
-    D("about to read (fd=%d, len=%d)\n", h->bulk_out, len);
-    n = bulk_read(h->bulk_out, data, len);
-    if (n != len) {
-        D("ERROR: fd = %d, n = %d, errno = %d (%s)\n",
-            h->bulk_out, n, errno, strerror(errno));
-        return -1;
-    }
-    D("[ done fd=%d ]\n", h->bulk_out);
-    return 0;
-}
-
-static void usb_ffs_kick(usb_handle *h)
-{
-    int err;
-
-    err = ioctl(h->bulk_in, FUNCTIONFS_CLEAR_HALT);
-    if (err < 0)
-        D("[ kick: source (fd=%d) clear halt failed (%d) ]", h->bulk_in, errno);
-
-    err = ioctl(h->bulk_out, FUNCTIONFS_CLEAR_HALT);
-    if (err < 0)
-        D("[ kick: sink (fd=%d) clear halt failed (%d) ]", h->bulk_out, errno);
-
-    adb_mutex_lock(&h->lock);
-    adb_close(h->control);
-    adb_close(h->bulk_out);
-    adb_close(h->bulk_in);
-    h->control = h->bulk_out = h->bulk_in = -1;
-
-    // notify usb_ffs_open_thread that we are disconnected
-    adb_cond_signal(&h->notify);
-    adb_mutex_unlock(&h->lock);
-}
-
-static void usb_ffs_init()
-{
-    usb_handle *h;
-    adb_thread_t tid;
-
-    D("[ usb_init - using FunctionFS ]\n");
-
-    h = calloc(1, sizeof(usb_handle));
-
-    h->write = usb_ffs_write;
-    h->read = usb_ffs_read;
-    h->kick = usb_ffs_kick;
-
-    h->control  = -1;
-    h->bulk_out = -1;
-    h->bulk_out = -1;
-
-    adb_cond_init(&h->notify, 0);
-    adb_mutex_init(&h->lock, 0);
-
-    D("[ usb_init - starting thread ]\n");
-    if (adb_thread_create(&tid, usb_ffs_open_thread, h)){
-        fatal_errno("[ cannot create usb thread ]\n");
-    }
-}
-
-void usb_init()
-{
-    if (access(USB_FFS_ADB_EP0, F_OK) == 0)
-        usb_ffs_init();
-    else
-        usb_adb_init();
-}
-
-int usb_write(usb_handle *h, const void *data, int len)
-{
-    return h->write(h, data, len);
-}
-
-int usb_read(usb_handle *h, void *data, int len)
-{
-    return h->read(h, data, len);
-}
-int usb_close(usb_handle *h)
-{
-    // nothing to do here
-    return 0;
-}
-
-void usb_kick(usb_handle *h)
-{
-    h->kick(h);
-}
diff --git a/minadbd21/utils.c b/minadbd21/utils.c
deleted file mode 100644
index 91518ba..0000000
--- a/minadbd21/utils.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "utils.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-char*
-buff_addc (char*  buff, char*  buffEnd, int  c)
-{
-    int  avail = buffEnd - buff;
-
-    if (avail <= 0)  /* already in overflow mode */
-        return buff;
-
-    if (avail == 1) {  /* overflowing, the last byte is reserved for zero */
-        buff[0] = 0;
-        return buff + 1;
-    }
-
-    buff[0] = (char) c;  /* add char and terminating zero */
-    buff[1] = 0;
-    return buff + 1;
-}
-
-char*
-buff_adds (char*  buff, char*  buffEnd, const char*  s)
-{
-    int  slen = strlen(s);
-
-    return buff_addb(buff, buffEnd, s, slen);
-}
-
-char*
-buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len)
-{
-    int  avail = (buffEnd - buff);
-
-    if (avail <= 0 || len <= 0)  /* already overflowing */
-        return buff;
-
-    if (len > avail)
-        len = avail;
-
-    memcpy(buff, data, len);
-
-    buff += len;
-
-    /* ensure there is a terminating zero */
-    if (buff >= buffEnd) {  /* overflow */
-        buff[-1] = 0;
-    } else
-        buff[0] = 0;
-
-    return buff;
-}
-
-char*
-buff_add  (char*  buff, char*  buffEnd, const char*  format, ... )
-{
-    int      avail;
-
-    avail = (buffEnd - buff);
-
-    if (avail > 0) {
-        va_list  args;
-        int      nn;
-
-        va_start(args, format);
-        nn = vsnprintf( buff, avail, format, args);
-        va_end(args);
-
-        if (nn < 0) {
-            /* some C libraries return -1 in case of overflow,
-             * but they will also do that if the format spec is
-             * invalid. We assume ADB is not buggy enough to
-             * trigger that last case. */
-            nn = avail;
-        }
-        else if (nn > avail) {
-            nn = avail;
-        }
-
-        buff += nn;
-
-        /* ensure that there is a terminating zero */
-        if (buff >= buffEnd)
-            buff[-1] = 0;
-        else
-            buff[0] = 0;
-    }
-    return buff;
-}
diff --git a/minadbd21/utils.h b/minadbd21/utils.h
deleted file mode 100644
index f70ecd2..0000000
--- a/minadbd21/utils.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef _ADB_UTILS_H
-#define _ADB_UTILS_H
-
-/* bounded buffer functions */
-
-/* all these functions are used to append data to a bounded buffer.
- *
- * after each operation, the buffer is guaranteed to be zero-terminated,
- * even in the case of an overflow. they all return the new buffer position
- * which allows one to use them in succession, only checking for overflows
- * at the end. For example:
- *
- *    BUFF_DECL(temp,p,end,1024);
- *    char*    p;
- *
- *    p = buff_addc(temp, end, '"');
- *    p = buff_adds(temp, end, string);
- *    p = buff_addc(temp, end, '"');
- *
- *    if (p >= end) {
- *        overflow detected. note that 'temp' is
- *        zero-terminated for safety. 
- *    }
- *    return strdup(temp);
- */
-
-/* tries to add a character to the buffer, in case of overflow
- * this will only write a terminating zero and return buffEnd.
- */
-char*   buff_addc (char*  buff, char*  buffEnd, int  c);
-
-/* tries to add a string to the buffer */
-char*   buff_adds (char*  buff, char*  buffEnd, const char*  s);
-
-/* tries to add a bytes to the buffer. the input can contain zero bytes,
- * but a terminating zero will always be appended at the end anyway
- */
-char*   buff_addb (char*  buff, char*  buffEnd, const void*  data, int  len);
-
-/* tries to add a formatted string to a bounded buffer */
-char*   buff_add  (char*  buff, char*  buffEnd, const char*  format, ... );
-
-/* convenience macro used to define a bounded buffer, as well as
- * a 'cursor' and 'end' variables all in one go.
- *
- * note: this doesn't place an initial terminating zero in the buffer,
- * you need to use one of the buff_ functions for this. or simply
- * do _cursor[0] = 0 manually.
- */
-#define  BUFF_DECL(_buff,_cursor,_end,_size)   \
-    char   _buff[_size], *_cursor=_buff, *_end = _cursor + (_size)
-
-#endif /* _ADB_UTILS_H */
diff --git a/minuitwrp/Android.mk b/minuitwrp/Android.mk
index ac09e49..d1c01e0 100644
--- a/minuitwrp/Android.mk
+++ b/minuitwrp/Android.mk
@@ -71,7 +71,8 @@
     external/zlib \
     system/core/include \
     external/freetype/include \
-    external/libcxx/include
+    external/libcxx/include \
+    $(LOCAL_PATH)/../twrpinstall/include
 
 ifneq ($(TW_INCLUDE_JPEG),)
     LOCAL_C_INCLUDES += \
diff --git a/minuitwrp/events.cpp b/minuitwrp/events.cpp
index 7e5bc42..6d576c6 100755
--- a/minuitwrp/events.cpp
+++ b/minuitwrp/events.cpp
@@ -32,7 +32,7 @@
 #include <android/hardware/vibrator/1.2/IVibrator.h>
 #endif
 
-#include "../common.h"
+#include "common.h"
 
 #include "minui.h"
 
diff --git a/mtp/ffs/Android.mk b/mtp/ffs/Android.mk
index 740afcb..0f8bda9 100755
--- a/mtp/ffs/Android.mk
+++ b/mtp/ffs/Android.mk
@@ -13,9 +13,10 @@
     system/core/include \
     bionic/libc/private/ \
     bootable/recovery/twrplibusbhost/include \
-    bootable/recovery/install/include
+    bootable/recovery/twrpinstall/include
 
-LOCAL_SHARED_LIBRARIES += libc++ libaosprecovery
+LOCAL_SHARED_LIBRARIES += libc++
+LOCAL_STATIC_LIBRARIES += libtwrpinstall
 
 LOCAL_SRC_FILES = \
     MtpDataPacket.cpp \
diff --git a/openrecoveryscript.cpp b/openrecoveryscript.cpp
index c6f7d80..036d6ca 100755
--- a/openrecoveryscript.cpp
+++ b/openrecoveryscript.cpp
@@ -51,7 +51,7 @@
 #include "gui/pages.hpp"
 #include "orscmd/orscmd.h"
 #include "twinstall.h"
-#include "install/adb_install.h"
+#include "twinstall/adb_install.h"
 extern "C" {
 	#include "gui/gui.h"
 	#include "cutils/properties.h"
@@ -388,8 +388,9 @@
 				} else {
 					ret_val = 1; // failure
 				}
+				PartitionManager.Unlock_Block_Partitions();
 				sideload = 1; // Causes device to go to the home screen afterwards
-#ifdef USE_28_INSTALL 
+				pid_t sideload_child_pid = GetMiniAdbdPid();
 				if (sideload_child_pid != 0) {
 					LOGINFO("Signaling child sideload process to exit.\n");
 					struct stat st;
@@ -400,7 +401,6 @@
 					LOGINFO("Waiting for child sideload process to exit.\n");
 					waitpid(sideload_child_pid, &status, 0);
 				}
-#endif
 				property_set("ctl.start", "adbd");
 				gui_msg("done=Done.");
 			} else if (strcmp(command, "fixperms") == 0 || strcmp(command, "fixpermissions") == 0 || strcmp(command, "fixcontexts") == 0) {
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index f30e436..b3716d4 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -2769,6 +2769,8 @@
 
 	full_filename = path + "/" + filename;
 
+	Unlock_Block_Partitions();
+
 	gui_msg("image_flash_start=[IMAGE FLASH STARTED]");
 	gui_msg(Msg("img_to_flash=Image to flash: '{1}'")(full_filename));
 
@@ -3440,3 +3442,29 @@
 #endif
 	return true;
 }
+
+void TWPartitionManager::Unlock_Block_Partitions() {
+	int fd, OFF = 0;
+
+	const std::string block_path = "/dev/block/";
+	DIR* d = opendir(block_path.c_str());
+	if (d != NULL) {
+		struct dirent* de;
+		while ((de = readdir(d)) != NULL) {
+			if (de->d_type == DT_BLK) {
+				std::string block_device = block_path + de->d_name;
+				LOGINFO("block_Device: %s\n", block_device.c_str());
+				if ((fd = open(block_device.c_str(), O_RDONLY | O_CLOEXEC)) < 0) {
+					LOGERR("unable to open block device %s: %s\n", block_device.c_str(), strerror(errno));
+					continue;
+				}
+				if (ioctl(fd, BLKROSET, &OFF) == -1) {
+					LOGERR("Unable to unlock %s for flashing: %s\n", block_device.c_str());
+					continue;
+				}
+				close(fd);
+			}
+		}
+		closedir(d);
+	}
+}
\ No newline at end of file
diff --git a/partitions.hpp b/partitions.hpp
index 284baeb..9c2b65f 100755
--- a/partitions.hpp
+++ b/partitions.hpp
@@ -391,6 +391,7 @@
 	bool Recreate_Logs_Dir();                                                 // Recreate TWRP_AB_LOGS_DIR after wipe
 	std::vector<users_struct>* Get_Users_List();                              // Returns pointer to list of users
 	int Set_FDE_Encrypt_Status();                                             // Sets encryption state for FDE devices (ro.crypto.state and ro.crypto.type)
+	void Unlock_Block_Partitions();                                           // Unlock all block devices after update_engine runs
 
 private:
 	void Setup_Settings_Storage_Partition(TWPartition* Part);                 // Sets up settings storage
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index a7a5b79..07687ad 100755
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -86,6 +86,7 @@
 RECOVERY_BINARY_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/system/bin/charger
 RECOVERY_BINARY_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/system/bin/ueventd
 RECOVERY_BINARY_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/system/bin/watchdogd
+RECOVERY_BINARY_SOURCE_FILES += $(TARGET_RECOVERY_ROOT_OUT)/system/bin/minadbd
 
 RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcutils.so
 RECOVERY_LIBRARY_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrecovery.so
diff --git a/startupArgs.hpp b/startupArgs.hpp
index 6bb2cb8..f01a411 100755
--- a/startupArgs.hpp
+++ b/startupArgs.hpp
@@ -28,7 +28,7 @@
 #include "twrp-functions.hpp"
 #include "variables.h"
 #include "bootloader_message/include/bootloader_message/bootloader_message.h"
-#include "install/get_args.h"
+#include "twinstall/get_args.h"
 
 class startupArgs {
 public:
diff --git a/twinstallorig.h b/twinstallorig.h
deleted file mode 100644
index ea467a2..0000000
--- a/twinstallorig.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef RECOVERY_TWINSTALL_H_
-#define RECOVERY_TWINSTALL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int TWinstall_zip(const char* path, int* wipe_cache);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif  // RECOVERY_TWINSTALL_H_
diff --git a/twrpinstall/Android.bp b/twrpinstall/Android.bp
new file mode 100755
index 0000000..66ae163
--- /dev/null
+++ b/twrpinstall/Android.bp
@@ -0,0 +1,92 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+    name: "libtwrpinstall_defaults",
+
+    defaults: [
+        "recovery_defaults",
+    ],
+
+    header_libs: [
+        "libminadbd_headers",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libbootloader_message",
+        "libcrypto",
+        "libext4_utils",
+        "libfs_mgr",
+        "libfusesideload",
+        "libhidl-gen-utils",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libselinux",
+        "libtinyxml2",
+        "libutils",
+        "libz",
+        "libziparchive",
+    ],
+
+    static_libs: [
+        "libotautil",
+
+        // external dependencies
+        "libvintf_recovery",
+        "libvintf",
+        "libfstab",
+    ],
+}
+
+cc_library_static {
+    name: "libtwrpinstall",
+    recovery_available: true,
+
+    defaults: [
+        "libtwrpinstall_defaults",
+    ],
+
+    cflags: [
+        "-DAB_OTA_UPDATER=1"
+    ],
+
+    include_dirs: [
+        "bootable/recovery",
+        "bootable/recovery/install/include",
+    ],
+
+    srcs: [
+        "adb_install.cpp",
+        "asn1_decoder.cpp",
+        "install.cpp",
+        "installcommand.cpp",
+        "package.cpp",
+        "tw_atomic.cpp",
+        "twinstall.cpp",
+        "verifier.cpp",
+    ],
+    shared_libs: [
+        "librecovery_ui",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "librecovery_ui",
+    ],
+}
diff --git a/twrpinstall/ZipUtil.cpp b/twrpinstall/ZipUtil.cpp
new file mode 100755
index 0000000..f8134bc
--- /dev/null
+++ b/twrpinstall/ZipUtil.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "ZipUtil.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <utime.h>
+
+#include <string>
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <selinux/label.h>
+#include <selinux/selinux.h>
+#include <ziparchive/zip_archive.h>
+
+#include "otautil/dirutil.h"
+
+static constexpr mode_t UNZIP_DIRMODE = 0755;
+static constexpr mode_t UNZIP_FILEMODE = 0644;
+
+bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path,
+                             const std::string& dest_path, const struct utimbuf* timestamp,
+                             struct selabel_handle* sehnd) {
+    if (!zip_path.empty() && zip_path[0] == '/') {
+        LOG(ERROR) << "ExtractPackageRecursive(): zip_path must be a relative path " << zip_path;
+        return false;
+    }
+    if (dest_path.empty() || dest_path[0] != '/') {
+        LOG(ERROR) << "ExtractPackageRecursive(): dest_path must be an absolute path " << dest_path;
+        return false;
+    }
+
+    void* cookie;
+    std::string target_dir(dest_path);
+    if (dest_path.back() != '/') {
+        target_dir += '/';
+    }
+    std::string prefix_path(zip_path);
+    if (!zip_path.empty() && zip_path.back() != '/') {
+        prefix_path += '/';
+    }
+    const ZipString zip_prefix(prefix_path.c_str());
+
+    int ret = StartIteration(zip, &cookie, &zip_prefix, nullptr);
+    if (ret != 0) {
+        LOG(ERROR) << "failed to start iterating zip entries.";
+        return false;
+    }
+
+    std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration);
+    ZipEntry entry;
+    ZipString name;
+    int extractCount = 0;
+    while (Next(cookie, &entry, &name) == 0) {
+        std::string entry_name(name.name, name.name + name.name_length);
+        CHECK_LE(prefix_path.size(), entry_name.size());
+        std::string path = target_dir + entry_name.substr(prefix_path.size());
+        // Skip dir.
+        if (path.back() == '/') {
+            continue;
+        }
+        //TODO(b/31917448) handle the symlink.
+
+        if (dirCreateHierarchy(path.c_str(), UNZIP_DIRMODE, timestamp, true, sehnd) != 0) {
+            LOG(ERROR) << "failed to create dir for " << path;
+            return false;
+        }
+
+        char *secontext = NULL;
+        if (sehnd) {
+            selabel_lookup(sehnd, &secontext, path.c_str(), UNZIP_FILEMODE);
+            setfscreatecon(secontext);
+        }
+        android::base::unique_fd fd(open(path.c_str(), O_CREAT|O_WRONLY|O_TRUNC, UNZIP_FILEMODE));
+        if (fd == -1) {
+            PLOG(ERROR) << "Can't create target file \"" << path << "\"";
+            return false;
+        }
+        if (secontext) {
+            freecon(secontext);
+            setfscreatecon(NULL);
+        }
+
+        int err = ExtractEntryToFile(zip, &entry, fd);
+        if (err != 0) {
+            LOG(ERROR) << "Error extracting \"" << path << "\" : " << ErrorCodeString(err);
+            return false;
+        }
+
+        if (fsync(fd) != 0) {
+            PLOG(ERROR) << "Error syncing file descriptor when extracting \"" << path << "\"";
+            return false;
+        }
+
+        if (timestamp != nullptr && utime(path.c_str(), timestamp)) {
+            PLOG(ERROR) << "Error touching \"" << path << "\"";
+            return false;
+        }
+
+        LOG(INFO) << "Extracted file \"" << path << "\"";
+        ++extractCount;
+    }
+
+    LOG(INFO) << "Extracted " << extractCount << " file(s)";
+    return true;
+}
diff --git a/twrpinstall/ZipUtil.h b/twrpinstall/ZipUtil.h
new file mode 100644
index 0000000..cda405c
--- /dev/null
+++ b/twrpinstall/ZipUtil.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _OTAUTIL_ZIPUTIL_H
+#define _OTAUTIL_ZIPUTIL_H
+
+#include <utime.h>
+
+#include <string>
+
+#include <selinux/label.h>
+#include <ziparchive/zip_archive.h>
+
+/*
+ * Inflate all files under zip_path to the directory specified by
+ * dest_path, which must exist and be a writable directory. The zip_path
+ * is allowed to be an empty string, in which case the whole package
+ * will be extracted.
+ *
+ * Directory entries are not extracted.
+ *
+ * The immediate children of zip_path will become the immediate
+ * children of dest_path; e.g., if the archive contains the entries
+ *
+ *     a/b/c/one
+ *     a/b/c/two
+ *     a/b/c/d/three
+ *
+ * and ExtractPackageRecursive(a, "a/b/c", "/tmp", ...) is called, the resulting
+ * files will be
+ *
+ *     /tmp/one
+ *     /tmp/two
+ *     /tmp/d/three
+ *
+ * If timestamp is non-NULL, file timestamps will be set accordingly.
+ *
+ * Returns true on success, false on failure.
+ */
+bool ExtractPackageRecursive(ZipArchiveHandle zip, const std::string& zip_path,
+                             const std::string& dest_path, const struct utimbuf* timestamp,
+                             struct selabel_handle* sehnd);
+
+#endif // _OTAUTIL_ZIPUTIL_H
diff --git a/twrpinstall/adb_install.cpp b/twrpinstall/adb_install.cpp
new file mode 100755
index 0000000..5eb8c0b
--- /dev/null
+++ b/twrpinstall/adb_install.cpp
@@ -0,0 +1,377 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "twinstall/adb_install.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <atomic>
+#include <functional>
+#include <map>
+#include <utility>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/memory.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+
+#include "fuse_sideload.h"
+#include "twinstall/install.h"
+#include "twinstall/wipe_data.h"
+#include "minadbd_types.h"
+#include "otautil/sysutil.h"
+#include "recovery_ui/device.h"
+#include "recovery_ui/ui.h"
+
+// A CommandFunction returns a pair of (result, should_continue), which indicates the command
+// execution result and whether it should proceed to the next iteration. The execution result will
+// always be sent to the minadbd side.
+using CommandFunction = std::function<std::pair<bool, bool>()>;
+
+pid_t child;
+
+pid_t GetMiniAdbdPid() {
+  return child;
+}
+
+static bool SetUsbConfig(const std::string& state) {
+  android::base::SetProperty("sys.usb.config", state);
+  return android::base::WaitForProperty("sys.usb.state", state);
+}
+
+// Parses the minadbd command in |message|; returns MinadbdCommand::kError upon errors.
+static MinadbdCommand ParseMinadbdCommand(const std::string& message) {
+  if (!android::base::StartsWith(message, kMinadbdCommandPrefix)) {
+    LOG(ERROR) << "Failed to parse command in message " << message;
+    return MinadbdCommand::kError;
+  }
+
+  auto cmd_code_string = message.substr(strlen(kMinadbdCommandPrefix));
+  auto cmd_code = android::base::get_unaligned<uint32_t>(cmd_code_string.c_str());
+  if (cmd_code >= static_cast<uint32_t>(MinadbdCommand::kError)) {
+    LOG(ERROR) << "Unsupported command code: " << cmd_code;
+    return MinadbdCommand::kError;
+  }
+
+  return static_cast<MinadbdCommand>(cmd_code);
+}
+
+static bool WriteStatusToFd(MinadbdCommandStatus status, int fd) {
+  char message[kMinadbdMessageSize];
+  memcpy(message, kMinadbdStatusPrefix, strlen(kMinadbdStatusPrefix));
+  android::base::put_unaligned(message + strlen(kMinadbdStatusPrefix), status);
+
+  if (!android::base::WriteFully(fd, message, kMinadbdMessageSize)) {
+    PLOG(ERROR) << "Failed to write message " << message;
+    return false;
+  }
+  return true;
+}
+
+// Installs the package from FUSE. Returns the installation result and whether it should continue
+// waiting for new commands.
+static auto AdbInstallPackageHandler(int* result) {
+  // How long (in seconds) we wait for the package path to be ready. It doesn't need to be too long
+  // because the minadbd service has already issued an install command. FUSE_SIDELOAD_HOST_PATHNAME
+  // will start to exist once the host connects and starts serving a package. Poll for its
+  // appearance. (Note that inotify doesn't work with FUSE.)
+  constexpr int ADB_INSTALL_TIMEOUT = 15;
+  bool should_continue = true;
+  *result = INSTALL_ERROR;
+  for (int i = 0; i < ADB_INSTALL_TIMEOUT; ++i) {
+    PLOG(ERROR) << "i: " << i;
+    struct stat st;
+    if (stat(FUSE_SIDELOAD_HOST_PATHNAME, &st) != 0) {
+      if (errno == ENOENT && i < ADB_INSTALL_TIMEOUT - 1) {
+        sleep(1);
+        continue;
+      } else {
+        should_continue = false;
+        break;
+      }
+    }
+    *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0);
+    break;
+  }
+
+  // Calling stat() on this magic filename signals the FUSE to exit.
+  struct stat st;
+  stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
+  return std::make_pair(*result == INSTALL_SUCCESS, should_continue);
+}
+
+static auto AdbRebootHandler(MinadbdCommand command, int* result,
+                             Device::BuiltinAction* reboot_action) {
+  // Use Device::REBOOT_{FASTBOOT,RECOVERY,RESCUE}, instead of the ones with ENTER_. This allows
+  // rebooting back into fastboot/recovery/rescue mode through bootloader, which may use a newly
+  // installed bootloader/recovery image.
+  switch (command) {
+    case MinadbdCommand::kRebootBootloader:
+      *reboot_action = Device::REBOOT_BOOTLOADER;
+      break;
+    case MinadbdCommand::kRebootFastboot:
+      *reboot_action = Device::REBOOT_FASTBOOT;
+      break;
+    case MinadbdCommand::kRebootRecovery:
+      *reboot_action = Device::REBOOT_RECOVERY;
+      break;
+    case MinadbdCommand::kRebootRescue:
+      *reboot_action = Device::REBOOT_RESCUE;
+      break;
+    case MinadbdCommand::kRebootAndroid:
+    default:
+      *reboot_action = Device::REBOOT;
+      break;
+  }
+  *result = INSTALL_REBOOT;
+  return std::make_pair(true, false);
+}
+
+// Parses and executes the command from minadbd. Returns whether the caller should keep waiting for
+// next command.
+static bool HandleMessageFromMinadbd(int socket_fd,
+                                     const std::map<MinadbdCommand, CommandFunction>& command_map) {
+  char buffer[kMinadbdMessageSize];
+  if (!android::base::ReadFully(socket_fd, buffer, kMinadbdMessageSize)) {
+    PLOG(ERROR) << "Failed to read message from minadbd";
+    return false;
+  }
+
+  std::string message(buffer, buffer + kMinadbdMessageSize);
+  auto command_type = ParseMinadbdCommand(message);
+  if (command_type == MinadbdCommand::kError) {
+    return false;
+  }
+  if (command_map.find(command_type) == command_map.end()) {
+    LOG(ERROR) << "Unsupported command: "
+               << android::base::get_unaligned<unsigned int>(
+                      message.substr(strlen(kMinadbdCommandPrefix)).c_str());
+    return false;
+  }
+
+  // We have received a valid command, execute the corresponding function.
+  const auto& command_func = command_map.at(command_type);
+  const auto [result, should_continue] = command_func();
+  LOG(INFO) << "Command " << static_cast<uint32_t>(command_type) << " finished with " << result;
+  if (!WriteStatusToFd(result ? MinadbdCommandStatus::kSuccess : MinadbdCommandStatus::kFailure,
+                       socket_fd)) {
+    return false;
+  }
+  return should_continue;
+}
+
+// TODO(xunchang) add a wrapper function and kill the minadbd service there.
+static void ListenAndExecuteMinadbdCommands(
+    pid_t minadbd_pid, android::base::unique_fd&& socket_fd,
+    const std::map<MinadbdCommand, CommandFunction>& command_map) {
+  android::base::unique_fd epoll_fd(epoll_create1(O_CLOEXEC));
+  if (epoll_fd == -1) {
+    PLOG(ERROR) << "Failed to create epoll";
+    kill(minadbd_pid, SIGKILL);
+    return;
+  }
+
+  constexpr int EPOLL_MAX_EVENTS = 10;
+  struct epoll_event ev = {};
+  ev.events = EPOLLIN | EPOLLHUP;
+  ev.data.fd = socket_fd.get();
+  struct epoll_event events[EPOLL_MAX_EVENTS];
+  if (epoll_ctl(epoll_fd.get(), EPOLL_CTL_ADD, socket_fd.get(), &ev) == -1) {
+    PLOG(ERROR) << "Failed to add socket fd to epoll";
+    kill(minadbd_pid, SIGKILL);
+    return;
+  }
+
+  // Set the timeout to be 300s when waiting for minadbd commands.
+  constexpr int TIMEOUT_MILLIS = 300 * 1000;
+  while (true) {
+    // Poll for the status change of the socket_fd, and handle the message if the fd is ready to
+    // read.
+    int event_count =
+        TEMP_FAILURE_RETRY(epoll_wait(epoll_fd.get(), events, EPOLL_MAX_EVENTS, TIMEOUT_MILLIS));
+    if (event_count == -1) {
+      PLOG(ERROR) << "Failed to wait for epoll events";
+      kill(minadbd_pid, SIGKILL);
+      return;
+    }
+    if (event_count == 0) {
+      LOG(ERROR) << "Timeout waiting for messages from minadbd";
+      kill(minadbd_pid, SIGKILL);
+      return;
+    }
+
+    for (int n = 0; n < event_count; n++) {
+      if (events[n].events & EPOLLHUP) {
+        LOG(INFO) << "Socket has been closed";
+        kill(minadbd_pid, SIGKILL);
+        return;
+      }
+      if (!HandleMessageFromMinadbd(socket_fd.get(), command_map)) {
+        kill(minadbd_pid, SIGKILL);
+        return;
+      }
+    }
+  }
+}
+
+// Recovery starts minadbd service as a child process, and spawns another thread to listen for the
+// message from minadbd through a socket pair. Here is an example to execute one command from adb
+// host.
+//  a. recovery                    b. listener thread               c. minadbd service
+//
+//  a1. create socket pair
+//  a2. fork minadbd service
+//                                                                c3. wait for the adb commands
+//                                                                    from host
+//                                                                c4. after receiving host commands:
+//                                                                  1) set up pre-condition (i.e.
+//                                                                     start fuse for adb sideload)
+//                                                                  2) issue command through
+//                                                                     socket.
+//                                                                  3) wait for result
+//  a5. start listener thread
+//                               b6. listen for message from
+//                                   minadbd in a loop.
+//                               b7. After receiving a minadbd
+//                                   command from socket
+//                                 1) execute the command function
+//                                 2) send the result back to
+//                                    minadbd
+//  ......
+//                                                                 c8. exit upon receiving the
+//                                                                     result
+// a9.  wait for listener thread
+//      to exit.
+//
+// a10. wait for minadbd to
+//      exit
+//                               b11. exit the listening loop
+//
+static void CreateMinadbdServiceAndExecuteCommands(
+    const std::map<MinadbdCommand, CommandFunction>& command_map,
+    bool rescue_mode __unused, std::string install_file __unused) {
+  signal(SIGPIPE, SIG_IGN);
+
+  android::base::unique_fd recovery_socket;
+  android::base::unique_fd minadbd_socket;
+  if (!android::base::Socketpair(AF_UNIX, SOCK_STREAM, 0, &recovery_socket, &minadbd_socket)) {
+    PLOG(ERROR) << "Failed to create socket";
+    return;
+  }
+
+  child = fork();
+  if (child == -1) {
+    PLOG(ERROR) << "Failed to fork child process";
+    return;
+  }
+  if (child == 0) {
+    recovery_socket.reset();
+    std::vector<std::string> minadbd_commands = {
+      "/system/bin/minadbd",
+      "--socket_fd",
+      std::to_string(minadbd_socket.release()),
+    };
+    // if (rescue_mode) {
+    //   minadbd_commands.push_back("--rescue");
+    // }
+    auto exec_args = StringVectorToNullTerminatedArray(minadbd_commands);
+    execv(exec_args[0], exec_args.data());
+    _exit(EXIT_FAILURE);
+  }
+
+  minadbd_socket.reset();
+
+  // We need to call SetUsbConfig() after forking minadbd service. Because the function waits for
+  // the usb state to be updated, which depends on sys.usb.ffs.ready=1 set in the adb daemon.
+  if (!SetUsbConfig("sideload")) {
+    LOG(ERROR) << "Failed to set usb config to sideload";
+    return;
+  }
+
+  std::thread listener_thread(ListenAndExecuteMinadbdCommands, child,
+                              std::move(recovery_socket), std::ref(command_map));
+  if (listener_thread.joinable()) {
+    listener_thread.join();
+  }
+
+  int status;
+  waitpid(child, &status, 0);
+  if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+    if (WEXITSTATUS(status) == MinadbdErrorCode::kMinadbdAdbVersionError) {
+      LOG(ERROR) << "\nYou need adb 1.0.32 or newer to sideload\nto this device.\n";
+    } else if (!WIFSIGNALED(status)) {
+      LOG(ERROR) << "\n(adbd status " << WEXITSTATUS(status) << ")";
+    }
+  }
+
+  signal(SIGPIPE, SIG_DFL);
+}
+
+  int twrp_sideload(const char* install_file, Device::BuiltinAction* reboot_action) {
+
+  // Save the usb state to restore after the sideload operation.
+  std::string usb_state = android::base::GetProperty("sys.usb.state", "none");
+  // Clean up state and stop adbd.
+  if (usb_state != "none" && !SetUsbConfig("none")) {
+    LOG(ERROR) << "Failed to clear USB config";
+    return INSTALL_ERROR;
+  }
+
+  int install_result = INSTALL_ERROR;
+  std::map<MinadbdCommand, CommandFunction> command_map{
+  { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, &install_result) },
+  { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid,
+                                              &install_result, reboot_action) },
+  { MinadbdCommand::kRebootBootloader,
+    std::bind(&AdbRebootHandler, MinadbdCommand::kRebootBootloader, &install_result,
+              reboot_action) },
+  { MinadbdCommand::kRebootFastboot, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootFastboot,
+                                                &install_result, reboot_action) },
+  { MinadbdCommand::kRebootRecovery, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRecovery,
+                                                &install_result, reboot_action) },
+  { MinadbdCommand::kRebootRescue,
+    std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) },
+};
+
+  CreateMinadbdServiceAndExecuteCommands(command_map, false, install_file);
+
+  // Clean up before switching to the older state, for example setting the state
+  // to none sets sys/class/android_usb/android0/enable to 0.
+  if (!SetUsbConfig("none")) {
+    LOG(ERROR) << "Failed to clear USB config";
+  }
+
+  if (usb_state != "none") {
+    if (!SetUsbConfig(usb_state)) {
+      LOG(ERROR) << "Failed to set USB config to " << usb_state;
+    }
+  }
+
+  return install_result;
+}
diff --git a/verifier28/asn1_decoder.cpp b/twrpinstall/asn1_decoder.cpp
similarity index 98%
rename from verifier28/asn1_decoder.cpp
rename to twrpinstall/asn1_decoder.cpp
index 285214f..2d81a6e 100644
--- a/verifier28/asn1_decoder.cpp
+++ b/twrpinstall/asn1_decoder.cpp
@@ -14,9 +14,7 @@
  * limitations under the License.
  */
 
-#include "asn1_decoder.h"
-
-#include <stdint.h>
+#include "private/asn1_decoder.h"
 
 int asn1_context::peek_byte() const {
   if (length_ == 0) {
diff --git a/common.h b/twrpinstall/include/common.h
similarity index 100%
rename from common.h
rename to twrpinstall/include/common.h
diff --git a/install/include/installcommand.h b/twrpinstall/include/installcommand.h
similarity index 75%
rename from install/include/installcommand.h
rename to twrpinstall/include/installcommand.h
index 957f016..f265801 100644
--- a/install/include/installcommand.h
+++ b/twrpinstall/include/installcommand.h
@@ -20,20 +20,19 @@
 #define TMP_UPDATER_BINARY_PATH "/tmp/updater"
 
 #include <string>
+#include <ziparchive/zip_archive.h>
 
-#include "zipwrap.hpp"
-
-bool read_metadata_from_package(ZipWrap* zip, std::string* meta_data);
+bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data);
 
 int
-abupdate_binary_command(const char* path, ZipWrap* zip, int retry_count,
+abupdate_binary_command(const char* path, int retry_count,
                       int status_fd, std::vector<std::string>* cmd);
 int
 update_binary_command(const char* path, int retry_count,
                       int status_fd, std::vector<std::string>* cmd);
 
-bool verify_package_compatibility(ZipWrap *package_zip);
+bool verify_package_compatibility(ZipArchiveHandle package_zip);
 
-void read_source_target_build(ZipWrap* zip/*, std::vector<std::string>& log_buffer*/);
+void read_source_target_build(ZipArchiveHandle zip/*, std::vector<std::string>& log_buffer*/);
 
 #endif  // RECOVERY_INSTALL_COMMAND_H_
diff --git a/minadbd21/fuse_adb_provider.h b/twrpinstall/include/legacy_property_service.h
similarity index 69%
rename from minadbd21/fuse_adb_provider.h
rename to twrpinstall/include/legacy_property_service.h
index 0eb1f79..d20bdef 100644
--- a/minadbd21/fuse_adb_provider.h
+++ b/twrpinstall/include/legacy_property_service.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2007 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef __FUSE_ADB_PROVIDER_H
-#define __FUSE_ADB_PROVIDER_H
+#ifndef _LEGACY_PROPERTY_H
+#define _LEGACY_PROPERTY_H
 
-int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size);
+#include <stdbool.h>
 
-#endif
+void legacy_get_property_workspace(int *fd, int *sz);
+int legacy_properties_init();
+
+#endif	/* _LEGACY_PROPERTY_H */
diff --git a/verifier28/asn1_decoder.h b/twrpinstall/include/private/asn1_decoder.h
similarity index 98%
rename from verifier28/asn1_decoder.h
rename to twrpinstall/include/private/asn1_decoder.h
index 3e99211..e5337d9 100644
--- a/verifier28/asn1_decoder.h
+++ b/twrpinstall/include/private/asn1_decoder.h
@@ -17,6 +17,7 @@
 #ifndef ASN1_DECODER_H_
 #define ASN1_DECODER_H_
 
+#include <stddef.h>
 #include <stdint.h>
 
 class asn1_context {
diff --git a/twrpinstall/include/private/setup_commands.h b/twrpinstall/include/private/setup_commands.h
new file mode 100644
index 0000000..7fdc741
--- /dev/null
+++ b/twrpinstall/include/private/setup_commands.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Private headers exposed for testing purpose only.
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include <ziparchive/zip_archive.h>
+
+// Sets up the commands for a non-A/B update. Extracts the updater binary from the open zip archive
+// |zip| located at |package|. Stores the command line that should be called into |cmd|. The
+// |status_fd| is the file descriptor the child process should use to report back the progress of
+// the update.
+int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int retry_count,
+                             int status_fd, std::vector<std::string>* cmd);
+
+// Sets up the commands for an A/B update. Extracts the needed entries from the open zip archive
+// |zip| located at |package|. Stores the command line that should be called into |cmd|. The
+// |status_fd| is the file descriptor the child process should use to report back the progress of
+// the update. Note that since this applies to the sideloading flow only, it takes one less
+// parameter |retry_count| than the non-A/B version.
+int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd,
+                          std::vector<std::string>* cmd);
diff --git a/twrpinstall/include/set_metadata.h b/twrpinstall/include/set_metadata.h
new file mode 100644
index 0000000..9a46be9
--- /dev/null
+++ b/twrpinstall/include/set_metadata.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2014 The Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The purpose of these functions is to try to get and set the proper
+ * file permissions, SELinux contexts, owner, and group so that these
+ * files are accessible when we boot up to normal Android via MTP and to
+ * file manager apps. During early boot we try to read the contexts and
+ * owner / group info from /data/media or from /data/media/0 and store
+ * them in static variables. From there, we'll try to set the same
+ * contexts, owner, and group information on most files we create during
+ * operations like backups, copying the log, and MTP operations.
+ */
+
+#ifndef _RECOVERY_SET_CONTEXTS_H
+#define _RECOVERY_SET_CONTEXTS_H
+
+#include <sys/stat.h>
+#include "selinux/selinux.h"
+
+int tw_get_default_metadata(const char* filename);
+int tw_set_default_metadata(const char* filename);
+
+#endif //_RECOVERY_SET_CONTEXTS_H
diff --git a/install/include/tw_atomic.hpp b/twrpinstall/include/tw_atomic.hpp
similarity index 100%
rename from install/include/tw_atomic.hpp
rename to twrpinstall/include/tw_atomic.hpp
diff --git a/twinstall.h b/twrpinstall/include/twinstall.h
similarity index 100%
rename from twinstall.h
rename to twrpinstall/include/twinstall.h
diff --git a/twrpinstall/include/twinstall/adb_install.h b/twrpinstall/include/twinstall/adb_install.h
new file mode 100755
index 0000000..42321d4
--- /dev/null
+++ b/twrpinstall/include/twinstall/adb_install.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <recovery_ui/device.h>
+
+// Applies a package via `adb sideload` or `adb rescue`. Returns the install result (in `enum
+// InstallResult`). When a reboot has been requested, INSTALL_REBOOT will be the return value, with
+// the reboot target set in reboot_action.
+int twrp_sideload(const char* install_file, Device::BuiltinAction* reboot_action);
+pid_t GetMiniAdbdPid();
\ No newline at end of file
diff --git a/install/include/install/get_args.h b/twrpinstall/include/twinstall/get_args.h
similarity index 100%
rename from install/include/install/get_args.h
rename to twrpinstall/include/twinstall/get_args.h
diff --git a/twrpinstall/include/twinstall/install.h b/twrpinstall/include/twinstall/install.h
new file mode 100755
index 0000000..29647ad
--- /dev/null
+++ b/twrpinstall/include/twinstall/install.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stddef.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <ziparchive/zip_archive.h>
+
+#include "package.h"
+
+enum InstallResult {
+  INSTALL_SUCCESS,
+  INSTALL_ERROR,
+  INSTALL_CORRUPT,
+  INSTALL_NONE,
+  INSTALL_SKIPPED,
+  INSTALL_RETRY,
+  INSTALL_KEY_INTERRUPTED,
+  INSTALL_REBOOT,
+};
+
+enum class OtaType {
+  AB,
+  BLOCK,
+  BRICK,
+};
+
+static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
+static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
+
+// Installs the given update package. This function should also wipe the cache partition after a
+// successful installation if |should_wipe_cache| is true or an updater command asks to wipe the
+// cache.
+int install_package(const std::string& package, bool should_wipe_cache, bool needs_mount,
+                    int retry_count);
+
+// Verifies the package by ota keys. Returns true if the package is verified successfully,
+// otherwise returns false.
+bool verify_package(Package* package);
+
+// Reads meta data file of the package; parses each line in the format "key=value"; and writes the
+// result to |metadata|. Return true if succeed, otherwise return false.
+bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::string>* metadata);
+
+// Reads the "recovery.wipe" entry in the zip archive returns a list of partitions to wipe.
+std::vector<std::string> GetWipePartitionList(Package* wipe_package);
+
+// Verifies the compatibility info in a Treble-compatible package. Returns true directly if the
+// entry doesn't exist.
+bool verify_package_compatibility(ZipArchiveHandle package_zip);
+
+// Checks if the the metadata in the OTA package has expected values. Returns 0 on success.
+// Mandatory checks: ota-type, pre-device and serial number(if presents)
+// AB OTA specific checks: pre-build version, fingerprint, timestamp.
+int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type);
+bool HasUpdaterBinary(ZipArchiveHandle zip);
\ No newline at end of file
diff --git a/twrpinstall/include/twinstall/package.h b/twrpinstall/include/twinstall/package.h
new file mode 100755
index 0000000..50a4ffa
--- /dev/null
+++ b/twrpinstall/include/twinstall/package.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <functional>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include <ziparchive/zip_archive.h>
+
+#include "verifier.h"
+
+// This class serves as a wrapper for an OTA update package. It aims to provide the common
+// interface for both packages loaded in memory and packages read from fd.
+class Package : public VerifierInterface {
+ public:
+  static std::unique_ptr<Package> CreateMemoryPackage(
+      const std::string& path);
+  static std::unique_ptr<Package> CreateMemoryPackage(
+      std::vector<uint8_t> content);
+  static std::unique_ptr<Package> CreateFilePackage(const std::string& path,
+                                                    const std::function<void(float)>& set_progress);
+
+  virtual ~Package() = default;
+
+  // Opens the package as a zip file and returns the ZipArchiveHandle.
+  virtual ZipArchiveHandle GetZipArchiveHandle() = 0;
+
+  // Updates the progress in fraction during package verification.
+  void SetProgress(float progress) override;
+
+ protected:
+  // An optional function to update the progress.
+  std::function<void(float)> set_progress_;
+};
diff --git a/twrpinstall/include/twinstall/verifier.h b/twrpinstall/include/twinstall/verifier.h
new file mode 100644
index 0000000..5d66e85
--- /dev/null
+++ b/twrpinstall/include/twinstall/verifier.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <openssl/ec_key.h>
+#include <openssl/rsa.h>
+#include <openssl/sha.h>
+
+constexpr size_t MiB = 1024 * 1024;
+
+using HasherUpdateCallback = std::function<void(const uint8_t* addr, uint64_t size)>;
+
+struct RSADeleter {
+  void operator()(RSA* rsa) const {
+    RSA_free(rsa);
+  }
+};
+
+struct ECKEYDeleter {
+  void operator()(EC_KEY* ec_key) const {
+    EC_KEY_free(ec_key);
+  }
+};
+
+struct Certificate {
+  typedef enum {
+    KEY_TYPE_RSA,
+    KEY_TYPE_EC,
+  } KeyType;
+
+  Certificate(int hash_len_, KeyType key_type_, std::unique_ptr<RSA, RSADeleter>&& rsa_,
+              std::unique_ptr<EC_KEY, ECKEYDeleter>&& ec_)
+      : hash_len(hash_len_), key_type(key_type_), rsa(std::move(rsa_)), ec(std::move(ec_)) {}
+
+  // SHA_DIGEST_LENGTH (SHA-1) or SHA256_DIGEST_LENGTH (SHA-256)
+  int hash_len;
+  KeyType key_type;
+  std::unique_ptr<RSA, RSADeleter> rsa;
+  std::unique_ptr<EC_KEY, ECKEYDeleter> ec;
+};
+
+class VerifierInterface {
+ public:
+  virtual ~VerifierInterface() = default;
+
+  // Returns the package size in bytes.
+  virtual uint64_t GetPackageSize() const = 0;
+
+  // Reads |byte_count| data starting from |offset|, and puts the result in |buffer|.
+  virtual bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) = 0;
+
+  // Updates the hash contexts for |length| bytes data starting from |start|.
+  virtual bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
+                                  uint64_t length) = 0;
+
+  // Updates the progress in fraction during package verification.
+  virtual void SetProgress(float progress) = 0;
+};
+
+//  Looks for an RSA signature embedded in the .ZIP file comment given the path to the zip.
+//  Verifies that it matches one of the given public keys. Returns VERIFY_SUCCESS or
+//  VERIFY_FAILURE (if any error is encountered or no key matches the signature).
+int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys,
+                const std::function<void(float)>& set_progress = nullptr);
+
+// Checks that the RSA key has a modulus of 2048 or 4096 bits long, and public exponent is 3 or
+// 65537.
+bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa);
+
+// Checks that the field size of the curve for the EC key is 256 bits.
+bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& ec_key);
+
+// Parses a PEM-encoded x509 certificate from the given buffer and saves it into |cert|. Returns
+// false if there is a parsing failure or the signature's encryption algorithm is not supported.
+bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certificate* cert);
+
+// Iterates over the zip entries with the suffix "x509.pem" and returns a list of recognized
+// certificates. Returns an empty list if we fail to parse any of the entries.
+std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name);
+
+#define VERIFY_SUCCESS 0
+#define VERIFY_FAILURE 1
diff --git a/minadbd21/fuse_adb_provider.h b/twrpinstall/include/twinstall/wipe_data.h
old mode 100644
new mode 100755
similarity index 68%
copy from minadbd21/fuse_adb_provider.h
copy to twrpinstall/include/twinstall/wipe_data.h
index 0eb1f79..07b1e40
--- a/minadbd21/fuse_adb_provider.h
+++ b/twrpinstall/include/twinstall/wipe_data.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,9 +14,14 @@
  * limitations under the License.
  */
 
-#ifndef __FUSE_ADB_PROVIDER_H
-#define __FUSE_ADB_PROVIDER_H
+#pragma once
 
-int run_adb_fuse(int sfd, uint64_t file_size, uint32_t block_size);
+#include <functional>
 
-#endif
+struct selabel_handle;
+
+// Returns true on success.
+bool WipeCache(const std::function<bool()>& confirm);
+
+// Returns true on success.
+bool WipeData(bool convert_fbe);
diff --git a/twrpinstall/install.cpp b/twrpinstall/install.cpp
new file mode 100755
index 0000000..f3c7769
--- /dev/null
+++ b/twrpinstall/install.cpp
@@ -0,0 +1,753 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "twinstall/install.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+#include <algorithm>
+#include <atomic>
+#include <chrono>
+#include <condition_variable>
+#include <functional>
+#include <limits>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/parsedouble.h>
+#include <android-base/parseint.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#include <android-base/unique_fd.h>
+#include <vintf/VintfObjectRecovery.h>
+
+#include "twinstall/package.h"
+#include "twinstall/verifier.h"
+#include "twinstall/wipe_data.h"
+#include "otautil/error_code.h"
+#include "otautil/paths.h"
+#include "otautil/roots.h"
+#include "otautil/sysutil.h"
+#include "otautil/thermalutil.h"
+#include "private/setup_commands.h"
+
+using namespace std::chrono_literals;
+
+static constexpr int kRecoveryApiVersion = 3;
+// Assert the version defined in code and in Android.mk are consistent.
+static_assert(kRecoveryApiVersion == RECOVERY_API_VERSION, "Mismatching recovery API versions.");
+
+// Default allocation of progress bar segments to operations
+// static constexpr int VERIFICATION_PROGRESS_TIME = 60;
+// static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
+
+static std::condition_variable finish_log_temperature;
+
+bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::string>* metadata) {
+  CHECK(metadata != nullptr);
+
+  static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
+  ZipString path(METADATA_PATH);
+  ZipEntry entry;
+  if (FindEntry(zip, path, &entry) != 0) {
+    LOG(ERROR) << "Failed to find " << METADATA_PATH;
+    return false;
+  }
+
+  uint32_t length = entry.uncompressed_length;
+  std::string metadata_string(length, '\0');
+  int32_t err =
+      ExtractToMemory(zip, &entry, reinterpret_cast<uint8_t*>(&metadata_string[0]), length);
+  if (err != 0) {
+    LOG(ERROR) << "Failed to extract " << METADATA_PATH << ": " << ErrorCodeString(err);
+    return false;
+  }
+
+  for (const std::string& line : android::base::Split(metadata_string, "\n")) {
+    size_t eq = line.find('=');
+    if (eq != std::string::npos) {
+      metadata->emplace(android::base::Trim(line.substr(0, eq)),
+                        android::base::Trim(line.substr(eq + 1)));
+    }
+  }
+
+  return true;
+}
+
+// Gets the value for the given key in |metadata|. Returns an emtpy string if the key isn't
+// present.
+static std::string get_value(const std::map<std::string, std::string>& metadata,
+                             const std::string& key) {
+  const auto& it = metadata.find(key);
+  return (it == metadata.end()) ? "" : it->second;
+}
+
+static std::string OtaTypeToString(OtaType type) {
+  switch (type) {
+    case OtaType::AB:
+      return "AB";
+    case OtaType::BLOCK:
+      return "BLOCK";
+    case OtaType::BRICK:
+      return "BRICK";
+  }
+}
+
+// Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
+static void ReadSourceTargetBuild(const std::map<std::string, std::string>& metadata,
+                                  std::vector<std::string>* log_buffer) {
+  // Examples of the pre-build and post-build strings in metadata:
+  //   pre-build-incremental=2943039
+  //   post-build-incremental=2951741
+  auto source_build = get_value(metadata, "pre-build-incremental");
+  if (!source_build.empty()) {
+    log_buffer->push_back("source_build: " + source_build);
+  }
+
+  auto target_build = get_value(metadata, "post-build-incremental");
+  if (!target_build.empty()) {
+    log_buffer->push_back("target_build: " + target_build);
+  }
+}
+
+// Checks the build version, fingerprint and timestamp in the metadata of the A/B package.
+// Downgrading is not allowed unless explicitly enabled in the package and only for
+// incremental packages.
+static int CheckAbSpecificMetadata(const std::map<std::string, std::string>& metadata) {
+  // Incremental updates should match the current build.
+  auto device_pre_build = android::base::GetProperty("ro.build.version.incremental", "");
+  auto pkg_pre_build = get_value(metadata, "pre-build-incremental");
+  if (!pkg_pre_build.empty() && pkg_pre_build != device_pre_build) {
+    LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected "
+               << device_pre_build;
+    return INSTALL_ERROR;
+  }
+
+  auto device_fingerprint = android::base::GetProperty("ro.build.fingerprint", "");
+  auto pkg_pre_build_fingerprint = get_value(metadata, "pre-build");
+  if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != device_fingerprint) {
+    LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint << " but expected "
+               << device_fingerprint;
+    return INSTALL_ERROR;
+  }
+
+  // Check for downgrade version.
+  // int64_t build_timestamp =
+      // android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max());
+  // int64_t pkg_post_timestamp = 0;
+  // We allow to full update to the same version we are running, in case there
+  // is a problem with the current copy of that version.
+  auto pkg_post_timestamp_string = get_value(metadata, "post-timestamp");
+  // if (pkg_post_timestamp_string.empty() ||
+  //     !android::base::ParseInt(pkg_post_timestamp_string, &pkg_post_timestamp) ||
+  //     pkg_post_timestamp < build_timestamp) {
+  //   if (get_value(metadata, "ota-downgrade") != "yes") {
+  //     LOG(ERROR) << "Update package is older than the current build, expected a build "
+  //                   "newer than timestamp "
+  //                << build_timestamp << " but package has timestamp " << pkg_post_timestamp
+  //                << " and downgrade not allowed.";
+  //     return INSTALL_ERROR;
+  //   }
+  //   if (pkg_pre_build_fingerprint.empty()) {
+  //     LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed.";
+  //     return INSTALL_ERROR;
+  //   }
+  // }
+
+  return 0;
+}
+
+int CheckPackageMetadata(const std::map<std::string, std::string>& metadata, OtaType ota_type) {
+  auto package_ota_type = get_value(metadata, "ota-type");
+  auto expected_ota_type = OtaTypeToString(ota_type);
+  if (ota_type != OtaType::AB && ota_type != OtaType::BRICK) {
+    LOG(INFO) << "Skip package metadata check for ota type " << expected_ota_type;
+    return 0;
+  }
+
+  if (package_ota_type != expected_ota_type) {
+    LOG(ERROR) << "Unexpected ota package type, expects " << expected_ota_type << ", actual "
+               << package_ota_type;
+    return INSTALL_ERROR;
+  }
+
+  auto device = android::base::GetProperty("ro.product.device", "");
+  auto pkg_device = get_value(metadata, "pre-device");
+  if (pkg_device != device || pkg_device.empty()) {
+    LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << device;
+    return INSTALL_ERROR;
+  }
+
+  // We allow the package to not have any serialno; and we also allow it to carry multiple serial
+  // numbers split by "|"; e.g. serialno=serialno1|serialno2|serialno3 ... We will fail the
+  // verification if the device's serialno doesn't match any of these carried numbers.
+  auto pkg_serial_no = get_value(metadata, "serialno");
+  if (!pkg_serial_no.empty()) {
+    auto device_serial_no = android::base::GetProperty("ro.serialno", "");
+    bool serial_number_match = false;
+    for (const auto& number : android::base::Split(pkg_serial_no, "|")) {
+      if (device_serial_no == android::base::Trim(number)) {
+        serial_number_match = true;
+      }
+    }
+    if (!serial_number_match) {
+      LOG(ERROR) << "Package is for serial " << pkg_serial_no;
+      return INSTALL_ERROR;
+    }
+  }
+
+  if (ota_type == OtaType::AB) {
+    return CheckAbSpecificMetadata(metadata);
+  }
+
+  return 0;
+}
+
+int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd,
+                          std::vector<std::string>* cmd) {
+  CHECK(cmd != nullptr);
+
+  // For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset
+  // in the zip file.
+  static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
+  ZipString property_name(AB_OTA_PAYLOAD_PROPERTIES);
+  ZipEntry properties_entry;
+  if (FindEntry(zip, property_name, &properties_entry) != 0) {
+    LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD_PROPERTIES;
+    return INSTALL_CORRUPT;
+  }
+  uint32_t properties_entry_length = properties_entry.uncompressed_length;
+  std::vector<uint8_t> payload_properties(properties_entry_length);
+  int32_t err =
+      ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length);
+  if (err != 0) {
+    LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES << ": " << ErrorCodeString(err);
+    return INSTALL_CORRUPT;
+  }
+
+  static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
+  ZipString payload_name(AB_OTA_PAYLOAD);
+  ZipEntry payload_entry;
+  if (FindEntry(zip, payload_name, &payload_entry) != 0) {
+    LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD;
+    return INSTALL_CORRUPT;
+  }
+  long payload_offset = payload_entry.offset;
+  *cmd = {
+    "/system/bin/update_engine_sideload",
+    "--payload=file://" + package,
+    android::base::StringPrintf("--offset=%ld", payload_offset),
+    "--headers=" + std::string(payload_properties.begin(), payload_properties.end()),
+    android::base::StringPrintf("--status_fd=%d", status_fd),
+  };
+  return 0;
+}
+
+int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int retry_count,
+                             int status_fd, std::vector<std::string>* cmd) {
+  CHECK(cmd != nullptr);
+
+  // In non-A/B updates we extract the update binary from the package.
+  ZipString binary_name(UPDATE_BINARY_NAME);
+  ZipEntry binary_entry;
+  if (FindEntry(zip, binary_name, &binary_entry) != 0) {
+    LOG(ERROR) << "Failed to find update binary " << UPDATE_BINARY_NAME;
+    return INSTALL_CORRUPT;
+  }
+
+  LOG(ERROR) << "SetupNonAbUpdateCommands::here1";
+  const std::string binary_path = Paths::Get().temporary_update_binary();
+  unlink(binary_path.c_str());
+  LOG(ERROR) << "SetupNonAbUpdateCommands::here2";
+  android::base::unique_fd fd(
+      open(binary_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755));
+  if (fd == -1) {
+    PLOG(ERROR) << "Failed to create " << binary_path;
+    return INSTALL_ERROR;
+  }
+  LOG(ERROR) << "SetupNonAbUpdateCommands::here3";
+
+  int32_t error = ExtractEntryToFile(zip, &binary_entry, fd);
+  if (error != 0) {
+    LOG(ERROR) << "Failed to extract " << UPDATE_BINARY_NAME << ": " << ErrorCodeString(error);
+    return INSTALL_ERROR;
+  }
+  LOG(ERROR) << "SetupNonAbUpdateCommands::here4";
+
+  // When executing the update binary contained in the package, the arguments passed are:
+  //   - the version number for this interface
+  //   - an FD to which the program can write in order to update the progress bar.
+  //   - the name of the package zip file.
+  //   - an optional argument "retry" if this update is a retry of a failed update attempt.
+  *cmd = {
+    binary_path,
+    std::to_string(kRecoveryApiVersion),
+    std::to_string(status_fd),
+    package,
+  };
+  if (retry_count > 0) {
+    cmd->push_back("retry");
+  }
+  return 0;
+}
+
+static void log_max_temperature(int* max_temperature, const std::atomic<bool>& logger_finished) {
+  CHECK(max_temperature != nullptr);
+  std::mutex mtx;
+  std::unique_lock<std::mutex> lck(mtx);
+  while (!logger_finished.load() &&
+         finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
+    *max_temperature = std::max(*max_temperature, GetMaxValueFromThermalZone());
+  }
+}
+
+// If the package contains an update binary, extract it and run it.
+static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
+                             std::vector<std::string>* log_buffer, int retry_count,
+                             int* max_temperature) {
+  std::map<std::string, std::string> metadata;
+
+  if (!ReadMetadataFromPackage(zip, &metadata)) {
+    LOG(ERROR) << "Failed to parse metadata in the zip file";
+    // return INSTALL_CORRUPT;
+  }
+
+  bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false);
+  // Verifies against the metadata in the package first.
+  // if (int check_status = is_ab ? CheckPackageMetadata(metadata, OtaType::AB) : 0;
+  //     check_status != 0) {
+  //   log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
+    // return check_status;
+  // }
+
+  ReadSourceTargetBuild(metadata, log_buffer);
+  LOG(ERROR) << "try_update_binary::here1";
+  // The updater in child process writes to the pipe to communicate with recovery.
+  android::base::unique_fd pipe_read, pipe_write;
+  // Explicitly disable O_CLOEXEC using 0 as the flags (last) parameter to Pipe
+  // so that the child updater process will recieve a non-closed fd.
+  if (!android::base::Pipe(&pipe_read, &pipe_write, 0)) {
+    PLOG(ERROR) << "Failed to create pipe for updater-recovery communication";
+    return INSTALL_CORRUPT;
+  }
+
+  // The updater-recovery communication protocol.
+  //
+  //   progress <frac> <secs>
+  //       fill up the next <frac> part of of the progress bar over <secs> seconds. If <secs> is
+  //       zero, use `set_progress` commands to manually control the progress of this segment of the
+  //       bar.
+  //
+  //   set_progress <frac>
+  //       <frac> should be between 0.0 and 1.0; sets the progress bar within the segment defined by
+  //       the most recent progress command.
+  //
+  //   ui_print <string>
+  //       display <string> on the screen.
+  //
+  //   wipe_cache
+  //       a wipe of cache will be performed following a successful installation.
+  //
+  //   clear_display
+  //       turn off the text display.
+  //
+  //   enable_reboot
+  //       packages can explicitly request that they want the user to be able to reboot during
+  //       installation (useful for debugging packages that don't exit).
+  //
+  //   retry_update
+  //       updater encounters some issue during the update. It requests a reboot to retry the same
+  //       package automatically.
+  //
+  //   log <string>
+  //       updater requests logging the string (e.g. cause of the failure).
+  //
+
+  std::vector<std::string> args;
+
+  is_ab = false;
+  ZipString binary_name(UPDATE_BINARY_NAME);
+  ZipEntry binary_entry;
+  if (FindEntry(zip, binary_name, &binary_entry) != 0) {
+    LOG(ERROR) << "Failed to find update binary " << UPDATE_BINARY_NAME;
+    is_ab = true;
+  }
+
+  if (int update_status =
+          is_ab ? SetUpAbUpdateCommands(package, zip, pipe_write.get(), &args)
+                : SetUpNonAbUpdateCommands(package, zip, retry_count, pipe_write.get(), &args);
+      update_status != 0) {
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
+    // return update_status;
+  }
+
+  pid_t pid = fork();
+  if (pid == -1) {
+    PLOG(ERROR) << "Failed to fork update binary";
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kForkUpdateBinaryFailure));
+    return INSTALL_ERROR;
+  }
+
+  if (pid == 0) {
+    umask(022);
+    pipe_read.reset();
+
+    // Convert the std::string vector to a NULL-terminated char* vector suitable for execv.
+    auto chr_args = StringVectorToNullTerminatedArray(args);
+    execv(chr_args[0], chr_args.data());
+    // We shouldn't use LOG/PLOG in the forked process, since they may cause the child process to
+    // hang. This deadlock results from an improperly copied mutex in the ui functions.
+    // (Bug: 34769056)
+    fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
+    _exit(EXIT_FAILURE);
+  }
+  pipe_write.reset();
+
+  std::atomic<bool> logger_finished(false);
+  std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
+
+  *wipe_cache = false;
+  bool retry_update = false;
+
+  char buffer[1024];
+  FILE* from_child = android::base::Fdopen(std::move(pipe_read), "r");
+  while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
+    std::string line(buffer);
+    size_t space = line.find_first_of(" \n");
+    std::string command(line.substr(0, space));
+    if (command.empty()) continue;
+
+    // Get rid of the leading and trailing space and/or newline.
+    std::string args = space == std::string::npos ? "" : android::base::Trim(line.substr(space));
+
+    if (command == "progress") {
+      std::vector<std::string> tokens = android::base::Split(args, " ");
+      double fraction;
+      int seconds;
+      if (tokens.size() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) &&
+          android::base::ParseInt(tokens[1], &seconds)) {
+        // ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
+      } else {
+        LOG(ERROR) << "invalid \"progress\" parameters: " << line;
+      }
+    } else if (command == "set_progress") {
+      std::vector<std::string> tokens = android::base::Split(args, " ");
+      double fraction;
+      if (tokens.size() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) {
+        // ui->SetProgress(fraction);
+      } else {
+        LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
+      }
+    } else if (command == "ui_print") {
+      // ui->PrintOnScreenOnly("%s\n", args.c_str());
+      fflush(stdout);
+    } else if (command == "wipe_cache") {
+      *wipe_cache = true;
+    } else if (command == "clear_display") {
+      // ui->SetBackground(RecoveryUI::NONE);
+    } else if (command == "enable_reboot") {
+      // packages can explicitly request that they want the user
+      // to be able to reboot during installation (useful for
+      // debugging packages that don't exit).
+      // ui->SetEnableReboot(true);
+    } else if (command == "retry_update") {
+      retry_update = true;
+    } else if (command == "log") {
+      if (!args.empty()) {
+        // Save the logging request from updater and write to last_install later.
+        log_buffer->push_back(args);
+      } else {
+        LOG(ERROR) << "invalid \"log\" parameters: " << line;
+      }
+    } else {
+      LOG(ERROR) << "unknown command [" << command << "]";
+    }
+  }
+  fclose(from_child);
+
+  int status;
+  waitpid(pid, &status, 0);
+
+  logger_finished.store(true);
+  finish_log_temperature.notify_one();
+  temperature_logger.join();
+
+  if (retry_update) {
+    return INSTALL_RETRY;
+  }
+  if (WIFEXITED(status)) {
+    if (WEXITSTATUS(status) != EXIT_SUCCESS) {
+      LOG(ERROR) << "Error in " << package << " (status " << WEXITSTATUS(status) << ")";
+      return INSTALL_ERROR;
+    }
+  } else if (WIFSIGNALED(status)) {
+    LOG(ERROR) << "Error in " << package << " (killed by signal " << WTERMSIG(status) << ")";
+    return INSTALL_ERROR;
+  } else {
+    LOG(FATAL) << "Invalid status code " << status;
+  }
+
+  return INSTALL_SUCCESS;
+}
+
+// Verifes the compatibility info in a Treble-compatible package. Returns true directly if the
+// entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA
+// package.
+// bool verify_package_compatibility(ZipArchiveHandle package_zip __unused) {
+//   LOG(INFO) << "Verifying package compatibility...";
+
+//   static constexpr const char* COMPATIBILITY_ZIP_ENTRY = "compatibility.zip";
+//   ZipString compatibility_entry_name(COMPATIBILITY_ZIP_ENTRY);
+//   ZipEntry compatibility_entry;
+//   if (FindEntry(package_zip, compatibility_entry_name, &compatibility_entry) != 0) {
+//     LOG(INFO) << "Package doesn't contain " << COMPATIBILITY_ZIP_ENTRY << " entry";
+//     return true;
+//   }
+
+//   std::string zip_content(compatibility_entry.uncompressed_length, '\0');
+//   int32_t ret;
+//   if ((ret = ExtractToMemory(package_zip, &compatibility_entry,
+//                              reinterpret_cast<uint8_t*>(&zip_content[0]),
+//                              compatibility_entry.uncompressed_length)) != 0) {
+//     LOG(ERROR) << "Failed to read " << COMPATIBILITY_ZIP_ENTRY << ": " << ErrorCodeString(ret);
+//     return false;
+//   }
+
+//   ZipArchiveHandle zip_handle;
+//   ret = OpenArchiveFromMemory(static_cast<void*>(const_cast<char*>(zip_content.data())),
+//                               zip_content.size(), COMPATIBILITY_ZIP_ENTRY, &zip_handle);
+//   if (ret != 0) {
+//     LOG(ERROR) << "Failed to OpenArchiveFromMemory: " << ErrorCodeString(ret);
+//     return false;
+//   }
+
+//   // Iterate all the entries inside COMPATIBILITY_ZIP_ENTRY and read the contents.
+//   void* cookie;
+//   ret = StartIteration(zip_handle, &cookie, nullptr, nullptr);
+//   if (ret != 0) {
+//     LOG(ERROR) << "Failed to start iterating zip entries: " << ErrorCodeString(ret);
+//     CloseArchive(zip_handle);
+//     return false;
+//   }
+//   std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration);
+
+//   std::vector<std::string> compatibility_info;
+//   ZipEntry info_entry;
+//   ZipString info_name;
+//   while (Next(cookie, &info_entry, &info_name) == 0) {
+//     std::string content(info_entry.uncompressed_length, '\0');
+//     int32_t ret = ExtractToMemory(zip_handle, &info_entry, reinterpret_cast<uint8_t*>(&content[0]),
+//                                   info_entry.uncompressed_length);
+//     if (ret != 0) {
+//       LOG(ERROR) << "Failed to read " << info_name.name << ": " << ErrorCodeString(ret);
+//       CloseArchive(zip_handle);
+//       return false;
+//     }
+//     compatibility_info.emplace_back(std::move(content));
+//   }
+//   CloseArchive(zip_handle);
+
+//   // VintfObjectRecovery::CheckCompatibility returns zero on success.
+//   std::string err;
+//   int result = android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err);
+//   if (result == 0) {
+//     return true;
+//   }
+
+//   LOG(ERROR) << "Failed to verify package compatibility (result " << result << "): " << err;
+//   return false;
+// }
+
+static int really_install_package(const std::string& path, bool* wipe_cache __unused, bool needs_mount __unused,
+                                  std::vector<std::string>* log_buffer __unused, int retry_count __unused,
+                                  int* max_temperature __unused) {
+  // ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
+  // ui->Print("Finding update package...\n");
+  // Give verification half the progress bar...
+  // ui->SetProgressType(RecoveryUI::DETERMINATE);
+  // ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
+  LOG(INFO) << "Update location: " << path;
+
+  // Map the update package into memory.
+  // ui->Print("Opening update package...\n");
+  if (needs_mount) {
+    if (path[0] == '@') {
+      ensure_path_mounted(path.substr(1));
+    } else {
+      ensure_path_mounted(path);
+    }
+  }
+
+  auto package = Package::CreateMemoryPackage(
+      path);
+  if (!package) {
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kMapFileFailure));
+    return INSTALL_CORRUPT;
+  }
+
+  // Verify package.
+  if (!verify_package(package.get())) {
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
+    return INSTALL_CORRUPT;
+  }
+
+  // Try to open the package.
+  ZipArchiveHandle zip = package->GetZipArchiveHandle();
+  if (!zip) {
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
+    return INSTALL_CORRUPT;
+  }
+  LOG(ERROR) << "really_install_package::here1";
+
+  // Additionally verify the compatibility of the package if it's a fresh install.
+  if (retry_count == 0 && !verify_package_compatibility(zip)) {
+    log_buffer->push_back(android::base::StringPrintf("error: %d", kPackageCompatibilityFailure));
+    return INSTALL_CORRUPT;
+  }
+
+  // Verify and install the contents of the package.
+  // ui->Print("Installing update...\n");
+  // if (retry_count > 0) {
+    // ui->Print("Retry attempt: %d\n", retry_count);
+  // }
+  // ui->SetEnableReboot(false);
+  LOG(ERROR) << "really_install_package::here2";
+  int result =
+      try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature);
+  // ui->SetEnableReboot(true);
+  // ui->Print("\n");
+  return result;
+}
+
+int install_package(const std::string& path, bool should_wipe_cache, bool needs_mount,
+                    int retry_count) {
+  CHECK(!path.empty());
+
+  auto start = std::chrono::system_clock::now();
+
+  int start_temperature = GetMaxValueFromThermalZone();
+  int max_temperature = start_temperature;
+
+  int result;
+  std::vector<std::string> log_buffer;
+  // if (setup_install_mounts() != 0) {
+  //   LOG(ERROR) << "failed to set up expected mounts for install; aborting";
+  //   result = INSTALL_ERROR;
+  // } else {
+    bool updater_wipe_cache = false;
+    result = really_install_package(path, &updater_wipe_cache, needs_mount, &log_buffer,
+                                    retry_count, &max_temperature);
+    should_wipe_cache = should_wipe_cache || updater_wipe_cache;
+  // }
+
+  // Measure the time spent to apply OTA update in seconds.
+  std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
+  int time_total = static_cast<int>(duration.count());
+
+  bool has_cache = volume_for_mount_point("/cache") != nullptr;
+  // Skip logging the uncrypt_status on devices without /cache.
+  if (has_cache) {
+    static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
+    if (ensure_path_mounted(UNCRYPT_STATUS) != 0) {
+      LOG(WARNING) << "Can't mount " << UNCRYPT_STATUS;
+    } else {
+      std::string uncrypt_status;
+      if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) {
+        PLOG(WARNING) << "failed to read uncrypt status";
+      } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) {
+        LOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status;
+      } else {
+        log_buffer.push_back(android::base::Trim(uncrypt_status));
+      }
+    }
+  }
+
+  // The first two lines need to be the package name and install result.
+  std::vector<std::string> log_header = {
+    path,
+    result == INSTALL_SUCCESS ? "1" : "0",
+    "time_total: " + std::to_string(time_total),
+    "retry: " + std::to_string(retry_count),
+  };
+
+  int end_temperature = GetMaxValueFromThermalZone();
+  max_temperature = std::max(end_temperature, max_temperature);
+  if (start_temperature > 0) {
+    log_buffer.push_back("temperature_start: " + std::to_string(start_temperature));
+  }
+  if (end_temperature > 0) {
+    log_buffer.push_back("temperature_end: " + std::to_string(end_temperature));
+  }
+  if (max_temperature > 0) {
+    log_buffer.push_back("temperature_max: " + std::to_string(max_temperature));
+  }
+
+  std::string log_content =
+      android::base::Join(log_header, "\n") + "\n" + android::base::Join(log_buffer, "\n") + "\n";
+  const std::string& install_file = Paths::Get().temporary_install_file();
+  if (!android::base::WriteStringToFile(log_content, install_file)) {
+    PLOG(ERROR) << "failed to write " << install_file;
+  }
+
+  // Write a copy into last_log.
+  LOG(INFO) << log_content;
+
+  if (result == INSTALL_SUCCESS && should_wipe_cache) {
+    if (!WipeCache(nullptr)) {
+      result = INSTALL_ERROR;
+    }
+  }
+
+  return result;
+}
+
+bool verify_package(Package* package) {
+  static constexpr const char* CERTIFICATE_ZIP_FILE = "/system/etc/security/otacerts.zip";
+  std::vector<Certificate> loaded_keys = LoadKeysFromZipfile(CERTIFICATE_ZIP_FILE);
+  if (loaded_keys.empty()) {
+    LOG(ERROR) << "Failed to load keys";
+    return false;
+  }
+  LOG(INFO) << loaded_keys.size() << " key(s) loaded from " << CERTIFICATE_ZIP_FILE;
+
+  // Verify package.
+  // ui->Print("Verifying update package...\n");
+  // auto t0 = std::chrono::system_clock::now();
+  int err = verify_file(package, loaded_keys);
+  // if(err != VERIFY_SUCCESS) {
+
+  // }
+  // std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
+  // ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
+  if (err != VERIFY_SUCCESS) {
+    LOG(ERROR) << "Signature verification failed";
+    LOG(ERROR) << "error: " << kZipVerificationFailure;
+  //   return false;
+  }
+  return true;
+}
diff --git a/install/installcommand.cpp b/twrpinstall/installcommand.cpp
similarity index 81%
rename from install/installcommand.cpp
rename to twrpinstall/installcommand.cpp
index ee93484..a03cb01 100755
--- a/install/installcommand.cpp
+++ b/twrpinstall/installcommand.cpp
@@ -29,16 +29,9 @@
 
 #include "common.h"
 #include "installcommand.h"
-#include "zipwrap.hpp"
-#ifndef USE_MINZIP
 #include <ziparchive/zip_archive.h>
 #include <vintf/VintfObjectRecovery.h>
-#endif
-#ifdef USE_OLD_VERIFIER
-#include "verifier24/verifier.h"
-#else
-#include "install/install.h"
-#endif
+#include "twinstall/install.h"
 
 #ifdef AB_OTA_UPDATER
 
@@ -61,21 +54,29 @@
     return -1;
 }
 
-bool read_metadata_from_package(ZipWrap* zip, std::string* meta_data) {
-    long size = zip->GetUncompressedSize(METADATA_PATH);
-    if (size <= 0)
-		return false;
+bool read_metadata_from_package(ZipArchiveHandle zip, std::string* meta_data) {
+    ZipString binary_name(METADATA_PATH);
+    ZipEntry binary_entry;
+    if (FindEntry(zip, binary_name, &binary_entry) == 0) {
+        long size = binary_entry.uncompressed_length;
+        if (size <= 0)
+            return false;
 
-    meta_data->resize(size, '\0');
-    if (!zip->ExtractToBuffer(METADATA_PATH, reinterpret_cast<uint8_t*>(&(*meta_data)[0]))) {
-        printf("Failed to read metadata in update package.\n");
-        return false;
-    }
-    return true;
+        meta_data->resize(size, '\0');
+        int32_t ret = ExtractToMemory(zip, &binary_entry, reinterpret_cast<uint8_t*>(&(*meta_data)[0]),
+                                  size);
+        if (ret != 0) {
+            printf("Failed to read metadata in update package.\n");
+            CloseArchive(zip);
+            return false;
+        }
+        return true;
+      }
+      return false;
 }
 
 // Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
-void read_source_target_build(ZipWrap* zip/*, std::vector<std::string>& log_buffer*/) {
+void read_source_target_build(ZipArchiveHandle zip/*, std::vector<std::string>& log_buffer*/) {
     std::string meta_data;
     if (!read_metadata_from_package(zip, &meta_data)) {
         return;
@@ -107,7 +108,7 @@
 // Parses the metadata of the OTA package in |zip| and checks whether we are
 // allowed to accept this A/B package. Downgrading is not allowed unless
 // explicitly enabled in the package and only for incremental packages.
-static int check_newer_ab_build(ZipWrap* zip)
+static int check_newer_ab_build(ZipArchiveHandle zip)
 {
     std::string metadata_str;
     if (!read_metadata_from_package(zip, &metadata_str)) {
@@ -183,33 +184,48 @@
 }
 
 int
-abupdate_binary_command(const char* path, ZipWrap* zip, int retry_count __unused,
+abupdate_binary_command(const char* path, int retry_count __unused,
                       int status_fd, std::vector<std::string>* cmd)
 {
-    read_source_target_build(zip);
-    int ret = check_newer_ab_build(zip);
+    auto package = Package::CreateMemoryPackage(path);
+	if (!package) {
+		return INSTALL_CORRUPT;
+	}
+
+	ZipArchiveHandle Zip = package->GetZipArchiveHandle();
+    read_source_target_build(Zip);
+    int ret = check_newer_ab_build(Zip);
     if (ret) {
         return ret;
     }
 
     // For A/B updates we extract the payload properties to a buffer and obtain
     // the RAW payload offset in the zip file.
-    if (!zip->EntryExists(AB_OTA_PAYLOAD_PROPERTIES)) {
+    // if (!Zip->EntryExists(AB_OTA_PAYLOAD_PROPERTIES)) {
+	ZipString binary_name(AB_OTA_PAYLOAD_PROPERTIES);
+    ZipEntry binary_entry;
+    if (FindEntry(Zip, binary_name, &binary_entry) != 0) {
         printf("Can't find %s\n", AB_OTA_PAYLOAD_PROPERTIES);
         return INSTALL_CORRUPT;
     }
     std::vector<unsigned char> payload_properties(
-            zip->GetUncompressedSize(AB_OTA_PAYLOAD_PROPERTIES));
-    if (!zip->ExtractToBuffer(AB_OTA_PAYLOAD_PROPERTIES, payload_properties.data())) {
+            binary_entry.uncompressed_length);
+    int32_t extract_ret = ExtractToMemory(Zip, &binary_entry, reinterpret_cast<uint8_t*>(payload_properties.data()),
+                                  binary_entry.uncompressed_length);
+    if (extract_ret != 0) {
         printf("Can't extract %s\n", AB_OTA_PAYLOAD_PROPERTIES);
-        return INSTALL_CORRUPT;
+        CloseArchive(Zip);
+        return false;
     }
 
-    if (!zip->EntryExists(AB_OTA_PAYLOAD)) {
+    ZipString ab_ota_payload(AB_OTA_PAYLOAD);
+    ZipEntry ab_ota_payload_entry;
+    if (FindEntry(Zip, ab_ota_payload, &ab_ota_payload_entry) != 0) {
         printf("Can't find %s\n", AB_OTA_PAYLOAD);
         return INSTALL_CORRUPT;
     }
-    long payload_offset = zip->GetEntryOffset(AB_OTA_PAYLOAD);
+    // long payload_offset = Zip->GetEntryOffset(AB_OTA_PAYLOAD);
+    long payload_offset = ab_ota_payload_entry.offset;
     *cmd = {
         "/system/bin/update_engine_sideload",
         android::base::StringPrintf("--payload=file://%s", path),
@@ -223,10 +239,10 @@
 
 #else
 
-void read_source_target_build(ZipWrap* zip __unused /*, std::vector<std::string>& log_buffer*/) {return;}
+void read_source_target_build(ZipArchiveHandle zip __unused /*, std::vector<std::string>& log_buffer*/) {return;}
 
 int
-abupdate_binary_command(__unused const char* path, __unused ZipWrap* zip, __unused int retry_count,
+abupdate_binary_command(__unused const char* path, __unused int retry_count,
                       __unused int status_fd, __unused std::vector<std::string>* cmd)
 {
     printf("No support for AB OTA zips included\n");
@@ -256,31 +272,23 @@
     return 0;
 }
 
-#ifdef USE_MINZIP
-bool verify_package_compatibility(ZipWrap *package_zip) {
-  if (package_zip->EntryExists("compatibility.zip"))
-    printf("Cannot verify treble package compatibility, must build TWRP in Oreo tree or higher.\n");
-  return true;
-}
-#else
 // Verifes the compatibility info in a Treble-compatible package. Returns true directly if the
 // entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA
 // package.
-bool verify_package_compatibility(ZipWrap *zw) {
-  ZipArchiveHandle package_zip = zw->GetZipArchiveHandle();
+bool verify_package_compatibility(ZipArchiveHandle zw) {
   printf("Verifying package compatibility...\n");
 
   static constexpr const char* COMPATIBILITY_ZIP_ENTRY = "compatibility.zip";
   ZipString compatibility_entry_name(COMPATIBILITY_ZIP_ENTRY);
   ZipEntry compatibility_entry;
-  if (FindEntry(package_zip, compatibility_entry_name, &compatibility_entry) != 0) {
+  if (FindEntry(zw, compatibility_entry_name, &compatibility_entry) != 0) {
     printf("Package doesn't contain %s entry\n", COMPATIBILITY_ZIP_ENTRY);
     return true;
   }
 
   std::string zip_content(compatibility_entry.uncompressed_length, '\0');
   int32_t ret;
-  if ((ret = ExtractToMemory(package_zip, &compatibility_entry,
+  if ((ret = ExtractToMemory(zw, &compatibility_entry,
                              reinterpret_cast<uint8_t*>(&zip_content[0]),
                              compatibility_entry.uncompressed_length)) != 0) {
     printf("Failed to read %s: %s\n", COMPATIBILITY_ZIP_ENTRY, ErrorCodeString(ret));
@@ -331,4 +339,3 @@
   printf("Failed to verify package compatibility (result %i): %s\n", result, err.c_str());
   return false;
 }
-#endif
diff --git a/twrpinstall/legacy_property_service.cpp b/twrpinstall/legacy_property_service.cpp
new file mode 100644
index 0000000..c3990f7
--- /dev/null
+++ b/twrpinstall/legacy_property_service.cpp
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <dirent.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "../../bionic/libc/private/bionic_futex.h"
+
+#include <cutils/properties.h>
+
+#include "legacy_properties.h"
+
+#include <sys/mman.h>
+// Not available in 5.0
+//#include <sys/atomics.h>
+#include "legacy_property_service.h"
+
+#ifndef INT32_MAX
+#define INT32_MAX	(2147483647)
+#endif
+
+static int property_area_inited = 0;
+
+typedef struct {
+    void *data;
+    size_t size;
+    int fd;
+} workspace;
+
+static int init_workspace(workspace *w, size_t size)
+{
+    void *data;
+    int fd;
+
+        /* dev is a tmpfs that we can use to carve a shared workspace
+         * out of, so let's do that...
+         */
+    fd = open("/dev/__legacy_properties__", O_RDWR | O_CREAT, 0600);
+    if (fd < 0)
+        return -1;
+
+    if (ftruncate(fd, size) < 0)
+        goto out;
+
+    data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+    if(data == MAP_FAILED)
+        goto out;
+
+    close(fd);
+
+    fd = open("/dev/__legacy_properties__", O_RDONLY);
+    if (fd < 0)
+        return -1;
+
+    unlink("/dev/__legacy_properties__");
+
+    w->data = data;
+    w->size = size;
+    w->fd = fd;
+    return 0;
+
+out:
+    close(fd);
+    return -1;
+}
+
+/* (8 header words + 247 toc words) = 1020 bytes */
+/* 1024 bytes header and toc + 247 prop_infos @ 128 bytes = 32640 bytes */
+
+#define PA_COUNT_MAX  247
+#define PA_INFO_START 1024
+#define PA_SIZE       32768
+
+static workspace pa_workspace;
+static prop_info *pa_info_array;
+
+prop_area *__legacy_property_area__;
+
+static int init_property_area(void)
+{
+    prop_area *pa;
+
+    if(pa_info_array)
+        return -1;
+
+    if(init_workspace(&pa_workspace, PA_SIZE))
+        return -1;
+
+    fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC);
+
+    pa_info_array = (prop_info*) (((char*) pa_workspace.data) + PA_INFO_START);
+
+    pa = (prop_area*)(pa_workspace.data);
+    memset(pa, 0, PA_SIZE);
+    pa->magic = PROP_AREA_MAGIC;
+    pa->version = PROP_AREA_VERSION;
+
+    /* plug into the lib property services */
+    __legacy_property_area__ = pa;
+    property_area_inited = 1;
+    return 0;
+}
+
+static void update_prop_info(prop_info *pi, const char *value, unsigned len)
+{
+    pi->serial = pi->serial | 1;
+    memcpy(pi->value, value, len + 1);
+    pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff);
+    __futex_wake(&pi->serial, INT32_MAX);
+}
+
+static const prop_info *__legacy_property_find(const char *name)
+{
+    prop_area *pa = __legacy_property_area__;
+    unsigned count = pa->count;
+    unsigned *toc = pa->toc;
+    unsigned len = strlen(name);
+    prop_info *pi;
+
+    while(count--) {
+        unsigned entry = *toc++;
+        if(TOC_NAME_LEN(entry) != len) continue;
+
+        pi = TOC_TO_INFO(pa, entry);
+        if(memcmp(name, pi->name, len)) continue;
+
+        return pi;
+    }
+
+    return 0;
+}
+
+static int legacy_property_set(const char *name, const char *value)
+{
+    prop_area *pa;
+    prop_info *pi;
+
+    int namelen = strlen(name);
+    int valuelen = strlen(value);
+
+    if(namelen >= PROP_NAME_MAX) return -1;
+    if(valuelen >= PROP_VALUE_MAX) return -1;
+    if(namelen < 1) return -1;
+
+    pi = (prop_info*) __legacy_property_find(name);
+
+
+    if(pi != 0) {
+        /* ro.* properties may NEVER be modified once set */
+        if(!strncmp(name, "ro.", 3)) return -1;
+
+        pa = __legacy_property_area__;
+        update_prop_info(pi, value, valuelen);
+        pa->serial++;
+        __futex_wake(&pa->serial, INT32_MAX);
+    } else {
+        pa = __legacy_property_area__;
+        if(pa->count == PA_COUNT_MAX) return -1;
+
+        pi = pa_info_array + pa->count;
+        pi->serial = (valuelen << 24);
+        memcpy(pi->name, name, namelen + 1);
+        memcpy(pi->value, value, valuelen + 1);
+
+        pa->toc[pa->count] =
+            (namelen << 24) | (((unsigned long) pi) - ((unsigned long) pa));
+
+        pa->count++;
+        pa->serial++;
+        __futex_wake(&pa->serial, INT32_MAX);
+    }
+
+    return 0;
+}
+
+void legacy_get_property_workspace(int *fd, int *sz)
+{
+    *fd = pa_workspace.fd;
+    *sz = pa_workspace.size;
+}
+
+static void copy_property_to_legacy(const char *key, const char *value, void *cookie __unused)
+{
+    legacy_property_set(key, value);
+}
+
+int legacy_properties_init()
+{
+    if(init_property_area() != 0)
+        return -1;
+
+    if(property_list(copy_property_to_legacy, 0) != 0)
+        return -1;
+
+    return 0;
+}
diff --git a/twrpinstall/package.cpp b/twrpinstall/package.cpp
new file mode 100755
index 0000000..ba1d5df
--- /dev/null
+++ b/twrpinstall/package.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "twinstall/package.h"
+
+#include <string.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+
+#include "otautil/error_code.h"
+#include "otautil/sysutil.h"
+
+// This class wraps the package in memory, i.e. a memory mapped package, or a package loaded
+// to a string/vector.
+class MemoryPackage : public Package {
+ public:
+  // Constructs the class from a file. We will memory maps the file later.
+  MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map);
+
+  // Constructs the class from the package bytes in |content|.
+  MemoryPackage(std::vector<uint8_t> content);
+
+  ~MemoryPackage() override;
+
+  // Memory maps the package file if necessary. Initializes the start address and size of the
+  // package.
+  uint64_t GetPackageSize() const override {
+    return package_size_;
+  }
+
+  bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
+
+  ZipArchiveHandle GetZipArchiveHandle() override;
+
+  bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
+                          uint64_t length) override;
+
+ private:
+  const uint8_t* addr_;    // Start address of the package in memory.
+  uint64_t package_size_;  // Package size in bytes.
+
+  // The memory mapped package.
+  std::unique_ptr<MemMapping> map_;
+  // A copy of the package content, valid only if we create the class with the exact bytes of
+  // the package.
+  std::vector<uint8_t> package_content_;
+  // The physical path to the package, empty if we create the class with the package content.
+  std::string path_;
+
+  // The ZipArchiveHandle of the package.
+  ZipArchiveHandle zip_handle_;
+};
+
+void Package::SetProgress(float progress) {
+  if (set_progress_) {
+    set_progress_(progress);
+  }
+}
+
+class FilePackage : public Package {
+ public:
+  FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
+              const std::function<void(float)>& set_progress);
+
+  ~FilePackage() override;
+
+  uint64_t GetPackageSize() const override {
+    return package_size_;
+  }
+
+  bool ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) override;
+
+  ZipArchiveHandle GetZipArchiveHandle() override;
+
+  bool UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers, uint64_t start,
+                          uint64_t length) override;
+
+ private:
+  android::base::unique_fd fd_;  // The underlying fd to the open package.
+  uint64_t package_size_;
+  std::string path_;  // The physical path to the package.
+
+  ZipArchiveHandle zip_handle_;
+};
+
+std::unique_ptr<Package> Package::CreateMemoryPackage(
+    const std::string& path) {
+  std::unique_ptr<MemMapping> mmap = std::make_unique<MemMapping>();
+  if (!mmap->MapFile(path)) {
+    LOG(ERROR) << "failed to map file";
+    return nullptr;
+  }
+
+  return std::make_unique<MemoryPackage>(path, std::move(mmap));
+}
+
+std::unique_ptr<Package> Package::CreateFilePackage(
+    const std::string& path, const std::function<void(float)>& set_progress) {
+  android::base::unique_fd fd(open(path.c_str(), O_RDONLY));
+  if (fd == -1) {
+    PLOG(ERROR) << "Failed to open " << path;
+    return nullptr;
+  }
+
+  off64_t file_size = lseek64(fd.get(), 0, SEEK_END);
+  if (file_size == -1) {
+    PLOG(ERROR) << "Failed to get the package size";
+    return nullptr;
+  }
+
+  return std::make_unique<FilePackage>(std::move(fd), file_size, path, set_progress);
+}
+
+std::unique_ptr<Package> Package::CreateMemoryPackage(
+    std::vector<uint8_t> content) {
+  return std::make_unique<MemoryPackage>(std::move(content));
+}
+
+MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map)
+    : map_(std::move(map)), path_(path), zip_handle_(nullptr) {
+  addr_ = map_->addr;
+  package_size_ = map_->length;
+}
+
+MemoryPackage::MemoryPackage(std::vector<uint8_t> content)
+    : package_content_(std::move(content)), zip_handle_(nullptr) {
+  CHECK(!package_content_.empty());
+  addr_ = package_content_.data();
+  package_size_ = package_content_.size();
+}
+
+MemoryPackage::~MemoryPackage() {
+  if (zip_handle_) {
+    CloseArchive(zip_handle_);
+  }
+}
+
+bool MemoryPackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
+  if (byte_count > package_size_ || offset > package_size_ - byte_count) {
+    LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
+               << ", total package_size: " << package_size_;
+    return false;
+  }
+  memcpy(buffer, addr_ + offset, byte_count);
+  return true;
+}
+
+bool MemoryPackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
+                                       uint64_t start, uint64_t length) {
+  if (length > package_size_ || start > package_size_ - length) {
+    LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
+               << ", total package_size: " << package_size_;
+    return false;
+  }
+
+  for (const auto& hasher : hashers) {
+    hasher(addr_ + start, length);
+  }
+  return true;
+}
+
+ZipArchiveHandle MemoryPackage::GetZipArchiveHandle() {
+  if (zip_handle_) {
+    return zip_handle_;
+  }
+
+  if (auto err = OpenArchiveFromMemory(const_cast<uint8_t*>(addr_), package_size_, path_.c_str(),
+                                       &zip_handle_);
+      err != 0) {
+    LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
+    return nullptr;
+  }
+
+  return zip_handle_;
+}
+
+FilePackage::FilePackage(android::base::unique_fd&& fd, uint64_t file_size, const std::string& path,
+                         const std::function<void(float)>& set_progress)
+    : fd_(std::move(fd)), package_size_(file_size), path_(path), zip_handle_(nullptr) {
+  set_progress_ = set_progress;
+}
+
+FilePackage::~FilePackage() {
+  if (zip_handle_) {
+    CloseArchive(zip_handle_);
+  }
+}
+
+bool FilePackage::ReadFullyAtOffset(uint8_t* buffer, uint64_t byte_count, uint64_t offset) {
+  if (byte_count > package_size_ || offset > package_size_ - byte_count) {
+    LOG(ERROR) << "Out of bound read, offset: " << offset << ", size: " << byte_count
+               << ", total package_size: " << package_size_;
+    return false;
+  }
+
+  if (!android::base::ReadFullyAtOffset(fd_.get(), buffer, byte_count, offset)) {
+    PLOG(ERROR) << "Failed to read " << byte_count << " bytes data at offset " << offset;
+    return false;
+  }
+
+  return true;
+}
+
+bool FilePackage::UpdateHashAtOffset(const std::vector<HasherUpdateCallback>& hashers,
+                                     uint64_t start, uint64_t length) {
+  if (length > package_size_ || start > package_size_ - length) {
+    LOG(ERROR) << "Out of bound read, offset: " << start << ", size: " << length
+               << ", total package_size: " << package_size_;
+    return false;
+  }
+
+  uint64_t so_far = 0;
+  while (so_far < length) {
+    uint64_t read_size = std::min<uint64_t>(length - so_far, 16 * MiB);
+    std::vector<uint8_t> buffer(read_size);
+    if (!ReadFullyAtOffset(buffer.data(), read_size, start + so_far)) {
+      return false;
+    }
+
+    for (const auto& hasher : hashers) {
+      hasher(buffer.data(), read_size);
+    }
+    so_far += read_size;
+  }
+
+  return true;
+}
+
+ZipArchiveHandle FilePackage::GetZipArchiveHandle() {
+  if (zip_handle_) {
+    return zip_handle_;
+  }
+
+  if (auto err = OpenArchiveFd(fd_.get(), path_.c_str(), &zip_handle_); err != 0) {
+    LOG(ERROR) << "Can't open package" << path_ << " : " << ErrorCodeString(err);
+    return nullptr;
+  }
+
+  return zip_handle_;
+}
diff --git a/twrpinstall/set_metadata.cpp b/twrpinstall/set_metadata.cpp
new file mode 100644
index 0000000..2e1d769
--- /dev/null
+++ b/twrpinstall/set_metadata.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The purpose of these functions is to try to get and set the proper
+ * file permissions, SELinux contexts, owner, and group so that these
+ * files are accessible when we boot up to normal Android via MTP and to
+ * file manager apps. During early boot we try to read the contexts and
+ * owner / group info from /data/media or from /data/media/0 and store
+ * them in static variables. From there, we'll try to set the same
+ * contexts, owner, and group information on most files we create during
+ * operations like backups, copying the log, and MTP operations.
+ */
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "selinux/selinux.h"
+
+static security_context_t selinux_context;
+struct stat s;
+static int has_stat = 0;
+
+int tw_get_context(const char* filename) {
+	if (lgetfilecon(filename, &selinux_context) >= 0) {
+		printf("tw_get_context got selinux context: %s\n", selinux_context);
+		return 0;
+	} else {
+		printf("tw_get_context failed to get selinux context\n");
+		selinux_context = NULL;
+	}
+	return -1;
+}
+
+int tw_get_stat(const char* filename) {
+	if (lstat(filename, &s) == 0) {
+		has_stat = 1;
+		return 0;
+	}
+	printf("tw_get_stat failed to lstat '%s'\n", filename);
+	return -1;
+}
+
+int tw_get_default_metadata(const char* filename) {
+	if (tw_get_context(filename) == 0 && tw_get_stat(filename) == 0)
+		return 0;
+	return -1;
+}
+
+// Most of this logging is disabled to prevent log spam if we are trying
+// to set contexts and permissions on file systems that do not support
+// these types of things (e.g. vfat / FAT / FAT32).
+int tw_set_default_metadata(const char* filename) {
+	int ret = 0;
+	struct stat st;
+
+	if (selinux_context == NULL) {
+		//printf("selinux_context was null, '%s'\n", filename);
+		ret = -1;
+	} else if (lsetfilecon(filename, selinux_context) < 0) {
+		//printf("Failed to set default contexts on '%s'.\n", filename);
+		ret = -1;
+	}
+
+	if (lstat(filename, &st) == 0 && st.st_mode & S_IFREG && chmod(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) < 0) {
+		//printf("Failed to chmod '%s'\n", filename);
+		ret = -1;
+	}
+
+	if (has_stat && chown(filename, s.st_uid, s.st_gid) < 0) {
+		//printf("Failed to lchown '%s'.\n", filename);
+		ret = -1;
+	}
+	//printf("Done trying to set defaults on '%s'\n");
+	return ret;
+}
diff --git a/install/tw_atomic.cpp b/twrpinstall/tw_atomic.cpp
similarity index 100%
rename from install/tw_atomic.cpp
rename to twrpinstall/tw_atomic.cpp
diff --git a/twinstall.cpp b/twrpinstall/twinstall.cpp
similarity index 78%
rename from twinstall.cpp
rename to twrpinstall/twinstall.cpp
index fd33828..65a83a6 100755
--- a/twinstall.cpp
+++ b/twrpinstall/twinstall.cpp
@@ -35,24 +35,16 @@
 #include <stdio.h>
 #include <cutils/properties.h>
 
+#include <android-base/unique_fd.h>
+
 #include "twcommon.h"
 #include "mtdutils/mounts.h"
 #include "mtdutils/mtdutils.h"
 
-#ifdef USE_MINZIP
-#include "minzip/SysUtil.h"
-#else
 #include "otautil/sysutil.h"
 #include <ziparchive/zip_archive.h>
-#endif
-#include "zipwrap.hpp"
-#ifdef USE_OLD_VERIFIER
-#include "verifier24/verifier.h"
-#elif USE_28_VERIFIER
-#include "verifier28/verifier.h"
-#else
-#include "install/verifier.h"
-#endif
+#include "twinstall/install.h"
+#include "twinstall/verifier.h"
 #include "variables.h"
 #include "data.hpp"
 #include "partitions.hpp"
@@ -129,15 +121,17 @@
 }
 #endif
 
-static int Install_Theme(const char* path, ZipWrap *Zip) {
+static int Install_Theme(const char* path, ZipArchiveHandle Zip) {
 #ifdef TW_OEM_BUILD // We don't do custom themes in OEM builds
-	Zip->Close();
+	CloseArchive(Zip);
 	return INSTALL_CORRUPT;
 #else
-	if (!Zip->EntryExists("ui.xml")) {
+	ZipString binary_name("ui.xml");
+	ZipEntry binary_entry;
+	if (FindEntry(Zip, binary_name, &binary_entry) != 0) {
+		CloseArchive(Zip);
 		return INSTALL_CORRUPT;
 	}
-	Zip->Close();
 	if (!PartitionManager.Mount_Settings_Storage(true))
 		return INSTALL_ERROR;
 	string theme_path = DataManager::GetSettingsStoragePath();
@@ -157,44 +151,60 @@
 #endif
 }
 
-static int Prepare_Update_Binary(const char *path, ZipWrap *Zip, int* wipe_cache) {
+static int Prepare_Update_Binary(ZipArchiveHandle Zip) {
 	char arches[PATH_MAX];
-	std::string binary_name = ASSUMED_UPDATE_BINARY_NAME;
 	property_get("ro.product.cpu.abilist", arches, "error");
 	if (strcmp(arches, "error") == 0)
 		property_get("ro.product.cpu.abi", arches, "error");
 	vector<string> split = TWFunc::split_string(arches, ',', true);
 	std::vector<string>::iterator arch;
-	std::string base_name = binary_name;
+	std::string base_name = UPDATE_BINARY_NAME;
 	base_name += "-";
-	for (arch = split.begin(); arch != split.end(); arch++) {
-		std::string temp = base_name + *arch;
-		if (Zip->EntryExists(temp)) {
-			binary_name = temp;
-			break;
+	ZipEntry binary_entry;
+	ZipString update_binary_string(UPDATE_BINARY_NAME);
+	if (FindEntry(Zip, update_binary_string, &binary_entry) != 0) {
+		for (arch = split.begin(); arch != split.end(); arch++) {
+			std::string temp = base_name + *arch;
+			ZipString binary_name(temp.c_str());
+			if (FindEntry(Zip, binary_name, &binary_entry) != 0) {
+				ZipString binary_name(temp.c_str());
+				break;
+			}
 		}
 	}
-	LOGINFO("Extracting updater binary '%s'\n", binary_name.c_str());
-	if (!Zip->ExtractEntry(binary_name.c_str(), TMP_UPDATER_BINARY_PATH, 0755)) {
-		Zip->Close();
-		LOGERR("Could not extract '%s'\n", ASSUMED_UPDATE_BINARY_NAME);
+	LOGINFO("Extracting updater binary '%s'\n", UPDATE_BINARY_NAME);
+	unlink(TMP_UPDATER_BINARY_PATH);
+	android::base::unique_fd fd(
+		open(TMP_UPDATER_BINARY_PATH, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755));
+	if (fd == -1) {
+		return INSTALL_ERROR;
+	}
+	int32_t err = ExtractEntryToFile(Zip, &binary_entry, fd);
+	if (err != 0) {
+		CloseArchive(Zip);
+		LOGERR("Could not extract '%s'\n", UPDATE_BINARY_NAME);
 		return INSTALL_ERROR;
 	}
 
 	// If exists, extract file_contexts from the zip file
-	if (!Zip->EntryExists("file_contexts")) {
-		Zip->Close();
+	ZipString file_contexts("file_contexts");
+	ZipEntry file_contexts_entry;
+	if (FindEntry(Zip, file_contexts, &file_contexts_entry) != 0) {
 		LOGINFO("Zip does not contain SELinux file_contexts file in its root.\n");
 	} else {
 		const string output_filename = "/file_contexts";
 		LOGINFO("Zip contains SELinux file_contexts file in its root. Extracting to %s\n", output_filename.c_str());
-		if (!Zip->ExtractEntry("file_contexts", output_filename, 0644)) {
-			Zip->Close();
+		android::base::unique_fd fd(
+			open(output_filename.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0644));
+		if (fd == -1) {
+			return INSTALL_ERROR;
+		}
+		if (ExtractEntryToFile(Zip, &file_contexts_entry, fd)) {
+			CloseArchive(Zip);
 			LOGERR("Could not extract '%s'\n", output_filename.c_str());
 			return INSTALL_ERROR;
 		}
 	}
-	Zip->Close();
 	return INSTALL_SUCCESS;
 }
 
@@ -233,7 +243,7 @@
 }
 #endif
 
-static int Run_Update_Binary(const char *path, ZipWrap *Zip, int* wipe_cache, zip_type ztype) {
+static int Run_Update_Binary(const char *path, int* wipe_cache, zip_type ztype) {
 	int ret_val, pipe_fd[2], status, zip_verify;
 	char buffer[1024];
 	FILE* child_data;
@@ -254,7 +264,7 @@
     if (ztype == UPDATE_BINARY_ZIP_TYPE) {
 		ret_val = update_binary_command(path, 0, pipe_fd[1], &args);
     } else if (ztype == AB_OTA_ZIP_TYPE) {
-		ret_val = abupdate_binary_command(path, Zip, 0, pipe_fd[1], &args);
+		ret_val = abupdate_binary_command(path, 0, pipe_fd[1], &args);
 	} else {
 		LOGERR("Unknown zip type %i\n", ztype);
 		ret_val = INSTALL_CORRUPT;
@@ -296,7 +306,7 @@
 			int seconds_float = strtol(seconds_char, NULL, 10);
 
 			if (zip_verify)
-				DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRAC), seconds_float);
+				DataManager::ShowProgress(fraction_float * (1 - VERIFICATION_PROGRESS_FRACTION), seconds_float);
 			else
 				DataManager::ShowProgress(fraction_float, seconds_float);
 		} else if (strcmp(command, "set_progress") == 0) {
@@ -344,11 +354,6 @@
 int TWinstall_zip(const char* path, int* wipe_cache) {
 	int ret_val, zip_verify = 1, unmount_system = 1;
 
-	if (strcmp(path, "error") == 0) {
-		LOGERR("Failed to get adb sideload file: '%s'\n", path);
-		return INSTALL_CORRUPT;
-	}
-
 	gui_msg(Msg("installing_zip=Installing zip file '{1}'")(path));
 	if (strlen(path) < 9 || strncmp(path, "/sideload", 9) != 0) {
 		string digest_str;
@@ -369,32 +374,22 @@
 #endif
 	DataManager::SetProgress(0);
 
-	MemMapping map;
-#ifdef USE_MINZIP
-	if (sysMapFile(path, &map) != 0) {
-#else
-	if (!map.MapFile(path)) {
-#endif
-		gui_msg(Msg(msg::kError, "fail_sysmap=Failed to map file '{1}'")(path));
-		return -1;
+	auto package = Package::CreateMemoryPackage(path);
+	if (!package) {
+		return INSTALL_CORRUPT;
 	}
 
 	if (zip_verify) {
 		gui_msg("verify_zip_sig=Verifying zip signature...");
-#ifdef USE_OLD_VERIFIER
-		ret_val = verify_file(map.addr, map.length);
-#else
-		std::vector<Certificate> loadedKeys;
-		if (!load_keys("/res/keys", loadedKeys)) {
-			LOGINFO("Failed to load keys");
-			gui_err("verify_zip_fail=Zip signature verification failed!");
-#ifdef USE_MINZIP
-			sysReleaseMap(&map);
-#endif
+		static constexpr const char* CERTIFICATE_ZIP_FILE = "/system/etc/security/otacerts.zip";
+		std::vector<Certificate> loaded_keys = LoadKeysFromZipfile(CERTIFICATE_ZIP_FILE);
+		if (loaded_keys.empty()) {
+			LOGERR("Failed to load keys\n");
 			return -1;
 		}
-		ret_val = verify_file(map.addr, map.length, loadedKeys, std::bind(&DataManager::SetProgress, std::placeholders::_1));
-#endif
+		LOGINFO("%zu key(s) loaded from %s\n", loaded_keys.size(), CERTIFICATE_ZIP_FILE);
+
+		ret_val = verify_file(package.get(), loaded_keys, std::bind(&DataManager::SetProgress, std::placeholders::_1));
 		if (ret_val != VERIFY_SUCCESS) {
 			LOGINFO("Zip signature verification failed: %i\n", ret_val);
 			gui_err("verify_zip_fail=Zip signature verification failed!");
@@ -406,12 +401,9 @@
 			gui_msg("verify_zip_done=Zip signature verified successfully.");
 		}
 	}
-	ZipWrap Zip;
-	if (!Zip.Open(path, &map)) {
-		gui_err("zip_corrupt=Zip file is corrupt!");
-#ifdef USE_MINZIP
-			sysReleaseMap(&map);
-#endif
+
+	ZipArchiveHandle Zip = package->GetZipArchiveHandle();
+	if (!Zip) {
 		return INSTALL_CORRUPT;
 	}
 
@@ -427,23 +419,25 @@
 
 	time_t start, stop;
 	time(&start);
-	if (Zip.EntryExists(ASSUMED_UPDATE_BINARY_NAME)) {
+
+	ZipString update_binary_name(UPDATE_BINARY_NAME);
+	ZipEntry update_binary_entry;
+	if (FindEntry(Zip, update_binary_name, &update_binary_entry) == 0) {
 		LOGINFO("Update binary zip\n");
 		// Additionally verify the compatibility of the package.
-		if (!verify_package_compatibility(&Zip)) {
+		if (!verify_package_compatibility(Zip)) {
 			gui_err("zip_compatible_err=Zip Treble compatibility error!");
-			Zip.Close();
-#ifdef USE_MINZIP
-			sysReleaseMap(&map);
-#endif
+			CloseArchive(Zip);
 			ret_val = INSTALL_CORRUPT;
 		} else {
-			ret_val = Prepare_Update_Binary(path, &Zip, wipe_cache);
+			ret_val = Prepare_Update_Binary(Zip);
 			if (ret_val == INSTALL_SUCCESS)
-				ret_val = Run_Update_Binary(path, &Zip, wipe_cache, UPDATE_BINARY_ZIP_TYPE);
+				ret_val = Run_Update_Binary(path, wipe_cache, UPDATE_BINARY_ZIP_TYPE);
 		}
 	} else {
-		if (Zip.EntryExists(AB_OTA)) {
+		ZipString ab_binary_name(AB_OTA);
+		ZipEntry ab_binary_entry;
+		if (FindEntry(Zip, ab_binary_name, &ab_binary_entry) == 0) {
 			LOGINFO("AB zip\n");
 			gui_msg(Msg(msg::kHighlight, "flash_ab_inactive=Flashing A/B zip to inactive slot: {1}")(PartitionManager.Get_Active_Slot_Display()=="A"?"B":"A"));
 			// We need this so backuptool can do its magic
@@ -451,9 +445,9 @@
 			bool vendor_mount_state = PartitionManager.Is_Mounted_By_Path("/vendor");
 			PartitionManager.Mount_By_Path(PartitionManager.Get_Android_Root_Path(), true);
 			PartitionManager.Mount_By_Path("/vendor", true);
-			TWFunc::Exec_Cmd("cp -f /system/bin/sh /tmp/sh");
+			TWFunc::copy_file("/system/bin/sh", "/tmp/sh", 0755);
 			mount("/tmp/sh", "/system/bin/sh", "auto", MS_BIND, NULL);
-			ret_val = Run_Update_Binary(path, &Zip, wipe_cache, AB_OTA_ZIP_TYPE);
+			ret_val = Run_Update_Binary(path, wipe_cache, AB_OTA_ZIP_TYPE);
 			umount("/system/bin/sh");
 			unlink("/tmp/sh");
 			if (!vendor_mount_state)
@@ -461,13 +455,14 @@
 			if (!system_mount_state)
 				PartitionManager.UnMount_By_Path(PartitionManager.Get_Android_Root_Path(), true);
 			gui_warn("flash_ab_reboot=To flash additional zips, please reboot recovery to switch to the updated slot.");
-
 		} else {
-			if (Zip.EntryExists("ui.xml")) {
+			ZipString binary_name("ui.xml");
+			ZipEntry binary_entry;
+			if (FindEntry(Zip, binary_name, &binary_entry) != 0) {
 				LOGINFO("TWRP theme zip\n");
-				ret_val = Install_Theme(path, &Zip);
+				ret_val = Install_Theme(path, Zip);
 			} else {
-				Zip.Close();
+				CloseArchive(Zip);
 				ret_val = INSTALL_CORRUPT;
 			}
 		}
@@ -479,8 +474,5 @@
 	} else {
 		LOGINFO("Install took %i second(s).\n", total_time);
 	}
-#ifdef USE_MINZIP
-	sysReleaseMap(&map);
-#endif
 	return ret_val;
 }
diff --git a/twrpinstall/verifier.cpp b/twrpinstall/verifier.cpp
new file mode 100755
index 0000000..f577961
--- /dev/null
+++ b/twrpinstall/verifier.cpp
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "twinstall/verifier.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include <android-base/logging.h>
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/ecdsa.h>
+#include <openssl/evp.h>
+#include <openssl/obj_mac.h>
+#include <openssl/pem.h>
+#include <openssl/rsa.h>
+#include <ziparchive/zip_archive.h>
+
+#include "otautil/print_sha1.h"
+#include "private/asn1_decoder.h"
+
+/*
+ * Simple version of PKCS#7 SignedData extraction. This extracts the
+ * signature OCTET STRING to be used for signature verification.
+ *
+ * For full details, see http://www.ietf.org/rfc/rfc3852.txt
+ *
+ * The PKCS#7 structure looks like:
+ *
+ *   SEQUENCE (ContentInfo)
+ *     OID (ContentType)
+ *     [0] (content)
+ *       SEQUENCE (SignedData)
+ *         INTEGER (version CMSVersion)
+ *         SET (DigestAlgorithmIdentifiers)
+ *         SEQUENCE (EncapsulatedContentInfo)
+ *         [0] (CertificateSet OPTIONAL)
+ *         [1] (RevocationInfoChoices OPTIONAL)
+ *         SET (SignerInfos)
+ *           SEQUENCE (SignerInfo)
+ *             INTEGER (CMSVersion)
+ *             SEQUENCE (SignerIdentifier)
+ *             SEQUENCE (DigestAlgorithmIdentifier)
+ *             SEQUENCE (SignatureAlgorithmIdentifier)
+ *             OCTET STRING (SignatureValue)
+ */
+static bool read_pkcs7(const uint8_t* pkcs7_der, size_t pkcs7_der_len,
+                       std::vector<uint8_t>* sig_der) {
+  CHECK(sig_der != nullptr);
+  sig_der->clear();
+
+  asn1_context ctx(pkcs7_der, pkcs7_der_len);
+
+  std::unique_ptr<asn1_context> pkcs7_seq(ctx.asn1_sequence_get());
+  if (pkcs7_seq == nullptr || !pkcs7_seq->asn1_sequence_next()) {
+    return false;
+  }
+
+  std::unique_ptr<asn1_context> signed_data_app(pkcs7_seq->asn1_constructed_get());
+  if (signed_data_app == nullptr) {
+    return false;
+  }
+
+  std::unique_ptr<asn1_context> signed_data_seq(signed_data_app->asn1_sequence_get());
+  if (signed_data_seq == nullptr || !signed_data_seq->asn1_sequence_next() ||
+      !signed_data_seq->asn1_sequence_next() || !signed_data_seq->asn1_sequence_next() ||
+      !signed_data_seq->asn1_constructed_skip_all()) {
+    return false;
+  }
+
+  std::unique_ptr<asn1_context> sig_set(signed_data_seq->asn1_set_get());
+  if (sig_set == nullptr) {
+    return false;
+  }
+
+  std::unique_ptr<asn1_context> sig_seq(sig_set->asn1_sequence_get());
+  if (sig_seq == nullptr || !sig_seq->asn1_sequence_next() || !sig_seq->asn1_sequence_next() ||
+      !sig_seq->asn1_sequence_next() || !sig_seq->asn1_sequence_next()) {
+    return false;
+  }
+
+  const uint8_t* sig_der_ptr;
+  size_t sig_der_length;
+  if (!sig_seq->asn1_octet_string_get(&sig_der_ptr, &sig_der_length)) {
+    return false;
+  }
+
+  sig_der->resize(sig_der_length);
+  std::copy(sig_der_ptr, sig_der_ptr + sig_der_length, sig_der->begin());
+  return true;
+}
+
+int verify_file(VerifierInterface* package, const std::vector<Certificate>& keys,
+  const std::function<void(float)>& set_progress) {
+  CHECK(package);
+  package->SetProgress(0.0);
+
+  if (set_progress) {
+    set_progress(0.0);
+  }
+
+  // An archive with a whole-file signature will end in six bytes:
+  //
+  //   (2-byte signature start) $ff $ff (2-byte comment size)
+  //
+  // (As far as the ZIP format is concerned, these are part of the archive comment.) We start by
+  // reading this footer, this tells us how far back from the end we have to start reading to find
+  // the whole comment.
+
+#define FOOTER_SIZE 6
+  uint64_t length = package->GetPackageSize();
+
+  if (length < FOOTER_SIZE) {
+    LOG(ERROR) << "not big enough to contain footer";
+    return VERIFY_FAILURE;
+  }
+
+  uint8_t footer[FOOTER_SIZE];
+  if (!package->ReadFullyAtOffset(footer, FOOTER_SIZE, length - FOOTER_SIZE)) {
+    LOG(ERROR) << "Failed to read footer";
+    return VERIFY_FAILURE;
+  }
+
+  if (footer[2] != 0xff || footer[3] != 0xff) {
+    LOG(ERROR) << "footer is wrong";
+    return VERIFY_FAILURE;
+  }
+
+  size_t comment_size = footer[4] + (footer[5] << 8);
+  size_t signature_start = footer[0] + (footer[1] << 8);
+  LOG(INFO) << "comment is " << comment_size << " bytes; signature is " << signature_start
+            << " bytes from end";
+
+  if (signature_start > comment_size) {
+    LOG(ERROR) << "signature start: " << signature_start
+               << " is larger than comment size: " << comment_size;
+    return VERIFY_FAILURE;
+  }
+
+  if (signature_start <= FOOTER_SIZE) {
+    LOG(ERROR) << "Signature start is in the footer";
+    return VERIFY_FAILURE;
+  }
+
+#define EOCD_HEADER_SIZE 22
+
+  // The end-of-central-directory record is 22 bytes plus any comment length.
+  size_t eocd_size = comment_size + EOCD_HEADER_SIZE;
+
+  if (length < eocd_size) {
+    LOG(ERROR) << "not big enough to contain EOCD";
+    return VERIFY_FAILURE;
+  }
+
+  // Determine how much of the file is covered by the signature. This is everything except the
+  // signature data and length, which includes all of the EOCD except for the comment length field
+  // (2 bytes) and the comment data.
+  uint64_t signed_len = length - eocd_size + EOCD_HEADER_SIZE - 2;
+
+  uint8_t eocd[eocd_size];
+  if (!package->ReadFullyAtOffset(eocd, eocd_size, length - eocd_size)) {
+    LOG(ERROR) << "Failed to read EOCD of " << eocd_size << " bytes";
+    return VERIFY_FAILURE;
+  }
+
+  // If this is really is the EOCD record, it will begin with the magic number $50 $4b $05 $06.
+  if (eocd[0] != 0x50 || eocd[1] != 0x4b || eocd[2] != 0x05 || eocd[3] != 0x06) {
+    LOG(ERROR) << "signature length doesn't match EOCD marker";
+    return VERIFY_FAILURE;
+  }
+
+  for (size_t i = 4; i < eocd_size - 3; ++i) {
+    if (eocd[i] == 0x50 && eocd[i + 1] == 0x4b && eocd[i + 2] == 0x05 && eocd[i + 3] == 0x06) {
+      // If the sequence $50 $4b $05 $06 appears anywhere after the real one, libziparchive will
+      // find the later (wrong) one, which could be exploitable. Fail the verification if this
+      // sequence occurs anywhere after the real one.
+      LOG(ERROR) << "EOCD marker occurs after start of EOCD";
+      return VERIFY_FAILURE;
+    }
+  }
+
+  bool need_sha1 = false;
+  bool need_sha256 = false;
+  for (const auto& key : keys) {
+    switch (key.hash_len) {
+      case SHA_DIGEST_LENGTH:
+        need_sha1 = true;
+        break;
+      case SHA256_DIGEST_LENGTH:
+        need_sha256 = true;
+        break;
+    }
+  }
+
+  SHA_CTX sha1_ctx;
+  SHA256_CTX sha256_ctx;
+  SHA1_Init(&sha1_ctx);
+  SHA256_Init(&sha256_ctx);
+
+  std::vector<HasherUpdateCallback> hashers;
+  if (need_sha1) {
+    hashers.emplace_back(
+        std::bind(&SHA1_Update, &sha1_ctx, std::placeholders::_1, std::placeholders::_2));
+  }
+  if (need_sha256) {
+    hashers.emplace_back(
+        std::bind(&SHA256_Update, &sha256_ctx, std::placeholders::_1, std::placeholders::_2));
+  }
+
+  double frac = -1.0;
+  uint64_t so_far = 0;
+  while (so_far < signed_len) {
+    // On a Nexus 5X, experiment showed 16MiB beat 1MiB by 6% faster for a 1196MiB full OTA and
+    // 60% for an 89MiB incremental OTA. http://b/28135231.
+    uint64_t read_size = std::min<uint64_t>(signed_len - so_far, 16 * MiB);
+    package->UpdateHashAtOffset(hashers, so_far, read_size);
+    so_far += read_size;
+
+    double f = so_far / static_cast<double>(signed_len);
+    if (f > frac + 0.02 || read_size == so_far) {
+      package->SetProgress(f);
+      frac = f;
+      if (set_progress) {
+        set_progress(f);
+      }
+    }
+  }
+
+  uint8_t sha1[SHA_DIGEST_LENGTH];
+  SHA1_Final(sha1, &sha1_ctx);
+  uint8_t sha256[SHA256_DIGEST_LENGTH];
+  SHA256_Final(sha256, &sha256_ctx);
+
+  const uint8_t* signature = eocd + eocd_size - signature_start;
+  size_t signature_size = signature_start - FOOTER_SIZE;
+
+  LOG(INFO) << "signature (offset: " << std::hex << (length - signature_start)
+            << ", length: " << signature_size << "): " << print_hex(signature, signature_size);
+
+  std::vector<uint8_t> sig_der;
+  if (!read_pkcs7(signature, signature_size, &sig_der)) {
+    LOG(ERROR) << "Could not find signature DER block";
+    return VERIFY_FAILURE;
+  }
+
+  // Check to make sure at least one of the keys matches the signature. Since any key can match,
+  // we need to try each before determining a verification failure has happened.
+  size_t i = 0;
+  for (const auto& key : keys) {
+    const uint8_t* hash;
+    int hash_nid;
+    switch (key.hash_len) {
+      case SHA_DIGEST_LENGTH:
+        hash = sha1;
+        hash_nid = NID_sha1;
+        break;
+      case SHA256_DIGEST_LENGTH:
+        hash = sha256;
+        hash_nid = NID_sha256;
+        break;
+      default:
+        continue;
+    }
+
+    // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that the signing tool appends
+    // after the signature itself.
+    if (key.key_type == Certificate::KEY_TYPE_RSA) {
+      if (!RSA_verify(hash_nid, hash, key.hash_len, sig_der.data(), sig_der.size(),
+                      key.rsa.get())) {
+        LOG(INFO) << "failed to verify against RSA key " << i;
+        continue;
+      }
+
+      LOG(INFO) << "whole-file signature verified against RSA key " << i;
+      return VERIFY_SUCCESS;
+    } else if (key.key_type == Certificate::KEY_TYPE_EC && key.hash_len == SHA256_DIGEST_LENGTH) {
+      if (!ECDSA_verify(0, hash, key.hash_len, sig_der.data(), sig_der.size(), key.ec.get())) {
+        LOG(INFO) << "failed to verify against EC key " << i;
+        continue;
+      }
+
+      LOG(INFO) << "whole-file signature verified against EC key " << i;
+      return VERIFY_SUCCESS;
+    } else {
+      LOG(INFO) << "Unknown key type " << key.key_type;
+    }
+    i++;
+  }
+
+  if (need_sha1) {
+    LOG(INFO) << "SHA-1 digest: " << print_hex(sha1, SHA_DIGEST_LENGTH);
+  }
+  if (need_sha256) {
+    LOG(INFO) << "SHA-256 digest: " << print_hex(sha256, SHA256_DIGEST_LENGTH);
+  }
+  LOG(ERROR) << "failed to verify whole-file signature";
+  return VERIFY_FAILURE;
+}
+
+std::unique_ptr<RSA, RSADeleter> parse_rsa_key(FILE* file, uint32_t exponent) {
+    // Read key length in words and n0inv. n0inv is a precomputed montgomery
+    // parameter derived from the modulus and can be used to speed up
+    // verification. n0inv is 32 bits wide here, assuming the verification logic
+    // uses 32 bit arithmetic. However, BoringSSL may use a word size of 64 bits
+    // internally, in which case we don't have a valid n0inv. Thus, we just
+    // ignore the montgomery parameters and have BoringSSL recompute them
+    // internally. If/When the speedup from using the montgomery parameters
+    // becomes relevant, we can add more sophisticated code here to obtain a
+    // 64-bit n0inv and initialize the montgomery parameters in the key object.
+    uint32_t key_len_words = 0;
+    uint32_t n0inv = 0;
+    if (fscanf(file, " %i , 0x%x", &key_len_words, &n0inv) != 2) {
+        return nullptr;
+    }
+
+    if (key_len_words > 8192 / 32) {
+        LOG(ERROR) << "key length (" << key_len_words << ") too large";
+        return nullptr;
+    }
+
+    // Read the modulus.
+    std::unique_ptr<uint32_t[]> modulus(new uint32_t[key_len_words]);
+    if (fscanf(file, " , { %u", &modulus[0]) != 1) {
+        return nullptr;
+    }
+    for (uint32_t i = 1; i < key_len_words; ++i) {
+        if (fscanf(file, " , %u", &modulus[i]) != 1) {
+            return nullptr;
+        }
+    }
+
+    // Cconvert from little-endian array of little-endian words to big-endian
+    // byte array suitable as input for BN_bin2bn.
+    std::reverse((uint8_t*)modulus.get(),
+                 (uint8_t*)(modulus.get() + key_len_words));
+
+    // The next sequence of values is the montgomery parameter R^2. Since we
+    // generally don't have a valid |n0inv|, we ignore this (see comment above).
+    uint32_t rr_value;
+    if (fscanf(file, " } , { %u", &rr_value) != 1) {
+        return nullptr;
+    }
+    for (uint32_t i = 1; i < key_len_words; ++i) {
+        if (fscanf(file, " , %u", &rr_value) != 1) {
+            return nullptr;
+        }
+    }
+    if (fscanf(file, " } } ") != 0) {
+        return nullptr;
+    }
+
+    // Initialize the key.
+    std::unique_ptr<RSA, RSADeleter> key(RSA_new());
+    if (!key) {
+      return nullptr;
+    }
+
+    key->n = BN_bin2bn((uint8_t*)modulus.get(),
+                       key_len_words * sizeof(uint32_t), NULL);
+    if (!key->n) {
+      return nullptr;
+    }
+
+    key->e = BN_new();
+    if (!key->e || !BN_set_word(key->e, exponent)) {
+      return nullptr;
+    }
+
+    return key;
+}
+
+
+static std::vector<Certificate> IterateZipEntriesAndSearchForKeys(const ZipArchiveHandle& handle) {
+  void* cookie;
+  ZipString suffix("x509.pem");
+  int32_t iter_status = StartIteration(handle, &cookie, nullptr, &suffix);
+  if (iter_status != 0) {
+    LOG(ERROR) << "Failed to iterate over entries in the certificate zipfile: "
+               << ErrorCodeString(iter_status);
+    return {};
+  }
+
+  std::vector<Certificate> result;
+
+  ZipString name;
+  ZipEntry entry;
+  while ((iter_status = Next(cookie, &entry, &name)) == 0) {
+    std::vector<uint8_t> pem_content(entry.uncompressed_length);
+    if (int32_t extract_status =
+            ExtractToMemory(handle, &entry, pem_content.data(), pem_content.size());
+        extract_status != 0) {
+      LOG(ERROR) << "Failed to extract " << std::string(name.name, name.name + name.name_length);
+      return {};
+    }
+
+    Certificate cert(0, Certificate::KEY_TYPE_RSA, nullptr, nullptr);
+    // Aborts the parsing if we fail to load one of the key file.
+    if (!LoadCertificateFromBuffer(pem_content, &cert)) {
+      LOG(ERROR) << "Failed to load keys from "
+                 << std::string(name.name, name.name + name.name_length);
+      return {};
+    }
+
+    result.emplace_back(std::move(cert));
+  }
+
+  if (iter_status != -1) {
+    LOG(ERROR) << "Error while iterating over zip entries: " << ErrorCodeString(iter_status);
+    return {};
+  }
+
+  return result;
+}
+
+std::vector<Certificate> LoadKeysFromZipfile(const std::string& zip_name) {
+  ZipArchiveHandle handle;
+  if (int32_t open_status = OpenArchive(zip_name.c_str(), &handle); open_status != 0) {
+    LOG(ERROR) << "Failed to open " << zip_name << ": " << ErrorCodeString(open_status);
+    return {};
+  }
+
+  std::vector<Certificate> result = IterateZipEntriesAndSearchForKeys(handle);
+  CloseArchive(handle);
+  return result;
+}
+
+bool CheckRSAKey(const std::unique_ptr<RSA, RSADeleter>& rsa) {
+  if (!rsa) {
+    return false;
+  }
+
+  const BIGNUM* out_n;
+  const BIGNUM* out_e;
+  RSA_get0_key(rsa.get(), &out_n, &out_e, nullptr /* private exponent */);
+  auto modulus_bits = BN_num_bits(out_n);
+  if (modulus_bits != 2048 && modulus_bits != 4096) {
+    LOG(ERROR) << "Modulus should be 2048 or 4096 bits long, actual: " << modulus_bits;
+    return false;
+  }
+
+  BN_ULONG exponent = BN_get_word(out_e);
+  if (exponent != 3 && exponent != 65537) {
+    LOG(ERROR) << "Public exponent should be 3 or 65537, actual: " << exponent;
+    return false;
+  }
+
+  return true;
+}
+
+bool CheckECKey(const std::unique_ptr<EC_KEY, ECKEYDeleter>& ec_key) {
+  if (!ec_key) {
+    return false;
+  }
+
+  const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get());
+  if (!ec_group) {
+    LOG(ERROR) << "Failed to get the ec_group from the ec_key";
+    return false;
+  }
+  auto degree = EC_GROUP_get_degree(ec_group);
+  if (degree != 256) {
+    LOG(ERROR) << "Field size of the ec key should be 256 bits long, actual: " << degree;
+    return false;
+  }
+
+  return true;
+}
+
+bool LoadCertificateFromBuffer(const std::vector<uint8_t>& pem_content, Certificate* cert) {
+  std::unique_ptr<BIO, decltype(&BIO_free)> content(
+      BIO_new_mem_buf(pem_content.data(), pem_content.size()), BIO_free);
+
+  std::unique_ptr<X509, decltype(&X509_free)> x509(
+      PEM_read_bio_X509(content.get(), nullptr, nullptr, nullptr), X509_free);
+  if (!x509) {
+    LOG(ERROR) << "Failed to read x509 certificate";
+    return false;
+  }
+
+  int nid = X509_get_signature_nid(x509.get());
+  switch (nid) {
+    // SignApk has historically accepted md5WithRSA certificates, but treated them as
+    // sha1WithRSA anyway. Continue to do so for backwards compatibility.
+    case NID_md5WithRSA:
+    case NID_md5WithRSAEncryption:
+    case NID_sha1WithRSA:
+    case NID_sha1WithRSAEncryption:
+      cert->hash_len = SHA_DIGEST_LENGTH;
+      break;
+    case NID_sha256WithRSAEncryption:
+    case NID_ecdsa_with_SHA256:
+      cert->hash_len = SHA256_DIGEST_LENGTH;
+      break;
+    default:
+      LOG(ERROR) << "Unrecognized signature nid " << OBJ_nid2ln(nid);
+      return false;
+  }
+
+  std::unique_ptr<EVP_PKEY, decltype(&EVP_PKEY_free)> public_key(X509_get_pubkey(x509.get()),
+                                                                 EVP_PKEY_free);
+  if (!public_key) {
+    LOG(ERROR) << "Failed to extract the public key from x509 certificate";
+    return false;
+  }
+
+  int key_type = EVP_PKEY_id(public_key.get());
+  if (key_type == EVP_PKEY_RSA) {
+    cert->key_type = Certificate::KEY_TYPE_RSA;
+    cert->ec.reset();
+    cert->rsa.reset(EVP_PKEY_get1_RSA(public_key.get()));
+    if (!cert->rsa || !CheckRSAKey(cert->rsa)) {
+      LOG(ERROR) << "Failed to validate the rsa key info from public key";
+      return false;
+    }
+  } else if (key_type == EVP_PKEY_EC) {
+    cert->key_type = Certificate::KEY_TYPE_EC;
+    cert->rsa.reset();
+    cert->ec.reset(EVP_PKEY_get1_EC_KEY(public_key.get()));
+    if (!cert->ec || !CheckECKey(cert->ec)) {
+      LOG(ERROR) << "Failed to validate the ec key info from the public key";
+      return false;
+    }
+  } else {
+    LOG(ERROR) << "Unrecognized public key type " << OBJ_nid2ln(key_type);
+    return false;
+  }
+
+  return true;
+}
diff --git a/verifier28/verifier.cpp b/verifier28/verifier.cpp
deleted file mode 100644
index 283e043..0000000
--- a/verifier28/verifier.cpp
+++ /dev/null
@@ -1,553 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "verifier.h"
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <algorithm>
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include <android-base/logging.h>
-#include <openssl/bn.h>
-#include <openssl/ecdsa.h>
-#include <openssl/obj_mac.h>
-
-#include "asn1_decoder.h"
-#include "otautil/print_sha1.h"
-
-static constexpr size_t MiB = 1024 * 1024;
-
-/*
- * Simple version of PKCS#7 SignedData extraction. This extracts the
- * signature OCTET STRING to be used for signature verification.
- *
- * For full details, see http://www.ietf.org/rfc/rfc3852.txt
- *
- * The PKCS#7 structure looks like:
- *
- *   SEQUENCE (ContentInfo)
- *     OID (ContentType)
- *     [0] (content)
- *       SEQUENCE (SignedData)
- *         INTEGER (version CMSVersion)
- *         SET (DigestAlgorithmIdentifiers)
- *         SEQUENCE (EncapsulatedContentInfo)
- *         [0] (CertificateSet OPTIONAL)
- *         [1] (RevocationInfoChoices OPTIONAL)
- *         SET (SignerInfos)
- *           SEQUENCE (SignerInfo)
- *             INTEGER (CMSVersion)
- *             SEQUENCE (SignerIdentifier)
- *             SEQUENCE (DigestAlgorithmIdentifier)
- *             SEQUENCE (SignatureAlgorithmIdentifier)
- *             OCTET STRING (SignatureValue)
- */
-static bool read_pkcs7(const uint8_t* pkcs7_der, size_t pkcs7_der_len,
-                       std::vector<uint8_t>* sig_der) {
-  CHECK(sig_der != nullptr);
-  sig_der->clear();
-
-  asn1_context ctx(pkcs7_der, pkcs7_der_len);
-
-  std::unique_ptr<asn1_context> pkcs7_seq(ctx.asn1_sequence_get());
-  if (pkcs7_seq == nullptr || !pkcs7_seq->asn1_sequence_next()) {
-    return false;
-  }
-
-  std::unique_ptr<asn1_context> signed_data_app(pkcs7_seq->asn1_constructed_get());
-  if (signed_data_app == nullptr) {
-    return false;
-  }
-
-  std::unique_ptr<asn1_context> signed_data_seq(signed_data_app->asn1_sequence_get());
-  if (signed_data_seq == nullptr ||
-      !signed_data_seq->asn1_sequence_next() ||
-      !signed_data_seq->asn1_sequence_next() ||
-      !signed_data_seq->asn1_sequence_next() ||
-      !signed_data_seq->asn1_constructed_skip_all()) {
-    return false;
-  }
-
-  std::unique_ptr<asn1_context> sig_set(signed_data_seq->asn1_set_get());
-  if (sig_set == nullptr) {
-    return false;
-  }
-
-  std::unique_ptr<asn1_context> sig_seq(sig_set->asn1_sequence_get());
-  if (sig_seq == nullptr ||
-      !sig_seq->asn1_sequence_next() ||
-      !sig_seq->asn1_sequence_next() ||
-      !sig_seq->asn1_sequence_next() ||
-      !sig_seq->asn1_sequence_next()) {
-    return false;
-  }
-
-  const uint8_t* sig_der_ptr;
-  size_t sig_der_length;
-  if (!sig_seq->asn1_octet_string_get(&sig_der_ptr, &sig_der_length)) {
-    return false;
-  }
-
-  sig_der->resize(sig_der_length);
-  std::copy(sig_der_ptr, sig_der_ptr + sig_der_length, sig_der->begin());
-  return true;
-}
-
-/*
- * Looks for an RSA signature embedded in the .ZIP file comment given the path to the zip. Verifies
- * that it matches one of the given public keys. A callback function can be optionally provided for
- * posting the progress.
- *
- * Returns VERIFY_SUCCESS or VERIFY_FAILURE (if any error is encountered or no key matches the
- * signature).
- */
-int verify_file(const unsigned char* addr, size_t length, const std::vector<Certificate>& keys,
-                const std::function<void(float)>& set_progress) {
-  if (set_progress) {
-    set_progress(0.0);
-  }
-
-  // An archive with a whole-file signature will end in six bytes:
-  //
-  //   (2-byte signature start) $ff $ff (2-byte comment size)
-  //
-  // (As far as the ZIP format is concerned, these are part of the archive comment.) We start by
-  // reading this footer, this tells us how far back from the end we have to start reading to find
-  // the whole comment.
-
-#define FOOTER_SIZE 6
-
-  if (length < FOOTER_SIZE) {
-    LOG(ERROR) << "not big enough to contain footer";
-    return VERIFY_FAILURE;
-  }
-
-  const unsigned char* footer = addr + length - FOOTER_SIZE;
-
-  if (footer[2] != 0xff || footer[3] != 0xff) {
-    LOG(ERROR) << "footer is wrong";
-    return VERIFY_FAILURE;
-  }
-
-  size_t comment_size = footer[4] + (footer[5] << 8);
-  size_t signature_start = footer[0] + (footer[1] << 8);
-  LOG(INFO) << "comment is " << comment_size << " bytes; signature is " << signature_start
-            << " bytes from end";
-
-  if (signature_start > comment_size) {
-    LOG(ERROR) << "signature start: " << signature_start << " is larger than comment size: "
-               << comment_size;
-    return VERIFY_FAILURE;
-  }
-
-  if (signature_start <= FOOTER_SIZE) {
-    LOG(ERROR) << "Signature start is in the footer";
-    return VERIFY_FAILURE;
-  }
-
-#define EOCD_HEADER_SIZE 22
-
-  // The end-of-central-directory record is 22 bytes plus any comment length.
-  size_t eocd_size = comment_size + EOCD_HEADER_SIZE;
-
-  if (length < eocd_size) {
-    LOG(ERROR) << "not big enough to contain EOCD";
-    return VERIFY_FAILURE;
-  }
-
-  // Determine how much of the file is covered by the signature. This is everything except the
-  // signature data and length, which includes all of the EOCD except for the comment length field
-  // (2 bytes) and the comment data.
-  size_t signed_len = length - eocd_size + EOCD_HEADER_SIZE - 2;
-
-  const unsigned char* eocd = addr + length - eocd_size;
-
-  // If this is really is the EOCD record, it will begin with the magic number $50 $4b $05 $06.
-  if (eocd[0] != 0x50 || eocd[1] != 0x4b || eocd[2] != 0x05 || eocd[3] != 0x06) {
-    LOG(ERROR) << "signature length doesn't match EOCD marker";
-    return VERIFY_FAILURE;
-  }
-
-  for (size_t i = 4; i < eocd_size-3; ++i) {
-    if (eocd[i] == 0x50 && eocd[i+1] == 0x4b && eocd[i+2] == 0x05 && eocd[i+3] == 0x06) {
-      // If the sequence $50 $4b $05 $06 appears anywhere after the real one, libziparchive will
-      // find the later (wrong) one, which could be exploitable. Fail the verification if this
-      // sequence occurs anywhere after the real one.
-      LOG(ERROR) << "EOCD marker occurs after start of EOCD";
-      return VERIFY_FAILURE;
-    }
-  }
-
-  bool need_sha1 = false;
-  bool need_sha256 = false;
-  for (const auto& key : keys) {
-    switch (key.hash_len) {
-      case SHA_DIGEST_LENGTH: need_sha1 = true; break;
-      case SHA256_DIGEST_LENGTH: need_sha256 = true; break;
-    }
-  }
-
-  SHA_CTX sha1_ctx;
-  SHA256_CTX sha256_ctx;
-  SHA1_Init(&sha1_ctx);
-  SHA256_Init(&sha256_ctx);
-
-  double frac = -1.0;
-  size_t so_far = 0;
-  while (so_far < signed_len) {
-    // On a Nexus 5X, experiment showed 16MiB beat 1MiB by 6% faster for a
-    // 1196MiB full OTA and 60% for an 89MiB incremental OTA.
-    // http://b/28135231.
-    size_t size = std::min(signed_len - so_far, 16 * MiB);
-
-    if (need_sha1) SHA1_Update(&sha1_ctx, addr + so_far, size);
-    if (need_sha256) SHA256_Update(&sha256_ctx, addr + so_far, size);
-    so_far += size;
-
-    if (set_progress) {
-      double f = so_far / (double)signed_len;
-      if (f > frac + 0.02 || size == so_far) {
-        set_progress(f);
-        frac = f;
-      }
-    }
-  }
-
-  uint8_t sha1[SHA_DIGEST_LENGTH];
-  SHA1_Final(sha1, &sha1_ctx);
-  uint8_t sha256[SHA256_DIGEST_LENGTH];
-  SHA256_Final(sha256, &sha256_ctx);
-
-  const uint8_t* signature = eocd + eocd_size - signature_start;
-  size_t signature_size = signature_start - FOOTER_SIZE;
-
-  LOG(INFO) << "signature (offset: " << std::hex << (length - signature_start) << ", length: "
-            << signature_size << "): " << print_hex(signature, signature_size);
-
-  std::vector<uint8_t> sig_der;
-  if (!read_pkcs7(signature, signature_size, &sig_der)) {
-    LOG(ERROR) << "Could not find signature DER block";
-    return VERIFY_FAILURE;
-  }
-
-  // Check to make sure at least one of the keys matches the signature. Since any key can match,
-  // we need to try each before determining a verification failure has happened.
-  size_t i = 0;
-  for (const auto& key : keys) {
-    const uint8_t* hash;
-    int hash_nid;
-    switch (key.hash_len) {
-      case SHA_DIGEST_LENGTH:
-        hash = sha1;
-        hash_nid = NID_sha1;
-        break;
-      case SHA256_DIGEST_LENGTH:
-        hash = sha256;
-        hash_nid = NID_sha256;
-        break;
-      default:
-        continue;
-    }
-
-    // The 6 bytes is the "(signature_start) $ff $ff (comment_size)" that the signing tool appends
-    // after the signature itself.
-    if (key.key_type == Certificate::KEY_TYPE_RSA) {
-      if (!RSA_verify(hash_nid, hash, key.hash_len, sig_der.data(), sig_der.size(),
-                      key.rsa.get())) {
-        LOG(INFO) << "failed to verify against RSA key " << i;
-        continue;
-      }
-
-      LOG(INFO) << "whole-file signature verified against RSA key " << i;
-      return VERIFY_SUCCESS;
-    } else if (key.key_type == Certificate::KEY_TYPE_EC && key.hash_len == SHA256_DIGEST_LENGTH) {
-      if (!ECDSA_verify(0, hash, key.hash_len, sig_der.data(), sig_der.size(), key.ec.get())) {
-        LOG(INFO) << "failed to verify against EC key " << i;
-        continue;
-      }
-
-      LOG(INFO) << "whole-file signature verified against EC key " << i;
-      return VERIFY_SUCCESS;
-    } else {
-      LOG(INFO) << "Unknown key type " << key.key_type;
-    }
-    i++;
-  }
-
-  if (need_sha1) {
-    LOG(INFO) << "SHA-1 digest: " << print_hex(sha1, SHA_DIGEST_LENGTH);
-  }
-  if (need_sha256) {
-    LOG(INFO) << "SHA-256 digest: " << print_hex(sha256, SHA256_DIGEST_LENGTH);
-  }
-  LOG(ERROR) << "failed to verify whole-file signature";
-  return VERIFY_FAILURE;
-}
-
-std::unique_ptr<RSA, RSADeleter> parse_rsa_key(FILE* file, uint32_t exponent) {
-    // Read key length in words and n0inv. n0inv is a precomputed montgomery
-    // parameter derived from the modulus and can be used to speed up
-    // verification. n0inv is 32 bits wide here, assuming the verification logic
-    // uses 32 bit arithmetic. However, BoringSSL may use a word size of 64 bits
-    // internally, in which case we don't have a valid n0inv. Thus, we just
-    // ignore the montgomery parameters and have BoringSSL recompute them
-    // internally. If/When the speedup from using the montgomery parameters
-    // becomes relevant, we can add more sophisticated code here to obtain a
-    // 64-bit n0inv and initialize the montgomery parameters in the key object.
-    uint32_t key_len_words = 0;
-    uint32_t n0inv = 0;
-    if (fscanf(file, " %i , 0x%x", &key_len_words, &n0inv) != 2) {
-        return nullptr;
-    }
-
-    if (key_len_words > 8192 / 32) {
-        LOG(ERROR) << "key length (" << key_len_words << ") too large";
-        return nullptr;
-    }
-
-    // Read the modulus.
-    std::unique_ptr<uint32_t[]> modulus(new uint32_t[key_len_words]);
-    if (fscanf(file, " , { %u", &modulus[0]) != 1) {
-        return nullptr;
-    }
-    for (uint32_t i = 1; i < key_len_words; ++i) {
-        if (fscanf(file, " , %u", &modulus[i]) != 1) {
-            return nullptr;
-        }
-    }
-
-    // Cconvert from little-endian array of little-endian words to big-endian
-    // byte array suitable as input for BN_bin2bn.
-    std::reverse((uint8_t*)modulus.get(),
-                 (uint8_t*)(modulus.get() + key_len_words));
-
-    // The next sequence of values is the montgomery parameter R^2. Since we
-    // generally don't have a valid |n0inv|, we ignore this (see comment above).
-    uint32_t rr_value;
-    if (fscanf(file, " } , { %u", &rr_value) != 1) {
-        return nullptr;
-    }
-    for (uint32_t i = 1; i < key_len_words; ++i) {
-        if (fscanf(file, " , %u", &rr_value) != 1) {
-            return nullptr;
-        }
-    }
-    if (fscanf(file, " } } ") != 0) {
-        return nullptr;
-    }
-
-    // Initialize the key.
-    std::unique_ptr<RSA, RSADeleter> key(RSA_new());
-    if (!key) {
-      return nullptr;
-    }
-
-    key->n = BN_bin2bn((uint8_t*)modulus.get(),
-                       key_len_words * sizeof(uint32_t), NULL);
-    if (!key->n) {
-      return nullptr;
-    }
-
-    key->e = BN_new();
-    if (!key->e || !BN_set_word(key->e, exponent)) {
-      return nullptr;
-    }
-
-    return key;
-}
-
-struct BNDeleter {
-  void operator()(BIGNUM* bn) const {
-    BN_free(bn);
-  }
-};
-
-std::unique_ptr<EC_KEY, ECKEYDeleter> parse_ec_key(FILE* file) {
-    uint32_t key_len_bytes = 0;
-    if (fscanf(file, " %i", &key_len_bytes) != 1) {
-        return nullptr;
-    }
-
-    std::unique_ptr<EC_GROUP, void (*)(EC_GROUP*)> group(
-        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1), EC_GROUP_free);
-    if (!group) {
-        return nullptr;
-    }
-
-    // Verify that |key_len| matches the group order.
-    if (key_len_bytes != BN_num_bytes(EC_GROUP_get0_order(group.get()))) {
-        return nullptr;
-    }
-
-    // Read the public key coordinates. Note that the byte order in the file is
-    // little-endian, so we convert to big-endian here.
-    std::unique_ptr<uint8_t[]> bytes(new uint8_t[key_len_bytes]);
-    std::unique_ptr<BIGNUM, BNDeleter> point[2];
-    for (int i = 0; i < 2; ++i) {
-        unsigned int byte = 0;
-        if (fscanf(file, " , { %u", &byte) != 1) {
-            return nullptr;
-        }
-        bytes[key_len_bytes - 1] = byte;
-
-        for (size_t i = 1; i < key_len_bytes; ++i) {
-            if (fscanf(file, " , %u", &byte) != 1) {
-                return nullptr;
-            }
-            bytes[key_len_bytes - i - 1] = byte;
-        }
-
-        point[i].reset(BN_bin2bn(bytes.get(), key_len_bytes, nullptr));
-        if (!point[i]) {
-            return nullptr;
-        }
-
-        if (fscanf(file, " }") != 0) {
-            return nullptr;
-        }
-    }
-
-    if (fscanf(file, " } ") != 0) {
-        return nullptr;
-    }
-
-    // Create and initialize the key.
-    std::unique_ptr<EC_KEY, ECKEYDeleter> key(EC_KEY_new());
-    if (!key || !EC_KEY_set_group(key.get(), group.get()) ||
-        !EC_KEY_set_public_key_affine_coordinates(key.get(), point[0].get(),
-                                                  point[1].get())) {
-        return nullptr;
-    }
-
-    return key;
-}
-
-// Reads a file containing one or more public keys as produced by
-// DumpPublicKey:  this is an RSAPublicKey struct as it would appear
-// as a C source literal, eg:
-//
-//  "{64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
-//
-// For key versions newer than the original 2048-bit e=3 keys
-// supported by Android, the string is preceded by a version
-// identifier, eg:
-//
-//  "v2 {64,0xc926ad21,{1795090719,...,-695002876},{-857949815,...,1175080310}}"
-//
-// (Note that the braces and commas in this example are actual
-// characters the parser expects to find in the file; the ellipses
-// indicate more numbers omitted from this example.)
-//
-// The file may contain multiple keys in this format, separated by
-// commas.  The last key must not be followed by a comma.
-//
-// A Certificate is a pair of an RSAPublicKey and a particular hash
-// (we support SHA-1 and SHA-256; we store the hash length to signify
-// which is being used).  The hash used is implied by the version number.
-//
-//       1: 2048-bit RSA key with e=3 and SHA-1 hash
-//       2: 2048-bit RSA key with e=65537 and SHA-1 hash
-//       3: 2048-bit RSA key with e=3 and SHA-256 hash
-//       4: 2048-bit RSA key with e=65537 and SHA-256 hash
-//       5: 256-bit EC key using the NIST P-256 curve parameters and SHA-256 hash
-//
-// Returns true on success, and appends the found keys (at least one) to certs.
-// Otherwise returns false if the file failed to parse, or if it contains zero
-// keys. The contents in certs would be unspecified on failure.
-bool load_keys(const char* filename, std::vector<Certificate>& certs) {
-  std::unique_ptr<FILE, decltype(&fclose)> f(fopen(filename, "re"), fclose);
-  if (!f) {
-    PLOG(ERROR) << "error opening " << filename;
-    return false;
-  }
-
-  while (true) {
-    certs.emplace_back(0, Certificate::KEY_TYPE_RSA, nullptr, nullptr);
-    Certificate& cert = certs.back();
-    uint32_t exponent = 0;
-
-    char start_char;
-    if (fscanf(f.get(), " %c", &start_char) != 1) return false;
-    if (start_char == '{') {
-      // a version 1 key has no version specifier.
-      cert.key_type = Certificate::KEY_TYPE_RSA;
-      exponent = 3;
-      cert.hash_len = SHA_DIGEST_LENGTH;
-    } else if (start_char == 'v') {
-      int version;
-      if (fscanf(f.get(), "%d {", &version) != 1) return false;
-      switch (version) {
-        case 2:
-          cert.key_type = Certificate::KEY_TYPE_RSA;
-          exponent = 65537;
-          cert.hash_len = SHA_DIGEST_LENGTH;
-          break;
-        case 3:
-          cert.key_type = Certificate::KEY_TYPE_RSA;
-          exponent = 3;
-          cert.hash_len = SHA256_DIGEST_LENGTH;
-          break;
-        case 4:
-          cert.key_type = Certificate::KEY_TYPE_RSA;
-          exponent = 65537;
-          cert.hash_len = SHA256_DIGEST_LENGTH;
-          break;
-        case 5:
-          cert.key_type = Certificate::KEY_TYPE_EC;
-          cert.hash_len = SHA256_DIGEST_LENGTH;
-          break;
-        default:
-          return false;
-      }
-    }
-
-    if (cert.key_type == Certificate::KEY_TYPE_RSA) {
-      cert.rsa = parse_rsa_key(f.get(), exponent);
-      if (!cert.rsa) {
-        return false;
-      }
-
-      LOG(INFO) << "read key e=" << exponent << " hash=" << cert.hash_len;
-    } else if (cert.key_type == Certificate::KEY_TYPE_EC) {
-      cert.ec = parse_ec_key(f.get());
-      if (!cert.ec) {
-        return false;
-      }
-    } else {
-      LOG(ERROR) << "Unknown key type " << cert.key_type;
-      return false;
-    }
-
-    // if the line ends in a comma, this file has more keys.
-    int ch = fgetc(f.get());
-    if (ch == ',') {
-      // more keys to come.
-      continue;
-    } else if (ch == EOF) {
-      break;
-    } else {
-      LOG(ERROR) << "unexpected character between keys";
-      return false;
-    }
-  }
-  return true;
-}
diff --git a/verifier28/verifier.h b/verifier28/verifier.h
deleted file mode 100644
index 665e5a9..0000000
--- a/verifier28/verifier.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _RECOVERY_VERIFIER_H
-#define _RECOVERY_VERIFIER_H
-
-#include <functional>
-#include <memory>
-#include <vector>
-
-#include <openssl/ec_key.h>
-#include <openssl/rsa.h>
-#include <openssl/sha.h>
-
-#define ASSUMED_UPDATE_BINARY_NAME  "META-INF/com/google/android/update-binary"
-
-enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_RETRY };
-
-static const float VERIFICATION_PROGRESS_FRAC = 0.25;
-
-struct RSADeleter {
-  void operator()(RSA* rsa) const {
-    RSA_free(rsa);
-  }
-};
-
-struct ECKEYDeleter {
-  void operator()(EC_KEY* ec_key) const {
-    EC_KEY_free(ec_key);
-  }
-};
-
-struct Certificate {
-    typedef enum {
-        KEY_TYPE_RSA,
-        KEY_TYPE_EC,
-    } KeyType;
-
-    Certificate(int hash_len_,
-                KeyType key_type_,
-                std::unique_ptr<RSA, RSADeleter>&& rsa_,
-                std::unique_ptr<EC_KEY, ECKEYDeleter>&& ec_)
-        : hash_len(hash_len_),
-          key_type(key_type_),
-          rsa(std::move(rsa_)),
-          ec(std::move(ec_)) {}
-
-    // SHA_DIGEST_LENGTH (SHA-1) or SHA256_DIGEST_LENGTH (SHA-256)
-    int hash_len;
-    KeyType key_type;
-    std::unique_ptr<RSA, RSADeleter> rsa;
-    std::unique_ptr<EC_KEY, ECKEYDeleter> ec;
-};
-
-/*
- * 'addr' and 'length' define an update package file that has been loaded (or mmap'ed, or
- * whatever) into memory. Verifies that the file is signed and the signature matches one of the
- * given keys. It optionally accepts a callback function for posting the progress to. Returns one
- * of the constants of VERIFY_SUCCESS and VERIFY_FAILURE.
- */
-int verify_file(const unsigned char* addr, size_t length, const std::vector<Certificate>& keys,
-                const std::function<void(float)>& set_progress = nullptr);
-
-bool load_keys(const char* filename, std::vector<Certificate>& certs);
-
-#define VERIFY_SUCCESS        0
-#define VERIFY_FAILURE        1
-
-#endif  /* _RECOVERY_VERIFIER_H */