AOSP10 TWRP Merge: fix conflicts and update libraries needed

This allows flame to boot TWRP. Still will need to work on
super partition for vendor and system access.

The plan will be to cherry-pick any updates to android-9.0
through gerrit.twrp.me to this branch as a WIP.
diff --git a/install/ZipUtil.cpp b/install/ZipUtil.cpp
new file mode 100755
index 0000000..f8134bc
--- /dev/null
+++ b/install/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/install/ZipUtil.h b/install/ZipUtil.h
new file mode 100644
index 0000000..cda405c
--- /dev/null
+++ b/install/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/install/adb_install.cpp b/install/adb_install.cpp
old mode 100644
new mode 100755
index 9497df5..44a58a0
--- a/install/adb_install.cpp
+++ b/install/adb_install.cpp
@@ -90,7 +90,7 @@
 
 // Installs the package from FUSE. Returns the installation result and whether it should continue
 // waiting for new commands.
-static auto AdbInstallPackageHandler(RecoveryUI* ui, int* result) {
+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
@@ -106,11 +106,11 @@
         continue;
       } else {
         should_continue = false;
-        ui->Print("\nTimed out waiting for fuse to be ready.\n\n");
+        // ui->Print("\nTimed out waiting for fuse to be ready.\n\n");
         break;
       }
     }
-    *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0, ui);
+    *result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0);
     break;
   }
 
@@ -182,7 +182,7 @@
 
 // TODO(xunchang) add a wrapper function and kill the minadbd service there.
 static void ListenAndExecuteMinadbdCommands(
-    RecoveryUI* ui, pid_t minadbd_pid, android::base::unique_fd&& socket_fd,
+    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) {
@@ -206,8 +206,8 @@
   constexpr int TIMEOUT_MILLIS = 300 * 1000;
   while (true) {
     // Reset the progress bar and the background image before each command.
-    ui->SetProgressType(RecoveryUI::EMPTY);
-    ui->SetBackground(RecoveryUI::NO_COMMAND);
+    // ui->SetProgressType(RecoveryUI::EMPTY);
+    // ui->SetBackground(RecoveryUI::NO_COMMAND);
 
     // Poll for the status change of the socket_fd, and handle the message if the fd is ready to
     // read.
@@ -272,8 +272,8 @@
 //                               b11. exit the listening loop
 //
 static void CreateMinadbdServiceAndExecuteCommands(
-    RecoveryUI* ui, const std::map<MinadbdCommand, CommandFunction>& command_map,
-    bool rescue_mode) {
+    const std::map<MinadbdCommand, CommandFunction>& command_map,
+    bool rescue_mode, std::string install_file) {
   signal(SIGPIPE, SIG_IGN);
 
   android::base::unique_fd recovery_socket;
@@ -291,8 +291,10 @@
   if (child == 0) {
     recovery_socket.reset();
     std::vector<std::string> minadbd_commands = {
-      "/system/bin/minadbd",
-      "--socket_fd",
+      "/sbin/recovery",
+      "recovery",
+      "--adbd",
+      install_file,
       std::to_string(minadbd_socket.release()),
     };
     if (rescue_mode) {
@@ -312,7 +314,7 @@
     return;
   }
 
-  std::thread listener_thread(ListenAndExecuteMinadbdCommands, ui, child,
+  std::thread listener_thread(ListenAndExecuteMinadbdCommands, child,
                               std::move(recovery_socket), std::ref(command_map));
   if (listener_thread.joinable()) {
     listener_thread.join();
@@ -331,7 +333,9 @@
   signal(SIGPIPE, SIG_DFL);
 }
 
-int ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) {
+// int ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action) {
+  int ApplyFromAdb(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.
@@ -340,24 +344,25 @@
     return INSTALL_ERROR;
   }
 
-  RecoveryUI* ui = device->GetUI();
+  // RecoveryUI* ui = device->GetUI();
 
   int install_result = INSTALL_ERROR;
   std::map<MinadbdCommand, CommandFunction> command_map{
-    { MinadbdCommand::kInstall, std::bind(&AdbInstallPackageHandler, ui, &install_result) },
-    { MinadbdCommand::kRebootAndroid, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootAndroid,
+  { 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::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) },
-  };
+  { MinadbdCommand::kRebootRecovery, std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRecovery,
+                                                &install_result, reboot_action) },
+  { MinadbdCommand::kRebootRescue,
+    std::bind(&AdbRebootHandler, MinadbdCommand::kRebootRescue, &install_result, reboot_action) },
+};
 
+/*
   if (!rescue_mode) {
     ui->Print(
         "\n\nNow send the package you want to apply\n"
@@ -371,8 +376,8 @@
 
     ui->Print("\n\nWaiting for rescue commands...\n");
   }
-
-  CreateMinadbdServiceAndExecuteCommands(ui, command_map, rescue_mode);
+*/
+  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.
diff --git a/install/fuse_sdcard_install.cpp b/install/fuse_sdcard_install.cpp
old mode 100644
new mode 100755
index 1aa8768..011847b
--- a/install/fuse_sdcard_install.cpp
+++ b/install/fuse_sdcard_install.cpp
@@ -184,7 +184,7 @@
       }
     }
 
-    result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/, ui);
+    result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, false, false, 0 /*retry_count*/);
     break;
   }
 
