[automerger skipped] [automerged blank] Fix misconfigured recovery host test 2p: d3cd440d2d 2p: affcbd2d7c am: 39063160c6 -s ours

am skip reason: Merged-In I13bb9595745f65a63070cf9fe030c9155f75e4d0 with SHA-1 620bd456d5 is already in history

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

Change-Id: I7e925039c138d28c27d63648dfba119c545ebdbc
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index bd95705..4cdeba0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -94,6 +94,8 @@
     shared_libs: [
         "android.hardware.boot@1.0",
         "android.hardware.boot@1.1",
+        "android.hardware.boot-V1-ndk",
+        "libboot_control_client",
         "libbase",
         "libbootloader_message",
         "libcrypto",
@@ -113,6 +115,8 @@
         "librecovery_utils",
         "libotautil",
         "libsnapshot_nobinder",
+        "libsnapshot_cow",
+        "liblz4",
         "update_metadata-protos",
     ],
 }
@@ -158,6 +162,7 @@
 
     shared_libs: [
         "android.hardware.health-V1-ndk", // from librecovery_utils
+        "android.hardware.boot-V1-ndk",
         "librecovery_ui",
     ],
 
diff --git a/bootloader_message/Android.bp b/bootloader_message/Android.bp
index 778fdb9..7622677 100644
--- a/bootloader_message/Android.bp
+++ b/bootloader_message/Android.bp
@@ -45,6 +45,7 @@
         "libbootloader_message_defaults",
     ],
     recovery_available: true,
+    vendor_available: true,
     host_supported: true,
 
     target: {
diff --git a/bootloader_message/include/bootloader_message/bootloader_message.h b/bootloader_message/include/bootloader_message/bootloader_message.h
index d58158d..8fba101 100644
--- a/bootloader_message/include/bootloader_message/bootloader_message.h
+++ b/bootloader_message/include/bootloader_message/bootloader_message.h
@@ -109,6 +109,7 @@
 #define MISC_MEMTAG_MODE_MEMTAG_ONCE 0x2
 #define MISC_MEMTAG_MODE_MEMTAG_KERNEL 0x4
 #define MISC_MEMTAG_MODE_MEMTAG_KERNEL_ONCE 0x8
+#define MISC_MEMTAG_MODE_MEMTAG_OFF 0x10
 
 #if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
 static_assert(sizeof(struct misc_virtual_ab_message) == 64,
diff --git a/etc/init.rc b/etc/init.rc
index e4afecf..03df27b 100644
--- a/etc/init.rc
+++ b/etc/init.rc
@@ -102,7 +102,7 @@
 on fs && property:sys.usb.configfs=1
     mount configfs none /config
     mkdir /config/usb_gadget/g1 0770 shell shell
-    write /config/usb_gadget/g1/idVendor 0x18D1
+    write /config/usb_gadget/g1/idVendor 0x${ro.recovery.usb.vid}
     mkdir /config/usb_gadget/g1/strings/0x409 0770
     write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}
     write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}
@@ -114,7 +114,7 @@
 
 on fs && property:sys.usb.configfs=0
     write /sys/class/android_usb/android0/f_ffs/aliases adb,fastboot
-    write /sys/class/android_usb/android0/idVendor 18D1
+    write /sys/class/android_usb/android0/idVendor ${ro.recovery.usb.vid}
     write /sys/class/android_usb/android0/iManufacturer ${ro.product.manufacturer}
     write /sys/class/android_usb/android0/iProduct ${ro.product.model}
     write /sys/class/android_usb/android0/iSerial ${ro.serialno}
@@ -139,19 +139,19 @@
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=adb && property:sys.usb.configfs=0
-    write /sys/class/android_usb/android0/idProduct D001
+    write /sys/class/android_usb/android0/idProduct ${ro.recovery.usb.adb.pid}
     write /sys/class/android_usb/android0/functions adb
     write /sys/class/android_usb/android0/enable 1
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=sideload && property:sys.usb.configfs=0
-    write /sys/class/android_usb/android0/idProduct D001
+    write /sys/class/android_usb/android0/idProduct ${ro.recovery.usb.adb.pid}
     write /sys/class/android_usb/android0/functions adb
     write /sys/class/android_usb/android0/enable 1
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=fastboot && property:sys.usb.configfs=0
-    write /sys/class/android_usb/android0/idProduct 4EE0
+    write /sys/class/android_usb/android0/idProduct ${ro.recovery.usb.fastboot.pid}
     write /sys/class/android_usb/android0/functions fastboot
     write /sys/class/android_usb/android0/enable 1
     setprop sys.usb.state ${sys.usb.config}
