Merge "Revert "Add ::1 to localhost in etc/hosts""
diff --git a/debuggerd/crasher/Android.bp b/debuggerd/crasher/Android.bp
index effd480..3af806b 100644
--- a/debuggerd/crasher/Android.bp
+++ b/debuggerd/crasher/Android.bp
@@ -19,10 +19,6 @@
     arch: {
         arm: {
             srcs: ["arm/crashglue.S"],
-
-            neon: {
-                asflags: ["-DHAS_VFP_D32"],
-            },
         },
         arm64: {
             srcs: ["arm64/crashglue.S"],
diff --git a/debuggerd/crasher/arm/crashglue.S b/debuggerd/crasher/arm/crashglue.S
index 4fbfd6e..8649056 100644
--- a/debuggerd/crasher/arm/crashglue.S
+++ b/debuggerd/crasher/arm/crashglue.S
@@ -32,7 +32,6 @@
 	fconstd   d13, #13
 	fconstd   d14, #14
 	fconstd   d15, #15
-#if defined(HAS_VFP_D32)
 	fconstd   d16, #16
 	fconstd   d17, #17
 	fconstd   d18, #18
@@ -49,7 +48,6 @@
 	fconstd   d29, #29
 	fconstd   d30, #30
 	fconstd   d31, #31
-#endif
 
 	mov lr, #0
 	ldr lr, [lr]
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index c08721b..9c1b136 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -445,6 +445,8 @@
   ASSERT_MATCH(result, "memory near x0 \\(\\[anon:");
 #elif defined(__arm__)
   ASSERT_MATCH(result, "memory near r0 \\(\\[anon:");
+#elif defined(__riscv)
+  ASSERT_MATCH(result, "memory near a0 \\(\\[anon:");
 #elif defined(__x86_64__)
   ASSERT_MATCH(result, "memory near rdi \\(\\[anon:");
 #else
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index e5b4d74..375ed8a 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -77,9 +77,9 @@
     .registers = std::move(regs), .uid = uid, .tid = target_tid,
     .thread_name = std::move(thread_name), .pid = pid, .command_line = std::move(command_line),
     .selinux_label = std::move(selinux_label), .siginfo = siginfo,
-#if defined(__aarch64__)
     // Only supported on aarch64 for now.
-        .tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
+#if defined(__aarch64__)
+    .tagged_addr_ctrl = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0),
     .pac_enabled_keys = prctl(PR_PAC_GET_ENABLED_KEYS, 0, 0, 0, 0),
 #endif
   };
@@ -88,7 +88,6 @@
         if (target_tid == tid) {
           return;
         }
-        async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "Adding thread %d", tid);
         threads[tid] = ThreadInfo{
             .uid = thread.uid,
             .tid = tid,
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index eed49fa..765174b 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -168,6 +168,7 @@
         "android.hardware.boot-V1-ndk",
         "libboot_control_client",
         "android.hardware.fastboot@1.1",
+        "android.hardware.fastboot-V1-ndk",
         "android.hardware.health@2.0",
         "android.hardware.health-V1-ndk",
         "libasyncio",
@@ -192,6 +193,7 @@
         "libc++fs",
         "libhealthhalutils",
         "libhealthshim",
+        "libfastbootshim",
         "libsnapshot_cow",
         "liblz4",
         "libsnapshot_nobinder",
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 3799d1f..f8befd3 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -57,8 +57,6 @@
 using android::fs_mgr::MetadataBuilder;
 using android::hal::CommandResult;
 using ::android::hardware::hidl_string;
-using ::android::hardware::fastboot::V1_0::Result;
-using ::android::hardware::fastboot::V1_0::Status;
 using android::snapshot::SnapshotManager;
 using MergeStatus = android::hal::BootControlClient::MergeStatus;
 
@@ -203,20 +201,21 @@
         return false;
     }
 
-    Result ret;
-    auto ret_val = fastboot_hal->doOemSpecificErase([&](Result result) { ret = result; });
-    if (!ret_val.isOk()) {
-        return false;
-    }
-    if (ret.status == Status::NOT_SUPPORTED) {
-        return false;
-    } else if (ret.status != Status::SUCCESS) {
-        device->WriteStatus(FastbootResult::FAIL, ret.message);
-    } else {
+    auto status = fastboot_hal->doOemSpecificErase();
+    if (status.isOk()) {
         device->WriteStatus(FastbootResult::OKAY, "Erasing succeeded");
+        return true;
     }
-
-    return true;
+    switch (status.getExceptionCode()) {
+        case EX_UNSUPPORTED_OPERATION:
+            return false;
+        case EX_SERVICE_SPECIFIC:
+            device->WriteStatus(FastbootResult::FAIL, status.getDescription());
+            return false;
+        default:
+            LOG(ERROR) << "Erase operation failed" << status.getDescription();
+            return false;
+    }
 }
 
 bool EraseHandler(FastbootDevice* device, const std::vector<std::string>& args) {
@@ -266,18 +265,16 @@
     if (args[0] == "oem postwipedata userdata") {
         return device->WriteStatus(FastbootResult::FAIL, "Unable to do oem postwipedata userdata");
     }
-
-    Result ret;
-    auto ret_val = fastboot_hal->doOemCommand(args[0], [&](Result result) { ret = result; });
-    if (!ret_val.isOk()) {
-        return device->WriteStatus(FastbootResult::FAIL, "Unable to do OEM command");
-    }
-    if (ret.status != Status::SUCCESS) {
-        return device->WriteStatus(FastbootResult::FAIL, ret.message);
+    std::string message;
+    auto status = fastboot_hal->doOemCommand(args[0], &message);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Unable to do OEM command " << args[0].c_str() << status.getDescription();
+        return device->WriteStatus(FastbootResult::FAIL,
+                                   "Unable to do OEM command " + status.getDescription());
     }
 
-    device->WriteInfo(ret.message);
-    return device->WriteStatus(FastbootResult::OKAY, ret.message);
+    device->WriteInfo(message);
+    return device->WriteStatus(FastbootResult::OKAY, message);
 }
 
 bool DownloadHandler(FastbootDevice* device, const std::vector<std::string>& args) {
diff --git a/fastboot/device/fastboot_device.cpp b/fastboot/device/fastboot_device.cpp
index 4932e5c..5afeb4f 100644
--- a/fastboot/device/fastboot_device.cpp
+++ b/fastboot/device/fastboot_device.cpp
@@ -25,6 +25,7 @@
 #include <android/binder_manager.h>
 #include <android/hardware/boot/1.0/IBootControl.h>
 #include <android/hardware/fastboot/1.1/IFastboot.h>
+#include <fastbootshim.h>
 #include <fs_mgr.h>
 #include <fs_mgr/roots.h>
 #include <health-shim/shim.h>
@@ -64,6 +65,27 @@
     return nullptr;
 }
 
+std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> get_fastboot_service() {
+    using aidl::android::hardware::fastboot::IFastboot;
+    using HidlFastboot = android::hardware::fastboot::V1_1::IFastboot;
+    using aidl::android::hardware::fastboot::FastbootShim;
+    auto service_name = IFastboot::descriptor + "/default"s;
+    ndk::SpAIBinder binder(AServiceManager_getService(service_name.c_str()));
+    std::shared_ptr<IFastboot> fastboot = IFastboot::fromBinder(binder);
+    if (fastboot != nullptr) {
+        LOG(INFO) << "Using AIDL fastboot service";
+        return fastboot;
+    }
+    LOG(INFO) << "Unable to get AIDL fastboot service, trying HIDL...";
+    android::sp<HidlFastboot> hidl_fastboot = HidlFastboot::getService();
+    if (hidl_fastboot != nullptr) {
+        LOG(INFO) << "Found and now using fastboot HIDL implementation";
+        return ndk::SharedRefBase::make<FastbootShim>(hidl_fastboot);
+    }
+    LOG(WARNING) << "No fastboot implementation is found.";
+    return nullptr;
+}
+
 FastbootDevice::FastbootDevice()
     : kCommandMap({
               {FB_CMD_SET_ACTIVE, SetActiveHandler},
@@ -87,7 +109,7 @@
       }),
       boot_control_hal_(BootControlClient::WaitForService()),
       health_hal_(get_health_service()),