diff --git a/install/include/install/adb_install.h b/install/include/install/adb_install.h
old mode 100644
new mode 100755
index 3a0a817..f7b15b2
--- a/install/include/install/adb_install.h
+++ b/install/include/install/adb_install.h
@@ -21,4 +21,4 @@
 // 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 ApplyFromAdb(Device* device, bool rescue_mode, Device::BuiltinAction* reboot_action);
+int ApplyFromAdb(const char* install_file, Device::BuiltinAction* reboot_action);
diff --git a/install/include/install/fuse_sdcard_install.h b/install/include/install/fuse_sdcard_install.h
old mode 100644
new mode 100755
index 43f2489..d9214ca
--- a/install/include/install/fuse_sdcard_install.h
+++ b/install/include/install/fuse_sdcard_install.h
@@ -16,17 +16,7 @@
 
 #pragma once
 
-<<<<<<< HEAD:adb_install.h
-#include <sys/types.h>
-
-//class RecoveryUI;
-
-//static void set_usb_driver(bool enabled);
-//static void maybe_restart_adbd();
-int apply_from_adb(const char* install_file, pid_t* child_pid);
-=======
 #include "recovery_ui/device.h"
 #include "recovery_ui/ui.h"
->>>>>>> android-10.0.0_r25:install/include/install/fuse_sdcard_install.h
 
 int ApplyFromSdcard(Device* device, RecoveryUI* ui);
diff --git a/install/include/install/install.h b/install/include/install/install.h
old mode 100644
new mode 100755
index c0a8f1f..9e6787f
--- a/install/include/install/install.h
+++ b/install/include/install/install.h
@@ -48,11 +48,11 @@
 // 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, RecoveryUI* ui);
+                    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, RecoveryUI* ui);
+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.
diff --git a/install/include/install/package.h b/install/include/install/package.h
old mode 100644
new mode 100755
index cd44d10..50a4ffa
--- a/install/include/install/package.h
+++ b/install/include/install/package.h
@@ -33,9 +33,9 @@
 class Package : public VerifierInterface {
  public:
   static std::unique_ptr<Package> CreateMemoryPackage(
-      const std::string& path, const std::function<void(float)>& set_progress);
+      const std::string& path);
   static std::unique_ptr<Package> CreateMemoryPackage(
-      std::vector<uint8_t> content, const std::function<void(float)>& set_progress);
+      std::vector<uint8_t> content);
   static std::unique_ptr<Package> CreateFilePackage(const std::string& path,
                                                     const std::function<void(float)>& set_progress);
 
diff --git a/install/include/install/wipe_data.h b/install/include/install/wipe_data.h
old mode 100644
new mode 100755
index b34891f..76ebf05
--- a/install/include/install/wipe_data.h
+++ b/install/include/install/wipe_data.h
@@ -24,7 +24,7 @@
 struct selabel_handle;
 
 // Returns true on success.
-bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm);
+bool WipeCache(const std::function<bool()>& confirm);
 
 // Returns true on success.
 bool WipeData(Device* device, bool convert_fbe);