@@ -166,21 +166,21 @@
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=sideload && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
-    write /config/usb_gadget/g1/idProduct 0xD001
+    write /config/usb_gadget/g1/idProduct 0x${ro.recovery.usb.adb.pid}
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=adb && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
-    write /config/usb_gadget/g1/idProduct 0xD001
+    write /config/usb_gadget/g1/idProduct 0x${ro.recovery.usb.adb.pid}
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
     symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
     setprop sys.usb.state ${sys.usb.config}
 
 on property:sys.usb.config=fastboot && property:sys.usb.ffs.ready=1 && property:sys.usb.configfs=1
-    write /config/usb_gadget/g1/idProduct 0x4EE0
+    write /config/usb_gadget/g1/idProduct 0x${ro.recovery.usb.fastboot.pid}
     write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "fastboot"
     symlink /config/usb_gadget/g1/functions/ffs.fastboot /config/usb_gadget/g1/configs/b.1/f1
     write /config/usb_gadget/g1/UDC ${sys.usb.controller}
diff --git a/install/wipe_data.cpp b/install/wipe_data.cpp
index 024c1e1..c65e6f4 100644
--- a/install/wipe_data.cpp
+++ b/install/wipe_data.cpp
@@ -25,6 +25,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "bootloader_message/bootloader_message.h"
 #include "install/snapshot_utils.h"
 #include "otautil/dirutil.h"
 #include "recovery_ui/ui.h"
@@ -100,6 +101,12 @@
       success &= EraseVolume(METADATA_ROOT, ui);
     }
   }
+  ui->Print("Resetting memtag message...\n");
+  std::string err;
+  if (!WriteMiscMemtagMessage({}, &err)) {
+    ui->Print("Failed to reset memtag message: %s\n", err.c_str());
+    success = false;
+  }
   if (success) {
     success &= device->PostWipeData();
   }
diff --git a/minadbd/OWNERS b/minadbd/OWNERS
new file mode 100644
index 0000000..8ee79dd
--- /dev/null
+++ b/minadbd/OWNERS
@@ -0,0 +1,2 @@
+enh@google.com
+shaju@google.com
diff --git a/minadbd/minadbd_services.cpp b/minadbd/minadbd_services.cpp
index 0abe867..16bcb5e 100644
--- a/minadbd/minadbd_services.cpp
+++ b/minadbd/minadbd_services.cpp
@@ -305,7 +305,7 @@
   }
 }
 
-asocket* daemon_service_to_socket(std::string_view) {
+asocket* daemon_service_to_socket(std::string_view, atransport*) {
   return nullptr;
 }
 
diff --git a/minui/graphics.cpp b/minui/graphics.cpp
index b24c2b1..41a3661 100644
--- a/minui/graphics.cpp
+++ b/minui/graphics.cpp
@@ -502,3 +502,7 @@
 void gr_rotate(GRRotation rot) {
   rotation = rot;
 }
+
+bool gr_has_multiple_connectors() {
+  return gr_backend->HasMultipleConnectors();
+}
diff --git a/minui/graphics.h b/minui/graphics.h
index 5408c93..ff063ae 100644
--- a/minui/graphics.h
+++ b/minui/graphics.h
@@ -40,8 +40,11 @@
   // Blank (or unblank) the specific screen.
   virtual void Blank(bool blank, DrmConnector index) = 0;
 
+  // Return true if the device supports multiple connectors.
+  virtual bool HasMultipleConnectors() = 0;
+
   // Device cleanup when drawing is done.
-  virtual ~MinuiBackend() {};
+  virtual ~MinuiBackend() = default;
 };
 
 #endif  // _GRAPHICS_H_
diff --git a/minui/graphics_drm.cpp b/minui/graphics_drm.cpp
index c557022..6c3a5bd 100644
--- a/minui/graphics_drm.cpp
+++ b/minui/graphics_drm.cpp
@@ -200,6 +200,10 @@
   }
 }
 
