Merge "Add IBootControl 1.1 support to libboot_control."
diff --git a/Android.bp b/Android.bp
index 0eb5fd9..45aafb0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -58,7 +58,6 @@
     ],
 
     shared_libs: [
-        "android.hardware.health@2.0",
         "libbase",
         "libbootloader_message",
         "libcrypto",
@@ -72,10 +71,8 @@
         "libinstall",
         "librecovery_fastboot",
         "libminui",
+        "librecovery_utils",
         "libotautil",
-
-        // external dependencies
-        "libhealthhalutils",
     ],
 }
 
@@ -104,6 +101,7 @@
     defaults: [
         "libinstall_defaults",
         "librecovery_defaults",
+        "librecovery_utils_defaults",
     ],
 
     srcs: [
@@ -148,7 +146,7 @@
     ],
 
     static_libs: [
-        "libotautil",
+        "librecovery_utils",
     ],
 
     init_rc: [
@@ -174,7 +172,7 @@
     ],
 
     static_libs: [
-        "libotautil",
+        "librecovery_utils",
     ],
 
     init_rc: [
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8405d20..d4e9e43 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -58,6 +58,17 @@
 $(call add-clean-step, find $(OUT_DIR) -type f -name "SystemUpdaterSample*" -print0 | xargs -0 rm -f)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/priv-app/SystemUpdaterSample)
 
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libbrotli.so)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib*/libbz.so)
+
+# Move recovery resources from /system to /vendor.
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/bin/applypatch)
+$(call add-clean-step, rm -r $(PRODUCT_OUT)/symbols/system/bin/applypatch)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/PACKAGING/target_files_intermediates/*-target_files-*/SYSTEM/bin/applypatch)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/PACKAGING/target_files_intermediates/*-target_files-*/SYSTEM/bin/install-recovery.sh)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/PACKAGING/target_files_intermediates/*-target_files-*/SYSTEM/etc/recovery-resource.dat)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/PACKAGING/target_files_intermediates/*-target_files-*/SYSTEM/recovery-from-boot.p)
+
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
diff --git a/OWNERS b/OWNERS
index b3f11dc..fe1c33d 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
 enh@google.com
-tbao@google.com
+nhdo@google.com
 xunchang@google.com
+zhaojiac@google.com
diff --git a/README.md b/README.md
index 0ccc10b..bd1cf7d 100644
--- a/README.md
+++ b/README.md
@@ -4,19 +4,33 @@
 Quick turn-around testing
 -------------------------
 
-    mm -j && m ramdisk-nodeps && m recoveryimage-nodeps
+* Devices using recovery-as-boot (e.g. Pixels, which set BOARD\_USES\_RECOVERY\_AS\_BOOT)
 
-    # To boot into the new recovery image
-    # without flashing the recovery partition:
-    adb reboot bootloader
-    fastboot boot $ANDROID_PRODUCT_OUT/recovery.img
+      # After setting up environment and lunch.
+      m -j bootimage
+      adb reboot bootloader
+
+      # Pixel devices don't support booting into recovery mode with `fastboot boot`.
+      fastboot flash boot
+
+      # Manually choose `Recovery mode` from bootloader menu.
+
+* Devices with a separate recovery image (e.g. Nexus)
+
+      # After setting up environment and lunch.
+      mm -j && m ramdisk-nodeps && m recoveryimage-nodeps
+      adb reboot bootloader
+
+      # To boot into the new recovery image without flashing the recovery partition:
+      fastboot boot $ANDROID_PRODUCT_OUT/recovery.img
 
 Running the tests
 -----------------
+
     # After setting up environment and lunch.
     mmma -j bootable/recovery
 
-    # Running the tests on device.
+    # Running the tests on device (under normal boot).
     adb root
     adb sync data
 
diff --git a/applypatch/Android.bp b/applypatch/Android.bp
index 42aa529..13a9625 100644
--- a/applypatch/Android.bp
+++ b/applypatch/Android.bp
@@ -31,6 +31,7 @@
     name: "libapplypatch",
 
     host_supported: true,
+    vendor_available: true,
 
     defaults: [
         "applypatch_defaults",
@@ -51,12 +52,15 @@
         "libbase",
         "libbspatch",
         "libbz",
-        "libcrypto",
         "libedify",
         "libotautil",
         "libz",
     ],
 