diff --git a/install/include/installcommand.h b/install/include/installcommand.h
new file mode 100644
index 0000000..957f016
--- /dev/null
+++ b/install/include/installcommand.h
@@ -0,0 +1,39 @@
+/*
+ * 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 RECOVERY_INSTALL_COMMAND_H_
+#define RECOVERY_INSTALL_COMMAND_H_
+
+#define TMP_UPDATER_BINARY_PATH "/tmp/updater"
+
+#include <string>
+
+#include "zipwrap.hpp"
+
+bool read_metadata_from_package(ZipWrap* zip, std::string* meta_data);
+
+int
+abupdate_binary_command(const char* path, ZipWrap* zip, 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);
+
+void read_source_target_build(ZipWrap* zip/*, std::vector<std::string>& log_buffer*/);
+
+#endif  // RECOVERY_INSTALL_COMMAND_H_
diff --git a/install/include/legacy_property_service.h b/install/include/legacy_property_service.h
new file mode 100644
index 0000000..d20bdef
--- /dev/null
+++ b/install/include/legacy_property_service.h
@@ -0,0 +1,25 @@
+/*
+ * 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 _LEGACY_PROPERTY_H
+#define _LEGACY_PROPERTY_H
+
+#include <stdbool.h>
+
+void legacy_get_property_workspace(int *fd, int *sz);
+int legacy_properties_init();
+
+#endif	/* _LEGACY_PROPERTY_H */
diff --git a/install/include/set_metadata.h b/install/include/set_metadata.h
new file mode 100644
index 0000000..9a46be9
--- /dev/null
+++ b/install/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/install/include/tw_atomic.hpp
new file mode 100644
index 0000000..0f29f02
--- /dev/null
+++ b/install/include/tw_atomic.hpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef _TWATOMIC_HPP_HEADER
+#define _TWATOMIC_HPP_HEADER
+
+#include <pthread.h>
+
+class TWAtomicInt
+{
+public:
+	TWAtomicInt(int initial_value = 0);
+	~TWAtomicInt();
+	void set_value(int new_value);
+	int get_value();
+
+private:
+	int value;
+	bool use_mutex;
+	pthread_mutex_t mutex_lock;
+};
+
+#endif //_TWATOMIC_HPP_HEADER
diff --git a/install/include/zipwrap.hpp b/install/include/zipwrap.hpp
new file mode 100755
index 0000000..7102116
--- /dev/null
+++ b/install/include/zipwrap.hpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) TeamWin
+ * This file is part of TWRP/TeamWin 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.
+ */
+
+#ifndef __ZIPWRAP_HPP
+#define __ZIPWRAP_HPP
+
+#include <string>
+#ifdef USE_MINZIP
+#include "minzip/Zip.h"
+#include "minzip/SysUtil.h"
+#else
+#include <ziparchive/zip_archive.h>
+#include "otautil/sysutil.h"
+#endif
+
+using namespace std;
+
+class ZipWrap {
+	public:
+		ZipWrap();
+		~ZipWrap();
+
+		bool Open(const char* file, MemMapping* map);
+		void Close();
+		bool EntryExists(const string& filename);
+		bool ExtractEntry(const string& source_file, const string& target_file, mode_t mode);
+
+		long GetUncompressedSize(const string& filename);
+		bool ExtractToBuffer(const string& filename, uint8_t* begin);
+		bool ExtractRecursive(const string& source_dir, const string& target_dir);
+#ifdef USE_MINZIP
+		loff_t GetEntryOffset(const string& filename);
+#else
+		off64_t GetEntryOffset(const string& filename);
+		ZipArchiveHandle GetZipArchiveHandle();
+#endif
+
+	private:
+#ifdef USE_MINZIP
+		ZipArchive Zip;
+#else
+		ZipArchiveHandle Zip;
+#endif
+		string zip_file;
+		bool zip_open;
+};
+
+#endif //__ZIPWRAP_HPP
diff --git a/install/install.cpp b/install/install.cpp
old mode 100644
new mode 100755
index 0e3cccf..55d51fc
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -64,8 +64,8 @@
 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 constexpr int VERIFICATION_PROGRESS_TIME = 60;
+// static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
 
 static std::condition_variable finish_log_temperature;
 
@@ -157,8 +157,6 @@
     return INSTALL_ERROR;
   }
 
-<<<<<<< HEAD:install.cpp
-=======
   // Check for downgrade version.
   int64_t build_timestamp =
       android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max());
@@ -182,7 +180,6 @@
     }
   }
 
->>>>>>> android-10.0.0_r25:install/install.cpp
   return 0;
 }
 
@@ -330,7 +327,7 @@
 // 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, RecoveryUI* ui) {
+                             int* max_temperature) {
   std::map<std::string, std::string> metadata;
   if (!ReadMetadataFromPackage(zip, &metadata)) {
     LOG(ERROR) << "Failed to parse metadata in the zip file";
@@ -442,7 +439,7 @@
       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);
+        // ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
       } else {
         LOG(ERROR) << "invalid \"progress\" parameters: " << line;
       }
@@ -450,22 +447,22 @@
       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);