-      fastboot_hal_(IFastboot::getService()),
+      fastboot_hal_(get_fastboot_service()),
       active_slot_("") {
     if (android::base::GetProperty("fastbootd.protocol", "usb") == "tcp") {
         transport_ = std::make_unique<ClientTcpTransport>();
diff --git a/fastboot/device/fastboot_device.h b/fastboot/device/fastboot_device.h
index 9df8fa5..fcaf249 100644
--- a/fastboot/device/fastboot_device.h
+++ b/fastboot/device/fastboot_device.h
@@ -23,8 +23,8 @@
 #include <vector>
 
 #include <BootControlClient.h>
+#include <aidl/android/hardware/fastboot/IFastboot.h>
 #include <aidl/android/hardware/health/IHealth.h>
-#include <android/hardware/fastboot/1.1/IFastboot.h>
 
 #include "commands.h"
 #include "transport.h"
@@ -52,7 +52,7 @@
     Transport* get_transport() { return transport_.get(); }
     BootControlClient* boot_control_hal() const { return boot_control_hal_.get(); }
     BootControlClient* boot1_1() const;
-    android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal() {
+    std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> fastboot_hal() {
         return fastboot_hal_;
     }
     std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal() { return health_hal_; }
@@ -65,7 +65,7 @@
     std::unique_ptr<Transport> transport_;
     std::unique_ptr<BootControlClient> boot_control_hal_;
     std::shared_ptr<aidl::android::hardware::health::IHealth> health_hal_;
-    android::sp<android::hardware::fastboot::V1_1::IFastboot> fastboot_hal_;
+    std::shared_ptr<aidl::android::hardware::fastboot::IFastboot> fastboot_hal_;
     std::vector<char> download_data_;
     std::string active_slot_;
 };
diff --git a/fastboot/device/variables.cpp b/fastboot/device/variables.cpp
index b6eb2cd..5f99656 100644
--- a/fastboot/device/variables.cpp
+++ b/fastboot/device/variables.cpp
@@ -41,9 +41,7 @@
 #endif
 
 using MergeStatus = android::hal::BootControlClient::MergeStatus;
-using ::android::hardware::fastboot::V1_0::FileSystemType;
-using ::android::hardware::fastboot::V1_0::Result;
-using ::android::hardware::fastboot::V1_0::Status;
+using aidl::android::hardware::fastboot::FileSystemType;
 using namespace android::fs_mgr;
 using namespace std::string_literals;
 
@@ -104,17 +102,16 @@
         *message = "Fastboot HAL not found";
         return false;
     }
+    std::string device_variant = "";
+    auto status = fastboot_hal->getVariant(&device_variant);
 
-    Result ret;
-    auto ret_val = fastboot_hal->getVariant([&](std::string device_variant, Result result) {
-        *message = device_variant;
-        ret = result;
-    });
-    if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+    if (!status.isOk()) {
         *message = "Unable to get device variant";
+        LOG(ERROR) << message->c_str() << status.getDescription();
         return false;
     }
 
+    *message = device_variant;
     return true;
 }
 
@@ -147,17 +144,14 @@
         return false;
     }
 
-    Result ret;
-    auto ret_val = fastboot_hal->getBatteryVoltageFlashingThreshold(
-            [&](int32_t voltage_threshold, Result result) {
-                *message = battery_voltage >= voltage_threshold ? "yes" : "no";
-                ret = result;
-            });
-
-    if (!ret_val.isOk() || ret.status != Status::SUCCESS) {
+    auto voltage_threshold = 0;
+    auto status = fastboot_hal->getBatteryVoltageFlashingThreshold(&voltage_threshold);
+    if (!status.isOk()) {
         *message = "Unable to get battery voltage flashing threshold";
+        LOG(ERROR) << message->c_str() << status.getDescription();
         return false;
     }
+    *message = battery_voltage >= voltage_threshold ? "yes" : "no";
 
     return true;
 }
@@ -169,18 +163,14 @@
         *message = "Fastboot HAL not found";
         return false;
     }
-
-    Result ret;
-    auto ret_val =
-            fastboot_hal->getOffModeChargeState([&](bool off_mode_charging_state, Result result) {
-                *message = off_mode_charging_state ? "1" : "0";
-                ret = result;
-            });
-    if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+    bool off_mode_charging_state = false;
+    auto status = fastboot_hal->getOffModeChargeState(&off_mode_charging_state);
+    if (!status.isOk()) {
         *message = "Unable to get off mode charge state";
+        LOG(ERROR) << message->c_str() << status.getDescription();
         return false;
     }
-
+    *message = off_mode_charging_state ? "1" : "0";
     return true;
 }
 
@@ -337,14 +327,11 @@
     }
 
     FileSystemType type;