+    shared_libs: [
+        "libcrypto",
+    ],
+
     target: {
         darwin: {
             enabled: false,
@@ -66,6 +70,7 @@
 
 cc_library_static {
     name: "libapplypatch_modes",
+    vendor_available: true,
 
     defaults: [
         "applypatch_defaults",
@@ -78,14 +83,18 @@
     static_libs: [
         "libapplypatch",
         "libbase",
-        "libcrypto",
         "libedify",
         "libotautil",
     ],
+
+    shared_libs: [
+        "libcrypto",
+    ],
 }
 
 cc_binary {
     name: "applypatch",
+    vendor: true,
 
     defaults: [
         "applypatch_defaults",
@@ -100,18 +109,24 @@
         "libapplypatch",
         "libedify",
         "libotautil",
+
+        // External dependencies.
         "libbspatch",
+        "libbrotli",
+        "libbz",
     ],
 
     shared_libs: [
         "libbase",
-        "libbrotli",
-        "libbz",
         "libcrypto",
         "liblog",
         "libz",
         "libziparchive",
     ],
+
+    init_rc: [
+        "vendor_flash_recovery.rc",
+    ],
 }
 
 cc_library_host_static {
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 90d8e86..adda697 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -47,7 +47,7 @@
 using namespace std::string_literals;
 
 static bool GenerateTarget(const Partition& target, const FileContents& source_file,
-                           const Value& patch, const Value* bonus_data);
+                           const Value& patch, const Value* bonus_data, bool backup_source);
 
 bool LoadFileContents(const std::string& filename, FileContents* file) {
   // No longer allow loading contents from eMMC partitions.
@@ -266,7 +266,7 @@
 }
 
 bool PatchPartition(const Partition& target, const Partition& source, const Value& patch,
-                    const Value* bonus) {
+                    const Value* bonus, bool backup_source) {
   LOG(INFO) << "Patching " << target.name;
 
   // We try to load and check against the target hash first.
@@ -279,8 +279,8 @@
   }
 
   FileContents source_file;
-  if (ReadPartitionToBuffer(source, &source_file, true)) {
-    return GenerateTarget(target, source_file, patch, bonus);
+  if (ReadPartitionToBuffer(source, &source_file, backup_source)) {
+    return GenerateTarget(target, source_file, patch, bonus, backup_source);
   }
 
   LOG(ERROR) << "Failed to find any match";
@@ -326,7 +326,7 @@
 }
 
 static bool GenerateTarget(const Partition& target, const FileContents& source_file,
-                           const Value& patch, const Value* bonus_data) {
+                           const Value& patch, const Value* bonus_data, bool backup_source) {
   uint8_t expected_sha1[SHA_DIGEST_LENGTH];
   if (ParseSha1(target.hash, expected_sha1) != 0) {
     LOG(ERROR) << "Failed to parse target hash \"" << target.hash << "\"";
@@ -351,11 +351,11 @@
   }
 
   // We write the original source to cache, in case the partition write is interrupted.
-  if (!CheckAndFreeSpaceOnCache(source_file.data.size())) {
+  if (backup_source && !CheckAndFreeSpaceOnCache(source_file.data.size())) {
     LOG(ERROR) << "Not enough free space on /cache";
     return false;
   }
-  if (!SaveFileContents(Paths::Get().cache_temp_source(), &source_file)) {
+  if (backup_source && !SaveFileContents(Paths::Get().cache_temp_source(), &source_file)) {
     LOG(ERROR) << "Failed to back up source file";
     return false;
   }
@@ -415,7 +415,9 @@
   }
 
   // Delete the backup copy of the source.
-  unlink(Paths::Get().cache_temp_source().c_str());
+  if (backup_source) {
+    unlink(Paths::Get().cache_temp_source().c_str());
+  }
 
   // Success!
   return true;
diff --git a/applypatch/applypatch_modes.cpp b/applypatch/applypatch_modes.cpp
index b466598..bb5eeae 100644
--- a/applypatch/applypatch_modes.cpp
+++ b/applypatch/applypatch_modes.cpp
@@ -87,7 +87,7 @@
     bonus = std::make_unique<Value>(Value::Type::BLOB, std::move(bonus_contents));
   }
 
-  return PatchPartition(target, source, patch, bonus.get()) ? 0 : 1;
+  return PatchPartition(target, source, patch, bonus.get(), false) ? 0 : 1;
 }
 
 static void Usage() {
diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h
index 6fc6f0f..799f4b2 100644
--- a/applypatch/include/applypatch/applypatch.h
+++ b/applypatch/include/applypatch/applypatch.h
@@ -73,10 +73,11 @@
 // the 'target' Partition. While patching, it will backup the data on the source partition to
 // /cache, so that the patching could be resumed on interruption even if both of the source and
 // target partitions refer to the same device. The function is idempotent if called multiple times.
-// An optional arg 'bonus' can be provided, if the patch was generated with a bonus output.
-// Returns the patching result.
+// 'bonus' can be provided if the patch was generated with a bonus output, or nullptr.
+// 'backup_source' indicates whether the source partition should be backed up prior to the update
+// (e.g. when doing in-place update). Returns the patching result.
 bool PatchPartition(const Partition& target, const Partition& source, const Value& patch,
-                    const Value* bonus);
+                    const Value* bonus, bool backup_source);
 
 // Returns whether the contents of the eMMC target or the cached file match the embedded hash.
 // It will look for the backup on /cache if the given partition doesn't match the checksum.
diff --git a/applypatch/vendor_flash_recovery.rc b/applypatch/vendor_flash_recovery.rc
new file mode 100644
index 0000000..37a7c2b
--- /dev/null
+++ b/applypatch/vendor_flash_recovery.rc
@@ -0,0 +1,3 @@
+service vendor_flash_recovery /vendor/bin/install-recovery.sh
+    class main
+    oneshot
diff --git a/edify/Android.bp b/edify/Android.bp
index 42947eb..73048d2 100644
--- a/edify/Android.bp
+++ b/edify/Android.bp
@@ -16,6 +16,7 @@
     name: "libedify",
 
     host_supported: true,
+    vendor_available: true,
 
     srcs: [
         "expr.cpp",
diff --git a/fsck_unshare_blocks.cpp b/fsck_unshare_blocks.cpp
index 9dc0fd8..e0b2d96 100644
--- a/fsck_unshare_blocks.cpp
+++ b/fsck_unshare_blocks.cpp
@@ -36,7 +36,7 @@
 #include <android-base/unique_fd.h>
 #include <fs_mgr/roots.h>
 
-#include "otautil/roots.h"
+#include "recovery_utils/roots.h"
 
 static constexpr const char* SYSTEM_E2FSCK_BIN = "/system/bin/e2fsck_static";
 static constexpr const char* TMP_E2FSCK_BIN = "/tmp/e2fsck.bin";
diff --git a/install/Android.bp b/install/Android.bp
index 89cc3f2..d4606e9 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -19,10 +19,6 @@
         "recovery_defaults",
     ],
 
-    header_libs: [
-        "libminadbd_headers",
-    ],
-
     shared_libs: [
         "libbase",
         "libbootloader_message",
@@ -32,7 +28,6 @@
         "libfusesideload",
         "libhidl-gen-utils",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libselinux",
         "libtinyxml2",
@@ -42,6 +37,7 @@
     ],
 
     static_libs: [
+        "librecovery_utils",
         "libotautil",
 
         // external dependencies
@@ -69,6 +65,10 @@
         "wipe_device.cpp",
     ],
 
+    header_libs: [
+        "libminadbd_headers",
+    ],
+
     shared_libs: [
         "librecovery_ui",
     ],
diff --git a/install/adb_install.cpp b/install/adb_install.cpp
index ed66442..ee79a32 100644
--- a/install/adb_install.cpp
+++ b/install/adb_install.cpp
@@ -44,7 +44,7 @@
 #include "fuse_sideload.h"
 #include "install/install.h"
 #include "install/wipe_data.h"
-#include "minadbd_types.h"
+#include "minadbd/types.h"
 #include "otautil/sysutil.h"
 #include "recovery_ui/device.h"
 #include "recovery_ui/ui.h"
diff --git a/install/fuse_install.cpp b/install/fuse_install.cpp
index 8a7a278..143b5d3 100644
--- a/install/fuse_install.cpp
+++ b/install/fuse_install.cpp
@@ -37,7 +37,7 @@
 #include "fuse_provider.h"
 #include "fuse_sideload.h"
 #include "install/install.h"
-#include "otautil/roots.h"
+#include "recovery_utils/roots.h"
 
 static constexpr const char* SDCARD_ROOT = "/sdcard";
 // How long (in seconds) we wait for the fuse-provided package file to
diff --git a/install/install.cpp b/install/install.cpp
index 9d67b01..9166f9c 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -51,11 +51,11 @@
 #include "install/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"
 #include "recovery_ui/ui.h"
+#include "recovery_utils/roots.h"
+#include "recovery_utils/thermalutil.h"
 
 using namespace std::chrono_literals;
 
diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp
index 765a815..82660be 100644
--- a/install/wipe_data.cpp
+++ b/install/wipe_data.cpp
@@ -28,9 +28,9 @@
 #include <android-base/stringprintf.h>
 
 #include "otautil/dirutil.h"
-#include "otautil/logging.h"
-#include "otautil/roots.h"
 #include "recovery_ui/ui.h"
+#include "recovery_utils/logging.h"
+#include "recovery_utils/roots.h"
 
 constexpr const char* CACHE_ROOT = "/cache";
 constexpr const char* DATA_ROOT = "/data";
@@ -120,4 +120,4 @@
   }
   ui->Print("Data wipe %s.\n", success ? "complete" : "failed");
   return success;
-}
\ No newline at end of file
+}
diff --git a/minadbd/Android.bp b/minadbd/Android.bp
index afd57ad..b7075e6 100644
--- a/minadbd/Android.bp
+++ b/minadbd/Android.bp
@@ -26,6 +26,10 @@
     include_dirs: [
         "system/core/adb",
     ],