+        // ui->SetProgress(fraction);
       } else {
         LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
       }
     } else if (command == "ui_print") {
-      ui->PrintOnScreenOnly("%s\n", args.c_str());
+      // 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);
+      // 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);
+      // ui->SetEnableReboot(true);
     } else if (command == "retry_update") {
       retry_update = true;
     } else if (command == "log") {
@@ -576,16 +573,16 @@
 
 static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
                                   std::vector<std::string>* log_buffer, int retry_count,
-                                  int* max_temperature, RecoveryUI* ui) {
-  ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
-  ui->Print("Finding update package...\n");
+                                  int* max_temperature) {
+  // 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);
+  // 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");
+  // ui->Print("Opening update package...\n");
 
   if (needs_mount) {
     if (path[0] == '@') {
@@ -596,14 +593,14 @@
   }
 
   auto package = Package::CreateMemoryPackage(
-      path, std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
+      path);
   if (!package) {
     log_buffer->push_back(android::base::StringPrintf("error: %d", kMapFileFailure));
     return INSTALL_CORRUPT;
   }
 
   // Verify package.
-  if (!verify_package(package.get(), ui)) {
+  if (!verify_package(package.get())) {
     log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
     return INSTALL_CORRUPT;
   }
@@ -622,21 +619,21 @@
   }
 
   // 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);
+  // ui->Print("Installing update...\n");
+  // if (retry_count > 0) {
+    // ui->Print("Retry attempt: %d\n", retry_count);
+  // }
+  // ui->SetEnableReboot(false);
   int result =
-      try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature, ui);
-  ui->SetEnableReboot(true);
-  ui->Print("\n");
+      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, RecoveryUI* ui) {
+                    int retry_count) {
   CHECK(!path.empty());
 
   auto start = std::chrono::system_clock::now();
@@ -652,7 +649,7 @@
   } else {
     bool updater_wipe_cache = false;
     result = really_install_package(path, &updater_wipe_cache, needs_mount, &log_buffer,
-                                    retry_count, &max_temperature, ui);
+                                    retry_count, &max_temperature);
     should_wipe_cache = should_wipe_cache || updater_wipe_cache;
   }
 
@@ -709,7 +706,7 @@
   LOG(INFO) << log_content;
 
   if (result == INSTALL_SUCCESS && should_wipe_cache) {
-    if (!WipeCache(ui, nullptr)) {
+    if (!WipeCache(nullptr)) {
       result = INSTALL_ERROR;
     }
   }
@@ -717,7 +714,7 @@
   return result;
 }
 