+bool MinuiBackendDrm::HasMultipleConnectors() {
+  return (drm[DRM_SEC].GRSurfaceDrms[0] && drm[DRM_SEC].GRSurfaceDrms[1]);
+}
+
 static drmModeCrtc* find_crtc_for_connector(int fd, drmModeRes* resources,
                                             drmModeConnector* connector) {
   // Find the encoder. If we already have one, just use it.
diff --git a/minui/graphics_drm.h b/minui/graphics_drm.h
index fe3beaf..a8c9886 100644
--- a/minui/graphics_drm.h
+++ b/minui/graphics_drm.h
@@ -60,6 +60,7 @@
   GRSurface* Flip() override;
   void Blank(bool) override;
   void Blank(bool blank, DrmConnector index) override;
+  bool HasMultipleConnectors() override;
 
  private:
   void DrmDisableCrtc(int drm_fd, drmModeCrtc* crtc);
diff --git a/minui/graphics_fbdev.cpp b/minui/graphics_fbdev.cpp
index 1cb0c0a..4a7d325 100644
--- a/minui/graphics_fbdev.cpp
+++ b/minui/graphics_fbdev.cpp
@@ -47,6 +47,11 @@
   fprintf(stderr, "Unsupported multiple connectors, blank = %d, index = %d\n", blank, index);
 }
 
+bool MinuiBackendFbdev::HasMultipleConnectors() {
+  fprintf(stderr, "Unsupported multiple connectors\n");
+  return false;
+}
+
 void MinuiBackendFbdev::SetDisplayedFramebuffer(size_t n) {
   if (n > 1 || !double_buffered) return;
 
diff --git a/minui/graphics_fbdev.h b/minui/graphics_fbdev.h
index 7e193c4..c772428 100644
--- a/minui/graphics_fbdev.h
+++ b/minui/graphics_fbdev.h
@@ -57,6 +57,7 @@
   GRSurface* Flip() override;
   void Blank(bool) override;
   void Blank(bool blank, DrmConnector index) override;
+  bool HasMultipleConnectors() override;
 
  private:
   void SetDisplayedFramebuffer(size_t n);
diff --git a/minui/include/minui/minui.h b/minui/include/minui/minui.h
index f9be82f..2353ed3 100644
--- a/minui/include/minui/minui.h
+++ b/minui/include/minui/minui.h
@@ -129,6 +129,7 @@
 void gr_flip();
 void gr_fb_blank(bool blank);
 void gr_fb_blank(bool blank, int index);
+bool gr_has_multiple_connectors();
 
 // Clears entire surface to current color.
 void gr_clear();
diff --git a/otautil/verifier.cpp b/otautil/verifier.cpp
index 8a65566..83ad708 100644
--- a/otautil/verifier.cpp
+++ b/otautil/verifier.cpp
@@ -309,13 +309,15 @@
 }
 
 static std::vector<Certificate> IterateZipEntriesAndSearchForKeys(const ZipArchiveHandle& handle) {
-  void* cookie;
+  void* cookie{};
+
   int32_t iter_status = StartIteration(handle, &cookie, "", "x509.pem");
   if (iter_status != 0) {
     LOG(ERROR) << "Failed to iterate over entries in the certificate zipfile: "
                << ErrorCodeString(iter_status);
     return {};
   }
+  std::unique_ptr<void, decltype(&EndIteration)> cookie_guard(cookie, &EndIteration);
 
   std::vector<Certificate> result;
 
diff --git a/recovery-persist.cpp b/recovery-persist.cpp
index ad101ed..55699b2 100644
--- a/recovery-persist.cpp
+++ b/recovery-persist.cpp
@@ -77,6 +77,10 @@
   }
 }
 
