[automerger skipped] Import translations. DO NOT MERGE ANYWHERE am: fd33b4992d -s ours am: 19f396653d -s ours

am skip reason: subject contains skip directive

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

Change-Id: Ib4ee7f35160b71ce56fc10c99df43563dc5cc47c
diff --git a/Android.bp b/Android.bp
index 8e29dc8..bd2d0b0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -79,6 +79,7 @@
         "librecovery_utils",
         "libotautil",
         "libsnapshot_nobinder",
+        "update_metadata-protos",
     ],
 }
 
diff --git a/Android.mk b/Android.mk
index 9f69153..5816749 100644
--- a/Android.mk
+++ b/Android.mk
@@ -56,12 +56,10 @@
 LOCAL_MODULE := recovery_deps
 
 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/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index 6ad4a61..8586028 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -965,7 +965,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 +1035,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..aa8d129 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) {
@@ -265,7 +265,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/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/install/install.cpp b/install/install.cpp
index d404997..1c711f6 100644
--- a/install/install.cpp
+++ b/install/install.cpp
@@ -67,8 +67,11 @@
 // 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);
@@ -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;
   }
@@ -699,3 +704,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/minadbd/Android.bp b/minadbd/Android.bp
index 4cdcac6..b6ca59e 100644
--- a/minadbd/Android.bp
+++ b/minadbd/Android.bp
@@ -135,4 +135,5 @@
     test_suites: [
         "device-tests",
     ],
+    require_root: true,
 }
diff --git a/minadbd/AndroidTest.xml b/minadbd/AndroidTest.xml
index 7ea235b..dbcbac2 100644
--- a/minadbd/AndroidTest.xml
+++ b/minadbd/AndroidTest.xml
@@ -18,9 +18,10 @@
         <option name="cleanup" value="true" />
         <option name="push" value="minadbd_test->/data/local/tmp/minadbd_test" />
     </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
     <option name="test-suite-tag" value="apct" />
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="minadbd_test" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/minui/Android.bp b/minui/Android.bp
index fff3a8e..8258816 100644
--- a/minui/Android.bp
+++ b/minui/Android.bp
@@ -27,14 +27,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/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/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/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..a9a088a 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -95,6 +95,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,
@@ -128,6 +146,7 @@
 
     data: [
         "testdata/*",
+        ":recovery_image",
         ":res-testdata",
     ],
 }
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..fc7c2bf 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;
@@ -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/zip_test.cpp b/tests/unit/zip_test.cpp
index 0753d64..ec9585c 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));
 
diff --git a/tools/recovery_l10n/res/values-ur/strings.xml b/tools/recovery_l10n/res/values-ur/strings.xml
index da03f19..13dc6b3 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/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/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)) {}