-bool verify_package(Package* package, RecoveryUI* ui) {
+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()) {
@@ -727,11 +724,11 @@
   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();
+  // ui->Print("Verifying update package...\n");
+  // auto t0 = std::chrono::system_clock::now();
   int err = verify_file(package, loaded_keys);
-  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);
+  // 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;
diff --git a/install/installcommand.cpp b/install/installcommand.cpp
new file mode 100755
index 0000000..f421056
--- /dev/null
+++ b/install/installcommand.cpp
@@ -0,0 +1,316 @@
+/*
+ * 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 <string>
+#include <vector>
+
+#ifdef AB_OTA_UPDATER
+#include <inttypes.h>
+#include <map>
+#include <android-base/parseint.h>
+#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
+#endif
+#include <cutils/properties.h>
+
+#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
+
+#ifdef AB_OTA_UPDATER
+
+static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
+static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
+static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
+
+// This function parses and returns the build.version.incremental
+static int parse_build_number(std::string str) {
+    size_t pos = str.find("=");
+    if (pos != std::string::npos) {
+        std::string num_string = android::base::Trim(str.substr(pos+1));
+        int build_number;
+        if (android::base::ParseInt(num_string.c_str(), &build_number, 0)) {
+            return build_number;
+        }
+    }
+
+    printf("Failed to parse build number in %s.\n", str.c_str());
+    return -1;
+}
+
+bool read_metadata_from_package(ZipWrap* zip, std::string* meta_data) {
+    long size = zip->GetUncompressedSize(METADATA_PATH);
+    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;
+}
+
+// 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*/) {
+    std::string meta_data;
+    if (!read_metadata_from_package(zip, &meta_data)) {
+        return;
+    }
+    // Examples of the pre-build and post-build strings in metadata:
+    // pre-build-incremental=2943039
+    // post-build-incremental=2951741
+    std::vector<std::string> lines = android::base::Split(meta_data, "\n");
+    for (const std::string& line : lines) {
+        std::string str = android::base::Trim(line);
+        if (android::base::StartsWith(str, "pre-build-incremental")){
+            int source_build = parse_build_number(str);
+            if (source_build != -1) {
+                printf("source_build: %d\n", source_build);
+                /*log_buffer.push_back(android::base::StringPrintf("source_build: %d",
+                        source_build));*/
+            }
+        } else if (android::base::StartsWith(str, "post-build-incremental")) {
+            int target_build = parse_build_number(str);
+            if (target_build != -1) {
+                printf("target_build: %d\n", target_build);
+                /*log_buffer.push_back(android::base::StringPrintf("target_build: %d",
+                        target_build));*/
+            }
+        }
+    }
+}
+
+// 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)
+{
+    std::string metadata_str;
+    if (!read_metadata_from_package(zip, &metadata_str)) {
+        return INSTALL_CORRUPT;
+    }
+    std::map<std::string, std::string> metadata;
+    for (const std::string& line : android::base::Split(metadata_str, "\n")) {
+        size_t eq = line.find('=');
+        if (eq != std::string::npos) {
+            metadata[line.substr(0, eq)] = line.substr(eq + 1);
+        }
+    }
+    char value[PROPERTY_VALUE_MAX];
+
+    property_get("ro.product.device", value, "");
+    const std::string& pkg_device = metadata["pre-device"];
+    if (pkg_device != value || pkg_device.empty()) {
+        printf("Package is for product %s but expected %s\n",
+             pkg_device.c_str(), value);
+        return INSTALL_ERROR;
+    }
+
+    // We allow the package to not have any serialno, but if it has a non-empty
+    // value it should match.
+    property_get("ro.serialno", value, "");
+    const std::string& pkg_serial_no = metadata["serialno"];
+    if (!pkg_serial_no.empty() && pkg_serial_no != value) {
+        printf("Package is for serial %s\n", pkg_serial_no.c_str());
+        return INSTALL_ERROR;
+    }
+
+    if (metadata["ota-type"] != "AB") {
+        printf("Package is not A/B\n");
+        return INSTALL_ERROR;
+    }
+
+    // Incremental updates should match the current build.
+    property_get("ro.build.version.incremental", value, "");
+    const std::string& pkg_pre_build = metadata["pre-build-incremental"];
+    if (!pkg_pre_build.empty() && pkg_pre_build != value) {
+        printf("Package is for source build %s but expected %s\n",
+             pkg_pre_build.c_str(), value);
+        return INSTALL_ERROR;
+    }
+    property_get("ro.build.fingerprint", value, "");
+    const std::string& pkg_pre_build_fingerprint = metadata["pre-build"];
+    if (!pkg_pre_build_fingerprint.empty() &&
+        pkg_pre_build_fingerprint != value) {
+        printf("Package is for source build %s but expected %s\n",
+             pkg_pre_build_fingerprint.c_str(), value);
+        return INSTALL_ERROR;
+    }
+
+    return 0;
+}
+
+int
+abupdate_binary_command(const char* path, ZipWrap* zip, int retry_count __unused,
+                      int status_fd, std::vector<std::string>* cmd)
+{
+    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)) {
+        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())) {
+        printf("Can't extract %s\n", AB_OTA_PAYLOAD_PROPERTIES);
+        return INSTALL_CORRUPT;
+    }
+
+    if (!zip->EntryExists(AB_OTA_PAYLOAD)) {
+        printf("Can't find %s\n", AB_OTA_PAYLOAD);
+        return INSTALL_CORRUPT;
+    }
+    long payload_offset = zip->GetEntryOffset(AB_OTA_PAYLOAD);
+    *cmd = {
+        "/sbin/update_engine_sideload",
+        android::base::StringPrintf("--payload=file://%s", path),
+        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 INSTALL_SUCCESS;
+}
+
+#else
+
+void read_source_target_build(ZipWrap* zip __unused /*, std::vector<std::string>& log_buffer*/) {return;}
+
+int
+abupdate_binary_command(__unused const char* path, __unused ZipWrap* zip, __unused int retry_count,
+                      __unused int status_fd, __unused std::vector<std::string>* cmd)
+{
+    printf("No support for AB OTA zips included\n");
+    return INSTALL_CORRUPT;
+}
+
+#endif
+
+int
+update_binary_command(const char* path, int retry_count,
+                      int status_fd, std::vector<std::string>* cmd)
+{
+    char charfd[16];
+    sprintf(charfd, "%i", status_fd);
+    cmd->push_back(TMP_UPDATER_BINARY_PATH);
+    cmd->push_back(EXPAND(RECOVERY_API_VERSION));
+    cmd->push_back(charfd);
+    cmd->push_back(path);
+    /**cmd = {
+        TMP_UPDATER_BINARY_PATH,
+        EXPAND(RECOVERY_API_VERSION),   // defined in Android.mk
+        charfd,
+        path,
+    };*/
+    if (retry_count > 0)
+        cmd->push_back("retry");
+    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();
+  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) {
+    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,
+                             reinterpret_cast<uint8_t*>(&zip_content[0]),
+                             compatibility_entry.uncompressed_length)) != 0) {
+    printf("Failed to read %s: %s\n", 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) {
+    printf("Failed to OpenArchiveFromMemory: %s\n", 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) {
+    printf("Failed to start iterating zip entries: %s\n", 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) {
+      printf("Failed to read %s: %s\n", 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. TODO THIS CAUSES A WEIRD COMPILE ERROR
+  std::string err;
+  int result = android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err);
+  if (result == 0) {
+    return true;
+  }
+
+  printf("Failed to verify package compatibility (result %i): %s\n", result, err.c_str());
+  return false;
+}
+#endif
diff --git a/install/legacy_property_service.cpp b/install/legacy_property_service.cpp
new file mode 100644
index 0000000..c3990f7
--- /dev/null
+++ b/install/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/install/package.cpp b/install/package.cpp
old mode 100644
new mode 100755
index 4402f48..22673cf
--- a/install/package.cpp
+++ b/install/package.cpp
@@ -32,11 +32,10 @@
 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,
-                const std::function<void(float)>& set_progress);
+  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, const std::function<void(float)>& set_progress);
+  MemoryPackage(std::vector<uint8_t> content);
 
   ~MemoryPackage() override;
 
@@ -102,14 +101,14 @@
 };
 
 std::unique_ptr<Package> Package::CreateMemoryPackage(
-    const std::string& path, const std::function<void(float)>& set_progress) {
+    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), set_progress);
+  return std::make_unique<MemoryPackage>(path, std::move(mmap));
 }
 
 std::unique_ptr<Package> Package::CreateFilePackage(
@@ -130,25 +129,21 @@
 }
 
 std::unique_ptr<Package> Package::CreateMemoryPackage(
-    std::vector<uint8_t> content, const std::function<void(float)>& set_progress) {
-  return std::make_unique<MemoryPackage>(std::move(content), set_progress);
+    std::vector<uint8_t> content) {
+  return std::make_unique<MemoryPackage>(std::move(content));
 }
 