-    Result ret;
-    auto ret_val =
-            fastboot_hal->getPartitionType(args[0], [&](FileSystemType fs_type, Result result) {
-                type = fs_type;
-                ret = result;
-            });
-    if (!ret_val.isOk() || (ret.status != Status::SUCCESS)) {
+    auto status = fastboot_hal->getPartitionType(args[0], &type);
+
+    if (!status.isOk()) {
         *message = "Unable to retrieve partition type";
+        LOG(ERROR) << message->c_str() << status.getDescription();
     } else {
         switch (type) {
             case FileSystemType::RAW:
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index bebf19e..dd61272 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -251,41 +251,8 @@
     },
     symlinks: [
         "clean_scratch_files",
-    ],
-}
-
-cc_binary {
-    name: "set-verity-state",
-    srcs: ["set-verity-state.cpp"],
-    shared_libs: [
-        "libbase",
-        "libbinder",
-        "libcrypto",
-        "libcrypto_utils",
-        "libfs_mgr_binder",
-        "libutils",
-    ],
-    static_libs: [
-        "libavb_user",
-    ],
-    header_libs: [
-        "libcutils_headers",
-    ],
-
-    cflags: ["-Werror"],
-    cppflags: [
-        "-DALLOW_DISABLE_VERITY=0",
-    ],
-    product_variables: {
-        debuggable: {
-            cppflags: [
-                "-UALLOW_DISABLE_VERITY",
-                "-DALLOW_DISABLE_VERITY=1",
-            ],
-        },
-    },
-    symlinks: [
-        "enable-verity",
         "disable-verity",
+        "enable-verity",
+        "set-verity-state",
     ],
 }
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 27137a2..1c1ab48 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -2191,36 +2191,22 @@
         std::vector<std::string> tokens = android::base::Split(target.data, " \t\r\n");
         if (tokens[0] != "0" && tokens[0] != "1") {
             LOG(WARNING) << "Unrecognized device mapper version in " << target.data;
-            return {};
         }
 
         // Hashtree algorithm & root digest are the 8th & 9th token in the output.
-        return HashtreeInfo{.algorithm = android::base::Trim(tokens[7]),
-                            .root_digest = android::base::Trim(tokens[8])};
+        return HashtreeInfo{
+                .algorithm = android::base::Trim(tokens[7]),
+                .root_digest = android::base::Trim(tokens[8]),
+                .check_at_most_once = target.data.find("check_at_most_once") != std::string::npos};
     }
 
     return {};
 }
 
 bool fs_mgr_verity_is_check_at_most_once(const android::fs_mgr::FstabEntry& entry) {
-    if (!entry.fs_mgr_flags.avb) {
-        return false;
-    }
-
-    DeviceMapper& dm = DeviceMapper::Instance();
-    std::string device = GetVerityDeviceName(entry);
-
-    std::vector<DeviceMapper::TargetInfo> table;
-    if (dm.GetState(device) == DmDeviceState::INVALID || !dm.GetTableInfo(device, &table)) {
-        return false;
-    }
-    for (const auto& target : table) {
-        if (strcmp(target.spec.target_type, "verity") == 0 &&
-            target.data.find("check_at_most_once") != std::string::npos) {
-            return true;
-        }
-    }
-    return false;
+    auto hashtree_info = fs_mgr_get_hashtree_info(entry);
+    if (!hashtree_info) return false;
+    return hashtree_info->check_at_most_once;
 }
 
 std::string fs_mgr_get_super_partition_name(int slot) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 6290057..bb24abf 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -69,6 +69,7 @@
 namespace {
 
 constexpr char kDataScratchSizeMbProp[] = "fs_mgr.overlayfs.data_scratch_size_mb";
+constexpr char kPreferCacheBackingStorageProp[] = "fs_mgr.overlayfs.prefer_cache_backing_storage";
 
 bool fs_mgr_access(const std::string& path) {
     return access(path.c_str(), F_OK) == 0;
@@ -101,6 +102,10 @@
 const auto kScratchMountPoint = "/mnt/scratch"s;
 const auto kCacheMountPoint = "/cache"s;
 
+bool IsABDevice() {
+    return !android::base::GetProperty("ro.boot.slot_suffix", "").empty();
+}
+
 std::vector<const std::string> OverlayMountPoints() {
     // Never fallback to legacy cache mount point if within a DSU system,
     // because running a DSU system implies the device supports dynamic
@@ -108,6 +113,15 @@
     if (fs_mgr_is_dsu_running()) {
         return {kScratchMountPoint};
     }
+
+    // For non-A/B devices prefer cache backing storage if
+    // kPreferCacheBackingStorageProp property set.
+    if (!IsABDevice() &&
+        android::base::GetBoolProperty(kPreferCacheBackingStorageProp, false) &&
+        android::base::GetIntProperty("ro.vendor.api_level", -1) < __ANDROID_API_T__) {
+        return {kCacheMountPoint, kScratchMountPoint};
+    }
+
     return {kScratchMountPoint, kCacheMountPoint};
 }
 
@@ -462,6 +476,28 @@
     return true;
 }
 
+OverlayfsTeardownResult TeardownDataScratch(IImageManager* images,
+                                            const std::string& partition_name, bool was_mounted) {
+    if (!images) {
+        return OverlayfsTeardownResult::Error;
+    }
+    if (!images->DisableImage(partition_name)) {
+        return OverlayfsTeardownResult::Error;
+    }
+    if (was_mounted) {
+        // If overlayfs was mounted, don't bother trying to unmap since
+        // it'll fail and create error spam.
+        return OverlayfsTeardownResult::Busy;
+    }
+    if (!images->UnmapImageIfExists(partition_name)) {
+        return OverlayfsTeardownResult::Busy;
+    }
+    if (!images->DeleteBackingImage(partition_name)) {
+        return OverlayfsTeardownResult::Busy;
+    }
+    return OverlayfsTeardownResult::Ok;
+}
+
 OverlayfsTeardownResult fs_mgr_overlayfs_teardown_scratch(const std::string& overlay,
                                                           bool* change) {
     // umount and delete kScratchMountPoint storage if we have logical partitions
@@ -484,24 +520,9 @@
 
     auto images = IImageManager::Open("remount", 10s);
     if (images && images->BackingImageExists(partition_name)) {
-        if (!images->DisableImage(partition_name)) {
-            return OverlayfsTeardownResult::Error;
-        }
-        if (was_mounted) {
-            // If overlayfs was mounted, don't bother trying to unmap since
-            // it'll fail and create error spam.
-            return OverlayfsTeardownResult::Busy;
-        }
-        if (!images->UnmapImageIfExists(partition_name)) {
-            return OverlayfsTeardownResult::Busy;
-        }
-        if (!images->DeleteBackingImage(partition_name)) {
-            return OverlayfsTeardownResult::Busy;
-        }
-
         // No need to check super partition, if we knew we had a scratch device
         // in /data.
-        return OverlayfsTeardownResult::Ok;
+        return TeardownDataScratch(images.get(), partition_name, was_mounted);
     }
 
     auto slot_number = fs_mgr_overlayfs_slot_number();
@@ -1103,6 +1124,8 @@
     }
     if (!images->MapImageDevice(partition_name, 10s, scratch_device)) {
         LERROR << "could not map scratch image";
+        // If we cannot use this image, then remove it.
+        TeardownDataScratch(images.get(), partition_name, false /* was_mounted */);
         return false;
     }
     return true;
@@ -1136,6 +1159,7 @@
         if (CreateScratchOnData(scratch_device, partition_exists)) {
             return true;
         }
+        LOG(WARNING) << "Failed to allocate scratch on /data, fallback to use free space on super";
     }
     // If that fails, see if we can land on super.
     if (CanUseSuperPartition(fstab)) {
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 2edaaad..eac3ff2 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -22,6 +22,7 @@
 #include <sys/vfs.h>
 #include <unistd.h>
 
+#include <iostream>
 #include <string>
 #include <thread>
 #include <utility>
@@ -33,6 +34,7 @@
 #include <android-base/strings.h>
 #include <android/os/IVold.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <bootloader_message/bootloader_message.h>
 #include <cutils/android_reboot.h>
 #include <fs_mgr_overlayfs.h>
@@ -50,17 +52,34 @@
 namespace {
 
 void usage() {
-    LOG(INFO) << getprogname()
-              << " [-h] [-R] [-T fstab_file] [partition]...\n"
-                 "\t-h --help\tthis help\n"
-                 "\t-R --reboot\tdisable verity & reboot to facilitate remount\n"
-                 "\t-T --fstab\tcustom fstab file location\n"
-                 "\tpartition\tspecific partition(s) (empty does all)\n"
-                 "\n"
-                 "Remount specified partition(s) read-write, by name or mount point.\n"
-                 "-R notwithstanding, verity must be disabled on partition(s).\n"
-                 "-R within a DSU guest system reboots into the DSU instead of the host system,\n"
-                 "this command would enable DSU (one-shot) if not already enabled.";
+    const std::string progname = getprogname();
+    if (progname == "disable-verity" || progname == "enable-verity" ||
+        progname == "set-verity-state") {
+        std::cout << "Usage: disable-verity\n"
+                  << "       enable-verity\n"
+                  << "       set-verity-state [0|1]\n"
+                  << R"(
+Options:
+    -h --help       this help
+    -R --reboot     automatic reboot if needed for new settings to take effect
+    -v --verbose    be noisy)"
+                  << std::endl;
+    } else {
+        std::cout << "Usage: " << progname << " [-h] [-R] [-T fstab_file] [partition]...\n"
+                  << R"(
+Options:
+    -h --help       this help
+    -R --reboot     disable verity & reboot to facilitate remount
+    -v --verbose    be noisy
+    -T --fstab      custom fstab file location
+    partition       specific partition(s) (empty does all)
+
+Remount specified partition(s) read-write, by name or mount point.
+-R notwithstanding, verity must be disabled on partition(s).
+-R within a DSU guest system reboots into the DSU instead of the host system,
+this command would enable DSU (one-shot) if not already enabled.)"
+                  << std::endl;
+    }
 }
 
 const std::string system_mount_point(const android::fs_mgr::FstabEntry& entry) {
@@ -79,23 +98,32 @@
     return &(*it);
 }
 
-auto verbose = false;
+class MyLogger {
+  public:
+    explicit MyLogger(bool verbose) : verbose_(verbose) {}
 
-void MyLogger(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
-              const char* file, unsigned int line, const char* message) {
-    if (verbose || severity == android::base::ERROR || message[0] != '[') {
-        fprintf(stderr, "%s\n", message);
+    void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
+                    const char* file, unsigned int line, const char* message) {
+        // By default, print ERROR logs and logs of this program (does not start with '[')
+        // Print [libfs_mgr] INFO logs only if -v is given.
+        if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
+            fprintf(stderr, "%s\n", message);
+        }
+        logd_(id, severity, tag, file, line, message);
     }
-    static auto logd = android::base::LogdLogger();
-    logd(id, severity, tag, file, line, message);
-}
 