+static bool file_exists(const char* filename) {
+  return access(filename, R_OK) == 0;
+}
+
 static bool rotated = false;
 
 ssize_t logsave(
@@ -141,7 +145,7 @@
     if (has_cache) {
       // Collects and reports the non-a/b update metrics from last_install; and removes the file
       // to avoid duplicate report.
-      if (access(LAST_INSTALL_FILE_IN_CACHE, F_OK) && unlink(LAST_INSTALL_FILE_IN_CACHE) == -1) {
+      if (file_exists(LAST_INSTALL_FILE_IN_CACHE) && unlink(LAST_INSTALL_FILE_IN_CACHE) == -1) {
         PLOG(ERROR) << "Failed to unlink " << LAST_INSTALL_FILE_IN_CACHE;
       }
 
@@ -152,9 +156,9 @@
       }
     }
 
-    /* Is there something in pmsg? */
-    if (access(LAST_PMSG_FILE, R_OK)) {
-        return 0;
+    /* Is there something in pmsg? If not, no need to proceed. */
+    if (!file_exists(LAST_PMSG_FILE)) {
+      return 0;
     }
 
     // Take last pmsg file contents and send it off to the logsave
@@ -164,18 +168,18 @@
     // For those device without /cache, the last_install file has been copied to
     // /data/misc/recovery from pmsg. Looks for the sideload history only.
     if (!has_cache) {
-      if (access(LAST_INSTALL_FILE, F_OK) && unlink(LAST_INSTALL_FILE) == -1) {
+      if (file_exists(LAST_INSTALL_FILE) && unlink(LAST_INSTALL_FILE) == -1) {
         PLOG(ERROR) << "Failed to unlink " << LAST_INSTALL_FILE;
       }
     }
 
     /* Is there a last console log too? */
     if (rotated) {
-        if (!access(LAST_CONSOLE_FILE, R_OK)) {
-            copy_file(LAST_CONSOLE_FILE, LAST_KMSG_FILE);
-        } else if (!access(ALT_LAST_CONSOLE_FILE, R_OK)) {
-            copy_file(ALT_LAST_CONSOLE_FILE, LAST_KMSG_FILE);
-        }
+      if (file_exists(LAST_CONSOLE_FILE)) {
+        copy_file(LAST_CONSOLE_FILE, LAST_KMSG_FILE);
+      } else if (file_exists(ALT_LAST_CONSOLE_FILE)) {
+        copy_file(ALT_LAST_CONSOLE_FILE, LAST_KMSG_FILE);
+      }
     }
 
     return 0;
diff --git a/recovery_ui/include/recovery_ui/screen_ui.h b/recovery_ui/include/recovery_ui/screen_ui.h
index 92b3c25..99ad534 100644
--- a/recovery_ui/include/recovery_ui/screen_ui.h
+++ b/recovery_ui/include/recovery_ui/screen_ui.h
@@ -245,6 +245,9 @@
       const std::vector<std::string>& backup_headers, const std::vector<std::string>& backup_items,
       const std::function<int(int, bool)>& key_handler) override;
 
+  // For Lid switch handle
+  int SetSwCallback(int code, int value) override;
+
  protected:
   static constexpr int kMenuIndent = 4;
 
@@ -404,6 +407,9 @@
 
   std::mutex updateMutex;
 
+  // Switch the display to active one after graphics is ready
+  bool is_graphics_available;
+
  private:
   void SetLocale(const std::string&);
 
diff --git a/recovery_ui/include/recovery_ui/stub_ui.h b/recovery_ui/include/recovery_ui/stub_ui.h
index 511b131..49689ba 100644
--- a/recovery_ui/include/recovery_ui/stub_ui.h
+++ b/recovery_ui/include/recovery_ui/stub_ui.h
@@ -80,6 +80,10 @@
   }
 
   void SetTitle(const std::vector<std::string>& /* lines */) override {}
+
+  int SetSwCallback(int /* code */, int /* value */) override {
+    return 0;
+  }
 };
 
 #endif  // RECOVERY_STUB_UI_H
diff --git a/recovery_ui/include/recovery_ui/ui.h b/recovery_ui/include/recovery_ui/ui.h
index 512732f..c3e3ee2 100644
--- a/recovery_ui/include/recovery_ui/ui.h
+++ b/recovery_ui/include/recovery_ui/ui.h
@@ -231,6 +231,8 @@
   bool InitScreensaver();
   void SetScreensaverState(ScreensaverState state);
 
+  virtual int SetSwCallback(int code, int value) = 0;
+
   // Key event input queue
   std::mutex key_queue_mutex;
   std::condition_variable key_queue_cond;
diff --git a/recovery_ui/screen_ui.cpp b/recovery_ui/screen_ui.cpp
index b2c828f..ee3cbb1 100644
--- a/recovery_ui/screen_ui.cpp
+++ b/recovery_ui/screen_ui.cpp
@@ -48,6 +48,11 @@
 #include "recovery_ui/device.h"
 #include "recovery_ui/ui.h"
 