-MemoryPackage::MemoryPackage(const std::string& path, std::unique_ptr<MemMapping> map,
-                             const std::function<void(float)>& set_progress)
+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;
-  set_progress_ = set_progress;
 }
 
-MemoryPackage::MemoryPackage(std::vector<uint8_t> content,
-                             const std::function<void(float)>& set_progress)
+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();
-  set_progress_ = set_progress;
 }
 
 MemoryPackage::~MemoryPackage() {
diff --git a/install/set_metadata.cpp b/install/set_metadata.cpp
new file mode 100644
index 0000000..2e1d769
--- /dev/null
+++ b/install/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/install/tw_atomic.cpp
new file mode 100644
index 0000000..31cdd85
--- /dev/null
+++ b/install/tw_atomic.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include "tw_atomic.hpp"
+
+/*
+ * According to this documentation:
+ * https://developer.android.com/training/articles/smp.html
+ * it is recommended to use mutexes instead of atomics. This class
+ * provides us with a wrapper to make "atomic" variables easy to use.
+ */
+
+TWAtomicInt::TWAtomicInt(int initial_value /* = 0 */) {
+	if (pthread_mutex_init(&mutex_lock, NULL) != 0) {
+		// This should hopefully never happen. If it does, the
+		// operations will not be atomic, but we will allow things to
+		// continue anyway after logging the issue and just hope for
+		// the best.
+		printf("TWAtomic error initializing mutex.\n");
+		use_mutex = false;
+	} else {
+		use_mutex = true;
+	}
+	value = initial_value;
+}
+
+TWAtomicInt::~TWAtomicInt() {
+	if (use_mutex)
+		pthread_mutex_destroy(&mutex_lock);
+}
+
+void TWAtomicInt::set_value(int new_value) {
+	if (use_mutex) {
+		pthread_mutex_lock(&mutex_lock);
+		value = new_value;
+		pthread_mutex_unlock(&mutex_lock);
+	} else {
+		value = new_value;
+	}
+}
+
+int TWAtomicInt::get_value(void) {
+	int ret_val;
+
+	if (use_mutex) {
+		pthread_mutex_lock(&mutex_lock);
+		ret_val = value;
+		pthread_mutex_unlock(&mutex_lock);
+	} else {
+		ret_val = value;
+	}
+	return ret_val;
+}
diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp
old mode 100644
new mode 100755
index 765a815..b0e44c7
--- a/install/wipe_data.cpp
+++ b/install/wipe_data.cpp
@@ -36,12 +36,12 @@
 constexpr const char* DATA_ROOT = "/data";
 constexpr const char* METADATA_ROOT = "/metadata";
 
-static bool EraseVolume(const char* volume, RecoveryUI* ui, bool convert_fbe) {
+static bool EraseVolume(const char* volume, bool convert_fbe) {
   bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
   bool is_data = (strcmp(volume, DATA_ROOT) == 0);
 
-  ui->SetBackground(RecoveryUI::ERASING);
-  ui->SetProgressType(RecoveryUI::INDETERMINATE);
+  // ui->SetBackground(RecoveryUI::ERASING);
+  // ui->SetProgressType(RecoveryUI::INDETERMINATE);
 
   std::vector<saved_log_file> log_files;
   if (is_cache) {
@@ -50,7 +50,7 @@
     log_files = ReadLogFilesToMemory();
   }
 
-  ui->Print("Formatting %s...\n", volume);
+  // ui->Print("Formatting %s...\n", volume);
 
   ensure_path_unmounted(volume);
 
@@ -84,10 +84,10 @@
   return (result == 0);
 }
 
-bool WipeCache(RecoveryUI* ui, const std::function<bool()>& confirm_func) {
+bool WipeCache(const std::function<bool()>& confirm_func) {
   bool has_cache = volume_for_mount_point("/cache") != nullptr;
   if (!has_cache) {
-    ui->Print("No /cache partition found.\n");
+    // ui->Print("No /cache partition found.\n");
     return false;
   }
 
@@ -95,29 +95,29 @@
     return false;
   }
 
-  ui->Print("\n-- Wiping cache...\n");
-  bool success = EraseVolume("/cache", ui, false);
-  ui->Print("Cache wipe %s.\n", success ? "complete" : "failed");
+  // ui->Print("\n-- Wiping cache...\n");
+  bool success = EraseVolume("/cache", false);
+  // ui->Print("Cache wipe %s.\n", success ? "complete" : "failed");
   return success;
 }
 
 bool WipeData(Device* device, bool convert_fbe) {
-  RecoveryUI* ui = device->GetUI();
-  ui->Print("\n-- Wiping data...\n");
+  // RecoveryUI* ui = device->GetUI();
+  // ui->Print("\n-- Wiping data...\n");
   bool success = device->PreWipeData();
   if (success) {
-    success &= EraseVolume(DATA_ROOT, ui, convert_fbe);
+    success &= EraseVolume(DATA_ROOT, convert_fbe);
     bool has_cache = volume_for_mount_point("/cache") != nullptr;
     if (has_cache) {
-      success &= EraseVolume(CACHE_ROOT, ui, false);
+      success &= EraseVolume(CACHE_ROOT, false);
     }
     if (volume_for_mount_point(METADATA_ROOT) != nullptr) {
-      success &= EraseVolume(METADATA_ROOT, ui, false);
+      success &= EraseVolume(METADATA_ROOT, false);
     }
   }
   if (success) {
     success &= device->PostWipeData();
   }
-  ui->Print("Data wipe %s.\n", success ? "complete" : "failed");
+  // ui->Print("Data wipe %s.\n", success ? "complete" : "failed");
   return success;
 }
\ No newline at end of file
diff --git a/install/zipwrap.cpp b/install/zipwrap.cpp
new file mode 100755
index 0000000..ddd13de
--- /dev/null
+++ b/install/zipwrap.cpp
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) TeamWin
+ * This file is part of TWRP/TeamWin 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.
+ */
+
+#include "zipwrap.hpp"
+#include <string>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#ifdef USE_MINZIP
+#include "minzip/Zip.h"
+#include "minzip/SysUtil.h"
+#else
+#include <ziparchive/zip_archive.h>
+#include "ZipUtil.h"
+#include "otautil/sysutil.h"
+#endif
+
+ZipWrap::ZipWrap() {
+	zip_open = false;
+}
+
+ZipWrap::~ZipWrap() {
+	if (zip_open)
+		Close();
+}
+
+bool ZipWrap::Open(const char* file, MemMapping* map) {
+	if (zip_open) {
+		printf("ZipWrap '%s' is already open\n", zip_file.c_str());
+		return true;
+	}
+	zip_file = file;
+#ifdef USE_MINZIP
+	if (mzOpenZipArchive(map->addr, map->length, &Zip) != 0)
+		return false;
+#else
+	if (OpenArchiveFromMemory(map->addr, map->length, file, &Zip) != 0)
+		return false;
+#endif
+	zip_open = true;
+	return true;
+}
+
+void ZipWrap::Close() {
+	if (zip_open)
+#ifdef USE_MINZIP
+		mzCloseZipArchive(&Zip);
+#else
+		CloseArchive(Zip);
+#endif
+	zip_open = false;
+}
+
+bool ZipWrap::EntryExists(const string& filename) {
+#ifdef USE_MINZIP
+	const ZipEntry* file_location = mzFindZipEntry(&Zip, filename.c_str());
+	if (file_location != NULL)
+		return true;
+	return false;
+#else
+	ZipString zip_string(filename.c_str());
+	ZipEntry file_entry;
+
+	if (FindEntry(Zip, zip_string, &file_entry) != 0)
+		return false;
+	return true;
+#endif
+}
+
+bool ZipWrap::ExtractEntry(const string& source_file, const string& target_file, mode_t mode) {
+	if (access(target_file.c_str(), F_OK) == 0 && unlink(target_file.c_str()) != 0)
+		printf("Unable to unlink '%s': %s\n", target_file.c_str(), strerror(errno));
+	
+	int fd = creat(target_file.c_str(), mode);
+	if (fd < 0) {
+		printf("Failed to create '%s'\n", target_file.c_str());
+		return false;
+	}
+
+#ifdef USE_MINZIP
+	const ZipEntry* file_entry = mzFindZipEntry(&Zip, source_file.c_str());
+	if (file_entry == NULL) {
+		printf("'%s' does not exist in zip '%s'\n", source_file.c_str(), zip_file.c_str());
+		return false;
+	}
+	int ret_val = mzExtractZipEntryToFile(&Zip, file_entry, fd);
+	close(fd);
+
+	if (!ret_val) {
+		printf("Could not extract '%s'\n", target_file.c_str());
+		return false;
+	}
+#else
+	ZipString zip_string(source_file.c_str());
+	ZipEntry file_entry;
+
+	if (FindEntry(Zip, zip_string, &file_entry) != 0)
+		return false;
+	int32_t ret_val = ExtractEntryToFile(Zip, &file_entry, fd);
+	close(fd);
+
+	if (ret_val != 0) {
+		printf("Could not extract '%s'\n", target_file.c_str());
+		return false;
+	}
+#endif
+	return true;
+}
+
+bool ZipWrap::ExtractRecursive(const string& source_dir, const string& target_dir) {
+	struct utimbuf timestamp = { 1217592000, 1217592000 };  // 8/1/2008 default
+#ifdef USE_MINZIP
+	return mzExtractRecursive(&Zip, source_dir.c_str(), target_dir.c_str(), &timestamp, NULL, NULL, NULL);
+#else
+	return ExtractPackageRecursive(Zip, source_dir, target_dir, &timestamp, NULL);
+#endif
+}
+
+long ZipWrap::GetUncompressedSize(const string& filename) {
+#ifdef USE_MINZIP
+	const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
+	if (file_entry == NULL) {
+		printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
+		return 0;
+	}
+	return file_entry->uncompLen;
+#else
+	ZipString zip_string(filename.c_str());
+	ZipEntry file_entry;
+
+	if (FindEntry(Zip, zip_string, &file_entry) != 0)
+		return 0;
+	return file_entry.uncompressed_length;
+#endif
+}
+
+bool ZipWrap::ExtractToBuffer(const string& filename, uint8_t* buffer) {
+#ifdef USE_MINZIP
+	const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
+	if (file_entry == NULL) {
+		printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
+		return false;
+	}
+	if (!mzExtractZipEntryToBuffer(&Zip, file_entry, buffer)) {
+		printf("Failed to read '%s'\n", filename.c_str());
+		return false;
+	}
+#else
+	ZipString zip_string(filename.c_str());
+	ZipEntry file_entry;
+
+	if (FindEntry(Zip, zip_string, &file_entry) != 0)
+		return false;
+	if (ExtractToMemory(Zip, &file_entry, buffer, file_entry.uncompressed_length) != 0) {
+		printf("Failed to read '%s'\n", filename.c_str());
+		return false;
+	}
+#endif
+	return true;
+}
+
+#ifdef USE_MINZIP
+loff_t ZipWrap::GetEntryOffset(const string& filename) {
+	const ZipEntry* file_entry = mzFindZipEntry(&Zip, filename.c_str());
+	if (file_entry == NULL) {
+		printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
+		return 0;
+	}
+	return mzGetZipEntryOffset(file_entry);
+}
+#else
+off64_t ZipWrap::GetEntryOffset(const string& filename) {
+	ZipString zip_string(filename.c_str());
+	ZipEntry file_entry;
+
+	if (FindEntry(Zip, zip_string, &file_entry) != 0) {
+		printf("'%s' does not exist in zip '%s'\n", filename.c_str(), zip_file.c_str());
+		return 0;
+	}
+	return file_entry.offset;
+}
+
+ZipArchiveHandle ZipWrap::GetZipArchiveHandle() {
+	return Zip;
+}
+#endif