-[[noreturn]] void reboot() {
+  private:
+    android::base::LogdLogger logd_;
+    bool verbose_;
+};
+
+[[noreturn]] void reboot(const std::string& name) {
     LOG(INFO) << "Rebooting device for new settings to take effect";
     ::sync();
-    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,remount");
+    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
     ::sleep(60);
-    ::exit(0);  // SUCCESS
+    LOG(ERROR) << "Failed to reboot";
+    ::exit(1);
 }
 
 static android::sp<android::os::IVold> GetVold() {
@@ -111,8 +139,6 @@
     }
 }
 
-}  // namespace
-
 enum RemountStatus {
     REMOUNT_SUCCESS = 0,
     UNKNOWN_PARTITION = 5,
@@ -412,6 +438,68 @@
     return REMOUNT_FAILED;
 }
 
+struct SetVerityStateResult {
+    bool success = false;
+    bool want_reboot = false;
+};
+
+SetVerityStateResult SetVerityState(bool enable_verity) {
+    const auto ab_suffix = android::base::GetProperty("ro.boot.slot_suffix", "");
+    bool verity_enabled = false;
+
+    std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
+                                                              &avb_ops_user_free);
+    if (!ops) {
+        LOG(ERROR) << "Error getting AVB ops";
+        return {};
+    }
+
+    if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
+        LOG(ERROR) << "Error getting verity state";
+        return {};
+    }
+
+    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
+        LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
+        return {.success = true, .want_reboot = false};
+    }
+
+    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
+        LOG(ERROR) << "Error setting verity state";
+        return {};
+    }
+
+    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
+    return {.success = true, .want_reboot = true};
+}
+
+bool SetupOrTeardownOverlayfs(bool enable) {
+    bool want_reboot = false;
+    if (enable) {
+        if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
+            LOG(ERROR) << "Overlayfs setup failed.";
+            return want_reboot;
+        }
+        if (want_reboot) {
+            printf("enabling overlayfs\n");
+        }
+    } else {
+        auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
+        if (rv == OverlayfsTeardownResult::Error) {
+            LOG(ERROR) << "Overlayfs teardown failed.";
+            return want_reboot;
+        }
+        if (rv == OverlayfsTeardownResult::Busy) {
+            LOG(ERROR) << "Overlayfs is still active until reboot.";
+            return true;
+        }
+        if (want_reboot) {
+            printf("disabling overlayfs\n");
+        }
+    }
+    return want_reboot;
+}
+
 static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
                       RemountCheckResult* check_result) {
     Fstab partitions;
@@ -457,6 +545,8 @@
     return retval;
 }
 
+}  // namespace
+
 int main(int argc, char* argv[]) {
     // Do not use MyLogger() when running as clean_scratch_files, as stdout/stderr of daemon process
     // are discarded.
@@ -465,7 +555,70 @@
         return 0;
     }
 
-    android::base::InitLogging(argv, MyLogger);
+    android::base::InitLogging(argv, MyLogger(false /* verbose */));
+
+    const char* fstab_file = nullptr;
+    bool auto_reboot = false;
+    bool verbose = false;
+    std::vector<std::string> partition_args;
+
+    struct option longopts[] = {
+            {"fstab", required_argument, nullptr, 'T'},
+            {"help", no_argument, nullptr, 'h'},
+            {"reboot", no_argument, nullptr, 'R'},
+            {"verbose", no_argument, nullptr, 'v'},
+            {0, 0, nullptr, 0},
+    };
+    for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
+        switch (opt) {
+            case 'h':
+                usage();
+                return 0;
+            case 'R':
+                auto_reboot = true;
+                break;
+            case 'T':
+                if (fstab_file) {
+                    LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
+                    usage();
+                    return 1;
+                }
+                fstab_file = optarg;
+                break;
+            case 'v':
+                verbose = true;
+                break;
+            default:
+                LOG(ERROR) << "Bad argument -" << char(opt);
+                usage();
+                return 1;
+        }
+    }
+
+    if (verbose) {
+        android::base::SetLogger(MyLogger(verbose));
+    }
+
+    bool remount = false;
+    bool enable_verity = false;
+    const std::string progname = getprogname();
+    if (progname == "enable-verity") {
+        enable_verity = true;
+    } else if (progname == "disable-verity") {
+        enable_verity = false;
+    } else if (progname == "set-verity-state") {
+        if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
+            enable_verity = (argv[optind] == "1"s);
+        } else {
+            usage();
+            return 1;
+        }
+    } else {
+        remount = true;
+        for (; optind < argc; ++optind) {
+            partition_args.emplace_back(argv[optind]);
+        }
+    }
 
     // Make sure we are root.
     if (::getuid() != 0) {
@@ -486,45 +639,34 @@
         return 1;
     }
 
-    const char* fstab_file = nullptr;
-    auto auto_reboot = false;
-    std::vector<std::string> partition_args;
+    // Start a threadpool to service waitForService() callbacks as
+    // fs_mgr_overlayfs_* might call waitForService() to get the image service.
+    android::ProcessState::self()->startThreadPool();
 
-    struct option longopts[] = {
-            {"fstab", required_argument, nullptr, 'T'},
-            {"help", no_argument, nullptr, 'h'},
-            {"reboot", no_argument, nullptr, 'R'},
-            {"verbose", no_argument, nullptr, 'v'},
-            {0, 0, nullptr, 0},
-    };
-    for (int opt; (opt = ::getopt_long(argc, argv, "hRT:v", longopts, nullptr)) != -1;) {
-        switch (opt) {
-            case 'h':
-                usage();
-                return 0;
-            case 'R':
-                auto_reboot = true;
-                break;
-            case 'T':
-                if (fstab_file) {
-                    LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T" << optarg;
-                    usage();
-                    return 1;
-                }
-                fstab_file = optarg;
-                break;
-            case 'v':
-                verbose = true;
-                break;
-            default:
-                LOG(ERROR) << "Bad Argument -" << char(opt);
-                usage();
-                return 1;
+    if (!remount) {
+        // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
+        // contract, androidboot.vbmeta.digest is set by the bootloader
+        // when using AVB).
+        if (android::base::GetProperty("ro.boot.vbmeta.digest", "").empty()) {
+            LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
+            return 1;
         }
-    }
 
-    for (; argc > optind; ++optind) {
-        partition_args.emplace_back(argv[optind]);
+        auto ret = SetVerityState(enable_verity);
+
+        // Disable any overlayfs unconditionally if we want verity enabled.
+        // Enable overlayfs only if verity is successfully disabled or is already disabled.
+        if (enable_verity || ret.success) {
+            ret.want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
+        }
+
+        if (ret.want_reboot) {
+            if (auto_reboot) {
+                reboot(progname);
+            }
+            std::cout << "Reboot the device for new settings to take effect" << std::endl;
+        }
+        return ret.success ? 0 : 1;
     }
 
     // Make sure checkpointing is disabled if necessary.
@@ -549,7 +691,11 @@
     } else if (check_result.setup_overlayfs) {
         LOG(INFO) << "Overlayfs enabled.";
     }
-
+    if (result == REMOUNT_SUCCESS) {
+        LOG(INFO) << "remount succeeded";
+    } else {
+        LOG(ERROR) << "remount failed";
+    }
     if (check_result.reboot_later) {
         if (auto_reboot) {
             // If (1) remount requires a reboot to take effect, (2) system is currently
@@ -560,16 +706,11 @@
                 LOG(ERROR) << "Unable to automatically enable DSU";
                 return rv;
             }
-            reboot();
+            reboot("remount");
         } else {
             LOG(INFO) << "Now reboot your device for settings to take effect";
         }
         return REMOUNT_SUCCESS;
     }
-    if (result == REMOUNT_SUCCESS) {
-        printf("remount succeeded\n");
-    } else {
-        printf("remount failed\n");
-    }
     return result;
 }
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 29a5e60..43de6d8 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -71,6 +71,8 @@
     std::string algorithm;
     // The root digest of the merkle tree.
     std::string root_digest;