+enum DirectRenderManager {
+    DRM_INNER,
+    DRM_OUTER,
+};
+
 // Return the current time as a double (including fractions of a second).
 static double now() {
   struct timeval tv;
@@ -334,7 +339,8 @@
       stage(-1),
       max_stage(-1),
       locale_(""),
-      rtl_locale_(false) {}
+      rtl_locale_(false),
+      is_graphics_available(false) {}
 
 ScreenRecoveryUI::~ScreenRecoveryUI() {
   progress_thread_stopped_ = true;
@@ -906,6 +912,7 @@
   if (!InitGraphics()) {
     return false;
   }
+  is_graphics_available = true;
 
   if (!InitTextParams()) {
     return false;
@@ -950,6 +957,9 @@
   // Keep the progress bar updated, even when the process is otherwise busy.
   progress_thread_ = std::thread(&ScreenRecoveryUI::ProgressThreadLoop, this);
 
+  // set the callback for hall sensor event
+  (void)ev_sync_sw_state([this](auto&& a, auto&& b) { return this->SetSwCallback(a, b);});
+
   return true;
 }
 
@@ -1367,3 +1377,45 @@
     }
   }
 }
+
+int ScreenRecoveryUI::SetSwCallback(int code, int value) {
+  if (!is_graphics_available) { return -1; }
+  if (code > SW_MAX) { return -1; }
+  if (code != SW_LID) { return 0; }
+
+  /* detect dual display */
+  if (!gr_has_multiple_connectors()) { return -1; }
+
+  /* turn off all screen */
+  gr_fb_blank(true, DirectRenderManager::DRM_INNER);
+  gr_fb_blank(true, DirectRenderManager::DRM_OUTER);
+  gr_color(0, 0, 0, 255);
+  gr_clear();
+
+  /* turn on the screen */
+  gr_fb_blank(false, value);
+  gr_flip();
+
+  /* set the retation */
+  std::string rotation_str;
+  if (value == DirectRenderManager::DRM_OUTER) {
+    rotation_str =
+      android::base::GetProperty("ro.minui.second_rotation", "ROTATION_NONE");
+  } else {
+    rotation_str =
+      android::base::GetProperty("ro.minui.default_rotation", "ROTATION_NONE");
+  }
+
+  if (rotation_str == "ROTATION_RIGHT") {
+    gr_rotate(GRRotation::RIGHT);
+  } else if (rotation_str == "ROTATION_DOWN") {
+    gr_rotate(GRRotation::DOWN);
+  } else if (rotation_str == "ROTATION_LEFT") {
+    gr_rotate(GRRotation::LEFT);
+  } else {  // "ROTATION_NONE" or unknown string
+    gr_rotate(GRRotation::NONE);
+  }
+  Redraw();
+
+  return 0;
+}
diff --git a/recovery_ui/ui.cpp b/recovery_ui/ui.cpp
index 6e67b1d..eb87f52 100644
--- a/recovery_ui/ui.cpp
+++ b/recovery_ui/ui.cpp
@@ -341,6 +341,11 @@
     ProcessKey(ev.code, ev.value);
   }
 
+  // For Lid switch handle
+  if (ev.type == EV_SW) {
+    SetSwCallback(ev.code, ev.value);
+  }
+
   return 0;
 }
 
diff --git a/tools/recovery_l10n/res/values-ky/strings.xml b/tools/recovery_l10n/res/values-ky/strings.xml
index 67dca2a..45fcd15 100644
--- a/tools/recovery_l10n/res/values-ky/strings.xml
+++ b/tools/recovery_l10n/res/values-ky/strings.xml
@@ -1,7 +1,7 @@
 <?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>
diff --git a/tools/recovery_l10n/res/values-nb/strings.xml b/tools/recovery_l10n/res/values-nb/strings.xml
index 61d1173..e8cad13 100644
--- a/tools/recovery_l10n/res/values-nb/strings.xml
+++ b/tools/recovery_l10n/res/values-nb/strings.xml
@@ -7,7 +7,7 @@
     <string name="recovery_error" msgid="5748178989622716736">"Feil!"</string>
     <string name="recovery_installing_security" msgid="9184031299717114342">"Installerer sikkerhetsoppdateringen"</string>
     <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Kan ikke laste inn Android-systemet. Dataene dine er muligens skadet. Hvis du fortsetter å se denne meldingen, må du muligens tilbakestille til fabrikkstandard og tømme alle brukerdataene som er lagret på denne enheten."</string>