+
+    header_libs: [
+        "libminadbd_headers",
+    ],
 }
 
 // `libminadbd_services` is analogous to the `libadbd_services` for regular `adbd`, but providing
@@ -36,6 +40,7 @@
 
     defaults: [
         "minadbd_defaults",
+        "librecovery_utils_defaults",
     ],
 
     srcs: [
@@ -44,6 +49,7 @@
     ],
 
     static_libs: [
+        "librecovery_utils",
         "libotautil",
     ],
 
@@ -58,9 +64,12 @@
 cc_library_headers {
     name: "libminadbd_headers",
     recovery_available: true,
-    // TODO create a include dir
     export_include_dirs: [
-        ".",
+        "include",
+    ],
+    // adb_install.cpp
+    visibility: [
+        "//bootable/recovery/install",
     ],
 }
 
@@ -90,6 +99,7 @@
 
     defaults: [
         "minadbd_defaults",
+        "librecovery_utils_defaults",
     ],
 
     srcs: [
@@ -100,13 +110,14 @@
     static_libs: [
         "libminadbd_services",
         "libfusesideload",
+        "librecovery_utils",
         "libotautil",
         "libadbd",
-        "libcrypto",
     ],
 
     shared_libs: [
         "libbase",
+        "libcrypto",
         "libcutils",
         "liblog",
     ],
diff --git a/minadbd/README.md b/minadbd/README.md
index 5a0a067..9a19583 100644
--- a/minadbd/README.md
+++ b/minadbd/README.md
@@ -1,8 +1,24 @@
-minadbd is now mostly built from libadbd. The fuse features are unique to
-minadbd, and services.c has been modified as follows:
+minadbd
+=======
 
-  - all services 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.
+`minadbd` is analogous to the regular `adbd`, but providing the minimal services to support
+recovery-specific use cases. Generally speaking, `adbd` = `libadbd` + `libadbd_services`, whereas
+`minadbd` = `libadbd` + `libminadbd_services`.
+
+Although both modules may be installed into the recovery image, only one of them, or none, can be
+active at any given time.
+
+- The start / stop of `adbd` is managed via system property `sys.usb.config`, when setting to `adb`
+  or `none` respectively. Upon starting recovery mode, `adbd` is started in debuggable builds by
+  default; otherwise `adbd` will stay off at all times in user builds. See the triggers in
+  `bootable/recovery/etc/init.rc`.
+
+- `minadbd` is started by `recovery` as needed.
+  - When requested to start `minadbd`, `recovery` stops `adbd` first, if it's running; it then forks
+    and execs `minadbd` in a separate process.
+  - `minadbd` talks to host-side `adb` server to get user requests.
+    - `minadbd` handles some requests directly, e.g. querying device properties for rescue service.
+    - `minadbd` communicates with `recovery` to fulfill requests regarding package installation. See
+      the comments in `bootable/recovery/install/adb_install.cpp` for the IPC protocol between
+      `recovery` and `minadbd`.
+  - Upon exiting `minadbd`, `recovery` restarts `adbd` if it was previously running.
diff --git a/minadbd/minadbd_types.h b/minadbd/include/minadbd/types.h
similarity index 100%
rename from minadbd/minadbd_types.h
rename to minadbd/include/minadbd/types.h
diff --git a/minadbd/minadbd.cpp b/minadbd/minadbd.cpp
index c80d549..7b82faa 100644
--- a/minadbd/minadbd.cpp
+++ b/minadbd/minadbd.cpp
@@ -28,8 +28,8 @@
 #include "adb_auth.h"
 #include "transport.h"
 
+#include "minadbd/types.h"
 #include "minadbd_services.h"
-#include "minadbd_types.h"
 
 using namespace std::string_literals;
 
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index c31afbe..eb91fb3 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -43,7 +43,8 @@
 #include "adb_utils.h"
 #include "fuse_adb_provider.h"
 #include "fuse_sideload.h"
-#include "minadbd_types.h"
+#include "minadbd/types.h"
+#include "recovery_utils/battery_utils.h"
 #include "services.h"
 #include "sysdeps.h"
 
@@ -160,7 +161,10 @@
 // If given an empty string, dumps all the supported properties (analogous to `adb shell getprop`)
 // in lines, e.g. "[prop]: [value]".
 static void RescueGetpropHostService(unique_fd sfd, const std::string& prop) {
+  constexpr const char* kRescueBatteryLevelProp = "rescue.battery_level";
   static const std::set<std::string> kGetpropAllowedProps = {
+    // clang-format off
+    kRescueBatteryLevelProp,
     "ro.build.date.utc",
     "ro.build.fingerprint",
     "ro.build.flavor",
@@ -170,18 +174,28 @@
     "ro.build.version.incremental",
     "ro.product.device",
     "ro.product.vendor.device",
+    // clang-format on
   };
+
+  auto query_prop = [](const std::string& key) {
+    if (key == kRescueBatteryLevelProp) {
+      auto battery_info = GetBatteryInfo();
+      return std::to_string(battery_info.capacity);
+    }
+    return android::base::GetProperty(key, "");
+  };
+
   std::string result;
   if (prop.empty()) {
     for (const auto& key : kGetpropAllowedProps) {
-      auto value = android::base::GetProperty(key, "");
+      auto value = query_prop(key);
       if (value.empty()) {
         continue;
       }
       result += "[" + key + "]: [" + value + "]\n";
     }
   } else if (kGetpropAllowedProps.find(prop) != kGetpropAllowedProps.end()) {
-    result = android::base::GetProperty(prop, "") + "\n";
+    result = query_prop(prop) + "\n";
   }
   if (result.empty()) {
     result = "\n";
diff --git a/minadbd/minadbd_services_test.cpp b/minadbd/minadbd_services_test.cpp
index f878737..b694a57 100644
--- a/minadbd/minadbd_services_test.cpp
+++ b/minadbd/minadbd_services_test.cpp
@@ -35,8 +35,8 @@
 #include "adb_io.h"
 #include "fuse_adb_provider.h"
 #include "fuse_sideload.h"
+#include "minadbd/types.h"
 #include "minadbd_services.h"
-#include "minadbd_types.h"
 #include "socket.h"
 
 class MinadbdServicesTest : public ::testing::Test {
diff --git a/otautil/Android.bp b/otautil/Android.bp
index 871dcae..3b3f9cb 100644
--- a/otautil/Android.bp
+++ b/otautil/Android.bp
@@ -16,6 +16,7 @@
     name: "libotautil",
 
     host_supported: true,
+    vendor_available: true,
     recovery_available: true,
 
     defaults: [
@@ -39,33 +40,4 @@
     export_include_dirs: [
         "include",
     ],
-
-    target: {
-        android: {
-            srcs: [
-                "logging.cpp",
-                "mounts.cpp",
-                "parse_install_logs.cpp",
-                "roots.cpp",
-                "thermalutil.cpp",
-            ],
-
-            include_dirs: [
-                "system/vold",
-            ],
-
-            static_libs: [
-                "libfstab",
-            ],
-
-            shared_libs: [
-                "libext4_utils",
-                "libfs_mgr",
-            ],
-
-            export_static_lib_headers: [
-                "libfstab",
-            ],
-        },
-    },
 }
diff --git a/recovery-persist.cpp b/recovery-persist.cpp
index 294017a..6dbf862 100644
--- a/recovery-persist.cpp
+++ b/recovery-persist.cpp
@@ -43,8 +43,8 @@
 #include <metricslogger/metrics_logger.h>
 #include <private/android_logger.h> /* private pmsg functions */
 
-#include "otautil/logging.h"
-#include "otautil/parse_install_logs.h"
+#include "recovery_utils/logging.h"
+#include "recovery_utils/parse_install_logs.h"
 
 constexpr const char* LAST_LOG_FILE = "/data/misc/recovery/last_log";
 constexpr const char* LAST_PMSG_FILE = "/sys/fs/pstore/pmsg-ramoops-0";
diff --git a/recovery-refresh.cpp b/recovery-refresh.cpp
index d41755d..42acd05 100644
--- a/recovery-refresh.cpp
+++ b/recovery-refresh.cpp
@@ -38,11 +38,12 @@
 //
 
 #include <string.h>
+
 #include <string>
 
 #include <private/android_logger.h> /* private pmsg functions */
 
-#include "otautil/logging.h"
+#include "recovery_utils/logging.h"
 
 int main(int argc, char **argv) {
     static const char filter[] = "recovery/";
diff --git a/recovery.cpp b/recovery.cpp
index 4862dfc..f59a940 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -42,7 +42,6 @@
 #include <android-base/strings.h>
 #include <cutils/properties.h> /* for property_list */
 #include <fs_mgr/roots.h>
-#include <healthhalutils/HealthHalUtils.h>
 #include <ziparchive/zip_archive.h>
 
 #include "bootloader_message/bootloader_message.h"
@@ -55,12 +54,13 @@
 #include "install/wipe_device.h"
 #include "otautil/boot_state.h"
 #include "otautil/error_code.h"
-#include "otautil/logging.h"
 #include "otautil/paths.h"
-#include "otautil/roots.h"
 #include "otautil/sysutil.h"
 #include "recovery_ui/screen_ui.h"
 #include "recovery_ui/ui.h"
+#include "recovery_utils/battery_utils.h"
+#include "recovery_utils/logging.h"
+#include "recovery_utils/roots.h"
 
 static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
 static constexpr const char* LAST_KMSG_FILE = "/cache/recovery/last_kmsg";
@@ -453,74 +453,17 @@
   printf("%s=%s\n", key, name);
 }
 
-static bool is_battery_ok(int* required_battery_level) {
-  using android::hardware::health::V1_0::BatteryStatus;
-  using android::hardware::health::V2_0::get_health_service;
-  using android::hardware::health::V2_0::IHealth;
-  using android::hardware::health::V2_0::Result;
-  using android::hardware::health::V2_0::toString;
+static bool IsBatteryOk(int* required_battery_level) {
+  // GmsCore enters recovery mode to install package when having enough battery percentage.
+  // Normally, the threshold is 40% without charger and 20% with charger. So we check the battery
+  // level against a slightly lower limit.
+  constexpr int BATTERY_OK_PERCENTAGE = 20;
+  constexpr int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15;
 
-  android::sp<IHealth> health = get_health_service();
-
-  static constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
-  int wait_second = 0;
-  while (true) {
-    auto charge_status = BatteryStatus::UNKNOWN;
-
-    if (health == nullptr) {
-      LOG(WARNING) << "no health implementation is found, assuming defaults";
-    } else {
-      health
-          ->getChargeStatus([&charge_status](auto res, auto out_status) {
-            if (res == Result::SUCCESS) {
-              charge_status = out_status;
-            }
-          })
-          .isOk();  // should not have transport error
-    }
-
-    // Treat unknown status as charged.
-    bool charged = (charge_status != BatteryStatus::DISCHARGING &&
-                    charge_status != BatteryStatus::NOT_CHARGING);
-
-    Result res = Result::UNKNOWN;
-    int32_t capacity = INT32_MIN;
-    if (health != nullptr) {
-      health
-          ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) {
-            res = out_res;
-            capacity = out_capacity;
-          })
-          .isOk();  // should not have transport error
-    }
-
-    LOG(INFO) << "charge_status " << toString(charge_status) << ", charged " << charged
-              << ", status " << toString(res) << ", capacity " << capacity;
-    // At startup, the battery drivers in devices like N5X/N6P take some time to load
-    // the battery profile. Before the load finishes, it reports value 50 as a fake
-    // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
-    // to finish loading the battery profile earlier than 10 seconds after kernel startup.
-    if (res == Result::SUCCESS && capacity == 50) {
-      if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
-        sleep(1);
-        wait_second++;
-        continue;
-      }
-    }
-    // If we can't read battery percentage, it may be a device without battery. In this
-    // situation, use 100 as a fake battery percentage.
-    if (res != Result::SUCCESS) {
-      capacity = 100;
-    }
-
-    // GmsCore enters recovery mode to install package when having enough battery percentage.
-    // Normally, the threshold is 40% without charger and 20% with charger. So we should check
-    // battery with a slightly lower limitation.
-    static constexpr int BATTERY_OK_PERCENTAGE = 20;
-    static constexpr int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15;
-    *required_battery_level = charged ? BATTERY_WITH_CHARGER_OK_PERCENTAGE : BATTERY_OK_PERCENTAGE;
-    return capacity >= *required_battery_level;
-  }
+  auto battery_info = GetBatteryInfo();
+  *required_battery_level =
+      battery_info.charging ? BATTERY_WITH_CHARGER_OK_PERCENTAGE : BATTERY_OK_PERCENTAGE;
+  return battery_info.capacity >= *required_battery_level;
 }
 
 // Set the retry count to |retry_count| in BCB.
@@ -713,12 +656,10 @@
     // to log the update attempt since update_package is non-NULL.
     save_current_log = true;
 
-    int required_battery_level;
-    if (retry_count == 0 && !is_battery_ok(&required_battery_level)) {
+    if (int required_battery_level; retry_count == 0 && !IsBatteryOk(&required_battery_level)) {
       ui->Print("battery capacity is not enough for installing package: %d%% needed\n",
                 required_battery_level);
-      // Log the error code to last_install when installation skips due to
-      // low battery.
+      // Log the error code to last_install when installation skips due to low battery.
       log_failure_code(kLowBattery, update_package);
       status = INSTALL_SKIPPED;
     } else if (retry_count == 0 && bootreason_in_blacklist()) {
diff --git a/recovery_main.cpp b/recovery_main.cpp
index 28197bf..89253dc 100644
--- a/recovery_main.cpp
+++ b/recovery_main.cpp
@@ -51,14 +51,14 @@
 #include "fastboot/fastboot.h"
 #include "install/wipe_data.h"
 #include "otautil/boot_state.h"
-#include "otautil/logging.h"
 #include "otautil/paths.h"
-#include "otautil/roots.h"
 #include "otautil/sysutil.h"
 #include "recovery.h"
 #include "recovery_ui/device.h"
 #include "recovery_ui/stub_ui.h"
 #include "recovery_ui/ui.h"
+#include "recovery_utils/logging.h"
+#include "recovery_utils/roots.h"
 
 static constexpr const char* COMMAND_FILE = "/cache/recovery/command";
 static constexpr const char* LOCALE_FILE = "/cache/recovery/last_locale";
@@ -351,6 +351,12 @@
   std::string locale;
   std::string reason;
 
+  // The code here is only interested in the options that signal the intent to start fastbootd or
+  // recovery. Unrecognized options are likely meant for recovery, which will be processed later in
+  // start_recovery(). Suppress the warnings for such -- even if some flags were indeed invalid, the
+  // code in start_recovery() will capture and report them.
+  opterr = 0;
+
   int arg;
   int option_index;
   while ((arg = getopt_long(args_to_parse.size() - 1, args_to_parse.data(), "", OPTIONS,
@@ -374,6 +380,7 @@
     }
   }
   optind = 1;
+  opterr = 1;
 
   if (locale.empty()) {
     if (HasCache()) {
diff --git a/recovery_utils/Android.bp b/recovery_utils/Android.bp
new file mode 100644
index 0000000..bf79a2e
--- /dev/null
+++ b/recovery_utils/Android.bp
@@ -0,0 +1,81 @@
+// 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: "librecovery_utils_defaults",
+
+    defaults: [
+        "recovery_defaults",
+    ],
+
+    shared_libs: [
+        "android.hardware.health@2.0",
+        "libbase",
+        "libext4_utils",
+        "libfs_mgr",
+        "libhidlbase",
+        "libselinux",
+        "libutils",
+    ],
+
+    static_libs: [
+        "libotautil",
+
+        // External dependencies.
+        "libfstab",
+        "libhealthhalutils",
+    ],
+}
+
+// A utility lib that's local to recovery (in contrast, libotautil is exposed to device-specific
+// recovery_ui lib as well as device-specific updater).
+cc_library_static {
+    name: "librecovery_utils",
+
+    recovery_available: true,
+
+    defaults: [
+        "librecovery_utils_defaults",
+    ],
+
+    srcs: [
+        "battery_utils.cpp",
+        "logging.cpp",
+        "parse_install_logs.cpp",
+        "roots.cpp",
+        "thermalutil.cpp",
+    ],
+
+    header_libs: [
+        "libvold_headers",
+    ],
+
+    export_include_dirs: [
+        "include",
+    ],
+
+    export_static_lib_headers: [
+        // roots.h includes <fstab/fstab.h>.
+        "libfstab",
+    ],
+
+    // Should avoid exposing to the libs that might be used in device-specific codes (e.g.
+    // libedify, libotautil, librecovery_ui).
+    visibility: [
+        "//bootable/recovery",
+        "//bootable/recovery/install",
+        "//bootable/recovery/minadbd",
+        "//bootable/recovery/tests",
+    ],
+}
diff --git a/recovery_utils/battery_utils.cpp b/recovery_utils/battery_utils.cpp
new file mode 100644
index 0000000..323f525
--- /dev/null
+++ b/recovery_utils/battery_utils.cpp
@@ -0,0 +1,89 @@
+/*
+ * 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 "recovery_utils/battery_utils.h"
+
+#include <stdint.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <healthhalutils/HealthHalUtils.h>
+
+BatteryInfo GetBatteryInfo() {
+  using android::hardware::health::V1_0::BatteryStatus;
+  using android::hardware::health::V2_0::get_health_service;
+  using android::hardware::health::V2_0::IHealth;
+  using android::hardware::health::V2_0::Result;
+  using android::hardware::health::V2_0::toString;
+
+  android::sp<IHealth> health = get_health_service();
+
+  int wait_second = 0;
+  while (true) {
+    auto charge_status = BatteryStatus::UNKNOWN;
+
+    if (health == nullptr) {
+      LOG(WARNING) << "No health implementation is found; assuming defaults";
+    } else {
+      health
+          ->getChargeStatus([&charge_status](auto res, auto out_status) {
+            if (res == Result::SUCCESS) {
+              charge_status = out_status;
+            }
+          })
+          .isOk();  // should not have transport error
+    }
+
+    // Treat unknown status as on charger. See hardware/interfaces/health/1.0/types.hal for the
+    // meaning of the return values.
+    bool charging = (charge_status != BatteryStatus::DISCHARGING &&
+                     charge_status != BatteryStatus::NOT_CHARGING);
+
+    Result res = Result::UNKNOWN;
+    int32_t capacity = INT32_MIN;
+    if (health != nullptr) {
+      health
+          ->getCapacity([&res, &capacity](auto out_res, auto out_capacity) {
+            res = out_res;
+            capacity = out_capacity;
+          })
+          .isOk();  // should not have transport error
+    }
+
+    LOG(INFO) << "charge_status " << toString(charge_status) << ", charging " << charging
+              << ", status " << toString(res) << ", capacity " << capacity;
+
+    constexpr int BATTERY_READ_TIMEOUT_IN_SEC = 10;
+    // At startup, the battery drivers in devices like N5X/N6P take some time to load
+    // the battery profile. Before the load finishes, it reports value 50 as a fake
+    // capacity. BATTERY_READ_TIMEOUT_IN_SEC is set that the battery drivers are expected
+    // to finish loading the battery profile earlier than 10 seconds after kernel startup.
+    if (res == Result::SUCCESS && capacity == 50) {
+      if (wait_second < BATTERY_READ_TIMEOUT_IN_SEC) {
+        sleep(1);
+        wait_second++;
+        continue;
+      }
+    }
+    // If we can't read battery percentage, it may be a device without battery. In this
+    // situation, use 100 as a fake battery percentage.
+    if (res != Result::SUCCESS) {
+      capacity = 100;
+    }
+
+    return BatteryInfo{ charging, capacity };
+  }
+}
diff --git a/recovery_utils/include/recovery_utils/battery_utils.h b/recovery_utils/include/recovery_utils/battery_utils.h
new file mode 100644
index 0000000..a95f71d
--- /dev/null
+++ b/recovery_utils/include/recovery_utils/battery_utils.h
@@ -0,0 +1,33 @@
+/*
+ * 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>
+
+struct BatteryInfo {
+  // Whether the device is on charger. Note that the value will be `true` if the battery status is
+  // unknown (BATTERY_STATUS_UNKNOWN).
+  bool charging;
+
+  // The remaining battery capacity percentage (i.e. between 0 and 100). See getCapacity in
+  // hardware/interfaces/health/2.0/IHealth.hal. Returns 100 in case it fails to read a value from
+  // the health HAL.
+  int32_t capacity;
+};
+
+// Returns the battery status for OTA installation purpose.
+BatteryInfo GetBatteryInfo();
diff --git a/otautil/include/otautil/logging.h b/recovery_utils/include/recovery_utils/logging.h
similarity index 100%
rename from otautil/include/otautil/logging.h
rename to recovery_utils/include/recovery_utils/logging.h
diff --git a/otautil/include/otautil/parse_install_logs.h b/recovery_utils/include/recovery_utils/parse_install_logs.h
similarity index 100%
rename from otautil/include/otautil/parse_install_logs.h
rename to recovery_utils/include/recovery_utils/parse_install_logs.h
diff --git a/otautil/include/otautil/roots.h b/recovery_utils/include/recovery_utils/roots.h
similarity index 100%
rename from otautil/include/otautil/roots.h
rename to recovery_utils/include/recovery_utils/roots.h
diff --git a/otautil/include/otautil/thermalutil.h b/recovery_utils/include/recovery_utils/thermalutil.h
similarity index 100%
rename from otautil/include/otautil/thermalutil.h
rename to recovery_utils/include/recovery_utils/thermalutil.h
diff --git a/otautil/logging.cpp b/recovery_utils/logging.cpp
similarity index 98%
rename from otautil/logging.cpp
rename to recovery_utils/logging.cpp
index 3db0e8a..52f12a8 100644
--- a/otautil/logging.cpp
+++ b/recovery_utils/logging.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "otautil/logging.h"
+#include "recovery_utils/logging.h"
 
 #include <dirent.h>
 #include <errno.h>
@@ -38,7 +38,7 @@
 
 #include "otautil/dirutil.h"
 #include "otautil/paths.h"
-#include "otautil/roots.h"
+#include "recovery_utils/roots.h"
 
 constexpr const char* LOG_FILE = "/cache/recovery/log";
 constexpr const char* LAST_INSTALL_FILE = "/cache/recovery/last_install";
diff --git a/otautil/parse_install_logs.cpp b/recovery_utils/parse_install_logs.cpp
similarity index 98%
rename from otautil/parse_install_logs.cpp
rename to recovery_utils/parse_install_logs.cpp
index 13a7299..c863176 100644
--- a/otautil/parse_install_logs.cpp
+++ b/recovery_utils/parse_install_logs.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "otautil/parse_install_logs.h"
+#include "recovery_utils/parse_install_logs.h"
 
 #include <unistd.h>
 
diff --git a/otautil/roots.cpp b/recovery_utils/roots.cpp
similarity index 97%
rename from otautil/roots.cpp
rename to recovery_utils/roots.cpp
index 4315517..f717ec2 100644
--- a/otautil/roots.cpp
+++ b/recovery_utils/roots.cpp
@@ -14,15 +14,12 @@
  * limitations under the License.
  */
 
-#include "otautil/roots.h"
+#include "recovery_utils/roots.h"
 
-#include <ctype.h>
 #include <fcntl.h>
-#include <inttypes.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/mount.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/wait.h>
@@ -33,16 +30,13 @@
 #include <vector>
 
 #include <android-base/logging.h>
-#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/unique_fd.h>
 #include <cryptfs.h>
 #include <ext4_utils/wipe.h>
 #include <fs_mgr.h>
 #include <fs_mgr/roots.h>
-#include <fs_mgr_dm_linear.h>
 
-#include "otautil/mounts.h"
 #include "otautil/sysutil.h"
 
 using android::fs_mgr::Fstab;
diff --git a/otautil/thermalutil.cpp b/recovery_utils/thermalutil.cpp
similarity index 97%
rename from otautil/thermalutil.cpp
rename to recovery_utils/thermalutil.cpp
index 4660e05..5436355 100644
--- a/otautil/thermalutil.cpp
+++ b/recovery_utils/thermalutil.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "otautil/thermalutil.h"
+#include "recovery_utils/thermalutil.h"
 
 #include <dirent.h>
 #include <stdio.h>
diff --git a/tests/Android.bp b/tests/Android.bp
index a867040..5b881e3 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -64,7 +64,6 @@
     "libbase",
     "libbrotli",
     "libbz",
-    "libcrypto",
     "libz",
     "libziparchive",
 ]
@@ -91,8 +90,6 @@
     "libfs_mgr",
     "libhidl-gen-utils",
     "libhidlbase",
-    "libhidltransport",
-    "libhwbinder_noltopgo",
     "libbinderthreadstate",
     "liblp",
     "libvndksupport",
@@ -102,6 +99,7 @@
 cc_test {
     name: "recovery_unit_test",
     isolated: true,
+    require_root: true,
 
     defaults: [
         "recovery_test_defaults",
@@ -119,6 +117,7 @@
         "librecovery_ui",
         "libfusesideload",
         "libminui",
+        "librecovery_utils",
         "libotautil",
         "libupdater_device",
         "libupdater_core",
diff --git a/tests/unit/applypatch_test.cpp b/tests/unit/applypatch_test.cpp
index 794f2c1..218a224 100644
--- a/tests/unit/applypatch_test.cpp
+++ b/tests/unit/applypatch_test.cpp
@@ -141,7 +141,7 @@
   ASSERT_TRUE(LoadFileContents(from_testdata_base("bonus.file"), &bonus_fc));
   Value bonus(Value::Type::BLOB, std::string(bonus_fc.data.cbegin(), bonus_fc.data.cend()));
 
-  ASSERT_TRUE(PatchPartition(target_partition, source_partition, patch, &bonus));
+  ASSERT_TRUE(PatchPartition(target_partition, source_partition, patch, &bonus, false));
 }
 
 // Tests patching an eMMC target without a separate bonus file (i.e. recovery-from-boot patch has
@@ -151,7 +151,7 @@
   ASSERT_TRUE(LoadFileContents(from_testdata_base("recovery-from-boot-with-bonus.p"), &patch_fc));
   Value patch(Value::Type::BLOB, std::string(patch_fc.data.cbegin(), patch_fc.data.cend()));
 
-  ASSERT_TRUE(PatchPartition(target_partition, source_partition, patch, nullptr));
+  ASSERT_TRUE(PatchPartition(target_partition, source_partition, patch, nullptr, false));
 }
 
 class FreeCacheTest : public ::testing::Test {
diff --git a/tests/unit/battery_utils_test.cpp b/tests/unit/battery_utils_test.cpp
new file mode 100644
index 0000000..55639fd
--- /dev/null
+++ b/tests/unit/battery_utils_test.cpp
@@ -0,0 +1,27 @@
+/*
+ * 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 agree 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 <android-base/logging.h>
+#include <gtest/gtest.h>
+
+#include "recovery_utils/battery_utils.h"
+
+TEST(BatteryInfoTest, GetBatteryInfo) {
+  auto info = GetBatteryInfo();
+  // 0 <= capacity <= 100
+  ASSERT_LE(0, info.capacity);
+  ASSERT_LE(info.capacity, 100);
+}
diff --git a/tests/unit/parse_install_logs_test.cpp b/tests/unit/parse_install_logs_test.cpp
index 72169a0..052f71c 100644
--- a/tests/unit/parse_install_logs_test.cpp
+++ b/tests/unit/parse_install_logs_test.cpp
@@ -22,7 +22,7 @@
 #include <android-base/strings.h>
 #include <gtest/gtest.h>
 
-#include "otautil/parse_install_logs.h"
+#include "recovery_utils/parse_install_logs.h"
 
 TEST(ParseInstallLogsTest, EmptyFile) {
   TemporaryFile last_install;
diff --git a/tools/recovery_l10n/res/values-en-rXC/strings.xml b/tools/recovery_l10n/res/values-en-rXC/strings.xml
index 61390f1..18b077f 100644
--- a/tools/recovery_l10n/res/values-en-rXC/strings.xml
+++ b/tools/recovery_l10n/res/values-en-rXC/strings.xml
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="recovery_installing" msgid="2013591905463558223">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎Installing system update‎‏‎‎‏‎"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎Erasing‎‏‎‎‏‎"</string>
-    <string name="recovery_no_command" msgid="4465476568623024327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎No command‎‏‎‎‏‎"</string>
-    <string name="recovery_error" msgid="5748178989622716736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎Error!‎‏‎‎‏‎"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎Installing security update‎‏‎‎‏‎"</string>
-    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎Cannot load Android system. Your data may be corrupt. If you continue to get this message, you may need to perform a factory data reset and erase all user data stored on this device.‎‏‎‎‏‎"</string>
-    <string name="recovery_try_again" msgid="7168248750158873496">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎Try again‎‏‎‎‏‎"</string>
-    <string name="recovery_factory_data_reset" msgid="7321351565602894783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎Factory data reset‎‏‎‎‏‎"</string>
-    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎Wipe all user data?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ THIS CAN NOT BE UNDONE!‎‏‎‎‏‎"</string>
-    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎Cancel‎‏‎‎‏‎"</string>
+    <string name="recovery_installing" msgid="2013591905463558223">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‏‏‏‏‎Installing system update‎‏‎‎‏‎"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‎‎‏‏‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‎‎‎‎‎Erasing‎‏‎‎‏‎"</string>
+    <string name="recovery_no_command" msgid="4465476568623024327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‎‏‏‏‎No command‎‏‎‎‏‎"</string>
+    <string name="recovery_error" msgid="5748178989622716736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎Error!‎‏‎‎‏‎"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‏‏‎‎Installing security update‎‏‎‎‏‎"</string>
+    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎Cannot load Android system. Your data may be corrupt. If you continue to get this message, you may need to perform a factory data reset and erase all user data stored on this device.‎‏‎‎‏‎"</string>
+    <string name="recovery_try_again" msgid="7168248750158873496">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎Try again‎‏‎‎‏‎"</string>
+    <string name="recovery_factory_data_reset" msgid="7321351565602894783">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‏‏‎Factory data reset‎‏‎‎‏‎"</string>
+    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎Wipe all user data?‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎ THIS CAN NOT BE UNDONE!‎‏‎‎‏‎"</string>
+    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‎‎‎‏‏‎‎‎‎Cancel‎‏‎‎‏‎"</string>
 </resources>
diff --git a/updater/Android.bp b/updater/Android.bp
index 063366e..8a60ef7 100644
--- a/updater/Android.bp
+++ b/updater/Android.bp
@@ -41,11 +41,14 @@
         "libziparchive",
         "libz",
         "libbase",
-        "libcrypto",
         "libcrypto_utils",
         "libcutils",
         "libutils",
     ],
+
+    shared_libs: [
+        "libcrypto",
+    ],
 }
 
 cc_defaults {
@@ -78,6 +81,7 @@
         "blockimg.cpp",
         "commands.cpp",
         "install.cpp",
+        "mounts.cpp",
         "updater.cpp",
     ],
 
diff --git a/updater/Android.mk b/updater/Android.mk
index 93525c1..6f54d89 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -44,7 +44,7 @@
     libziparchive \
     libz \
     libbase \
-    libcrypto \
+    libcrypto_static \
     libcrypto_utils \
     libcutils \
     libutils
diff --git a/updater/install.cpp b/updater/install.cpp
index be0ceb0..62ff87e 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -60,7 +60,6 @@
 #include "edify/updater_runtime_interface.h"
 #include "otautil/dirutil.h"
 #include "otautil/error_code.h"
-#include "otautil/mounts.h"
 #include "otautil/print_sha1.h"
 #include "otautil/sysutil.h"
 
@@ -271,7 +270,7 @@
     return StringValue("");
   }
 
-  bool result = PatchPartition(target, source, *values[0], nullptr);
+  bool result = PatchPartition(target, source, *values[0], nullptr, true);
   return StringValue(result ? "t" : "");
 }
 
diff --git a/otautil/mounts.cpp b/updater/mounts.cpp
similarity index 98%
rename from otautil/mounts.cpp
rename to updater/mounts.cpp
index 951311b..943d35c 100644
--- a/otautil/mounts.cpp
+++ b/updater/mounts.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "otautil/mounts.h"
+#include "mounts.h"
 
 #include <errno.h>
 #include <fcntl.h>
diff --git a/otautil/include/otautil/mounts.h b/updater/mounts.h
similarity index 100%
rename from otautil/include/otautil/mounts.h
rename to updater/mounts.h
diff --git a/updater/simulator_runtime.cpp b/updater/simulator_runtime.cpp
index d2074d6..3ed7bf3 100644
--- a/updater/simulator_runtime.cpp
+++ b/updater/simulator_runtime.cpp
@@ -32,7 +32,7 @@
 #include <ext4_utils/wipe.h>
 #include <selinux/label.h>
 
-#include "otautil/mounts.h"
+#include "mounts.h"
 #include "otautil/sysutil.h"
 
 std::string SimulatorRuntime::GetProperty(const std::string_view key,
diff --git a/updater/updater_main.cpp b/updater/updater_main.cpp
index 055a8ac..33d5b5b 100644
--- a/updater/updater_main.cpp
+++ b/updater/updater_main.cpp
@@ -22,6 +22,7 @@
 
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
+#include <openssl/crypto.h>
 #include <selinux/android.h>
 #include <selinux/label.h>
 #include <selinux/selinux.h>
@@ -56,22 +57,28 @@
   // (which is redirected to recovery.log).
   android::base::InitLogging(argv, &UpdaterLogger);
 
+  // Run the libcrypto KAT(known answer tests) based self tests.
+  if (BORINGSSL_self_test() != 1) {
+    LOG(ERROR) << "Failed to run the boringssl self tests";
+    return EXIT_FAILURE;
+  }
+
   if (argc != 4 && argc != 5) {
     LOG(ERROR) << "unexpected number of arguments: " << argc;
-    return 1;
+    return EXIT_FAILURE;
   }
 
   char* version = argv[1];
   if ((version[0] != '1' && version[0] != '2' && version[0] != '3') || version[1] != '\0') {
     // We support version 1, 2, or 3.
     LOG(ERROR) << "wrong updater binary API; expected 1, 2, or 3; got " << argv[1];
-    return 1;
+    return EXIT_FAILURE;
   }
 
   int fd;
   if (!android::base::ParseInt(argv[2], &fd)) {
     LOG(ERROR) << "Failed to parse fd in " << argv[2];
-    return 1;
+    return EXIT_FAILURE;
   }
 
   std::string package_name = argv[3];
@@ -82,7 +89,7 @@
       is_retry = true;
     } else {
       LOG(ERROR) << "unexpected argument: " << argv[4];
-      return 1;
+      return EXIT_FAILURE;
     }
   }
 
@@ -98,12 +105,12 @@
 
   Updater updater(std::make_unique<UpdaterRuntime>(sehandle));
   if (!updater.Init(fd, package_name, is_retry)) {
-    return 1;
+    return EXIT_FAILURE;
   }
 
   if (!updater.RunUpdate()) {
-    return 1;
+    return EXIT_FAILURE;
   }
 
-  return 0;
+  return EXIT_SUCCESS;
 }
\ No newline at end of file
diff --git a/updater/updater_runtime.cpp b/updater/updater_runtime.cpp
index 761f999..c4222a5 100644
--- a/updater/updater_runtime.cpp
+++ b/updater/updater_runtime.cpp
@@ -31,7 +31,7 @@
 #include <selinux/label.h>
 #include <tune2fs.h>
 
-#include "otautil/mounts.h"
+#include "mounts.h"
 #include "otautil/sysutil.h"
 
 std::string UpdaterRuntime::GetProperty(const std::string_view key,
diff --git a/updater_sample/OWNERS b/updater_sample/OWNERS
deleted file mode 100644
index 5c1c370..0000000
--- a/updater_sample/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-zhaojiac@google.com
-zhomart@google.com
diff --git a/updater_sample/tests/Android.bp b/updater_sample/tests/Android.bp
index 7867770..806babd 100644
--- a/updater_sample/tests/Android.bp
+++ b/updater_sample/tests/Android.bp
@@ -23,7 +23,8 @@
     ],
 
     static_libs: [
-        "android-support-test",
+        "androidx.test.runner",
+        "androidx.test.rules",
         "mockito-target-minus-junit4",
         "guava",
     ],
diff --git a/updater_sample/tests/AndroidManifest.xml b/updater_sample/tests/AndroidManifest.xml
index 76af5f1..a2da3f7 100644
--- a/updater_sample/tests/AndroidManifest.xml
+++ b/updater_sample/tests/AndroidManifest.xml
@@ -26,7 +26,7 @@
         <uses-library android:name="android.test.runner" />
     </application>
 
-    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
                      android:targetPackage="com.example.android.systemupdatersample"
                      android:label="Tests for SystemUpdaterSample."/>
 
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateConfigTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateConfigTest.java
index 48d0e42..ae66683 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateConfigTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateConfigTest.java
@@ -21,9 +21,10 @@
 import static org.junit.Assert.assertTrue;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.example.android.systemupdatersample.tests.R;
 import com.google.common.io.CharStreams;
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateManagerTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateManagerTest.java
index 5ad16d4..af891f0 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateManagerTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/UpdateManagerTest.java
@@ -30,10 +30,11 @@
 import android.os.ResultReceiver;
 import android.os.UpdateEngine;
 import android.os.UpdateEngineCallback;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.annotation.UiThreadTest;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.annotation.UiThreadTest;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.example.android.systemupdatersample.services.PrepareUpdateService;
 import com.example.android.systemupdatersample.tests.R;
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/util/FileDownloaderTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/util/FileDownloaderTest.java
index a136ff0..ede2457 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/util/FileDownloaderTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/util/FileDownloaderTest.java
@@ -19,9 +19,10 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.example.android.systemupdatersample.tests.R;
 
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
index 0308693..9931e7b 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/util/PayloadSpecsTest.java
@@ -22,9 +22,10 @@
 import static org.junit.Assert.assertEquals;
 
 import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.example.android.systemupdatersample.PayloadSpec;
 import com.example.android.systemupdatersample.tests.R;
diff --git a/updater_sample/tests/src/com/example/android/systemupdatersample/util/UpdateConfigsTest.java b/updater_sample/tests/src/com/example/android/systemupdatersample/util/UpdateConfigsTest.java
index 4ccae93..4a967a9 100644
--- a/updater_sample/tests/src/com/example/android/systemupdatersample/util/UpdateConfigsTest.java
+++ b/updater_sample/tests/src/com/example/android/systemupdatersample/util/UpdateConfigsTest.java
@@ -18,8 +18,8 @@
 
 import static org.junit.Assert.assertArrayEquals;
 
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import com.example.android.systemupdatersample.UpdateConfig;