+    // If check_at_most_once is enabled.
+    bool check_at_most_once;
 };
 
 // fs_mgr_mount_all() updates fstab entries that reference device-mapper.
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index b93fd32..a9682a1 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -16,6 +16,7 @@
 
 #include <stdint.h>
 
+#include <cstdint>
 #include <memory>
 #include <optional>
 #include <string>
@@ -150,6 +151,7 @@
     bool SetFd(android::base::borrowed_fd fd);
     bool Sync();
     bool Truncate(off_t length);
+    bool EnsureSpaceAvailable(const uint64_t bytes_needed) const;
 
   private:
     android::base::unique_fd owned_fd_;
@@ -165,6 +167,7 @@
     bool is_dev_null_ = false;
     bool merge_in_progress_ = false;
     bool is_block_device_ = false;
+    uint64_t cow_image_size_ = INT64_MAX;
 };
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index e58f45a..0eb231b 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -84,7 +84,13 @@
                            << ", compression bound: " << bound << ", ret: " << compressed_size;
                 return {};
             }
-            buffer.resize(compressed_size);
+            // Don't run compression if the compressed output is larger
+            if (compressed_size >= length) {
+                buffer.resize(length);
+                memcpy(buffer.data(), data, length);
+            } else {
+                buffer.resize(compressed_size);
+            }
             return buffer;
         }
         default:
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
index a4d2277..139a29f 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_decompress.cpp
@@ -273,6 +273,18 @@
                        << actual_buffer_size << " bytes";
             return false;
         }
+        // If input size is same as output size, then input is uncompressed.
+        if (stream_->Size() == output_size) {
+            size_t bytes_read = 0;
+            stream_->Read(output_buffer, output_size, &bytes_read);
+            if (bytes_read != output_size) {
+                LOG(ERROR) << "Failed to read all input at once. Expected: " << output_size
+                           << " actual: " << bytes_read;
+                return false;
+            }
+            sink_->ReturnData(output_buffer, output_size);
+            return true;
+        }
         std::string input_buffer;
         input_buffer.resize(stream_->Size());
         size_t bytes_read = 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
index 5f5d1fb..43c17a6 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_writer.cpp
@@ -30,9 +30,29 @@
 #include <lz4.h>
 #include <zlib.h>
 
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
 namespace android {
 namespace snapshot {
 
+namespace {
+std::string GetFdPath(int fd) {
+    const auto fd_path = "/proc/self/fd/" + std::to_string(fd);
+    std::string file_path(512, '\0');
+    const auto err = readlink(fd_path.c_str(), file_path.data(), file_path.size());
+    if (err <= 0) {
+        PLOG(ERROR) << "Failed to determine path for fd " << fd;
+        file_path.clear();
+    } else {
+        file_path.resize(err);
+    }
+    return file_path;
+}
+}  // namespace
+
 static_assert(sizeof(off_t) == sizeof(uint64_t));
 
 using android::base::borrowed_fd;
@@ -163,12 +183,25 @@
     } else {
         fd_ = fd;
 
-        struct stat stat;
+        struct stat stat {};
         if (fstat(fd.get(), &stat) < 0) {
             PLOG(ERROR) << "fstat failed";
             return false;
         }
+        const auto file_path = GetFdPath(fd.get());
         is_block_device_ = S_ISBLK(stat.st_mode);
+        if (is_block_device_) {
+            uint64_t size_in_bytes = 0;
+            if (ioctl(fd.get(), BLKGETSIZE64, &size_in_bytes)) {
+                PLOG(ERROR) << "Failed to get total size for: " << fd.get();
+                return false;
+            }
+            cow_image_size_ = size_in_bytes;
+            LOG(INFO) << "COW image " << file_path << " has size " << size_in_bytes;
+        } else {
+            LOG(INFO) << "COW image " << file_path
+                      << " is not a block device, assuming unlimited space.";
+        }
     }
     return true;
 }
@@ -343,7 +376,8 @@
             op.data_length = static_cast<uint16_t>(data.size());
 
             if (!WriteOperation(op, data.data(), data.size())) {
-                PLOG(ERROR) << "AddRawBlocks: write failed";
+                PLOG(ERROR) << "AddRawBlocks: write failed, bytes requested: " << size
+                            << ", bytes written: " << i * header_.block_size;
                 return false;
             }
         } else {
@@ -512,12 +546,26 @@
     return true;
 }
 