-    <string name="recovery_try_again" msgid="7168248750158873496">"Prøv på nytt"</string>
+    <string name="recovery_try_again" msgid="7168248750158873496">"Prøv igjen"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Tilbakestill til fabrikkstandard"</string>
     <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Vil du viske ut alle brukerdataene?\n\n DETTE KAN IKKE ANGRES!"</string>
     <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Avbryt"</string>
diff --git a/tools/recovery_l10n/res/values-or/strings.xml b/tools/recovery_l10n/res/values-or/strings.xml
index 683bf19..25b28e6 100644
--- a/tools/recovery_l10n/res/values-or/strings.xml
+++ b/tools/recovery_l10n/res/values-or/strings.xml
@@ -10,5 +10,5 @@
     <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_cancel_wipe_data" msgid="66987687653647384">"ବାତିଲ କରନ୍ତୁ"</string>
+    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"ବାତିଲ୍‌ କରନ୍ତୁ"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-ro/strings.xml b/tools/recovery_l10n/res/values-ro/strings.xml
index 2f1cccd..585db83 100644
--- a/tools/recovery_l10n/res/values-ro/strings.xml
+++ b/tools/recovery_l10n/res/values-ro/strings.xml
@@ -6,9 +6,9 @@
     <string name="recovery_no_command" msgid="4465476568623024327">"Nicio comandă"</string>
     <string name="recovery_error" msgid="5748178989622716736">"Eroare!"</string>
     <string name="recovery_installing_security" msgid="9184031299717114342">"Se instalează actualizarea de securitate"</string>
-    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Nu se poate încărca sistemul Android. Datele tale pot fi corupte. Dacă primești în continuare acest mesaj, poate fi necesar să revii la setările din fabrică și să ștergi toate datele utilizatorului stocate pe acest dispozitiv."</string>
+    <string name="recovery_wipe_data_menu_header" msgid="550255032058254478">"Nu se poate încărca sistemul Android. Datele dvs. pot fi corupte. Dacă primiți în continuare acest mesaj, poate fi necesar să reveniți la setările din fabrică și să ștergeți toate datele utilizatorului stocate pe acest dispozitiv."</string>
     <string name="recovery_try_again" msgid="7168248750158873496">"Reîncercați"</string>
     <string name="recovery_factory_data_reset" msgid="7321351565602894783">"Revenire la setările din fabrică"</string>
-    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Șterge toate datele utilizatorului?\n\n ACEST LUCRU NU POATE FI ANULAT!"</string>
-    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Anulează"</string>
+    <string name="recovery_wipe_data_confirmation" msgid="5439823343348043954">"Ștergeți toate datele utilizatorului?\n\n ACEST LUCRU NU POATE FI ANULAT!"</string>
+    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"Anulați"</string>
 </resources>
diff --git a/tools/recovery_l10n/res/values-te/strings.xml b/tools/recovery_l10n/res/values-te/strings.xml
index 5747075..38ca612 100644
--- a/tools/recovery_l10n/res/values-te/strings.xml
+++ b/tools/recovery_l10n/res/values-te/strings.xml
@@ -10,5 +10,5 @@
     <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_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయండి"</string>
+    <string name="recovery_cancel_wipe_data" msgid="66987687653647384">"రద్దు చేయి"</string>
 </resources>
diff --git a/update_verifier/Android.bp b/update_verifier/Android.bp
index 220b007..3c4ec4a 100644
--- a/update_verifier/Android.bp
+++ b/update_verifier/Android.bp
@@ -73,8 +73,13 @@
         "libvold_binder",
     ],
 
+    whole_static_libs: [
+        "libsnapshot_snapuserd",
+    ],
+
     shared_libs: [
         "android.hardware.boot@1.0",
+        "libboot_control_client",
         "libbase",
         "libcutils",
         "libbinder",
@@ -114,6 +119,7 @@
         "libprotobuf-cpp-lite",
         "libbinder",
         "libutils",
+        "libboot_control_client",
     ],
 
     init_rc: [
diff --git a/update_verifier/include/update_verifier/update_verifier.h b/update_verifier/include/update_verifier/update_verifier.h
index 4c64b1e..0cccc90 100644
--- a/update_verifier/include/update_verifier/update_verifier.h
+++ b/update_verifier/include/update_verifier/update_verifier.h
@@ -21,6 +21,7 @@
 #include <string>
 #include <vector>
 
+#include <snapuserd/snapuserd_client.h>
 #include "otautil/rangeset.h"
 
 // The update verifier performs verification upon the first boot to a new slot on A/B devices.
@@ -68,4 +69,8 @@
 
   // The function to read the device property; default value: android::base::GetProperty()
   std::function<std::string(const std::string&)> property_reader_;
+
+  // Check if snapuserd daemon has already completed the update verification
+  // Applicable only for VABC with userspace snapshots
+  bool CheckVerificationStatus();
 };
