[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: 25491dc368 -s ours

am skip reason: subject contains skip directive

Original change: https://googleplex-android-review.googlesource.com/c/platform/bootable/recovery/+/14469279

Change-Id: I5e18ff98765ae143a1dc8057572748371a9bcc9f
diff --git a/Android.bp b/Android.bp
index 8e29dc8..52de770 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,6 +12,40 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS.  PLEASE
+//     CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+//     DEPENDING ON IT IN YOUR PROJECT. ***
+package {
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+// See: http://go/android-license-faq
+license {
+    name: "bootable_recovery_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+        "SPDX-license-identifier-MIT",
+        "SPDX-license-identifier-OFL", // by exception only
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "recovery_defaults",
 
@@ -79,6 +113,7 @@
         "librecovery_utils",
         "libotautil",
         "libsnapshot_nobinder",
+        "update_metadata-protos",
     ],
 }
 
diff --git a/Android.mk b/Android.mk
index 9f69153..96af417 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,6 +28,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := librecovery_ui_ext
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-OFL
+LOCAL_LICENSE_CONDITIONS := by_exception_only notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
 
 # LOCAL_MODULE_PATH for shared libraries is unsupported in multiarch builds.
 LOCAL_MULTILIB := first
@@ -54,14 +57,15 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := recovery_deps
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0 SPDX-license-identifier-MIT SPDX-license-identifier-OFL
+LOCAL_LICENSE_CONDITIONS := by_exception_only notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/NOTICE
 
 ifeq ($(TARGET_USERIMAGES_USE_F2FS),true)
-ifeq ($(HOST_OS),linux)
 LOCAL_REQUIRED_MODULES += \
     make_f2fs.recovery \
     sload_f2fs.recovery
 endif
-endif
 
 # On A/B devices recovery-persist reads the recovery related file from the persist storage and
 # copies them into /data/misc/recovery. Then, for both A/B and non-A/B devices, recovery-persist
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..a1ce3c6
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,9 @@
+# *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS.  PLEASE
+#     CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE
+#     DEPENDING ON IT IN YOUR PROJECT. ***
+third_party {
+  # would be NOTICE save for OFL in:
+  #   fonts/README
+  #   fonts/OFL.txt
+  license_type: BY_EXCEPTION_ONLY
+}
diff --git a/README.md b/README.md
index bd1cf7d..5ab19d1 100644
--- a/README.md
+++ b/README.md
@@ -143,3 +143,17 @@
 Both of the two conditions need to be satisfied. Although `ro.adb.secure` is a runtime property, its
 value is set at build time (written into `/prop.default`). It defaults to `1` on `-user` builds, and
 `0` for other build variants. The value is overridable via `PRODUCT_DEFAULT_PROPERTY_OVERRIDES`.
+
+Localization of the background texts
+------------------------------------
+
+The recovery image supports localization of several background texts, e.g. installing, error,
+factory reset warnings, etc. For devices using `xxhdpi` and `xxxhdpi`, the build system generates
+these localization images dynamically since android-10 when building the recovery image. While
+the static images under res-*dpi/images/ is used for other display resolutions and as a
+backup.
+
+Check the invocation of the image_generator tool in the [makefile]. And the detailed usage of the
+image_generator is documented [here](./tools/image_generator/README.md).
+
+[makefile]: https://android.googlesource.com/platform/build/+/refs/heads/master/core/Makefile#1800
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a304582..1237285 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -5,10 +5,6 @@
     },
     {
       "name": "recovery_unit_test"
-    },
-    {
-      "name": "recovery_host_test",
-      "host": true
     }
   ]
 }
diff --git a/applypatch/Android.bp b/applypatch/Android.bp
index 13a9625..0d6d23b 100644
--- a/applypatch/Android.bp
+++ b/applypatch/Android.bp
@@ -12,6 +12,23 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    default_applicable_licenses: ["bootable_recovery_applypatch_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+    name: "bootable_recovery_applypatch_license",
+    visibility: [":__subpackages__"],
+    license_kinds: [
+        "SPDX-license-identifier-Apache-2.0",
+    ],
+    license_text: [
+        "NOTICE",
+    ],
+}
+
 cc_defaults {
     name: "applypatch_defaults",
 
@@ -54,7 +71,7 @@
         "libbz",
         "libedify",
         "libotautil",
-        "libz",
+        "libz_stable",
     ],
 
     shared_libs: [
@@ -120,7 +137,7 @@
         "libbase",
         "libcrypto",
         "liblog",
-        "libz",
+        "libz_stable",
         "libziparchive",
     ],
 
@@ -129,9 +146,9 @@
     ],
 }
 
-cc_library_host_static {
+cc_library_static {
     name: "libimgdiff",
-
+    host_supported: true,
     defaults: [
         "applypatch_defaults",
     ],
@@ -152,14 +169,13 @@
         "liblog",
         "libotautil",
         "libutils",
-        "libz",
+        "libz_stable",
         "libziparchive",
     ],
 }
 
 cc_binary_host {
     name: "imgdiff",
-
     srcs: [
         "imgdiff_main.cpp",
     ],
@@ -180,6 +196,6 @@
         "liblog",
         "libbrotli",
         "libbz",
-        "libz",
+        "libz_stable",
     ],
 }
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index 6ad4a61..376c511 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -682,9 +682,9 @@
   }
 
   // Create a list of deflated zip entries, sorted by offset.
-  std::vector<std::pair<std::string, ZipEntry>> temp_entries;
+  std::vector<std::pair<std::string, ZipEntry64>> temp_entries;
   std::string name;
-  ZipEntry entry;
+  ZipEntry64 entry;
   while ((ret = Next(cookie, &entry, &name)) == 0) {
     if (entry.method == kCompressDeflated || limit_ > 0) {
       temp_entries.emplace_back(name, entry);
@@ -712,8 +712,14 @@
     // Add the end of zip file (mainly central directory) as a normal chunk.
     size_t entries_end = 0;
     if (!temp_entries.empty()) {
-      entries_end = static_cast<size_t>(temp_entries.back().second.offset +
-                                        temp_entries.back().second.compressed_length);
+      CHECK_GE(temp_entries.back().second.offset, 0);
+      if (__builtin_add_overflow(temp_entries.back().second.offset,
+                                 temp_entries.back().second.compressed_length, &entries_end)) {
+        LOG(ERROR) << "`entries_end` overflows on entry with offset "
+                   << temp_entries.back().second.offset << " and compressed_length "
+                   << temp_entries.back().second.compressed_length;
+        return false;
+      }
     }
     CHECK_LT(entries_end, file_content_.size());
     chunks_.emplace_back(CHUNK_NORMAL, entries_end, &file_content_,
@@ -735,8 +741,16 @@
         LOG(ERROR) << "Failed to add " << entry_name << " to target chunks";
         return false;
       }
-
-      pos += temp_entries[nextentry].second.compressed_length;
+      if (temp_entries[nextentry].second.compressed_length > std::numeric_limits<size_t>::max()) {
+        LOG(ERROR) << "Entry " << name << " compressed size exceeds size of address space. "
+                   << entry.compressed_length;
+        return false;
+      }
+      if (__builtin_add_overflow(pos, temp_entries[nextentry].second.compressed_length, &pos)) {
+        LOG(ERROR) << "`pos` overflows after adding "
+                   << temp_entries[nextentry].second.compressed_length;
+        return false;
+      }
       ++nextentry;
       continue;
     }
@@ -757,7 +771,13 @@
 }
 
 bool ZipModeImage::AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name,
-                                       ZipEntry* entry) {
+                                       ZipEntry64* entry) {
+  if (entry->compressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to add " << entry_name
+               << " because's compressed size exceeds size of address space. "
+               << entry->compressed_length;
+    return false;
+  }
   size_t compressed_len = entry->compressed_length;
   if (compressed_len == 0) return true;
 
@@ -775,6 +795,12 @@
     }
   } else if (entry->method == kCompressDeflated) {
     size_t uncompressed_len = entry->uncompressed_length;
+    if (uncompressed_len > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to add " << entry_name
+                 << " because's compressed size exceeds size of address space. "
+                 << uncompressed_len;
+      return false;
+    }
     std::vector<uint8_t> uncompressed_data(uncompressed_len);
     int ret = ExtractToMemory(handle, entry, uncompressed_data.data(), uncompressed_len);
     if (ret != 0) {
@@ -965,7 +991,7 @@
         used_src_ranges.Insert(src_ranges);
         split_src_ranges->push_back(std::move(src_ranges));
       }
-      src_ranges.Clear();
+      src_ranges = {};
 
       // We don't have enough space for the current chunk; start a new split image and handle
       // this chunk there.
@@ -1035,23 +1061,24 @@
   }
 
   ZipModeImage split_tgt_image(false);
-  split_tgt_image.Initialize(std::move(aligned_tgt_chunks), {});
+  split_tgt_image.Initialize(aligned_tgt_chunks, {});
   split_tgt_image.MergeAdjacentNormalChunks();
 
-  // Construct the dummy source file based on the src_ranges.
-  std::vector<uint8_t> src_content;
+  // Construct the split source file based on the split src ranges.
+  std::vector<uint8_t> split_src_content;
   for (const auto& r : split_src_ranges) {
     size_t end = std::min(src_image.file_content_.size(), r.second * BLOCK_SIZE);
-    src_content.insert(src_content.end(), src_image.file_content_.begin() + r.first * BLOCK_SIZE,
-                       src_image.file_content_.begin() + end);
+    split_src_content.insert(split_src_content.end(),
+                             src_image.file_content_.begin() + r.first * BLOCK_SIZE,
+                             src_image.file_content_.begin() + end);
   }
 
   // We should not have an empty src in our design; otherwise we will encounter an error in
-  // bsdiff since src_content.data() == nullptr.
-  CHECK(!src_content.empty());
+  // bsdiff since split_src_content.data() == nullptr.
+  CHECK(!split_src_content.empty());
 
   ZipModeImage split_src_image(true);
-  split_src_image.Initialize(split_src_chunks, std::move(src_content));
+  split_src_image.Initialize(split_src_chunks, split_src_content);
 
   split_tgt_images->push_back(std::move(split_tgt_image));
   split_src_images->push_back(std::move(split_src_image));
diff --git a/applypatch/include/applypatch/imgdiff_image.h b/applypatch/include/applypatch/imgdiff_image.h
index 6716051..b579e56 100644
--- a/applypatch/include/applypatch/imgdiff_image.h
+++ b/applypatch/include/applypatch/imgdiff_image.h
@@ -211,7 +211,7 @@
 
   bool Initialize(const std::string& filename) override;
 