-bool CowWriter::WriteOperation(const CowOperation& op, const void* data, size_t size) {
-    if (lseek(fd_.get(), next_op_pos_, SEEK_SET) < 0) {
-        PLOG(ERROR) << "lseek failed for writing operation.";
+bool CowWriter::EnsureSpaceAvailable(const uint64_t bytes_needed) const {
+    if (bytes_needed > cow_image_size_) {
+        LOG(ERROR) << "No space left on COW device. Required: " << bytes_needed
+                   << ", available: " << cow_image_size_;
+        errno = ENOSPC;
         return false;
     }
-    if (!android::base::WriteFully(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op))) {
+    return true;
+}
+
+bool CowWriter::WriteOperation(const CowOperation& op, const void* data, size_t size) {
+    if (!EnsureSpaceAvailable(next_op_pos_ + sizeof(op))) {
+        return false;
+    }
+    if (!EnsureSpaceAvailable(next_data_pos_ + size)) {
+        return false;
+    }
+
+    if (!android::base::WriteFullyAtOffset(fd_, reinterpret_cast<const uint8_t*>(&op), sizeof(op),
+                                           next_op_pos_)) {
         return false;
     }
     if (data != nullptr && size > 0) {
@@ -542,13 +590,8 @@
     next_op_pos_ += sizeof(CowOperation) + GetNextOpOffset(op, header_.cluster_ops);
 }
 
-bool CowWriter::WriteRawData(const void* data, size_t size) {
-    if (lseek(fd_.get(), next_data_pos_, SEEK_SET) < 0) {
-        PLOG(ERROR) << "lseek failed for writing data.";
-        return false;
-    }
-
-    if (!android::base::WriteFully(fd_, data, size)) {
+bool CowWriter::WriteRawData(const void* data, const size_t size) {
+    if (!android::base::WriteFullyAtOffset(fd_, data, size, next_data_pos_)) {
         return false;
     }
     return true;
diff --git a/fs_mgr/libsnapshot/utility.cpp b/fs_mgr/libsnapshot/utility.cpp
index cadd24d..a98bf0e 100644
--- a/fs_mgr/libsnapshot/utility.cpp
+++ b/fs_mgr/libsnapshot/utility.cpp
@@ -17,6 +17,7 @@
 #include <errno.h>
 #include <time.h>
 
+#include <filesystem>
 #include <iomanip>
 #include <sstream>
 
@@ -152,6 +153,24 @@
     }
 }
 
+bool FsyncDirectory(const char* dirname) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname, O_RDONLY | O_CLOEXEC)));
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open " << dirname;
+        return false;
+    }
+    if (fsync(fd) == -1) {
+        if (errno == EROFS || errno == EINVAL) {
+            PLOG(WARNING) << "Skip fsync " << dirname
+                          << " on a file system does not support synchronization";
+        } else {
+            PLOG(ERROR) << "Failed to fsync " << dirname;
+            return false;
+        }
+    }
+    return true;
+}
+
 bool WriteStringToFileAtomic(const std::string& content, const std::string& path) {
     const std::string tmp_path = path + ".tmp";
     {
@@ -175,11 +194,11 @@
         PLOG(ERROR) << "rename failed from " << tmp_path << " to " << path;
         return false;
     }
-    return true;
+    return FsyncDirectory(std::filesystem::path(path).parent_path().c_str());
 }
 
 std::ostream& operator<<(std::ostream& os, const Now&) {
-    struct tm now;
+    struct tm now {};
     time_t t = time(nullptr);
     localtime_r(&t, &now);
     return os << std::put_time(&now, "%Y%m%d-%H%M%S");
diff --git a/fs_mgr/libsnapshot/utility.h b/fs_mgr/libsnapshot/utility.h
index eff6f10..8c4c7c6 100644
--- a/fs_mgr/libsnapshot/utility.h
+++ b/fs_mgr/libsnapshot/utility.h
@@ -117,6 +117,7 @@
 // Note that rename() is an atomic operation. This function may not work properly if there
 // is an open fd to |path|, because that fd has an old view of the file.
 bool WriteStringToFileAtomic(const std::string& content, const std::string& path);
+bool FsyncDirectory(const char* dirname);
 
 // Writes current time to a given stream.
 struct Now {};
diff --git a/fs_mgr/set-verity-state.cpp b/fs_mgr/set-verity-state.cpp
deleted file mode 100644
index 84ee01f..0000000
--- a/fs_mgr/set-verity-state.cpp
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <getopt.h>
-#include <stdio.h>
-
-#include <android-base/file.h>
-#include <android-base/logging.h>
-#include <android-base/properties.h>
-#include <binder/ProcessState.h>
-#include <cutils/android_reboot.h>
-#include <fs_mgr_overlayfs.h>
-#include <libavb_user/libavb_user.h>
-
-#include "fs_mgr_priv_overlayfs.h"
-
-using namespace std::string_literals;
-
-namespace {
-
-void print_usage() {
-    printf("Usage:\n"
-           "\tdisable-verity\n"
-           "\tenable-verity\n"
-           "\tset-verity-state [0|1]\n"
-           "Options:\n"
-           "\t-h --help\tthis help\n"
-           "\t-R --reboot\tautomatic reboot if needed for new settings to take effect\n"
-           "\t-v --verbose\tbe noisy\n");
-}
-
-#ifdef ALLOW_DISABLE_VERITY
-const bool kAllowDisableVerity = true;
-#else
-const bool kAllowDisableVerity = false;
-#endif
-
-static bool SetupOrTeardownOverlayfs(bool enable) {
-    bool want_reboot = false;
-    if (enable) {
-        if (!fs_mgr_overlayfs_setup(nullptr, &want_reboot)) {
-            LOG(ERROR) << "Overlayfs setup failed.";
-            return want_reboot;
-        }
-        if (want_reboot) {
-            printf("enabling overlayfs\n");
-        }
-    } else {
-        auto rv = fs_mgr_overlayfs_teardown(nullptr, &want_reboot);
-        if (rv == OverlayfsTeardownResult::Error) {
-            LOG(ERROR) << "Overlayfs teardown failed.";
-            return want_reboot;
-        }
-        if (rv == OverlayfsTeardownResult::Busy) {
-            LOG(ERROR) << "Overlayfs is still active until reboot.";
-            return true;
-        }
-        if (want_reboot) {
-            printf("disabling overlayfs\n");
-        }
-    }
-    return want_reboot;
-}
-
-/* Helper function to get A/B suffix, if any. If the device isn't
- * using A/B the empty string is returned. Otherwise either "_a",
- * "_b", ... is returned.
- */
-std::string get_ab_suffix() {
-    return android::base::GetProperty("ro.boot.slot_suffix", "");
-}
-
-bool is_avb_device_locked() {
-    return android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked";
-}
-
-bool is_debuggable() {
-    return android::base::GetBoolProperty("ro.debuggable", false);
-}
-
-bool is_using_avb() {
-    // Figure out if we're using VB1.0 or VB2.0 (aka AVB) - by
-    // contract, androidboot.vbmeta.digest is set by the bootloader
-    // when using AVB).
-    return !android::base::GetProperty("ro.boot.vbmeta.digest", "").empty();
-}
-
-[[noreturn]] void reboot(const std::string& name) {
-    LOG(INFO) << "Rebooting device for new settings to take effect";
-    ::sync();
-    android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot," + name);
-    ::sleep(60);
-    LOG(ERROR) << "Failed to reboot";
-    ::exit(1);
-}
-
-struct SetVerityStateResult {
-    bool success = false;
-    bool want_reboot = false;
-};
-
-/* Use AVB to turn verity on/off */
-SetVerityStateResult SetVerityState(bool enable_verity) {
-    std::string ab_suffix = get_ab_suffix();
-    bool verity_enabled = false;
-
-    if (is_avb_device_locked()) {
-        LOG(ERROR) << "Device must be bootloader unlocked to change verity state";
-        return {};
-    }
-
-    std::unique_ptr<AvbOps, decltype(&avb_ops_user_free)> ops(avb_ops_user_new(),
-                                                              &avb_ops_user_free);
-    if (!ops) {
-        LOG(ERROR) << "Error getting AVB ops";
-        return {};
-    }
-
-    if (!avb_user_verity_get(ops.get(), ab_suffix.c_str(), &verity_enabled)) {
-        LOG(ERROR) << "Error getting verity state";
-        return {};
-    }
-
-    if ((verity_enabled && enable_verity) || (!verity_enabled && !enable_verity)) {
-        LOG(INFO) << "Verity is already " << (verity_enabled ? "enabled" : "disabled");
-        return {.success = true, .want_reboot = false};
-    }
-
-    if (!avb_user_verity_set(ops.get(), ab_suffix.c_str(), enable_verity)) {
-        LOG(ERROR) << "Error setting verity state";
-        return {};
-    }
-
-    LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
-    return {.success = true, .want_reboot = true};
-}
-
-class MyLogger {
-  public:
-    explicit MyLogger(bool verbose) : verbose_(verbose) {}
-
-    void operator()(android::base::LogId id, android::base::LogSeverity severity, const char* tag,
-                    const char* file, unsigned int line, const char* message) {
-        // Hide log starting with '[fs_mgr]' unless it's an error.
-        if (verbose_ || severity >= android::base::ERROR || message[0] != '[') {
-            fprintf(stderr, "%s\n", message);
-        }
-        logd_(id, severity, tag, file, line, message);
-    }
-
-  private:
-    android::base::LogdLogger logd_;
-    bool verbose_;
-};
-
-}  // namespace
-
-int main(int argc, char* argv[]) {
-    bool auto_reboot = false;
-    bool verbose = false;
-
-    struct option longopts[] = {
-            {"help", no_argument, nullptr, 'h'},
-            {"reboot", no_argument, nullptr, 'R'},
-            {"verbose", no_argument, nullptr, 'v'},
-            {0, 0, nullptr, 0},
-    };
-    for (int opt; (opt = ::getopt_long(argc, argv, "hRv", longopts, nullptr)) != -1;) {
-        switch (opt) {
-            case 'h':
-                print_usage();
-                return 0;
-            case 'R':
-                auto_reboot = true;
-                break;
-            case 'v':
-                verbose = true;
-                break;
-            default:
-                print_usage();
-                return 1;
-        }
-    }
-
-    android::base::InitLogging(argv, MyLogger(verbose));
-
-    bool enable_verity = false;
-    const std::string progname = getprogname();
-    if (progname == "enable-verity") {
-        enable_verity = true;
-    } else if (progname == "disable-verity") {
-        enable_verity = false;
-    } else if (optind < argc && (argv[optind] == "1"s || argv[optind] == "0"s)) {
-        // progname "set-verity-state"
-        enable_verity = (argv[optind] == "1"s);
-    } else {
-        print_usage();
-        return 1;
-    }
-
-    if (!kAllowDisableVerity || !is_debuggable()) {
-        errno = EPERM;
-        PLOG(ERROR) << "Cannot disable/enable verity on user build";
-        return 1;
-    }
-
-    if (getuid() != 0) {
-        errno = EACCES;
-        PLOG(ERROR) << "Must be running as root (adb root)";
-        return 1;
-    }
-
-    if (!is_using_avb()) {
-        LOG(ERROR) << "Expected AVB device, VB1.0 is no longer supported";
-        return 1;
-    }
-
-    int exit_code = 0;
-    bool want_reboot = false;
-
-    auto ret = SetVerityState(enable_verity);
-    if (ret.success) {
-        want_reboot |= ret.want_reboot;
-    } else {
-        exit_code = 1;
-    }
-
-    // Disable any overlayfs unconditionally if we want verity enabled.
-    // Enable overlayfs only if verity is successfully disabled or is already disabled.
-    if (enable_verity || ret.success) {
-        // Start a threadpool to service waitForService() callbacks as
-        // fs_mgr_overlayfs_* might call waitForService() to get the image service.
-        android::ProcessState::self()->startThreadPool();
-        want_reboot |= SetupOrTeardownOverlayfs(!enable_verity);
-    }
-
-    if (want_reboot) {
-        if (auto_reboot) {
-            reboot(progname);
-        }
-        printf("Reboot the device for new settings to take effect\n");
-    }
-
-    return exit_code;
-}
diff --git a/init/builtins.cpp b/init/builtins.cpp
index c8cb253..7cb8b11 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -879,6 +879,8 @@
             SetProperty("partition." + partition + ".verified.hash_alg", hashtree_info->algorithm);
             SetProperty("partition." + partition + ".verified.root_digest",
                         hashtree_info->root_digest);
+            SetProperty("partition." + partition + ".verified.check_at_most_once",
+                        hashtree_info->check_at_most_once ? "1" : "0");
         }
     }
 