diff --git a/update_verifier/update_verifier.cpp b/update_verifier/update_verifier.cpp
index a042f90..ea47a65 100644
--- a/update_verifier/update_verifier.cpp
+++ b/update_verifier/update_verifier.cpp
@@ -52,13 +52,14 @@
 #include <future>
 #include <thread>
 
+#include <BootControlClient.h>
+#include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
-#include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/os/IVold.h>
 #include <binder/BinderService.h>
 #include <binder/Status.h>
@@ -66,11 +67,6 @@
 
 #include "care_map.pb.h"
 
-using android::sp;
-using android::hardware::boot::V1_0::IBootControl;
-using android::hardware::boot::V1_0::BoolResult;
-using android::hardware::boot::V1_0::CommandResult;
-
 // TODO(xunchang) remove the prefix and use a default path instead.
 constexpr const char* kDefaultCareMapPrefix = "/data/ota_package/care_map";
 
@@ -91,7 +87,7 @@
 // partition's integrity.
 std::map<std::string, std::string> UpdateVerifier::FindDmPartitions() {
   static constexpr auto DM_PATH_PREFIX = "/sys/block/";
-  dirent** namelist;
+  dirent** namelist = nullptr;
   int n = scandir(DM_PATH_PREFIX, &namelist, dm_name_filter, alphasort);
   if (n == -1) {
     PLOG(ERROR) << "Failed to scan dir " << DM_PATH_PREFIX;
@@ -188,7 +184,28 @@
   return ret;
 }
 
+bool UpdateVerifier::CheckVerificationStatus() {
+  auto client =
+      android::snapshot::SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 5s);
+  if (!client) {
+    LOG(ERROR) << "Unable to connect to snapuserd";
+    return false;
+  }
+
+  return client->QueryUpdateVerification();
+}
+
 bool UpdateVerifier::VerifyPartitions() {
+  const bool userspace_snapshots =
+      android::base::GetBoolProperty("ro.virtual_ab.userspace.snapshots.enabled", false);
+
+  if (userspace_snapshots && CheckVerificationStatus()) {
+    LOG(INFO) << "Partitions verified by snapuserd daemon";
+    return true;
+  }
+
+  LOG(INFO) << "Partitions not verified by snapuserd daemon";
+
   auto dm_block_devices = FindDmPartitions();
   if (dm_block_devices.empty()) {
     LOG(ERROR) << "No dm-enabled block device is found.";
@@ -307,18 +324,21 @@
     LOG(INFO) << "Started with arg " << i << ": " << argv[i];
   }
 
-  sp<IBootControl> module = IBootControl::getService();
+  const auto module = android::hal::BootControlClient::WaitForService();
   if (module == nullptr) {
     LOG(ERROR) << "Error getting bootctrl module.";
     return reboot_device();
   }
 
-  uint32_t current_slot = module->getCurrentSlot();
-  BoolResult is_successful = module->isSlotMarkedSuccessful(current_slot);
-  LOG(INFO) << "Booting slot " << current_slot << ": isSlotMarkedSuccessful="
-            << static_cast<int32_t>(is_successful);
-
-  if (is_successful == BoolResult::FALSE) {
+  uint32_t current_slot = module->GetCurrentSlot();
+  const auto is_successful = module->IsSlotMarkedSuccessful(current_slot);
+  if (!is_successful.has_value()) {
+    LOG(INFO) << "Booting slot " << current_slot << " failed";
+  } else {
+    LOG(INFO) << "Booting slot " << current_slot
+              << ": isSlotMarkedSuccessful=" << is_successful.value();
+  }
+  if (is_successful.has_value() && !is_successful.value()) {
     // The current slot has not booted successfully.
 
     bool skip_verification = false;
@@ -364,8 +384,7 @@
     }
 
     if (!supports_checkpoint) {
-      CommandResult cr;
-      module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
+      const auto cr = module->MarkBootSuccessful();
       if (!cr.success) {
         LOG(ERROR) << "Error marking booted successfully: " << cr.errMsg;
         return reboot_device();