-  // Initialize a dummy ZipModeImage from an existing ImageChunk vector. For src img pieces, we
+  // Initialize a fake ZipModeImage from an existing ImageChunk vector. For src img pieces, we
   // reconstruct a new file_content based on the source ranges; but it's not needed for the tgt img
   // pieces; because for each chunk both the data and their offset within the file are unchanged.
   void Initialize(const std::vector<ImageChunk>& chunks, const std::vector<uint8_t>& file_content) {
@@ -257,7 +257,8 @@
   // Initialize image chunks based on the zip entries.
   bool InitializeChunks(const std::string& filename, ZipArchiveHandle handle);
   // Add the a zip entry to the list.
-  bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name, ZipEntry* entry);
+  bool AddZipEntryToChunks(ZipArchiveHandle handle, const std::string& entry_name,
+                           ZipEntry64* entry);
   // Return the real size of the zip file. (omit the trailing zeros that used for alignment)
   bool GetZipFileSize(size_t* input_file_size);
 
@@ -265,7 +266,7 @@
                                   const std::vector<ZipModeImage>& split_src_images,
                                   std::vector<SortedRangeSet>& split_src_ranges,
                                   size_t total_tgt_size);
-  // Construct the dummy split images based on the chunks info and source ranges; and move them into
+  // Construct the fake split images based on the chunks info and source ranges; and move them into
   // the given vectors. Return true if we add a new split image into |split_tgt_images|, and
   // false otherwise.
   static bool AddSplitImageFromChunkList(const ZipModeImage& tgt_image,
diff --git a/bootloader_message/Android.bp b/bootloader_message/Android.bp
index 6443a07..778fdb9 100644
--- a/bootloader_message/Android.bp
+++ b/bootloader_message/Android.bp
@@ -14,6 +14,15 @@
 // limitations under the License.
 //
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "libbootloader_message_defaults",
     srcs: ["bootloader_message.cpp"],
diff --git a/edify/Android.bp b/edify/Android.bp
index 0ab53d6..62ff911 100644
--- a/edify/Android.bp
+++ b/edify/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_library_static {
     name: "libedify",
 
diff --git a/edify/include/edify/expr.h b/edify/include/edify/expr.h
index cd9c701..3ddf7f5 100644
--- a/edify/include/edify/expr.h
+++ b/edify/include/edify/expr.h
@@ -60,7 +60,7 @@
     BLOB = 2,
   };
 
-  Value(Type type, const std::string& str) : type(type), data(str) {}
+  Value(Type type, std::string str) : type(type), data(std::move(str)) {}
 
   Type type;
   std::string data;
diff --git a/etc/init.rc b/etc/init.rc
index 3ec45db..5cacb8b 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -24,9 +24,6 @@
     symlink /system/bin /bin
     symlink /system/etc /etc
 
-    mount cgroup none /acct cpuacct
-    mkdir /acct/uid
-
     mkdir /sdcard
     mkdir /system
     mkdir /data
diff --git a/fuse_sideload/Android.bp b/fuse_sideload/Android.bp
index 9bf19eb..4eb21dc 100644
--- a/fuse_sideload/Android.bp
+++ b/fuse_sideload/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_library {
     name: "libfusesideload",
     recovery_available: true,
diff --git a/install/Android.bp b/install/Android.bp
index bed3bc5..8c88bd0 100644
--- a/install/Android.bp
+++ b/install/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "libinstall_defaults",
 
diff --git a/install/install.cpp b/install/install.cpp
index d404997..1b220cb 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -67,14 +67,17 @@
 // Default allocation of progress bar segments to operations
 static constexpr int VERIFICATION_PROGRESS_TIME = 60;
 static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
-
+// The charater used to separate dynamic fingerprints. e.x. sargo|aosp-sargo
+static const char* FINGERPRING_SEPARATOR = "|";
 static std::condition_variable finish_log_temperature;
+static bool isInStringList(const std::string& target_token, const std::string& str_list,
+                           const std::string& deliminator);
 
 bool ReadMetadataFromPackage(ZipArchiveHandle zip, std::map<std::string, std::string>* metadata) {
   CHECK(metadata != nullptr);
 
   static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
-  ZipEntry entry;
+  ZipEntry64 entry;
   if (FindEntry(zip, METADATA_PATH, &entry) != 0) {
     LOG(ERROR) << "Failed to find " << METADATA_PATH;
     return false;
@@ -151,7 +154,8 @@
 
   auto device_fingerprint = android::base::GetProperty("ro.build.fingerprint", "");
   auto pkg_pre_build_fingerprint = get_value(metadata, "pre-build");
-  if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != device_fingerprint) {
+  if (!pkg_pre_build_fingerprint.empty() &&
+      !isInStringList(device_fingerprint, pkg_pre_build_fingerprint, FINGERPRING_SEPARATOR)) {
     LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint << " but expected "
                << device_fingerprint;
     return false;
@@ -199,7 +203,8 @@
 
   auto device = android::base::GetProperty("ro.product.device", "");
   auto pkg_device = get_value(metadata, "pre-device");
-  if (pkg_device != device || pkg_device.empty()) {
+  // device name can be a | separated list, so need to check
+  if (pkg_device.empty() || !isInStringList(device, pkg_device, FINGERPRING_SEPARATOR)) {
     LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << device;
     return false;
   }
@@ -236,12 +241,18 @@
   // For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset
   // in the zip file.
   static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
-  ZipEntry properties_entry;
+  ZipEntry64 properties_entry;
   if (FindEntry(zip, AB_OTA_PAYLOAD_PROPERTIES, &properties_entry) != 0) {
     LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD_PROPERTIES;
     return false;
   }
-  uint32_t properties_entry_length = properties_entry.uncompressed_length;
+  auto properties_entry_length = properties_entry.uncompressed_length;
+  if (properties_entry_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES
+               << " because's uncompressed size exceeds size of address space. "
+               << properties_entry_length;
+    return false;
+  }
   std::vector<uint8_t> payload_properties(properties_entry_length);
   int32_t err =
       ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length);
@@ -251,7 +262,7 @@
   }
 
   static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
-  ZipEntry payload_entry;
+  ZipEntry64 payload_entry;
   if (FindEntry(zip, AB_OTA_PAYLOAD, &payload_entry) != 0) {
     LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD;
     return false;
@@ -273,7 +284,7 @@
 
   // In non-A/B updates we extract the update binary from the package.
   static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
-  ZipEntry binary_entry;
+  ZipEntry64 binary_entry;
   if (FindEntry(zip, UPDATE_BINARY_NAME, &binary_entry) != 0) {
     LOG(ERROR) << "Failed to find update binary " << UPDATE_BINARY_NAME;
     return false;
@@ -699,3 +710,18 @@
   }
   return true;
 }
+
+// Check if `target_token` is in string `str_list`, where `str_list` is expected to be a
+// list delimited by `deliminator`
+// E.X. isInStringList("a", "a|b|c|d", "|") => true
+// E.X. isInStringList("abc", "abc", "|") => true
+static bool isInStringList(const std::string& target_token, const std::string& str_list,
+                           const std::string& deliminator) {
+  if (target_token.length() > str_list.length()) {
+    return false;
+  } else if (target_token.length() == str_list.length() || deliminator.length() == 0) {
+    return target_token == str_list;
+  }
+  auto&& list = android::base::Split(str_list, deliminator);
+  return std::find(list.begin(), list.end(), target_token) != list.end();
+}
diff --git a/install/snapshot_utils.cpp b/install/snapshot_utils.cpp
index 7235e67..336e50f 100644
--- a/install/snapshot_utils.cpp
+++ b/install/snapshot_utils.cpp
@@ -32,7 +32,7 @@
   }
 
   RecoveryUI* ui = device->GetUI();
-  auto sm = SnapshotManager::NewForFirstStageMount();
+  auto sm = SnapshotManager::New();
   if (!sm) {
     ui->Print("Could not create SnapshotManager.\n");
     return false;
@@ -57,7 +57,7 @@
     return true;
   }
 
-  auto sm = SnapshotManager::NewForFirstStageMount();
+  auto sm = SnapshotManager::New();
   if (!sm) {
     // SnapshotManager could not be created. The device is still in a
     // consistent state and can continue with the mounting of the existing
diff --git a/install/verifier.cpp b/install/verifier.cpp
index ab75044..3f02601 100644
--- a/install/verifier.cpp
+++ b/install/verifier.cpp
@@ -321,8 +321,14 @@
   std::vector<Certificate> result;
 
   std::string_view name;
-  ZipEntry entry;
+  ZipEntry64 entry;
   while ((iter_status = Next(cookie, &entry, &name)) == 0) {
+    if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to extract " << name
+                 << " because's uncompressed size exceeds size of address space. "
+                 << entry.uncompressed_length;
+      return {};
+    }
     std::vector<uint8_t> pem_content(entry.uncompressed_length);
     if (int32_t extract_status =
             ExtractToMemory(handle, &entry, pem_content.data(), pem_content.size());
diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp
index 2872085..4eecf72 100644
--- a/install/wipe_data.cpp
+++ b/install/wipe_data.cpp
@@ -41,9 +41,6 @@
   bool is_cache = (strcmp(volume, CACHE_ROOT) == 0);
   bool is_data = (strcmp(volume, DATA_ROOT) == 0);
 
-  ui->SetBackground(RecoveryUI::ERASING);
-  ui->SetProgressType(RecoveryUI::INDETERMINATE);
-
   std::vector<saved_log_file> log_files;
   if (is_cache) {
     // If we're reformatting /cache, we load any past logs (i.e. "/cache/recovery/last_*") and the
@@ -97,6 +94,9 @@
   }
 
   ui->Print("\n-- Wiping cache...\n");
+  ui->SetBackground(RecoveryUI::ERASING);
+  ui->SetProgressType(RecoveryUI::INDETERMINATE);
+
   bool success = EraseVolume("/cache", ui, false);
   ui->Print("Cache wipe %s.\n", success ? "complete" : "failed");
   return success;
@@ -105,6 +105,8 @@
 bool WipeData(Device* device, bool convert_fbe) {
   RecoveryUI* ui = device->GetUI();
   ui->Print("\n-- Wiping data...\n");
+  ui->SetBackground(RecoveryUI::ERASING);
+  ui->SetProgressType(RecoveryUI::INDETERMINATE);
 
   if (!FinishPendingSnapshotMerges(device)) {
     ui->Print("Unable to check update status or complete merge, cannot wipe partitions.\n");
diff --git a/install/wipe_device.cpp b/install/wipe_device.cpp
index 89d5d31..915c87b 100644
--- a/install/wipe_device.cpp
+++ b/install/wipe_device.cpp
@@ -49,9 +49,14 @@
   constexpr char RECOVERY_WIPE_ENTRY_NAME[] = "recovery.wipe";
 
   std::string partition_list_content;
-  ZipEntry entry;
+  ZipEntry64 entry;
   if (FindEntry(zip, RECOVERY_WIPE_ENTRY_NAME, &entry) == 0) {
-    uint32_t length = entry.uncompressed_length;
+    auto length = entry.uncompressed_length;
+    if (length > std::numeric_limits<size_t>::max()) {
+      LOG(ERROR) << "Failed to extract " << RECOVERY_WIPE_ENTRY_NAME
+                 << " because's uncompressed size exceeds size of address space. " << length;
+      return {};
+    }
     partition_list_content = std::string(length, '\0');
     if (auto err = ExtractToMemory(
             zip, &entry, reinterpret_cast<uint8_t*>(partition_list_content.data()), length);
diff --git a/minadbd/Android.bp b/minadbd/Android.bp
index b6ca59e..2bcfece 100644
--- a/minadbd/Android.bp
+++ b/minadbd/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "minadbd_defaults",
 
@@ -24,7 +33,7 @@
     cpp_std: "experimental",
 
     include_dirs: [
-        "system/core/adb",
+        "packages/modules/adb",
     ],
 
     header_libs: [
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index ff91ba9..0abe867 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <chrono>
 #include <functional>
 #include <memory>
 #include <set>
@@ -142,10 +143,48 @@
   return kMinadbdSuccess;
 }
 
+static bool WaitForSocketClose(int fd, std::chrono::milliseconds timeout) {
+  const auto begin = std::chrono::steady_clock::now();
+  const auto end = begin + timeout;
+  while (std::chrono::steady_clock::now() < end) {
+    // We don't care about reading the socket, we just want to wait until
+    // socket closes. In this case .events = 0 will tell the kernel to wait
+    // for close events.
+    struct pollfd pfd = { .fd = fd, .events = 0 };
+    auto timeout_ms = std::chrono::duration_cast<std::chrono::milliseconds>(
+                          end - std::chrono::steady_clock::now())
+                          .count();
+    int rc = TEMP_FAILURE_RETRY(adb_poll(&pfd, 1, timeout_ms));
+    if (rc == 1) {
+      LOG(INFO) << "revents: " << pfd.revents;
+      if (pfd.revents & (POLLHUP | POLLRDHUP)) {
+        return true;
+      }
+    } else {
+      PLOG(ERROR) << "poll() failed";
+      // poll failed, almost definitely due to timeout
+      // If not, you're screwed anyway, because it probably means the kernel ran
+      // out of memory.
+      return false;
+    }
+  }
+  return false;
+}
+
 // Sideload service always exits after serving an install command.
 static void SideloadHostService(unique_fd sfd, const std::string& args) {
+  using namespace std::chrono_literals;
   MinadbdCommandStatus status;
-  exit(RunAdbFuseSideload(sfd.get(), args, &status));
+  auto error = RunAdbFuseSideload(sfd.get(), args, &status);
+  // No need to wait if the socket is already closed, meaning the other end
+  // already exited for some reason.
+  if (error != kMinadbdHostSocketIOError) {
+    // We sleep for a little bit just to wait for the host to receive last
+    // "DONEDONE" message. However minadbd process is likely to get terminated
+    // early due to exit_on_close
+    WaitForSocketClose(sfd, 3000ms);
+  }
+  exit(error);
 }
 
 // Rescue service waits for the next command after an install command.
diff --git a/minui/Android.bp b/minui/Android.bp
index fff3a8e..f68f6c8 100644
--- a/minui/Android.bp
+++ b/minui/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_library {
     name: "libminui",
     recovery_available: true,
@@ -27,14 +36,12 @@
     srcs: [
         "events.cpp",
         "graphics.cpp",
-        "graphics_adf.cpp",
         "graphics_drm.cpp",
         "graphics_fbdev.cpp",
         "resources.cpp",
     ],
 
     whole_static_libs: [
-        "libadf",
         "libdrm",
         "libsync",
     ],
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index d34da56..dce1e61 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -25,7 +25,6 @@
 
 #include <android-base/properties.h>
 
-#include "graphics_adf.h"
 #include "graphics_drm.h"
 #include "graphics_fbdev.h"
 #include "minui/minui.h"
@@ -362,15 +361,10 @@
            ret);
   }
 
-  auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendAdf>() };
+  auto backend = std::unique_ptr<MinuiBackend>{ std::make_unique<MinuiBackendDrm>() };
   gr_draw = backend->Init();
 
   if (!gr_draw) {
-    backend = std::make_unique<MinuiBackendDrm>();
-    gr_draw = backend->Init();
-  }
-
-  if (!gr_draw) {
     backend = std::make_unique<MinuiBackendFbdev>();
     gr_draw = backend->Init();
   }
diff --git a/minui/graphics_adf.cpp b/minui/graphics_adf.cpp
deleted file mode 100644
index 10cd607..0000000
--- a/minui/graphics_adf.cpp
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "graphics_adf.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-
-#include <adf/adf.h>
-#include <sync/sync.h>
-
-#include "minui/minui.h"
-
-GRSurfaceAdf::~GRSurfaceAdf() {
-  if (mmapped_buffer_) {
-    munmap(mmapped_buffer_, pitch * height);
-  }
-  if (fence_fd != -1) {
-    close(fence_fd);
-  }
-  if (fd != -1) {
-    close(fd);
-  }
-}
-
-std::unique_ptr<GRSurfaceAdf> GRSurfaceAdf::Create(int intf_fd, const drm_mode_modeinfo* mode,
-                                                   __u32 format, int* err) {
-  __u32 offset;
-  __u32 pitch;
-  auto fd = adf_interface_simple_buffer_alloc(intf_fd, mode->hdisplay, mode->vdisplay, format,
-                                              &offset, &pitch);
-
-  if (fd < 0) {
-    *err = fd;
-    return nullptr;
-  }
-
-  std::unique_ptr<GRSurfaceAdf> surf = std::unique_ptr<GRSurfaceAdf>(
-      new GRSurfaceAdf(mode->hdisplay, mode->vdisplay, pitch, (format == DRM_FORMAT_RGB565 ? 2 : 4),
-                       offset, pitch, fd));
-
-  auto mmapped =
-      mmap(nullptr, surf->pitch * surf->height, PROT_WRITE, MAP_SHARED, surf->fd, surf->offset);
-  if (mmapped == MAP_FAILED) {
-    *err = -errno;
-    return nullptr;
-  }
-  surf->mmapped_buffer_ = static_cast<uint8_t*>(mmapped);
-  return surf;
-}
-
-MinuiBackendAdf::MinuiBackendAdf() : intf_fd(-1), dev(), current_surface(0), n_surfaces(0) {}
-
-int MinuiBackendAdf::InterfaceInit() {
-  adf_interface_data intf_data;
-  if (int err = adf_get_interface_data(intf_fd, &intf_data); err < 0) return err;
-
-  int result = 0;
-  surfaces[0] = GRSurfaceAdf::Create(intf_fd, &intf_data.current_mode, format, &result);
-  if (!surfaces[0]) {
-    fprintf(stderr, "Failed to allocate surface 0: %s\n", strerror(-result));
-    goto done;
-  }
-
-  surfaces[1] = GRSurfaceAdf::Create(intf_fd, &intf_data.current_mode, format, &result);
-  if (!surfaces[1]) {
-    fprintf(stderr, "Failed to allocate surface 1: %s\n", strerror(-result));
-    n_surfaces = 1;
-  } else {
-    n_surfaces = 2;
-  }
-
-done:
-  adf_free_interface_data(&intf_data);
-  return result;
-}
-
-int MinuiBackendAdf::DeviceInit(adf_device* dev) {
-  adf_id_t intf_id;
-  int err = adf_find_simple_post_configuration(dev, &format, 1, &intf_id, &eng_id);
-  if (err < 0) return err;
-
-  err = adf_device_attach(dev, eng_id, intf_id);
-  if (err < 0 && err != -EALREADY) return err;
-
-  intf_fd = adf_interface_open(dev, intf_id, O_RDWR | O_CLOEXEC);
-  if (intf_fd < 0) return intf_fd;
-
-  err = InterfaceInit();
-  if (err < 0) {
-    close(intf_fd);
-    intf_fd = -1;
-  }
-
-  return err;
-}
-
-GRSurface* MinuiBackendAdf::Init() {
-  PixelFormat pixel_format = gr_pixel_format();
-  if (pixel_format == PixelFormat::ABGR) {
-    format = DRM_FORMAT_ABGR8888;
-  } else if (pixel_format == PixelFormat::BGRA) {
-    format = DRM_FORMAT_BGRA8888;
-  } else if (pixel_format == PixelFormat::RGBX) {
-    format = DRM_FORMAT_RGBX8888;
-  } else {
-    format = DRM_FORMAT_RGB565;
-  }
-
-  adf_id_t* dev_ids = nullptr;
-  ssize_t n_dev_ids = adf_devices(&dev_ids);
-  if (n_dev_ids == 0) {
-    return nullptr;
-  } else if (n_dev_ids < 0) {
-    fprintf(stderr, "enumerating adf devices failed: %s\n", strerror(-n_dev_ids));
-    return nullptr;
-  }
-
-  intf_fd = -1;
-
-  for (ssize_t i = 0; i < n_dev_ids && intf_fd < 0; i++) {
-    int err = adf_device_open(dev_ids[i], O_RDWR, &dev);
-    if (err < 0) {
-      fprintf(stderr, "opening adf device %u failed: %s\n", dev_ids[i], strerror(-err));
-      continue;
-    }
-
-    err = DeviceInit(&dev);
-    if (err < 0) {
-      fprintf(stderr, "initializing adf device %u failed: %s\n", dev_ids[i], strerror(-err));
-      adf_device_close(&dev);
-    }
-  }
-
-  free(dev_ids);
-
-  if (intf_fd < 0) return nullptr;
-
-  GRSurface* ret = Flip();
-
-  Blank(true);
-  Blank(false);
-
-  return ret;
-}
-
-void MinuiBackendAdf::Sync(GRSurfaceAdf* surf) {
-  static constexpr unsigned int kWarningTimeout = 3000;
-
-  if (surf == nullptr) return;
-
-  if (surf->fence_fd >= 0) {
-    int err = sync_wait(surf->fence_fd, kWarningTimeout);
-    if (err < 0) {
-      perror("adf sync fence wait error\n");
-    }
-
-    close(surf->fence_fd);
-    surf->fence_fd = -1;
-  }
-}
-
-GRSurface* MinuiBackendAdf::Flip() {
-  const auto& surf = surfaces[current_surface];
-
-  int fence_fd = adf_interface_simple_post(intf_fd, eng_id, surf->width, surf->height, format,
-                                           surf->fd, surf->offset, surf->pitch, -1);
-  if (fence_fd >= 0) surf->fence_fd = fence_fd;
-
-  current_surface = (current_surface + 1) % n_surfaces;
-  Sync(surfaces[current_surface].get());
-  return surfaces[current_surface].get();
-}
-
-void MinuiBackendAdf::Blank(bool blank) {
-  adf_interface_blank(intf_fd, blank ? DRM_MODE_DPMS_OFF : DRM_MODE_DPMS_ON);
-}
-
-MinuiBackendAdf::~MinuiBackendAdf() {
-  adf_device_close(&dev);
-  if (intf_fd >= 0) close(intf_fd);
-}
diff --git a/minui/graphics_adf.h b/minui/graphics_adf.h
deleted file mode 100644
index 79d8d2a..0000000
--- a/minui/graphics_adf.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <memory>
-
-#include <adf/adf.h>
-
-#include "graphics.h"
-#include "minui/minui.h"
-
-class GRSurfaceAdf : public GRSurface {
- public:
-  ~GRSurfaceAdf() override;
-
-  static std::unique_ptr<GRSurfaceAdf> Create(int intf_fd, const drm_mode_modeinfo* mode,
-                                              __u32 format, int* err);
-
-  uint8_t* data() override {
-    return mmapped_buffer_;
-  }
-
- private:
-  friend class MinuiBackendAdf;
-
-  GRSurfaceAdf(size_t width, size_t height, size_t row_bytes, size_t pixel_bytes, __u32 offset,
-               __u32 pitch, int fd)
-      : GRSurface(width, height, row_bytes, pixel_bytes), offset(offset), pitch(pitch), fd(fd) {}
-
-  const __u32 offset;
-  const __u32 pitch;
-
-  int fd;
-  int fence_fd{ -1 };
-  uint8_t* mmapped_buffer_{ nullptr };
-};
-
-class MinuiBackendAdf : public MinuiBackend {
- public:
-  MinuiBackendAdf();
-  ~MinuiBackendAdf() override;
-  GRSurface* Init() override;
-  GRSurface* Flip() override;
-  void Blank(bool) override;
-
- private:
-  int InterfaceInit();
-  int DeviceInit(adf_device* dev);
-  void Sync(GRSurfaceAdf* surf);
-
-  int intf_fd;
-  adf_id_t eng_id;
-  __u32 format;
-  adf_device dev;
-  size_t current_surface;
-  size_t n_surfaces;
-  std::unique_ptr<GRSurfaceAdf> surfaces[2];
-};
diff --git a/minui/resources.cpp b/minui/resources.cpp
index f635acd..d7b9277 100644
--- a/minui/resources.cpp
+++ b/minui/resources.cpp
@@ -450,5 +450,5 @@
 }
 
 void res_free_surface(GRSurface* surface) {
-  free(surface);
+  delete(surface);
 }
diff --git a/otautil/Android.bp b/otautil/Android.bp
index 3b3f9cb..557b8a3 100644
--- a/otautil/Android.bp
+++ b/otautil/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_library_static {
     name: "libotautil",
 
diff --git a/otautil/include/otautil/error_code.h b/otautil/include/otautil/error_code.h
index 2b73c13..7b52ce5 100644
--- a/otautil/include/otautil/error_code.h
+++ b/otautil/include/otautil/error_code.h
@@ -22,7 +22,7 @@
   kLowBattery = 20,
   kZipVerificationFailure,
   kZipOpenFailure,
-  kBootreasonInBlacklist,
+  kBootreasonInBlocklist,
   kPackageCompatibilityFailure,
   kScriptExecutionFailure,
   kMapFileFailure,
diff --git a/recovery.cpp b/recovery.cpp
index 7675121..36924fb 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -421,15 +421,15 @@
       case Device::REBOOT:
       case Device::SHUTDOWN:
         if (!ui->IsTextVisible()) {
-          return Device::REBOOT;
+          return chosen_action;
         }
         // okay to reboot; no need to ask.
         if (!update_in_progress) {
-          return Device::REBOOT;
+          return chosen_action;
         }
         // An update might have been failed. Ask if user really wants to reboot.
         if (AskToReboot(device, chosen_action)) {
-          return Device::REBOOT;
+          return chosen_action;
         }
         break;
 
@@ -559,15 +559,15 @@
   }
 }
 
-static bool bootreason_in_blacklist() {
+static bool bootreason_in_blocklist() {
   std::string bootreason = android::base::GetProperty("ro.boot.bootreason", "");
   if (!bootreason.empty()) {
     // More bootreasons can be found in "system/core/bootstat/bootstat.cpp".
-    static const std::vector<std::string> kBootreasonBlacklist{
+    static const std::vector<std::string> kBootreasonBlocklist{
       "kernel_panic",
       "Panic",
     };
-    for (const auto& str : kBootreasonBlacklist) {
+    for (const auto& str : kBootreasonBlocklist) {
       if (android::base::EqualsIgnoreCase(str, bootreason)) return true;
     }
   }
@@ -702,7 +702,7 @@
   }
 
   std::vector<std::string> title_lines =
-      android::base::Split(android::base::GetProperty("ro.bootimage.build.fingerprint", ""), ":");
+      android::base::Split(android::base::GetProperty("ro.build.fingerprint", ""), ":");
   title_lines.insert(std::begin(title_lines), "Android Recovery");
   ui->SetTitle(title_lines);
 
@@ -734,10 +734,10 @@
       // 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()) {
+    } else if (retry_count == 0 && bootreason_in_blocklist()) {
       // Skip update-on-reboot when bootreason is kernel_panic or similar
-      ui->Print("bootreason is in the blacklist; skip OTA installation\n");
-      log_failure_code(kBootreasonInBlacklist, update_package);
+      ui->Print("bootreason is in the blocklist; skip OTA installation\n");
+      log_failure_code(kBootreasonInBlocklist, update_package);
       status = INSTALL_SKIPPED;
     } else {
       // It's a fresh update. Initialize the retry_count in the BCB to 1; therefore we can later
diff --git a/recovery_ui/Android.bp b/recovery_ui/Android.bp
index 9dfee5f..f64b0d1 100644
--- a/recovery_ui/Android.bp
+++ b/recovery_ui/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_library {
     name: "librecovery_ui",
     recovery_available: true,
@@ -22,6 +31,7 @@
 
     srcs: [
         "device.cpp",
+        "ethernet_device.cpp",
         "ethernet_ui.cpp",
         "screen_ui.cpp",
         "stub_ui.cpp",
@@ -102,7 +112,7 @@
     ],
 
     srcs: [
-        "ethernet_device.cpp",
+        "default_ethernet_device.cpp",
     ],
 
     shared_libs: [
diff --git a/recovery_ui/default_ethernet_device.cpp b/recovery_ui/default_ethernet_device.cpp
new file mode 100644
index 0000000..1fdff0d
--- /dev/null
+++ b/recovery_ui/default_ethernet_device.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 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_ui/device.h"
+#include "recovery_ui/ethernet_device.h"
+#include "recovery_ui/ethernet_ui.h"
+
+Device* make_device() {
+  return new EthernetDevice(new EthernetRecoveryUI);
+}
diff --git a/recovery_ui/ethernet_device.cpp b/recovery_ui/ethernet_device.cpp
index 39ec65d..d79f41d 100644
--- a/recovery_ui/ethernet_device.cpp
+++ b/recovery_ui/ethernet_device.cpp
@@ -27,23 +27,9 @@
 #include <sys/types.h>
 
 #include "recovery_ui/device.h"
+#include "recovery_ui/ethernet_device.h"
 #include "recovery_ui/ethernet_ui.h"
 
-class EthernetDevice : public Device {
- public:
-  explicit EthernetDevice(EthernetRecoveryUI* ui);
-
-  void PreRecovery() override;
-  void PreFastboot() override;
-
- private:
-  int SetInterfaceFlags(const unsigned set, const unsigned clr);
-  void SetTitleIPv6LinkLocalAddress(const bool interface_up);
-
-  android::base::unique_fd ctl_sock_;
-  static const std::string interface;
-};
-
 const std::string EthernetDevice::interface = "eth0";
 
 EthernetDevice::EthernetDevice(EthernetRecoveryUI* ui)
@@ -129,8 +115,3 @@
 
   recovery_ui->SetIPv6LinkLocalAddress();
 }
-
-// -----------------------------------------------------------------------------------------
-Device* make_device() {
-  return new EthernetDevice(new EthernetRecoveryUI);
-}
diff --git a/recovery_ui/include/recovery_ui/ethernet_device.h b/recovery_ui/include/recovery_ui/ethernet_device.h
new file mode 100644
index 0000000..ea710ab
--- /dev/null
+++ b/recovery_ui/include/recovery_ui/ethernet_device.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2020 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 _ETHERNET_RECOVERY_DEVICE_H
+#define _ETHERNET_RECOVERY_DEVICE_H
+
+#include "device.h"
+
+#include <android-base/unique_fd.h>
+
+// Forward declaration to avoid including "ethernet_ui.h".
+class EthernetRecoveryUI;
+
+class EthernetDevice : public Device {
+ public:
+  explicit EthernetDevice(EthernetRecoveryUI* ui);
+
+  void PreRecovery() override;
+  void PreFastboot() override;
+
+ private:
+  int SetInterfaceFlags(const unsigned set, const unsigned clr);
+  void SetTitleIPv6LinkLocalAddress(const bool interface_up);
+
+  android::base::unique_fd ctl_sock_;
+  static const std::string interface;
+};
+
+#endif  // _ETHERNET_RECOVERY_DEVICE_H
diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h
index 08ec1d7..512732f 100644
--- a/recovery_ui/include/recovery_ui/ui.h
+++ b/recovery_ui/include/recovery_ui/ui.h
@@ -192,6 +192,8 @@
     return key_interrupted_;
   }
 
+  virtual bool IsUsbConnected();
+
  protected:
   void EnqueueKey(int key_code);
 
@@ -226,8 +228,6 @@
   void ProcessKey(int key_code, int updown);
   void TimeKey(int key_code, int count);
 
-  bool IsUsbConnected();
-
   bool InitScreensaver();
   void SetScreensaverState(ScreensaverState state);
 
diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp
index 087fc0e..b2c828f 100644
--- a/recovery_ui/screen_ui.cpp
+++ b/recovery_ui/screen_ui.cpp
@@ -37,6 +37,7 @@
 #include <unordered_map>
 #include <vector>
 
+#include <android-base/chrono_utils.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
@@ -448,7 +449,9 @@
     int frame_height = gr_get_height(frame);
     int frame_x = (ScreenWidth() - frame_width) / 2;
     int frame_y = GetAnimationBaseline();
-    DrawSurface(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
+    if (frame_x >= 0 && frame_y >= 0 && (frame_x + frame_width) < ScreenWidth() &&
+        (frame_y + frame_height) < ScreenHeight())
+      DrawSurface(frame, 0, 0, frame_width, frame_height, frame_x, frame_y);
   }
 
   if (progressBarType != EMPTY) {
@@ -879,10 +882,28 @@
   return true;
 }
 
+static bool InitGraphics() {
+  // Timeout is same as init wait for file default of 5 seconds and is arbitrary
+  const unsigned timeout = 500;  // 10ms increments
+  for (auto retry = timeout; retry > 0; --retry) {
+    if (gr_init() == 0) {
+      if (retry < timeout) {
+        // Log message like init wait for file completion log for consistency.
+        LOG(WARNING) << "wait for 'graphics' took " << ((timeout - retry) * 10) << "ms";
+      }
+      return true;
+    }
+    std::this_thread::sleep_for(10ms);
+  }
+  // Log message like init wait for file timeout log for consistency.
+  LOG(ERROR) << "timeout wait for 'graphics' took " << (timeout * 10) << "ms";
+  return false;
+}
+
 bool ScreenRecoveryUI::Init(const std::string& locale) {
   RecoveryUI::Init(locale);
 
-  if (gr_init() == -1) {
+  if (!InitGraphics()) {
     return false;
   }
 
diff --git a/recovery_utils/Android.bp b/recovery_utils/Android.bp
index bf79a2e..e0e9ec0 100644
--- a/recovery_utils/Android.bp
+++ b/recovery_utils/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "librecovery_utils_defaults",
 
diff --git a/recovery_utils/roots.cpp b/recovery_utils/roots.cpp
index 99f3c5d..1948447 100644
--- a/recovery_utils/roots.cpp
+++ b/recovery_utils/roots.cpp
@@ -259,6 +259,12 @@
     make_f2fs_cmd.push_back("-C");
     make_f2fs_cmd.push_back("utf8");
   }
+  if (v->fs_mgr_flags.fs_compress) {
+    make_f2fs_cmd.push_back("-O");
+    make_f2fs_cmd.push_back("compression");
+    make_f2fs_cmd.push_back("-O");
+    make_f2fs_cmd.push_back("extra_attr");
+  }
   make_f2fs_cmd.push_back(v->blk_device);
   if (length >= kSectorSize) {
     make_f2fs_cmd.push_back(std::to_string(length / kSectorSize));
diff --git a/tests/Android.bp b/tests/Android.bp
index 4c23255..5ef4d58 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "recovery_test_defaults",
 
@@ -31,7 +40,6 @@
         "libpng",
         "libprocessgroup",
         "libselinux",
-        "libz",
         "libziparchive",
     ],
 
@@ -65,7 +73,7 @@
     "libbase",
     "libbrotli",
     "libbz",
-    "libz",
+    "libz_stable",
     "libziparchive",
 ]
 
@@ -95,6 +103,24 @@
     "libc++fs",
 ]
 
+// recovery image for unittests.
+// ========================================================
+genrule {
+    name: "recovery_image",
+    cmd: "cat $(location testdata/recovery_head) <(cat $(location testdata/recovery_body) | $(location minigzip)) $(location testdata/recovery_tail) > $(out)",
+    srcs: [
+        "testdata/recovery_head",
+        "testdata/recovery_body",
+        "testdata/recovery_tail",
+    ],
+    tools: [
+        "minigzip",
+    ],
+    out: [
+        "testdata/recovery.img",
+    ],
+}
+
 cc_test {
     name: "recovery_unit_test",
     isolated: true,
@@ -122,12 +148,15 @@
         "libupdater_core",
         "libupdate_verifier",
 
-        "libgtest_prod",
         "libprotobuf-cpp-lite",
     ],
+    header_libs: [
+        "libgtest_prod_headers",
+    ],
 
     data: [
         "testdata/*",
+        ":recovery_image",
         ":res-testdata",
     ],
 }
@@ -182,3 +211,23 @@
         },
     },
 }
+
+cc_fuzz {
+    name: "libinstall_verify_package_fuzzer",
+    defaults: [
+        "recovery_test_defaults",
+    ],
+
+    srcs: ["fuzz/verify_package_fuzzer.cpp"],
+
+    corpus: [
+      "testdata/otasigned*.zip",
+    ],
+
+    static_libs: [
+        "libotautil",
+        "libinstall",
+        "librecovery_ui",
+        "libminui",
+    ],
+}
diff --git a/tests/AndroidTest.xml b/tests/AndroidTest.xml
new file mode 100644
index 0000000..0ac75e4
--- /dev/null
+++ b/tests/AndroidTest.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<configuration description="Runs recovery_host_test.">
+    <option name="null-device" value="true" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+        <option name="force-root" value="false" />
+    </target_preparer>
+    <option name="not-shardable" value="true" />
+
+    <test class="com.android.tradefed.testtype.HostGTest" >
+        <option name="module-name" value="recovery_host_test" />
+        <option name="native-test-timeout" value="5m"/>
+    </test>
+</configuration>
diff --git a/tests/fuzz/verify_package_fuzzer.cpp b/tests/fuzz/verify_package_fuzzer.cpp
new file mode 100644
index 0000000..baa44e0
--- /dev/null
+++ b/tests/fuzz/verify_package_fuzzer.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2020 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 "fuzzer/FuzzedDataProvider.h"
+
+#include "install/install.h"
+#include "install/package.h"
+#include "recovery_ui/stub_ui.h"
+
+std::unique_ptr<Package> CreatePackage(std::vector<uint8_t>& content) {
+  return Package::CreateMemoryPackage(content, [](float) -> void {});
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+  FuzzedDataProvider data_provider(data, size);
+  auto package_contents = data_provider.ConsumeRemainingBytes<uint8_t>();
+  if (package_contents.size() == 0) {
+    return 0;
+  }
+  auto package = CreatePackage(package_contents);
+  StubRecoveryUI ui;
+  verify_package(package.get(), &ui);
+  return 0;
+}
diff --git a/tests/testdata/recovery-from-boot.p b/tests/testdata/recovery-from-boot.p
index 06f6c29..81738ed 100644
--- a/tests/testdata/recovery-from-boot.p
+++ b/tests/testdata/recovery-from-boot.p
Binary files differ
diff --git a/tests/testdata/recovery.img b/tests/testdata/recovery.img
deleted file mode 100644
index b862e6f..0000000
--- a/tests/testdata/recovery.img
+++ /dev/null
Binary files differ
diff --git a/tests/testdata/recovery_body b/tests/testdata/recovery_body
new file mode 100644
index 0000000..48d7c10
--- /dev/null
+++ b/tests/testdata/recovery_body
Binary files differ
diff --git a/tests/testdata/recovery_head b/tests/testdata/recovery_head
new file mode 100644
index 0000000..7f494d0
--- /dev/null
+++ b/tests/testdata/recovery_head
Binary files differ
diff --git a/tests/testdata/recovery_tail b/tests/testdata/recovery_tail
new file mode 100644
index 0000000..7fe2c6c
--- /dev/null
+++ b/tests/testdata/recovery_tail
Binary files differ
diff --git a/tests/testdata/ziptest_dummy-update.zip b/tests/testdata/ziptest_fake-update.zip
similarity index 100%
rename from tests/testdata/ziptest_dummy-update.zip
rename to tests/testdata/ziptest_fake-update.zip
Binary files differ
diff --git a/tests/unit/host/imgdiff_test.cpp b/tests/unit/host/imgdiff_test.cpp
index e76ccbd..978ac7c 100644
--- a/tests/unit/host/imgdiff_test.cpp
+++ b/tests/unit/host/imgdiff_test.cpp
@@ -35,7 +35,6 @@
 
 using android::base::get_unaligned;
 
-// Sanity check for the given imgdiff patch header.
 static void verify_patch_header(const std::string& patch, size_t* num_normal, size_t* num_raw,
                                 size_t* num_deflate) {
   const size_t size = patch.size();
diff --git a/tests/unit/install_test.cpp b/tests/unit/install_test.cpp
index ee75349..c341547 100644
--- a/tests/unit/install_test.cpp
+++ b/tests/unit/install_test.cpp
@@ -76,7 +76,7 @@
 
 TEST(InstallTest, read_metadata_from_package_no_entry) {
   TemporaryFile temp_file;
-  BuildZipArchive({ { "dummy_entry", "" } }, temp_file.release(), kCompressStored);
+  BuildZipArchive({ { "fake_entry", "" } }, temp_file.release(), kCompressStored);
 
   ZipArchiveHandle zip;
   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
@@ -153,7 +153,7 @@
 TEST(InstallTest, SetUpNonAbUpdateCommands_MissingUpdateBinary) {
   TemporaryFile temp_file;
   // The archive must have something to be opened correctly.
-  BuildZipArchive({ { "dummy_entry", "" } }, temp_file.release(), kCompressStored);
+  BuildZipArchive({ { "fake_entry", "" } }, temp_file.release(), kCompressStored);
 
   // Missing update binary.
   ZipArchiveHandle zip;
@@ -190,7 +190,7 @@
 
   ZipArchiveHandle zip;
   ASSERT_EQ(0, OpenArchive(temp_file.path, &zip));
-  ZipEntry payload_entry;
+  ZipEntry64 payload_entry;
   ASSERT_EQ(0, FindEntry(zip, "payload.bin", &payload_entry));
 
   std::map<std::string, std::string> metadata;
@@ -334,7 +334,7 @@
   metadata = android::base::Join(
       std::vector<std::string>{
           "ota-type=BRICK",
-          "pre-device=dummy_device_type",
+          "pre-device=fake_device_type",
       },
       "\n");
   TestCheckPackageMetadata(metadata, OtaType::BRICK, false);
@@ -358,7 +358,7 @@
       std::vector<std::string>{
           "ota-type=BRICK",
           "pre-device=" + device,
-          "serialno=dummy_serial",
+          "serialno=fake_serial",
       },
       "\n");
   TestCheckPackageMetadata(metadata, OtaType::BRICK, false);
@@ -383,7 +383,7 @@
   ASSERT_NE("", serialno);
 
   std::vector<std::string> serial_numbers;
-  // Creates a dummy serial number string.
+  // Creates a fake serial number string.
   for (char c = 'a'; c <= 'z'; c++) {
     serial_numbers.emplace_back(serialno.size(), c);
   }
@@ -431,7 +431,7 @@
       std::vector<std::string>{
           "ota-type=AB",
           "pre-device=" + device,
-          "pre-build-incremental=dummy_build",
+          "pre-build-incremental=fake_build",
           "post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
       },
       "\n");
@@ -459,7 +459,35 @@
       std::vector<std::string>{
           "ota-type=AB",
           "pre-device=" + device,
-          "pre-build=dummy_build_fingerprint",
+          "pre-build=fake_build_fingerprint",
+          "post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
+      },
+      "\n");
+  TestCheckPackageMetadata(metadata, OtaType::AB, false);
+}
+
+TEST(InstallTest, CheckPackageMetadata_dynamic_fingerprint) {
+  std::string device = android::base::GetProperty("ro.product.device", "");
+  ASSERT_FALSE(device.empty());
+
+  std::string finger_print = android::base::GetProperty("ro.build.fingerprint", "");
+  ASSERT_FALSE(finger_print.empty());
+
+  std::string metadata = android::base::Join(
+      std::vector<std::string>{
+          "ota-type=AB",
+          "pre-device=please|work|" + device + "|please|work",
+          "pre-build=" + finger_print = "pass|this|test",
+          "post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
+      },
+      "\n");
+  TestCheckPackageMetadata(metadata, OtaType::AB, true);
+
+  metadata = android::base::Join(
+      std::vector<std::string>{
+          "ota-type=AB",
+          "pre-device=" + device,
+          "pre-build=fake_build_fingerprint",
           "post-timestamp=" + std::to_string(std::numeric_limits<int64_t>::max()),
       },
       "\n");
diff --git a/tests/unit/package_test.cpp b/tests/unit/package_test.cpp
index 5e31f7f..164a93d 100644
--- a/tests/unit/package_test.cpp
+++ b/tests/unit/package_test.cpp
@@ -106,7 +106,7 @@
 
     // Check that we can extract one zip entry.
     std::string_view entry_name = "dir1/file3.txt";
-    ZipEntry entry;
+    ZipEntry64 entry;
     ASSERT_EQ(0, FindEntry(zip, entry_name, &entry));
 
     std::vector<uint8_t> extracted(entry_name.size());
diff --git a/tests/unit/zip_test.cpp b/tests/unit/zip_test.cpp
index 0753d64..e065bb8 100644
--- a/tests/unit/zip_test.cpp
+++ b/tests/unit/zip_test.cpp
@@ -28,7 +28,7 @@
 #include "otautil/sysutil.h"
 
 TEST(ZipTest, OpenFromMemory) {
-  std::string zip_path = from_testdata_base("ziptest_dummy-update.zip");
+  std::string zip_path = from_testdata_base("ziptest_fake-update.zip");
   MemMapping map;
   ASSERT_TRUE(map.MapFile(zip_path));
 
@@ -37,7 +37,7 @@
   ASSERT_EQ(0, OpenArchiveFromMemory(map.addr, map.length, zip_path.c_str(), &handle));
 
   static constexpr const char* BINARY_PATH = "META-INF/com/google/android/update-binary";
-  ZipEntry binary_entry;
+  ZipEntry64 binary_entry;
   // Make sure the package opens correctly and its entry can be read.
   ASSERT_EQ(0, FindEntry(handle, BINARY_PATH, &binary_entry));
 
diff --git a/tools/image_generator/Android.bp b/tools/image_generator/Android.bp
index 8300040..c9748fa 100644
--- a/tools/image_generator/Android.bp
+++ b/tools/image_generator/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 java_library_host {
     name: "RecoveryImageGenerator",
 
diff --git a/tools/image_generator/README.md b/tools/image_generator/README.md
index 5d70354..1230ad5 100644
--- a/tools/image_generator/README.md
+++ b/tools/image_generator/README.md
@@ -19,3 +19,13 @@
 4. `resourceDirectory`: The resource directory that contains all the translated
    strings in xml format, e.g. bootable/recovery/tools/recovery_l10n/res/
 5. `outputFilename`: Path to the generated image.
+
+# Locales
+Supported locales and background texts are located in
+[tools/recovery_l10n/res/](../recovery_l10n/res/values). For each background text, the tool renders
+a localized image for every supported locale.
+
+Each individual localized image contains an encoded locale header string, and the rendered
+background text. The locale header string is generated by `Locale.forLanguageTag`. And sample
+result include `en-US`, `zh-CN`, etc. These individual images are then concatenated together to
+form the final resource image that locates in res/images, e.g. `install_text.png`
diff --git a/tools/recovery_l10n/Android.bp b/tools/recovery_l10n/Android.bp
index d0a6d4b..ac08e1a 100644
--- a/tools/recovery_l10n/Android.bp
+++ b/tools/recovery_l10n/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 android_app {
     name: "RecoveryLocalizer",
 
diff --git a/tools/recovery_l10n/res/values-ar/strings.xml b/tools/recovery_l10n/res/values-ar/strings.xml
index a9cd2d1..6919128 100644
--- a/tools/recovery_l10n/res/values-ar/strings.xml
+++ b/tools/recovery_l10n/res/values-ar/strings.xml
@@ -1,11 +1,11 @@
 <?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">"جارٍ تثبيت تحديث النظام"</string>
+    <string name="recovery_installing" msgid="2013591905463558223">"جارٍ تثبيت إعادة تحميل النظام"</string>
     <string name="recovery_erasing" msgid="7334826894904037088">"جارٍ محو البيانات"</string>
     <string name="recovery_no_command" msgid="4465476568623024327">"ليس هناك أي أمر"</string>
     <string name="recovery_error" msgid="5748178989622716736">"خطأ!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"جارٍ تثبيت تحديث الأمان"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"جارٍ تثبيت إعادة تحميل الأمان"</string>
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏يتعذَّر تحميل نظام Android، حيث قد تكون بياناتك تالفة. وإذا استمر ظهور هذه الرسالة، قد يتعيَّن عليك إجراء إعادة الضبط على الإعدادات الأصلية ومحو جميع بيانات المستخدم المُخزَّنة على هذا الجهاز."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"إعادة المحاولة"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"إعادة الضبط على الإعدادات الأصلية"</string>
diff --git a/tools/recovery_l10n/res/values-az/strings.xml b/tools/recovery_l10n/res/values-az/strings.xml
index d624e63..35194c4 100644
--- a/tools/recovery_l10n/res/values-az/strings.xml
+++ b/tools/recovery_l10n/res/values-az/strings.xml
@@ -5,7 +5,7 @@
     <string name="recovery_erasing" msgid="7334826894904037088">"Silinir"</string>
     <string name="recovery_no_command" msgid="4465476568623024327">"Əmr yoxdur"</string>
     <string name="recovery_error" msgid="5748178989622716736">"Xəta!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"Güvənlik güncəllənməsi quraşdırılır"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Təhlükəsizlik güncəlləməsi yüklənir"</string>
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android sistemi yüklənmir. Datanız zədələnə bilər. Bu mesajı yenə qəbul etsəniz, data zavod sıfırlamasını həyata keçirməli və bu cihazda saxlanmış istifadəçi datasının hamısını silməlisiniz."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"Yenidən cəhd edin"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Data zavod sıfırlaması"</string>
diff --git a/tools/recovery_l10n/res/values-ca/strings.xml b/tools/recovery_l10n/res/values-ca/strings.xml
index b14a76f..6b7bec0 100644
--- a/tools/recovery_l10n/res/values-ca/strings.xml
+++ b/tools/recovery_l10n/res/values-ca/strings.xml
@@ -9,6 +9,6 @@
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"No s\'ha pogut carregar el sistema Android. És possible que les teves dades estiguin malmeses. Si continues veient aquest missatge, pot ser que hagis de restablir les dades de fàbrica i esborrar totes les dades d\'usuari emmagatzemades en aquest dispositiu."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"Torna-ho a provar"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Restableix les dades de fàbrica"</string>
-    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Vols netejar totes les dades d\'usuari?\n\n AQUESTA ACCIÓ NO ES POT DESFER."</string>
+    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Vols eliminar totes les dades d\'usuari?\n\n AQUESTA ACCIÓ NO ES POT DESFER."</string>
     <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Cancel·la"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-fa/strings.xml b/tools/recovery_l10n/res/values-fa/strings.xml
index 7e1dbe7..1c1be9a 100644
--- a/tools/recovery_l10n/res/values-fa/strings.xml
+++ b/tools/recovery_l10n/res/values-fa/strings.xml
@@ -9,6 +9,6 @@
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏نمی‌توان سیستم Android را بارگیری کرد. ممکن است داده‌های شما خراب باشند. اگر همچنان این پیام را دریافت می‌کنید، شاید لازم باشد بازنشانی داده‌های کارخانه‌ای انجام دهید و همه داده‌های کاربر را که در این دستگاه ذخیره شده است پاک کنید."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"تلاش مجدد"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"بازنشانی داده‌های کارخانه"</string>
-    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"همه داده‌های کاربر محو شود؟\n\n این کار واگردشدنی نیست!"</string>
+    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"همه داده‌های کاربر پاک شود؟\n\n این کار قابل‌واگرد نیست!"</string>
     <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"لغو"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-fi/strings.xml b/tools/recovery_l10n/res/values-fi/strings.xml
index e825783..fddaf14 100644
--- a/tools/recovery_l10n/res/values-fi/strings.xml
+++ b/tools/recovery_l10n/res/values-fi/strings.xml
@@ -10,5 +10,5 @@
     <string name="recovery_try_again" msgid="7168248750158873496">"Yritä uudelleen"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Tehdasasetuksien palauttaminen"</string>
     <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Poistetaanko kaikki käyttäjätiedot?\n\nTÄTÄ EI VOI PERUA!"</string>
-    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Peru"</string>
+    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Peruuta"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-hy/strings.xml b/tools/recovery_l10n/res/values-hy/strings.xml
index 76c28a7..35a0ab1 100644
--- a/tools/recovery_l10n/res/values-hy/strings.xml
+++ b/tools/recovery_l10n/res/values-hy/strings.xml
@@ -9,6 +9,6 @@
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Չհաջողվեց բեռնել Android համակարգը։ Հնարավոր է՝ ձեր տվյալները վնասված են։ Եթե նորից տեսնեք այս հաղորդագրությունը, փորձեք վերակայել սարքի կարգավորումները և ջնջել օգտատիրոջ բոլոր տվյալները։"</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"Նորից փորձել"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Վերակայել բոլոր տվյալները"</string>
-    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Ջնջե՞լ օգտատիրոջ բոլոր տվյալները։\n\n ԱՅՍ ԳՈՐԾՈՂՈՒԹՅՈՒՆԸ ՀՆԱՐԱՎՈՐ ՉԻ ԼԻՆԻ ՀԵՏԱՐԿԵԼ"</string>
+    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Մաքրե՞լ օգտատիրոջ բոլոր տվյալները։\n\n ԱՅՍ ԳՈՐԾՈՂՈՒԹՅՈՒՆԸ ՀՆԱՐԱՎՈՐ ՉԻ ԼԻՆԻ ՀԵՏԱՐԿԵԼ"</string>
     <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Չեղարկել"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-iw/strings.xml b/tools/recovery_l10n/res/values-iw/strings.xml
index 0b81d05..8ca3bdf 100644
--- a/tools/recovery_l10n/res/values-iw/strings.xml
+++ b/tools/recovery_l10n/res/values-iw/strings.xml
@@ -2,10 +2,10 @@
 <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">"מתקין עדכון מערכת"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"מתבצעת מחיקה"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"מוחק"</string>
     <string name="recovery_no_command" msgid="4465476568623024327">"אין פקודה"</string>
     <string name="recovery_error" msgid="5748178989622716736">"שגיאה!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"התקנת עדכון אבטחה מתבצעת"</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"מתקין עדכון אבטחה"</string>
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏לא ניתן לטעון את מערכת Android. ייתכן שהנתונים שלך פגומים. אם הודעה זו תופיע שוב, ייתכן שיהיה עליך לבצע איפוס לנתוני היצרן ולמחוק את כל נתוני המשתמש ששמורים במכשיר זה."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"ניסיון נוסף"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"איפוס לנתוני היצרן"</string>
diff --git a/tools/recovery_l10n/res/values-ky/strings.xml b/tools/recovery_l10n/res/values-ky/strings.xml
index 45fcd15..837cf7d 100644
--- a/tools/recovery_l10n/res/values-ky/strings.xml
+++ b/tools/recovery_l10n/res/values-ky/strings.xml
@@ -1,12 +1,12 @@
 <?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">"Тутум жаңырууда"</string>
+    <string name="recovery_installing" msgid="2013591905463558223">"Тутум жаңыртуусу орнотулууда"</string>
     <string name="recovery_erasing" msgid="7334826894904037088">"Тазаланууда"</string>
     <string name="recovery_no_command" msgid="4465476568623024327">"Буйрук берилген жок"</string>
     <string name="recovery_error" msgid="5748178989622716736">"Ката!"</string>
-    <string name="recovery_installing_security" msgid="9184031299717114342">"Коопсуздук жаңырууда"</string>
-    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android системасы жүктөлбөй жатат. Дайын-даректериңиз бузук болушу мүмкүн. Бул билдирүү дагы деле келе берсе, түзмөктү кайра башынан жөндөп, анда сакталган бардык колдонуучу дайындарын тазалашыңыз керек."</string>
+    <string name="recovery_installing_security" msgid="9184031299717114342">"Коопсуздук жаңыртуусу орнотулууда"</string>
+    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android тутуму жүктөлбөй жатат. Дайын-даректериңиз бузук болушу мүмкүн. Бул билдирүү дагы деле келе берсе, түзмөктү кайра башынан жөндөп, анда сакталган бардык колдонуучу дайындарын тазалашыңыз керек."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"Кайталоо"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Кайра башынан жөндөө"</string>
     <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Колдонуучу дайындарынын баары жашырылсынбы?\n\n МУНУ АРТКА КАЙТАРУУ МҮМКҮН ЭМЕС!"</string>
diff --git a/tools/recovery_l10n/res/values-ne/strings.xml b/tools/recovery_l10n/res/values-ne/strings.xml
index 161d1e4..fa53e9d 100644
--- a/tools/recovery_l10n/res/values-ne/strings.xml
+++ b/tools/recovery_l10n/res/values-ne/strings.xml
@@ -6,7 +6,7 @@
     <string name="recovery_no_command" msgid="4465476568623024327">"कुनै आदेश छैन"</string>
     <string name="recovery_error" msgid="5748178989622716736">"त्रुटि!"</string>
     <string name="recovery_installing_security" msgid="9184031299717114342">"सुरक्षा सम्बन्धी अद्यावधिकलाई स्थापना गर्दै"</string>
-    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android प्रणाली लोड गर्न सकिएन। तपाईंको डेटा बिग्रेको हुन सक्छ। तपाईं यो सन्देश प्राप्त गर्नुहुन्छ भने तपाईंले फ्याक्ट्री डेटा रिसेट गर्न आवश्यक छ र यो डिभाइसमा भण्डारण गरेका सबै प्रयोगकर्ताको डेटा मेट्न पर्छ।"</string>
+    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Android प्रणाली लोड गर्न सकिएन। तपाईंको डेटा बिग्रेको हुन सक्छ। तपाईं यो सन्देश प्राप्त गर्नुहुन्छ भने तपाईंले फ्याक्ट्री डेटा रिसेट गर्न आवश्यक छ र यो यन्त्रमा भण्डारण गरेका सबै प्रयोगकर्ताको डेटा मेट्न पर्छ।"</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"फेरि प्रयास गर्नुहोस्"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"फ्याक्ट्री डेटा रिसेट"</string>
     <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"प्रयोगकर्ताको सबै डेटा मेट्ने हो?\n\n यो अन्डू गर्न सकिँदैन!"</string>
diff --git a/tools/recovery_l10n/res/values-sv/strings.xml b/tools/recovery_l10n/res/values-sv/strings.xml
index baf8e18..cf43b25 100644
--- a/tools/recovery_l10n/res/values-sv/strings.xml
+++ b/tools/recovery_l10n/res/values-sv/strings.xml
@@ -2,7 +2,7 @@
 <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">"Systemuppdatering installeras"</string>
-    <string name="recovery_erasing" msgid="7334826894904037088">"Raderar"</string>
+    <string name="recovery_erasing" msgid="7334826894904037088">"Rensar"</string>
     <string name="recovery_no_command" msgid="4465476568623024327">"Inget kommando"</string>
     <string name="recovery_error" msgid="5748178989622716736">"Fel!"</string>
     <string name="recovery_installing_security" msgid="9184031299717114342">"Säkerhetsuppdatering installeras"</string>
diff --git a/tools/recovery_l10n/res/values-ur/strings.xml b/tools/recovery_l10n/res/values-ur/strings.xml
index 13dc6b3..da03f19 100644
--- a/tools/recovery_l10n/res/values-ur/strings.xml
+++ b/tools/recovery_l10n/res/values-ur/strings.xml
@@ -6,9 +6,9 @@
     <string name="recovery_no_command" msgid="4465476568623024327">"کوئی کمانڈ نہیں ہے"</string>
     <string name="recovery_error" msgid="5748178989622716736">"خرابی!"</string>
     <string name="recovery_installing_security" msgid="9184031299717114342">"سیکیورٹی اپ ڈیٹ انسٹال ہو رہی ہے"</string>
-    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏Android سسٹم لوڈ نہیں کیا جا سکتا۔ آپ کا ڈیٹا خراب ہو سکتا ہے۔ اگر آپ کو مستقل یہ پیغام موصول ہوتا ہے تو آپ کو فیکٹری ڈیٹا ری سیٹ انجام دینے اور اس آلہ پر اسٹور کردہ سبھی صارف ڈیٹا کو مٹانے کی ضرورت پڑ سکتی ہے۔"</string>
+    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"‏Android سسٹم لوڈ نہیں کیا جا سکتا۔ آپ کا ڈیٹا خراب ہو سکتا ہے۔ اگر آپ کو مستقل یہ پیغام موصول ہوتا ہے تو آپ کو فیکٹری ڈیٹا کی دوبارہ ترتیب انجام دینے اور اس آلہ پر اسٹور کردہ سبھی صارف ڈیٹا کو مٹانے کی ضرورت پڑ سکتی ہے۔"</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"دوبارہ کوشش کریں"</string>
-    <string name="recovery_factory_data_reset" msgid="7321351565602894783">"فیکٹری ڈیٹا ری سیٹ"</string>
+    <string name="recovery_factory_data_reset" msgid="7321351565602894783">"فیکٹری ڈیٹا کی دوبارہ ترتیب"</string>
     <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"سبھی صارف ڈیٹا صاف کریں؟\n\n اسے کالعدم نہیں کیا جا سکتا!"</string>
     <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"منسوخ کریں"</string>
 </resources>
diff --git a/uncrypt/Android.bp b/uncrypt/Android.bp
index 107a7f0..fbb4c1f 100644
--- a/uncrypt/Android.bp
+++ b/uncrypt/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_binary {
     name: "uncrypt",
 
diff --git a/uncrypt/uncrypt.cpp b/uncrypt/uncrypt.cpp
index f1f4f69..c798e31 100644
--- a/uncrypt/uncrypt.cpp
+++ b/uncrypt/uncrypt.cpp
@@ -477,9 +477,9 @@
     return kUncryptRealpathFindError;
   }
 
-  bool encryptable;
-  bool encrypted;
-  bool f2fs_fs;
+  bool encryptable = false;
+  bool encrypted = false;
+  bool f2fs_fs = false;
   const std::string blk_dev = FindBlockDevice(path, &encryptable, &encrypted, &f2fs_fs);
   if (blk_dev.empty()) {
     LOG(ERROR) << "Failed to find block device for " << path;
diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp
index f656713..ff2eff9 100644
--- a/update_verifier/Android.bp
+++ b/update_verifier/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "update_verifier_defaults",
 
@@ -112,12 +121,12 @@
 
     version: {
         py2: {
-            enabled: true,
-            embedded_launcher: true,
-        },
-        py3: {
             enabled: false,
             embedded_launcher: false,
         },
+        py3: {
+            enabled: true,
+            embedded_launcher: true,
+        },
     },
 }
diff --git a/update_verifier/care_map_generator.py b/update_verifier/care_map_generator.py
index 051d98d..c6f2dad 100644
--- a/update_verifier/care_map_generator.py
+++ b/update_verifier/care_map_generator.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #
 # Copyright (C) 2018 The Android Open Source Project
 #
@@ -115,13 +115,13 @@
     content = input_care_map.read()
 
   if args.parse_proto:
-    result = ParseProtoMessage(content, args.fingerprint_enabled)
+    result = ParseProtoMessage(content, args.fingerprint_enabled).encode()
   else:
     care_map_proto = GenerateCareMapProtoFromLegacyFormat(
         content.rstrip().splitlines(), args.fingerprint_enabled)
     result = care_map_proto.SerializeToString()
 
-  with open(args.output_file, 'w') as output:
+  with open(args.output_file, 'wb') as output:
     output.write(result)
 
 
diff --git a/updater/Android.bp b/updater/Android.bp
index f00a192..35debaa 100644
--- a/updater/Android.bp
+++ b/updater/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 cc_defaults {
     name: "libupdater_static_libs",
 
@@ -27,7 +36,6 @@
         "libfec_rs",
         "libavb",
         "libverity_tree",
-        "libgtest_prod",
         "liblog",
         "liblp",
         "libselinux",
@@ -42,6 +50,9 @@
         "libcutils",
         "libutils",
     ],
+    header_libs: [
+        "libgtest_prod_headers",
+    ],
 }
 
 cc_defaults {
diff --git a/updater/Android.mk b/updater/Android.mk
index 46300d9..bb1c07d 100644
--- a/updater/Android.mk
+++ b/updater/Android.mk
@@ -34,7 +34,6 @@
     libfec_rs \
     libavb \
     libverity_tree \
-    libgtest_prod \
     liblog \
     liblp \
     libselinux \
@@ -72,6 +71,9 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE := updater
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../NOTICE
 
 LOCAL_SRC_FILES := \
     updater_main.cpp
@@ -93,6 +95,8 @@
     libtune2fs \
     $(tune2fs_static_libraries)
 
+LOCAL_HEADER_LIBRARIES := libgtest_prod_headers
+
 LOCAL_MODULE_CLASS := EXECUTABLES
 inc := $(call local-generated-sources-dir)/register.inc
 
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 2d41f61..b29aa8c 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -348,7 +348,7 @@
  */
 struct NewThreadInfo {
   ZipArchiveHandle za;
-  ZipEntry entry;
+  ZipEntry64 entry{};
   bool brotli_compressed;
 
   std::unique_ptr<RangeSinkWriter> writer;
@@ -1626,7 +1626,7 @@
 static Value* PerformBlockImageUpdate(const char* name, State* state,
                                       const std::vector<std::unique_ptr<Expr>>& argv,
                                       const CommandMap& command_map, bool dryrun) {
-  CommandParameters params = {};
+  CommandParameters params{};
   stash_map.clear();
   params.canwrite = !dryrun;
 
@@ -1687,7 +1687,7 @@
   }
 
   std::string_view path_data(patch_data_fn->data);
-  ZipEntry patch_entry;
+  ZipEntry64 patch_entry;
   if (FindEntry(za, path_data, &patch_entry) != 0) {
     LOG(ERROR) << name << "(): no file \"" << patch_data_fn->data << "\" in package";
     return StringValue("");
@@ -1695,7 +1695,7 @@
   params.patch_start = updater->GetMappedPackageAddress() + patch_entry.offset;
 
   std::string_view new_data(new_data_fn->data);
-  ZipEntry new_entry;
+  ZipEntry64 new_entry;
   if (FindEntry(za, new_data, &new_entry) != 0) {
     LOG(ERROR) << name << "(): no file \"" << new_data_fn->data << "\" in package";
     return StringValue("");
diff --git a/updater/commands.cpp b/updater/commands.cpp
index aed6336..1a7c272 100644
--- a/updater/commands.cpp
+++ b/updater/commands.cpp
@@ -128,7 +128,6 @@
       // No stashes, only source ranges.
       SourceInfo result(src_hash, src_ranges, {}, {});
 
-      // Sanity check the block count.
       if (result.blocks() != src_blocks) {
         *err =
             android::base::StringPrintf("mismatching block count: %zu (%s) vs %zu", result.blocks(),
@@ -262,7 +261,7 @@
       return {};
     }
   } else if (op == Type::ABORT) {
-    // No-op, other than sanity checking the input args.
+    // Abort takes no arguments, so there's nothing else to check.
     if (pos != tokens.size()) {
       *err = android::base::StringPrintf("invalid number of args: %zu (expected 0)",
                                          tokens.size() - pos);
diff --git a/updater/include/private/commands.h b/updater/include/private/commands.h
index 79f9154..7a23bb7 100644
--- a/updater/include/private/commands.h
+++ b/updater/include/private/commands.h
@@ -307,7 +307,7 @@
       : type_(type),
         index_(index),
         cmdline_(std::move(cmdline)),
-        patch_(std::move(patch)),
+        patch_(patch),
         target_(std::move(target)),
         source_(std::move(source)),
         stash_(std::move(stash)) {}
diff --git a/updater/install.cpp b/updater/install.cpp
index afa5195..2959650 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -35,6 +35,7 @@
 #include <unistd.h>
 #include <utime.h>
 
+#include <limits>
 #include <memory>
 #include <string>
 #include <vector>
@@ -115,7 +116,7 @@
     std::string dest_path = args[1];
 
     ZipArchiveHandle za = state->updater->GetPackageHandle();
-    ZipEntry entry;
+    ZipEntry64 entry;
     if (FindEntry(za, zip_path, &entry) != 0) {
       LOG(ERROR) << name << ": no " << zip_path << " in package";
       return StringValue("");
@@ -165,13 +166,18 @@
     const std::string& zip_path = args[0];
 
     ZipArchiveHandle za = state->updater->GetPackageHandle();
-    ZipEntry entry;
+    ZipEntry64 entry;
     if (FindEntry(za, zip_path, &entry) != 0) {
       return ErrorAbort(state, kPackageExtractFileFailure, "%s(): no %s in package", name,
                         zip_path.c_str());
     }
 
     std::string buffer;
+    if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+      return ErrorAbort(state, kPackageExtractFileFailure,
+                        "%s(): Entry `%s` Uncompressed size exceeds size of address space.", name,
+                        zip_path.c_str());
+    }
     buffer.resize(entry.uncompressed_length);
 
     int32_t ret =
diff --git a/updater/target_files.cpp b/updater/target_files.cpp
index 919ec4e..207146f 100644
--- a/updater/target_files.cpp
+++ b/updater/target_files.cpp
@@ -115,7 +115,7 @@
   }
 
   CHECK(handle_);
-  ZipEntry img_entry;
+  ZipEntry64 img_entry;
   return FindEntry(handle_, name, &img_entry) == 0;
 }
 
@@ -126,7 +126,7 @@
   }
 
   CHECK(handle_);
-  ZipEntry entry;
+  ZipEntry64 entry;
   if (auto find_err = FindEntry(handle_, name, &entry); find_err != 0) {
     LOG(ERROR) << "failed to find " << name << " in the package: " << ErrorCodeString(find_err);
     return false;
@@ -137,6 +137,13 @@
     return true;
   }
 
+  if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << name
+               << " because's uncompressed size exceeds size of address space. "
+               << entry.uncompressed_length;
+    return false;
+  }
+
   content->resize(entry.uncompressed_length);
   if (auto extract_err = ExtractToMemory(
           handle_, &entry, reinterpret_cast<uint8_t*>(&content->at(0)), entry.uncompressed_length);
@@ -157,7 +164,7 @@
   }
 
   CHECK(handle_);
-  ZipEntry entry;
+  ZipEntry64 entry;
   if (auto find_err = FindEntry(handle_, name, &entry); find_err != 0) {
     LOG(ERROR) << "failed to find " << name << " in the package: " << ErrorCodeString(find_err);
     return false;
diff --git a/updater/updater.cpp b/updater/updater.cpp
index 8f4a6ed..c526734 100644
--- a/updater/updater.cpp
+++ b/updater/updater.cpp
@@ -163,14 +163,19 @@
 
 bool Updater::ReadEntryToString(ZipArchiveHandle za, const std::string& entry_name,
                                 std::string* content) {
-  ZipEntry entry;
+  ZipEntry64 entry;
   int find_err = FindEntry(za, entry_name, &entry);
   if (find_err != 0) {
     LOG(ERROR) << "failed to find " << entry_name
                << " in the package: " << ErrorCodeString(find_err);
     return false;
   }
-
+  if (entry.uncompressed_length > std::numeric_limits<size_t>::max()) {
+    LOG(ERROR) << "Failed to extract " << entry_name
+               << " because's uncompressed size exceeds size of address space. "
+               << entry.uncompressed_length;
+    return false;
+  }
   content->resize(entry.uncompressed_length);
   int extract_err = ExtractToMemory(za, &entry, reinterpret_cast<uint8_t*>(&content->at(0)),
                                     entry.uncompressed_length);
diff --git a/updater/updater_runtime.cpp b/updater/updater_runtime.cpp
index e938305..bac078c 100644
--- a/updater/updater_runtime.cpp
+++ b/updater/updater_runtime.cpp
@@ -44,29 +44,25 @@
   return std::string(name);
 }
 
-static struct {
-  const char* name;
-  unsigned flag;
-} mount_flags_list[] = {
-  { "noatime", MS_NOATIME },
-  { "noexec", MS_NOEXEC },
-  { "nosuid", MS_NOSUID },
-  { "nodev", MS_NODEV },
-  { "nodiratime", MS_NODIRATIME },
-  { "ro", MS_RDONLY },
-  { "rw", 0 },
-  { "remount", MS_REMOUNT },
-  { "bind", MS_BIND },
-  { "rec", MS_REC },
-  { "unbindable", MS_UNBINDABLE },
-  { "private", MS_PRIVATE },
-  { "slave", MS_SLAVE },
-  { "shared", MS_SHARED },
-  { "defaults", 0 },
-  { 0, 0 },
-};
-
 static bool setMountFlag(const std::string& flag, unsigned* mount_flags) {
+  static constexpr std::pair<const char*, unsigned> mount_flags_list[] = {
+    { "noatime", MS_NOATIME },
+    { "noexec", MS_NOEXEC },
+    { "nosuid", MS_NOSUID },
+    { "nodev", MS_NODEV },
+    { "nodiratime", MS_NODIRATIME },
+    { "ro", MS_RDONLY },
+    { "rw", 0 },
+    { "remount", MS_REMOUNT },
+    { "bind", MS_BIND },
+    { "rec", MS_REC },
+    { "unbindable", MS_UNBINDABLE },
+    { "private", MS_PRIVATE },
+    { "slave", MS_SLAVE },
+    { "shared", MS_SHARED },
+    { "defaults", 0 },
+  };
+
   for (const auto& [name, value] : mount_flags_list) {
     if (flag == name) {
       *mount_flags |= value;
diff --git a/updater_sample/Android.bp b/updater_sample/Android.bp
index a014248..9222d06 100644
--- a/updater_sample/Android.bp
+++ b/updater_sample/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 android_app {
     name: "SystemUpdaterSample",
     sdk_version: "system_current",
diff --git a/updater_sample/tests/Android.bp b/updater_sample/tests/Android.bp
index 806babd..4bdfe2c 100644
--- a/updater_sample/tests/Android.bp
+++ b/updater_sample/tests/Android.bp
@@ -12,6 +12,15 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "bootable_recovery_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["bootable_recovery_license"],
+}
+
 android_test {
     name: "SystemUpdaterSampleTests",
     sdk_version: "system_current",