diff --git a/init/init.cpp b/init/init.cpp
index 4ca351c..540e2ca 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -513,7 +513,7 @@
 }
 
 static Result<void> DoLoadApex(const std::string& apex_name) {
-    if(auto result = ParseApexConfigs(apex_name); !result.ok()) {
+    if (auto result = ParseApexConfigs(apex_name); !result.ok()) {
         return result.error();
     }
 
@@ -747,6 +747,9 @@
     do {
         ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
         if (bytes_read < 0 && errno == EAGAIN) {
+            if (one_off) {
+                return;
+            }
             auto now = std::chrono::steady_clock::now();
             std::chrono::duration<double> waited = now - started;
             if (waited >= kDiagnosticTimeout) {
@@ -772,7 +775,7 @@
             HandleSigtermSignal(siginfo);
             break;
         default:
-            PLOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo;
+            LOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo;
             break;
     }
 }
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 4c27a56..1f4186d 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -567,6 +567,11 @@
 }
 
 static Result<void> UnmountAllApexes() {
+    // don't need to unmount because apexd doesn't use /data in Microdroid
+    if (IsMicrodroid()) {
+        return {};
+    }
+
     const char* args[] = {"/system/bin/apexd", "--unmount-all"};
     int status;
     if (logwrap_fork_execvp(arraysize(args), args, &status, false, LOG_KLOG, true, nullptr) != 0) {
diff --git a/init/security.cpp b/init/security.cpp
index 0e9f6c2..2ecf687 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -116,6 +116,13 @@
     if (SetMmapRndBitsMin(33, 24, false) && (!Has32BitAbi() || SetMmapRndBitsMin(16, 16, true))) {
         return {};
     }
+#elif defined(__riscv)
+    // TODO: sv48 and sv57 were both added to the kernel this year, so we
+    // probably just need some kernel fixes to enable higher ASLR randomization,
+    // but for now 24 is the maximum that the kernel supports.
+    if (SetMmapRndBitsMin(24, 18, false)) {
+        return {};
+    }
 #elif defined(__x86_64__)
     // x86_64 supports 28 - 32 rnd bits, but Android wants to ensure that the
     // theoretical maximum of 32 bits is always supported and used.
diff --git a/init/service.cpp b/init/service.cpp
index 331cd88..85ac2fc 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -16,6 +16,7 @@
 
 #include "service.h"
 
+#include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <linux/securebits.h>
@@ -506,8 +507,7 @@
 }
 
 // Enters namespaces, sets environment variables, writes PID files and runs the service executable.
-void Service::RunService(const std::vector<Descriptor>& descriptors,
-                         InterprocessFifo cgroups_activated) {
+void Service::RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo fifo) {
     if (auto result = EnterNamespaces(namespaces_, name_, mount_namespace_); !result.ok()) {
         LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
     }
@@ -529,11 +529,10 @@
 
     // Wait until the cgroups have been created and until the cgroup controllers have been
     // activated.
-    Result<uint8_t> byte = cgroups_activated.Read();
+    Result<uint8_t> byte = fifo.Read();
     if (!byte.ok()) {
         LOG(ERROR) << name_ << ": failed to read from notification channel: " << byte.error();
     }
-    cgroups_activated.Close();
     if (!*byte) {
         LOG(FATAL) << "Service '" << name_  << "' failed to start due to a fatal error";
         _exit(EXIT_FAILURE);
@@ -557,6 +556,12 @@
     // priority. Aborts on failure.
     SetProcessAttributesAndCaps();
 
+    // If SetProcessAttributes() called setsid(), report this to the parent.
+    if (RequiresConsole(proc_attr_)) {
+        fifo.Write(2);
+    }
+    fifo.Close();
+
     if (!ExpandArgsAndExecv(args_, sigstop_)) {
         PLOG(ERROR) << "cannot execv('" << args_[0]
                     << "'). See the 'Debugging init' section of init's README.md for tips";
@@ -598,11 +603,8 @@
         return {};
     }
 
-    InterprocessFifo cgroups_activated;
-
-    if (Result<void> result = cgroups_activated.Initialize(); !result.ok()) {
-        return result;
-    }
+    InterprocessFifo fifo;
+    OR_RETURN(fifo.Initialize());
 
     if (Result<void> result = CheckConsole(); !result.ok()) {
         return result;
@@ -660,11 +662,8 @@
 
     if (pid == 0) {
         umask(077);
-        cgroups_activated.CloseWriteFd();
-        RunService(descriptors, std::move(cgroups_activated));
+        RunService(descriptors, std::move(fifo));
         _exit(127);
-    } else {
-        cgroups_activated.CloseReadFd();
     }
 
     if (pid < 0) {
@@ -693,7 +692,7 @@
                          limit_percent_ != -1 || !limit_property_.empty();
         errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
         if (errno != 0) {
-            Result<void> result = cgroups_activated.Write(0);
+            Result<void> result = fifo.Write(0);
             if (!result.ok()) {
                 return Error() << "Sending notification failed: " << result.error();
             }
@@ -717,10 +716,35 @@
         LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
     }
 
-    if (Result<void> result = cgroups_activated.Write(1); !result.ok()) {
+    if (Result<void> result = fifo.Write(1); !result.ok()) {
         return Error() << "Sending cgroups activated notification failed: " << result.error();
     }
 
+    // Call setpgid() from the parent process to make sure that this call has
+    // finished before the parent process calls kill(-pgid, ...).
+    if (proc_attr_.console.empty()) {
+        if (setpgid(pid, pid) < 0) {
+            switch (errno) {
+                case EACCES:   // Child has already performed execve().
+                case ESRCH:    // Child process no longer exists.
+                    break;
+                default:
+                    PLOG(ERROR) << "setpgid() from parent failed";
+            }
+        }
+    } else {
+        // The Read() call below will return an error if the child is killed.
+        if (Result<uint8_t> result = fifo.Read(); !result.ok() || *result != 2) {
+            if (!result.ok()) {
+                return Error() << "Waiting for setsid() failed: " << result.error();
+            } else {
+                return Error() << "Waiting for setsid() failed: " << *result << " <> 2";
+            }
+        }
+    }
+
+    fifo.Close();
+
     NotifyStateChange("running");
     reboot_on_failure.Disable();
     return {};
diff --git a/init/service.h b/init/service.h
index b2c9909..2c2778d 100644
--- a/init/service.h
+++ b/init/service.h
@@ -155,7 +155,7 @@
     void ResetFlagsForStart();
     Result<void> CheckConsole();
     void ConfigureMemcg();
-    void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated);
+    void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo fifo);
     void SetMountNamespace();
     static unsigned long next_start_order_;
     static bool is_exec_service_running_;
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index a14969e..9585d05 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -240,11 +240,15 @@
         }
     }
 
-    if (!attr.console.empty()) {
+    if (RequiresConsole(attr)) {
         setsid();
         OpenConsole(attr.console);
     } else {
-        if (setpgid(0, getpid()) == -1) {
+        // Without PID namespaces, this call duplicates the setpgid() call from
+        // the parent process. With PID namespaces, this setpgid() call sets the
+        // process group ID for a child of the init process in the PID
+        // namespace.
+        if (setpgid(0, 0) == -1) {
             return ErrnoError() << "setpgid failed";
         }
         SetupStdio(attr.stdio_to_kmsg);
diff --git a/init/service_utils.h b/init/service_utils.h
index 65a2012..c66f2b4 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -89,6 +89,11 @@
     int priority;
     bool stdio_to_kmsg;
 };
+
+inline bool RequiresConsole(const ProcessAttributes& attr) {
+    return !attr.console.empty();
+}
+
 Result<void> SetProcessAttributes(const ProcessAttributes& attr);
 
 Result<void> WritePidToFiles(std::vector<std::string>* files);
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 6fc64df..f8c501f 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -24,6 +24,7 @@
 #include <unistd.h>
 
 #include <android-base/chrono_utils.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/scopeguard.h>
 #include <android-base/stringprintf.h>
@@ -36,6 +37,7 @@
 
 using android::base::boot_clock;
 using android::base::make_scope_guard;
+using android::base::ReadFileToString;
 using android::base::StringPrintf;
 using android::base::Timer;
 
@@ -51,8 +53,13 @@
         return 0;
     }
 
-    auto pid = siginfo.si_pid;
-    if (pid == 0) return 0;
+    const pid_t pid = siginfo.si_pid;
+    if (pid == 0) {
+        DCHECK_EQ(siginfo.si_signo, 0);
+        return 0;
+    }
+
+    DCHECK_EQ(siginfo.si_signo, SIGCHLD);
 
     // At this point we know we have a zombie pid, so we use this scopeguard to reap the pid
     // whenever the function returns from this point forward.
@@ -132,6 +139,11 @@
     }
     LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with "
               << alive_pids.size() << " of them still running";
+    for (pid_t pid : pids) {
+        std::string status = "(no-such-pid)";
+        ReadFileToString(StringPrintf("/proc/%d/status", pid), &status);
+        LOG(INFO) << "Still running: " << pid << ' ' << status;
+    }
 }
 
 }  // namespace init
diff --git a/init/subcontext.h b/init/subcontext.h
index 8acc032..93ebace 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -36,8 +36,10 @@
 
 class Subcontext {
   public:
-    Subcontext(std::vector<std::string> path_prefixes, std::string context, bool host = false)
-        : path_prefixes_(std::move(path_prefixes)), context_(std::move(context)), pid_(0) {
+    Subcontext(std::vector<std::string> path_prefixes, std::string_view context, bool host = false)
+        : path_prefixes_(std::move(path_prefixes)),
+          context_(context.begin(), context.end()),
+          pid_(0) {
         if (!host) {
             Fork();
         }
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index c88c7ff..3a98fdb 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -27,6 +27,8 @@
     // statsd
     "libstatspull.so",
     "libstatssocket.so",
+    // tethering LLNDK
+    "libcom.android.tethering.connectivity_native.so",
     // adbd
     "libadb_pairing_auth.so",
     "libadb_pairing_connection.so",
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ec760d3..1eec061 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -952,9 +952,10 @@
     mkdir /data_mirror/data_de/null 0700 root root
 
     # Bind mount CE and DE data directory to mirror's default volume directory.
-    # The 'slave' option (MS_SLAVE) is needed to cause the later bind mount of
-    # /data/data onto /data/user/0 to propagate to /data_mirror/data_ce/null/0.
-    mount none /data/user /data_mirror/data_ce/null bind rec slave
+    # Note that because the /data mount has the "shared" propagation type, the
+    # later bind mount of /data/data onto /data/user/0 will automatically
+    # propagate to /data_mirror/data_ce/null/0 as well.
+    mount none /data/user /data_mirror/data_ce/null bind rec
     mount none /data/user_de /data_mirror/data_de/null bind rec
 
     # Create mirror directory for jit profiles
@@ -1037,6 +1038,9 @@
     # Enable FUSE by default
     setprop persist.sys.fuse true
 
+    # Update dm-verity state and set partition.*.verified properties.
+    verity_update_state
+
 # It is recommended to put unnecessary data/ initialization from post-fs-data
 # to start-zygote in device's init.rc to unblock zygote start.
 on zygote-start && property:ro.crypto.state=unencrypted
@@ -1175,9 +1179,6 @@
     # Define default initial receive window size in segments.
     setprop net.tcp_def_init_rwnd 60
 
-    # Update dm-verity state and set partition.*.verified properties.
-    verity_update_state
-
     # Start standard binderized HAL daemons
     class_start hal
 
@@ -1222,7 +1223,7 @@
 # controlling access. On older kernels, the paranoid value is the only means of
 # controlling access. It is normally 3 (allow only root), but the shell user
 # can lower it to 1 (allowing thread-scoped pofiling) via security.perf_harden.
-on property:sys.init.perf_lsm_hooks=1
+on load_bpf_programs && property:sys.init.perf_lsm_hooks=1
     write /proc/sys/kernel/perf_event_paranoid -1
 on property:security.perf_harden=0 && property:sys.init.perf_lsm_hooks=""
     write /proc/sys/kernel/perf_event_paranoid 1
diff --git a/trusty/confirmationui/Android.bp b/trusty/confirmationui/Android.bp
index 29ef3c0..c5c5012 100644
--- a/trusty/confirmationui/Android.bp
+++ b/trusty/confirmationui/Android.bp
@@ -53,6 +53,24 @@
     ],
 }
 
+cc_fuzz {
+    name: "android.hardware.confirmationui-service.trusty_fuzzer",
+    defaults: ["service_fuzzer_defaults"],
+    vendor: true,
+    shared_libs: [
+        "android.hardware.confirmationui-V1-ndk",
+        "android.hardware.confirmationui.not-so-secure-input",
+        "android.hardware.confirmationui-lib.trusty",
+        "liblog",
+    ],
+    srcs: ["fuzzer.cpp"],
+    fuzz_config: {
+        cc: [
+            "nyamagoud@google.com",
+        ],
+    },
+}
+
 cc_library {
     name: "android.hardware.confirmationui-lib.trusty",
     defaults: [
diff --git a/trusty/confirmationui/fuzzer.cpp b/trusty/confirmationui/fuzzer.cpp
new file mode 100644
index 0000000..4446b79
--- /dev/null
+++ b/trusty/confirmationui/fuzzer.cpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2022 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 <TrustyConfirmationuiHal.h>
+#include <android-base/logging.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using aidl::android::hardware::confirmationui::createTrustyConfirmationUI;
+using aidl::android::hardware::confirmationui::IConfirmationUI;
+using android::fuzzService;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+    auto confirmationui = createTrustyConfirmationUI();
+
+    fuzzService(confirmationui->asBinder().get(), FuzzedDataProvider(data, size));
+
+    return 0;
+}
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index adc9fdf..31f0a72 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -109,6 +109,7 @@
         "keymint_use_latest_hal_aidl_ndk_shared",
     ],
     shared_libs: [
+        "android.hardware.security.rkp-V3-ndk",
         "android.hardware.security.secureclock-V1-ndk",
         "android.hardware.security.sharedsecret-V1-ndk",
         "lib_android_keymaster_keymint_utils",
diff --git a/trusty/storage/proxy/rpmb.c b/trusty/storage/proxy/rpmb.c
index f059935..b1b8232 100644
--- a/trusty/storage/proxy/rpmb.c
+++ b/trusty/storage/proxy/rpmb.c
@@ -322,9 +322,9 @@
 }
 
 static int send_mmc_rpmb_req(int mmc_fd, const struct storage_rpmb_send_req* req) {
-    struct {
+    union {
         struct mmc_ioc_multi_cmd multi;
-        struct mmc_ioc_cmd cmd_buf[3];
+        uint8_t raw[sizeof(struct mmc_ioc_multi_cmd) + sizeof(struct mmc_ioc_cmd) * 3];
     } mmc = {};
     struct mmc_ioc_cmd* cmd = mmc.multi.cmds;
     int rc;