Merge "trusty/storage: Add property indicating when fs is ready"
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 7afbbe7..15b5813 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -467,28 +467,36 @@
     arch: {
         arm: {
             src: "seccomp_policy/crash_dump.arm.policy",
+            required: [
+                "crash_dump.policy_other",
+            ],
         },
         arm64: {
             src: "seccomp_policy/crash_dump.arm64.policy",
+            required: [
+                "crash_dump.policy_other",
+            ],
         },
         riscv64: {
             src: "seccomp_policy/crash_dump.riscv64.policy",
         },
         x86: {
             src: "seccomp_policy/crash_dump.x86.policy",
+            required: [
+                "crash_dump.policy_other",
+            ],
         },
         x86_64: {
             src: "seccomp_policy/crash_dump.x86_64.policy",
+            required: [
+                "crash_dump.policy_other",
+            ],
         },
     },
-    required: [
-        "crash_dump.policy_other",
-    ],
 }
 
 
-// NB -- this installs "the other" architecture. (puts 32 bit config in on 64 bit device)
-// or at least that is the intention so that we get both of them populated
+// This installs the "other" architecture (so 32-bit on 64-bit device).
 prebuilt_etc {
     name: "crash_dump.policy_other",
     sub_dir: "seccomp_policy",
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/constants.h b/fastboot/constants.h
index f6fc74e..ad169d1 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -64,6 +64,7 @@
 #define FB_VAR_SLOT_UNBOOTABLE "slot-unbootable"
 #define FB_VAR_IS_LOGICAL "is-logical"
 #define FB_VAR_IS_USERSPACE "is-userspace"
+#define FB_VAR_IS_FORCE_DEBUGGABLE "is-force-debuggable"
 #define FB_VAR_HW_REVISION "hw-revision"
 #define FB_VAR_VARIANT "variant"
 #define FB_VAR_OFF_MODE_CHARGE_STATE "off-mode-charge"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 3799d1f..e929f42 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;
 
@@ -133,6 +131,7 @@
         {FB_VAR_PARTITION_TYPE, {GetPartitionType, GetAllPartitionArgsWithSlot}},
         {FB_VAR_IS_LOGICAL, {GetPartitionIsLogical, GetAllPartitionArgsWithSlot}},
         {FB_VAR_IS_USERSPACE, {GetIsUserspace, nullptr}},
+        {FB_VAR_IS_FORCE_DEBUGGABLE, {GetIsForceDebuggable, nullptr}},
         {FB_VAR_OFF_MODE_CHARGE_STATE, {GetOffModeChargeState, nullptr}},
         {FB_VAR_BATTERY_VOLTAGE, {GetBatteryVoltage, nullptr}},
         {FB_VAR_BATTERY_SOC_OK, {GetBatterySoCOk, nullptr}},
@@ -203,20 +202,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 +266,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..d2a7947 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:
@@ -392,6 +379,12 @@
     return true;
 }
 
+bool GetIsForceDebuggable(FastbootDevice* /* device */, const std::vector<std::string>& /* args */,
+                          std::string* message) {
+    *message = android::base::GetBoolProperty("ro.force.debuggable", false) ? "yes" : "no";
+    return true;
+}
+
 std::vector<std::vector<std::string>> GetAllPartitionArgsWithSlot(FastbootDevice* device) {
     std::vector<std::vector<std::string>> args;
     auto partitions = ListPartitions(device);
diff --git a/fastboot/device/variables.h b/fastboot/device/variables.h
index aa4d9fc..3b2d484 100644
--- a/fastboot/device/variables.h
+++ b/fastboot/device/variables.h
@@ -54,6 +54,8 @@
                            std::string* message);
 bool GetIsUserspace(FastbootDevice* device, const std::vector<std::string>& args,
                     std::string* message);
+bool GetIsForceDebuggable(FastbootDevice* device, const std::vector<std::string>& args,
+                          std::string* message);
 bool GetHardwareRevision(FastbootDevice* device, const std::vector<std::string>& args,
                          std::string* message);
 bool GetVariant(FastbootDevice* device, const std::vector<std::string>& args, std::string* message);
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index eac3ff2..23bc8e8 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -139,19 +139,6 @@
     }
 }
 
-enum RemountStatus {
-    REMOUNT_SUCCESS = 0,
-    UNKNOWN_PARTITION = 5,
-    INVALID_PARTITION,
-    VERITY_PARTITION,
-    BAD_OVERLAY,
-    NO_MOUNTS,
-    REMOUNT_FAILED,
-    BINDER_ERROR,
-    CHECKPOINTING,
-    GSID_ERROR,
-};
-
 static bool ReadFstab(const char* fstab_file, android::fs_mgr::Fstab* fstab) {
     if (fstab_file) {
         return android::fs_mgr::ReadFstabFromFile(fstab_file, fstab);
@@ -172,10 +159,10 @@
     return true;
 }
 
-static RemountStatus VerifyCheckpointing() {
+bool VerifyCheckpointing() {
     if (!android::base::GetBoolProperty("ro.virtual_ab.enabled", false) &&
         !android::base::GetBoolProperty("ro.virtual_ab.retrofit", false)) {
-        return REMOUNT_SUCCESS;
+        return true;
     }
 
     // Virtual A/B devices can use /data as backing storage; make sure we're
@@ -184,13 +171,13 @@
     bool checkpointing = false;
     if (!vold->isCheckpointing(&checkpointing).isOk()) {
         LOG(ERROR) << "Could not determine checkpointing status.";
-        return BINDER_ERROR;
+        return false;
     }
     if (checkpointing) {
         LOG(ERROR) << "Cannot use remount when a checkpoint is in progress.";
-        return CHECKPOINTING;
+        return false;
     }
-    return REMOUNT_SUCCESS;
+    return true;
 }
 
 static bool IsRemountable(Fstab& candidates, const FstabEntry& entry) {
@@ -247,8 +234,7 @@
     return partitions;
 }
 
-static RemountStatus GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv,
-                                    Fstab* partitions) {
+bool GetRemountList(const Fstab& fstab, const std::vector<std::string>& argv, Fstab* partitions) {
     auto candidates = fs_mgr_overlayfs_candidate_list(fstab);
 
     for (const auto& arg : argv) {
@@ -260,7 +246,7 @@
         auto it = FindPartition(fstab, partition);
         if (it == fstab.end()) {
             LOG(ERROR) << "Unknown partition " << arg;
-            return UNKNOWN_PARTITION;
+            return false;
         }
 
         const FstabEntry* entry = &*it;
@@ -275,7 +261,7 @@
         if (!fs_mgr_overlayfs_already_mounted(entry->mount_point) &&
             !IsRemountable(candidates, *entry)) {
             LOG(ERROR) << "Invalid partition " << arg;
-            return INVALID_PARTITION;
+            return false;
         }
         if (GetEntryForMountPoint(partitions, entry->mount_point) != nullptr) {
             continue;
@@ -283,7 +269,7 @@
         partitions->emplace_back(*entry);
     }
 
-    return REMOUNT_SUCCESS;
+    return true;
 }
 
 struct RemountCheckResult {
@@ -294,43 +280,18 @@
     bool remounted_anything = false;
 };
 
-static RemountStatus CheckVerity(const FstabEntry& entry, RemountCheckResult* result) {
-    if (!fs_mgr_is_verity_enabled(entry)) {
-        return REMOUNT_SUCCESS;
-    }
-
-    std::unique_ptr<AvbOps, decltype(&::avb_ops_user_free)> ops(avb_ops_user_new(),
-                                                                &::avb_ops_user_free);
-    if (!ops) {
-        return VERITY_PARTITION;
-    }
-    if (!avb_user_verity_set(ops.get(), fs_mgr_get_slot_suffix().c_str(), false)) {
-        return VERITY_PARTITION;
-    }
-    result->disabled_verity = true;
-    result->reboot_later = true;
-    return REMOUNT_SUCCESS;
-}
-
-static RemountStatus CheckVerityAndOverlayfs(Fstab* partitions, RemountCheckResult* result) {
-    RemountStatus status = REMOUNT_SUCCESS;
+bool CheckOverlayfs(Fstab* partitions, RemountCheckResult* result) {
+    bool ok = true;
     for (auto it = partitions->begin(); it != partitions->end();) {
         auto& entry = *it;
         const auto& mount_point = entry.mount_point;
 
-        if (auto rv = CheckVerity(entry, result); rv != REMOUNT_SUCCESS) {
-            LOG(ERROR) << "Skipping verified partition " << mount_point << " for remount";
-            status = rv;
-            it = partitions->erase(it);
-            continue;
-        }
-
         if (fs_mgr_wants_overlayfs(&entry)) {
             bool want_reboot = false;
             bool force = result->disabled_verity;
             if (!fs_mgr_overlayfs_setup(mount_point.c_str(), &want_reboot, force)) {
                 LOG(ERROR) << "Overlayfs setup for " << mount_point << " failed, skipping";
-                status = BAD_OVERLAY;
+                ok = false;
                 it = partitions->erase(it);
                 continue;
             }
@@ -342,45 +303,48 @@
         }
         it++;
     }
-    return status;
+    return ok;
 }
 
-static RemountStatus EnableDsuIfNeeded() {
+bool EnableDsuIfNeeded() {
     auto gsid = android::gsi::GetGsiService();
     if (!gsid) {
-        return REMOUNT_SUCCESS;
+        return true;
     }
 
     auto dsu_running = false;
     if (auto status = gsid->isGsiRunning(&dsu_running); !status.isOk()) {
         LOG(ERROR) << "Failed to get DSU running state: " << status;
-        return BINDER_ERROR;
+        return false;
     }
     auto dsu_enabled = false;
     if (auto status = gsid->isGsiEnabled(&dsu_enabled); !status.isOk()) {
         LOG(ERROR) << "Failed to get DSU enabled state: " << status;
-        return BINDER_ERROR;
+        return false;
     }
     if (dsu_running && !dsu_enabled) {
         std::string dsu_slot;
         if (auto status = gsid->getActiveDsuSlot(&dsu_slot); !status.isOk()) {
             LOG(ERROR) << "Failed to get active DSU slot: " << status;
-            return BINDER_ERROR;
+            return false;
         }
         LOG(INFO) << "DSU is running but disabled, enable DSU so that we stay within the "
                      "DSU guest system after reboot";
         int error = 0;
-        if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error);
-            !status.isOk() || error != android::gsi::IGsiService::INSTALL_OK) {
-            LOG(ERROR) << "Failed to enable DSU: " << status << ", error code: " << error;
-            return !status.isOk() ? BINDER_ERROR : GSID_ERROR;
+        if (auto status = gsid->enableGsi(/* oneShot = */ true, dsu_slot, &error); !status.isOk()) {
+            LOG(ERROR) << "Failed to enable DSU: " << status;
+            return false;
+        }
+        if (error != android::gsi::IGsiService::INSTALL_OK) {
+            LOG(ERROR) << "Failed to enable DSU, error code: " << error;
+            return false;
         }
         LOG(INFO) << "Successfully enabled DSU (one-shot mode)";
     }
-    return REMOUNT_SUCCESS;
+    return true;
 }
 
-static RemountStatus RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
+bool RemountPartition(Fstab& fstab, Fstab& mounts, FstabEntry& entry) {
     // unlock the r/o key for the mount point device
     if (entry.fs_mgr_flags.logical) {
         fs_mgr_update_logical_partition(&entry);
@@ -407,7 +371,7 @@
     }
     if (!found) {
         PLOG(INFO) << "skip unmounted partition dev:" << blk_device << " mnt:" << mount_point;
-        return REMOUNT_SUCCESS;
+        return true;
     }
     if (blk_device == "/dev/root") {
         auto from_fstab = GetEntryForMountPoint(&fstab, mount_point);
@@ -422,20 +386,19 @@
     }
 
     // Now remount!
-    if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
-                nullptr) == 0) {
-        return REMOUNT_SUCCESS;
-    }
-    if ((errno == EINVAL) && (mount_point != entry.mount_point)) {
-        mount_point = entry.mount_point;
-        if (::mount(blk_device.c_str(), mount_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
+    for (const auto& mnt_point : {mount_point, entry.mount_point}) {
+        if (::mount(blk_device.c_str(), mnt_point.c_str(), entry.fs_type.c_str(), MS_REMOUNT,
                     nullptr) == 0) {
-            return REMOUNT_SUCCESS;
+            LOG(INFO) << "Remounted " << mnt_point << " as RW";
+            return true;
+        }
+        if (errno != EINVAL || mount_point == entry.mount_point) {
+            break;
         }
     }
 
     PLOG(ERROR) << "failed to remount partition dev:" << blk_device << " mnt:" << mount_point;
-    return REMOUNT_FAILED;
+    return false;
 }
 
 struct SetVerityStateResult {
@@ -445,30 +408,33 @@
 
 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 {};
     }
-
+    bool verification_enabled = false;
+    if (!avb_user_verification_get(ops.get(), ab_suffix.c_str(), &verification_enabled)) {
+        LOG(ERROR) << "Error getting verification state";
+        return {};
+    }
+    if (!verification_enabled) {
+        LOG(WARNING) << "AVB verification is disabled, "
+                     << (enable_verity ? "enabling" : "disabling")
+                     << " verity state may have no effect";
+        return {.success = true, .want_reboot = false};
+    }
+    const auto verity_mode = android::base::GetProperty("ro.boot.veritymode", "");
+    const bool was_enabled = (verity_mode != "disabled");
+    if ((was_enabled && enable_verity) || (!was_enabled && !enable_verity)) {
+        LOG(INFO) << "Verity is already " << (enable_verity ? "enabled" : "disabled");
+        return {.success = true, .want_reboot = false};
+    }
     LOG(INFO) << "Successfully " << (enable_verity ? "enabled" : "disabled") << " verity";
     return {.success = true, .want_reboot = true};
 }
@@ -500,25 +466,48 @@
     return want_reboot;
 }
 
-static int do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
-                      RemountCheckResult* check_result) {
+bool do_remount(Fstab& fstab, const std::vector<std::string>& partition_args,
+                RemountCheckResult* check_result) {
     Fstab partitions;
     if (partition_args.empty()) {
         partitions = GetAllRemountablePartitions(fstab);
     } else {
-        if (auto rv = GetRemountList(fstab, partition_args, &partitions); rv != REMOUNT_SUCCESS) {
-            return rv;
+        if (!GetRemountList(fstab, partition_args, &partitions)) {
+            return false;
         }
     }
 
-    // Check verity and optionally setup overlayfs backing.
-    auto retval = CheckVerityAndOverlayfs(&partitions, check_result);
+    // Disable verity.
+    auto verity_result = SetVerityState(false /* enable_verity */);
+
+    // Treat error as fatal and suggest reboot only if verity is enabled.
+    // TODO(b/260041315): We check the device mapper for any "<partition>-verity" device present
+    // instead of checking ro.boot.veritymode because emulator has incorrect property value.
+    bool must_disable_verity = false;
+    for (const auto& partition : partitions) {
+        if (fs_mgr_is_verity_enabled(partition)) {
+            must_disable_verity = true;
+            break;
+        }
+    }
+    if (must_disable_verity) {
+        if (!verity_result.success) {
+            return false;
+        }
+        if (verity_result.want_reboot) {
+            check_result->reboot_later = true;
+            check_result->disabled_verity = true;
+        }
+    }
+
+    // Optionally setup overlayfs backing.
+    bool ok = CheckOverlayfs(&partitions, check_result);
 
     if (partitions.empty() || check_result->disabled_verity) {
         if (partitions.empty()) {
             LOG(WARNING) << "No remountable partitions were found.";
         }
-        return retval;
+        return ok;
     }
 
     // Mount overlayfs.
@@ -531,18 +520,18 @@
     android::fs_mgr::Fstab mounts;
     if (!android::fs_mgr::ReadFstabFromFile("/proc/mounts", &mounts) || mounts.empty()) {
         PLOG(ERROR) << "Failed to read /proc/mounts";
-        return NO_MOUNTS;
+        return false;
     }
 
     // Remount selected partitions.
     for (auto& entry : partitions) {
-        if (auto rv = RemountPartition(fstab, mounts, entry); rv != REMOUNT_SUCCESS) {
-            retval = rv;
-        } else {
+        if (RemountPartition(fstab, mounts, entry)) {
             check_result->remounted_anything = true;
+        } else {
+            ok = false;
         }
     }
-    return retval;
+    return ok;
 }
 
 }  // namespace
@@ -552,7 +541,7 @@
     // are discarded.
     if (argc > 0 && android::base::Basename(argv[0]) == "clean_scratch_files"s) {
         android::fs_mgr::CleanupOldScratchFiles();
-        return 0;
+        return EXIT_SUCCESS;
     }
 
     android::base::InitLogging(argv, MyLogger(false /* verbose */));
@@ -573,7 +562,7 @@
         switch (opt) {
             case 'h':
                 usage();
-                return 0;
+                return EXIT_SUCCESS;
             case 'R':
                 auto_reboot = true;
                 break;
@@ -581,7 +570,7 @@
                 if (fstab_file) {
                     LOG(ERROR) << "Cannot supply two fstabs: -T " << fstab_file << " -T " << optarg;
                     usage();
-                    return 1;
+                    return EXIT_FAILURE;
                 }
                 fstab_file = optarg;
                 break;
@@ -591,7 +580,7 @@
             default:
                 LOG(ERROR) << "Bad argument -" << char(opt);
                 usage();
-                return 1;
+                return EXIT_FAILURE;
         }
     }
 
@@ -611,7 +600,7 @@
             enable_verity = (argv[optind] == "1"s);
         } else {
             usage();
-            return 1;
+            return EXIT_FAILURE;
         }
     } else {
         remount = true;
@@ -623,7 +612,7 @@
     // Make sure we are root.
     if (::getuid() != 0) {
         LOG(ERROR) << "Not running as root. Try \"adb root\" first.";
-        return 1;
+        return EXIT_FAILURE;
     }
 
     // If somehow this executable is delivered on a "user" build, it can
@@ -631,12 +620,12 @@
     // letting if fall through and provide a lot of confusing failure messages.
     if (!ALLOW_ADBD_DISABLE_VERITY || !android::base::GetBoolProperty("ro.debuggable", false)) {
         LOG(ERROR) << "Device must be userdebug build";
-        return 1;
+        return EXIT_FAILURE;
     }
 
-    if (android::base::GetProperty("ro.boot.vbmeta.device_state", "") == "locked") {
+    if (android::base::GetProperty("ro.boot.verifiedbootstate", "") != "orange") {
         LOG(ERROR) << "Device must be bootloader unlocked";
-        return 1;
+        return EXIT_FAILURE;
     }
 
     // Start a threadpool to service waitForService() callbacks as
@@ -644,14 +633,6 @@
     android::ProcessState::self()->startThreadPool();
 
     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;
-        }
-
         auto ret = SetVerityState(enable_verity);
 
         // Disable any overlayfs unconditionally if we want verity enabled.
@@ -666,23 +647,23 @@
             }
             std::cout << "Reboot the device for new settings to take effect" << std::endl;
         }
-        return ret.success ? 0 : 1;
+        return ret.success ? EXIT_SUCCESS : EXIT_FAILURE;
     }
 
     // Make sure checkpointing is disabled if necessary.
-    if (auto rv = VerifyCheckpointing(); rv != REMOUNT_SUCCESS) {
-        return rv;
+    if (!VerifyCheckpointing()) {
+        return EXIT_FAILURE;
     }
 
     // Read the selected fstab.
     Fstab fstab;
     if (!ReadFstab(fstab_file, &fstab) || fstab.empty()) {
         PLOG(ERROR) << "Failed to read fstab";
-        return 1;
+        return EXIT_FAILURE;
     }
 
     RemountCheckResult check_result;
-    int result = do_remount(fstab, partition_args, &check_result);
+    bool remount_success = do_remount(fstab, partition_args, &check_result);
 
     if (check_result.disabled_verity && check_result.setup_overlayfs) {
         LOG(INFO) << "Verity disabled; overlayfs enabled.";
@@ -691,10 +672,10 @@
     } else if (check_result.setup_overlayfs) {
         LOG(INFO) << "Overlayfs enabled.";
     }
-    if (result == REMOUNT_SUCCESS) {
-        LOG(INFO) << "remount succeeded";
-    } else {
-        LOG(ERROR) << "remount failed";
+    if (remount_success && check_result.remounted_anything) {
+        LOG(INFO) << "Remount succeeded";
+    } else if (!remount_success) {
+        LOG(ERROR) << "Remount failed";
     }
     if (check_result.reboot_later) {
         if (auto_reboot) {
@@ -702,15 +683,15 @@
             // running a DSU guest and (3) DSU is disabled, then enable DSU so that the
             // next reboot would not take us back to the host system but stay within
             // the guest system.
-            if (auto rv = EnableDsuIfNeeded(); rv != REMOUNT_SUCCESS) {
+            if (!EnableDsuIfNeeded()) {
                 LOG(ERROR) << "Unable to automatically enable DSU";
-                return rv;
+                return EXIT_FAILURE;
             }
             reboot("remount");
         } else {
             LOG(INFO) << "Now reboot your device for settings to take effect";
         }
-        return REMOUNT_SUCCESS;
+        return EXIT_SUCCESS;
     }
-    return result;
+    return remount_success ? EXIT_SUCCESS : EXIT_FAILURE;
 }
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 68f8152..c87e564 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -1422,9 +1422,12 @@
 LOG RUN "flash vendor, and confirm vendor override disappears"
 
 is_bootloader_fastboot=true
-# cuttlefish?
-[[ "$(get_property ro.product.vendor.device)" == vsoc_* ]] &&
-  is_bootloader_fastboot=false
+# virtual device?
+case "$(get_property ro.product.vendor.device)" in
+  vsoc_* | emulator_* | emulator64_*)
+    is_bootloader_fastboot=false
+    ;;
+esac
 is_userspace_fastboot=false
 
 if ! ${is_bootloader_fastboot}; then
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 5c1e9ef..7bad6fd 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -193,6 +193,36 @@
     EXPECT_TRUE(service->is_override());
 }
 
+TEST(init, StartConsole) {
+    // Two different failures have been observed for this test: (1) No
+    // permission to open /dev/console and (2) getsid() != pid. Skip this test
+    // until these failures have been root-caused and fixed.
+    GTEST_SKIP() << "This test needs to be improved";
+    std::string init_script = R"init(
+service console /system/bin/sh
+    class core
+    console console
+    disabled
+    user root
+    group root shell log readproc
+    seclabel u:r:su:s0
+    setenv HOSTNAME console
+)init";
+
+    ActionManager action_manager;
+    ServiceList service_list;
+    TestInitText(init_script, BuiltinFunctionMap(), {}, &action_manager, &service_list);
+    ASSERT_EQ(std::distance(service_list.begin(), service_list.end()), 1);
+
+    auto service = service_list.begin()->get();
+    ASSERT_NE(service, nullptr);
+    ASSERT_RESULT_OK(service->Start());
+    const pid_t pid = service->pid();
+    ASSERT_GT(pid, 0);
+    EXPECT_EQ(getsid(pid), pid);
+    service->Stop();
+}
+
 static std::string GetSecurityContext() {
     char* ctx;
     if (getcon(&ctx) == -1) {
diff --git a/init/service.cpp b/init/service.cpp
index c260c07..ccc7191 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>
@@ -226,7 +227,7 @@
     }
 }
 
-void Service::SetProcessAttributesAndCaps() {
+void Service::SetProcessAttributesAndCaps(InterprocessFifo setsid_finished) {
     // Keep capabilites on uid change.
     if (capabilities_ && proc_attr_.uid) {
         // If Android is running in a container, some securebits might already
@@ -241,7 +242,7 @@
         }
     }
 
-    if (auto result = SetProcessAttributes(proc_attr_); !result.ok()) {
+    if (auto result = SetProcessAttributes(proc_attr_, std::move(setsid_finished)); !result.ok()) {
         LOG(FATAL) << "cannot set attribute for " << name_ << ": " << result.error();
     }
 
@@ -506,7 +507,8 @@
 }
 
 // Enters namespaces, sets environment variables, writes PID files and runs the service executable.
-void Service::RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo fifo) {
+void Service::RunService(const std::vector<Descriptor>& descriptors,
+                         InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished) {
     if (auto result = EnterNamespaces(namespaces_, name_, mount_namespace_); !result.ok()) {
         LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
     }
@@ -528,12 +530,12 @@
 
     // Wait until the cgroups have been created and until the cgroup controllers have been
     // activated.
-    Result<uint8_t> byte = fifo.Read();
+    Result<uint8_t> byte = cgroups_activated.Read();
     if (!byte.ok()) {
         LOG(ERROR) << name_ << ": failed to read from notification channel: " << byte.error();
     }
-    fifo.Close();
-    if (!*byte) {
+    cgroups_activated.Close();
+    if (*byte != kCgroupsActivated) {
         LOG(FATAL) << "Service '" << name_  << "' failed to start due to a fatal error";
         _exit(EXIT_FAILURE);
     }
@@ -554,7 +556,7 @@
 
     // As requested, set our gid, supplemental gids, uid, context, and
     // priority. Aborts on failure.
-    SetProcessAttributesAndCaps();
+    SetProcessAttributesAndCaps(std::move(setsid_finished));
 
     if (!ExpandArgsAndExecv(args_, sigstop_)) {
         PLOG(ERROR) << "cannot execv('" << args_[0]
@@ -597,8 +599,14 @@
         return {};
     }
 
-    InterprocessFifo fifo;
-    OR_RETURN(fifo.Initialize());
+    // cgroups_activated is used for communication from the parent to the child
+    // while setsid_finished is used for communication from the child process to
+    // the parent process. These two communication channels are separate because
+    // combining these into a single communication channel would introduce a
+    // race between the Write() calls by the parent and by the child.
+    InterprocessFifo cgroups_activated, setsid_finished;
+    OR_RETURN(cgroups_activated.Initialize());
+    OR_RETURN(setsid_finished.Initialize());
 
     if (Result<void> result = CheckConsole(); !result.ok()) {
         return result;
@@ -656,11 +664,13 @@
 
     if (pid == 0) {
         umask(077);
-        fifo.CloseWriteFd();
-        RunService(descriptors, std::move(fifo));
+        cgroups_activated.CloseWriteFd();
+        setsid_finished.CloseReadFd();
+        RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
         _exit(127);
     } else {
-        fifo.CloseReadFd();
+        cgroups_activated.CloseReadFd();
+        setsid_finished.CloseWriteFd();
     }
 
     if (pid < 0) {
@@ -689,7 +699,7 @@
                          limit_percent_ != -1 || !limit_property_.empty();
         errno = -createProcessGroup(proc_attr_.uid, pid_, use_memcg);
         if (errno != 0) {
-            Result<void> result = fifo.Write(0);
+            Result<void> result = cgroups_activated.Write(kActivatingCgroupsFailed);
             if (!result.ok()) {
                 return Error() << "Sending notification failed: " << result.error();
             }
@@ -713,10 +723,39 @@
         LmkdRegister(name_, proc_attr_.uid, pid_, oom_score_adjust_);
     }
 
-    if (Result<void> result = fifo.Write(1); !result.ok()) {
+    if (Result<void> result = cgroups_activated.Write(kCgroupsActivated); !result.ok()) {
         return Error() << "Sending cgroups activated notification failed: " << result.error();
     }
 
+    cgroups_activated.Close();
+
+    // Call setpgid() from the parent process to make sure that this call has
+    // finished before the parent process calls kill(-pgid, ...).
+    if (!RequiresConsole(proc_attr_)) {
+        if (setpgid(pid, pid) < 0) {
+            switch (errno) {
+                case EACCES:  // Child has already performed setpgid() followed by 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 = setsid_finished.Read();
+            !result.ok() || *result != kSetSidFinished) {
+            if (!result.ok()) {
+                return Error() << "Waiting for setsid() failed: " << result.error();
+            } else {
+                return Error() << "Waiting for setsid() failed: " << static_cast<uint32_t>(*result)
+                               << " <> " << static_cast<uint32_t>(kSetSidFinished);
+            }
+        }
+    }
+
+    setsid_finished.Close();
+
     NotifyStateChange("running");
     reboot_on_failure.Disable();
     return {};
diff --git a/init/service.h b/init/service.h
index b2c9909..54bf638 100644
--- a/init/service.h
+++ b/init/service.h
@@ -143,7 +143,7 @@
             flags_ &= ~SVC_ONESHOT;
         }
     }
-    Subcontext* subcontext() const { return subcontext_; }
+    const Subcontext* subcontext() const { return subcontext_; }
     const std::string& filename() const { return filename_; }
     void set_filename(const std::string& name) { filename_ = name; }
 
@@ -151,18 +151,19 @@
     void NotifyStateChange(const std::string& new_state) const;
     void StopOrReset(int how);
     void KillProcessGroup(int signal, bool report_oneshot = false);
-    void SetProcessAttributesAndCaps();
+    void SetProcessAttributesAndCaps(InterprocessFifo setsid_finished);
     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 cgroups_activated,
+                    InterprocessFifo setsid_finished);
     void SetMountNamespace();
     static unsigned long next_start_order_;
     static bool is_exec_service_running_;
     static std::chrono::time_point<std::chrono::steady_clock> exec_service_started_;
     static pid_t exec_service_pid_;
 
-    std::string name_;
+    const std::string name_;
     std::set<std::string> classnames_;
 
     unsigned flags_;
@@ -186,7 +187,7 @@
     // Environment variables that only get applied to the next run.
     std::vector<std::pair<std::string, std::string>> once_environment_vars_;
 
-    Subcontext* subcontext_;
+    const Subcontext* const subcontext_;
     Action onrestart_;  // Commands to execute on restart.
 
     std::vector<std::string> writepid_files_;
@@ -220,7 +221,7 @@
 
     bool updatable_ = false;
 
-    std::vector<std::string> args_;
+    const std::vector<std::string> args_;
 
     std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
 
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index a14969e..15bf963 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -232,7 +232,7 @@
     return {};
 }
 
-Result<void> SetProcessAttributes(const ProcessAttributes& attr) {
+Result<void> SetProcessAttributes(const ProcessAttributes& attr, InterprocessFifo setsid_finished) {
     if (attr.ioprio_class != IoSchedClass_NONE) {
         if (android_set_ioprio(getpid(), attr.ioprio_class, attr.ioprio_pri)) {
             PLOG(ERROR) << "failed to set pid " << getpid() << " ioprio=" << attr.ioprio_class
@@ -240,11 +240,17 @@
         }
     }
 
-    if (!attr.console.empty()) {
+    if (RequiresConsole(attr)) {
         setsid();
+        setsid_finished.Write(kSetSidFinished);
+        setsid_finished.Close();
         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..d4143aa 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -26,12 +26,20 @@
 #include <android-base/unique_fd.h>
 #include <cutils/iosched_policy.h>
 
+#include "interprocess_fifo.h"
 #include "mount_namespace.h"
 #include "result.h"
 
 namespace android {
 namespace init {
 
+// Constants used by Service::Start() for communication between parent and child.
+enum ServiceCode : uint8_t {
+    kActivatingCgroupsFailed,
+    kCgroupsActivated,
+    kSetSidFinished,
+};
+
 class Descriptor {
   public:
     Descriptor(const std::string& name, android::base::unique_fd fd)
@@ -89,7 +97,12 @@
     int priority;
     bool stdio_to_kmsg;
 };
-Result<void> SetProcessAttributes(const ProcessAttributes& attr);
+
+inline bool RequiresConsole(const ProcessAttributes& attr) {
+    return !attr.console.empty();
+}
+
+Result<void> SetProcessAttributes(const ProcessAttributes& attr, InterprocessFifo setsid_finished);
 
 Result<void> WritePidToFiles(std::vector<std::string>* files);
 
diff --git a/libsparse/append2simg.cpp b/libsparse/append2simg.cpp
index 99f4339..d3a43a8 100644
--- a/libsparse/append2simg.cpp
+++ b/libsparse/append2simg.cpp
@@ -64,60 +64,60 @@
     input_path = argv[2];
   } else {
     usage();
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   ret = asprintf(&tmp_path, "%s.append2simg", output_path);
   if (ret < 0) {
     fprintf(stderr, "Couldn't allocate filename\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   output = open(output_path, O_RDWR | O_BINARY);
   if (output < 0) {
     fprintf(stderr, "Couldn't open output file (%s)\n", strerror(errno));
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   sparse_output = sparse_file_import_auto(output, false, true);
   if (!sparse_output) {
     fprintf(stderr, "Couldn't import output file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   input = open(input_path, O_RDONLY | O_BINARY);
   if (input < 0) {
     fprintf(stderr, "Couldn't open input file (%s)\n", strerror(errno));
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   input_len = lseek64(input, 0, SEEK_END);
   if (input_len < 0) {
     fprintf(stderr, "Couldn't get input file length (%s)\n", strerror(errno));
-    exit(-1);
+    exit(EXIT_FAILURE);
   } else if (input_len % sparse_output->block_size) {
     fprintf(stderr, "Input file is not a multiple of the output file's block size");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
   lseek64(input, 0, SEEK_SET);
 
   output_block = sparse_output->len / sparse_output->block_size;
   if (sparse_file_add_fd(sparse_output, input, 0, input_len, output_block) < 0) {
     fprintf(stderr, "Couldn't add input file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
   sparse_output->len += input_len;
 
   tmp_fd = open(tmp_path, O_WRONLY | O_CREAT | O_BINARY, 0664);
   if (tmp_fd < 0) {
     fprintf(stderr, "Couldn't open temporary file (%s)\n", strerror(errno));
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   lseek64(output, 0, SEEK_SET);
   if (sparse_file_write(sparse_output, tmp_fd, false, true, false) < 0) {
     fprintf(stderr, "Failed to write sparse file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   sparse_file_destroy(sparse_output);
@@ -128,10 +128,10 @@
   ret = rename(tmp_path, output_path);
   if (ret < 0) {
     fprintf(stderr, "Failed to rename temporary file (%s)\n", strerror(errno));
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   free(tmp_path);
 
-  exit(0);
+  exit(EXIT_SUCCESS);
 }
diff --git a/libsparse/img2simg.cpp b/libsparse/img2simg.cpp
index 51580f7..c390506 100644
--- a/libsparse/img2simg.cpp
+++ b/libsparse/img2simg.cpp
@@ -61,14 +61,14 @@
         break;
       default:
         usage();
-        exit(-1);
+        exit(EXIT_FAILURE);
     }
   }
 
   extra = argc - optind;
   if (extra < 2 || extra > 3) {
     usage();
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   if (extra == 3) {
@@ -77,7 +77,7 @@
 
   if (block_size < 1024 || block_size % 4 != 0) {
     usage();
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   arg_in = argv[optind];
@@ -87,7 +87,7 @@
     in = open(arg_in, O_RDONLY | O_BINARY);
     if (in < 0) {
       fprintf(stderr, "Cannot open input file %s\n", arg_in);
-      exit(-1);
+      exit(EXIT_FAILURE);
     }
   }
 
@@ -98,7 +98,7 @@
     out = open(arg_out, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
     if (out < 0) {
       fprintf(stderr, "Cannot open output file %s\n", arg_out);
-      exit(-1);
+      exit(EXIT_FAILURE);
     }
   }
 
@@ -108,24 +108,24 @@
   s = sparse_file_new(block_size, len);
   if (!s) {
     fprintf(stderr, "Failed to create sparse file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   sparse_file_verbose(s);
   ret = sparse_file_read(s, in, mode, false);
   if (ret) {
     fprintf(stderr, "Failed to read file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   ret = sparse_file_write(s, out, false, true, false);
   if (ret) {
     fprintf(stderr, "Failed to write sparse file\n");
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   close(in);
   close(out);
 
-  exit(0);
+  exit(EXIT_SUCCESS);
 }
diff --git a/libsparse/simg2img.cpp b/libsparse/simg2img.cpp
index 8ba5f69..2301a83 100644
--- a/libsparse/simg2img.cpp
+++ b/libsparse/simg2img.cpp
@@ -41,13 +41,13 @@
 
   if (argc < 3) {
     usage();
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   out = open(argv[argc - 1], O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
   if (out < 0) {
     fprintf(stderr, "Cannot open output file %s\n", argv[argc - 1]);
-    exit(-1);
+    exit(EXIT_FAILURE);
   }
 
   for (i = 1; i < argc - 1; i++) {
@@ -57,14 +57,14 @@
       in = open(argv[i], O_RDONLY | O_BINARY);
       if (in < 0) {
         fprintf(stderr, "Cannot open input file %s\n", argv[i]);
-        exit(-1);
+        exit(EXIT_FAILURE);
       }
     }
 
     s = sparse_file_import(in, true, false);
     if (!s) {
       fprintf(stderr, "Failed to read sparse file\n");
-      exit(-1);
+      exit(EXIT_FAILURE);
     }
 
     if (lseek(out, 0, SEEK_SET) == -1) {
@@ -74,7 +74,7 @@
 
     if (sparse_file_write(s, out, false, false, false) < 0) {
       fprintf(stderr, "Cannot write output file\n");
-      exit(-1);
+      exit(EXIT_FAILURE);
     }
     sparse_file_destroy(s);
     close(in);
@@ -82,5 +82,5 @@
 
   close(out);
 
-  exit(0);
+  exit(EXIT_SUCCESS);
 }
diff --git a/libsparse/simg2simg.cpp b/libsparse/simg2simg.cpp
deleted file mode 100644
index a2c296e..0000000
--- a/libsparse/simg2simg.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2012 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.
- */
-
-#define _FILE_OFFSET_BITS 64
-#define _LARGEFILE64_SOURCE 1
-
-#include <fcntl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <sparse/sparse.h>
-
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-void usage() {
-  fprintf(stderr, "Usage: simg2simg <sparse image file> <sparse_image_file> <max_size>\n");
-}
-
-int main(int argc, char* argv[]) {
-  int in;
-  int out;
-  int i;
-  int ret;
-  struct sparse_file* s;
-  int64_t max_size;
-  struct sparse_file** out_s;
-  int files;
-  char filename[4096];
-
-  if (argc != 4) {
-    usage();
-    exit(-1);
-  }
-
-  max_size = atoll(argv[3]);
-
-  in = open(argv[1], O_RDONLY | O_BINARY);
-  if (in < 0) {
-    fprintf(stderr, "Cannot open input file %s\n", argv[1]);
-    exit(-1);
-  }
-
-  s = sparse_file_import(in, true, false);
-  if (!s) {
-    fprintf(stderr, "Failed to import sparse file\n");
-    exit(-1);
-  }
-
-  files = sparse_file_resparse(s, max_size, nullptr, 0);
-  if (files < 0) {
-    fprintf(stderr, "Failed to resparse\n");
-    exit(-1);
-  }
-
-  out_s = calloc(sizeof(struct sparse_file*), files);
-  if (!out_s) {
-    fprintf(stderr, "Failed to allocate sparse file array\n");
-    exit(-1);
-  }
-
-  files = sparse_file_resparse(s, max_size, out_s, files);
-  if (files < 0) {
-    fprintf(stderr, "Failed to resparse\n");
-    exit(-1);
-  }
-
-  for (i = 0; i < files; i++) {
-    ret = snprintf(filename, sizeof(filename), "%s.%d", argv[2], i);
-    if (ret >= (int)sizeof(filename)) {
-      fprintf(stderr, "Filename too long\n");
-      exit(-1);
-    }
-
-    out = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0664);
-    if (out < 0) {
-      fprintf(stderr, "Cannot open output file %s\n", argv[2]);
-      exit(-1);
-    }
-
-    ret = sparse_file_write(out_s[i], out, false, true, false);
-    if (ret) {
-      fprintf(stderr, "Failed to write sparse file\n");
-      exit(-1);
-    }
-    close(out);
-  }
-
-  close(in);
-
-  exit(0);
-}
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index f3acd6f..5e3fa7d 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -210,6 +210,7 @@
 
 #include <atomic>
 #include <functional>
+#include <memory>
 #include <type_traits>  // for common_type.
 
 #include <stdint.h>
diff --git a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
index 77cbdd4..a484441 100644
--- a/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
+++ b/property_service/libpropertyinfoserializer/property_info_serializer_test.cpp
@@ -399,7 +399,6 @@
       {"dalvik.vm.lockprof.threshold", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.stack-trace-file", "u:object_r:dalvik_prop:s0"},
       {"dalvik.vm.usejit", "u:object_r:dalvik_prop:s0"},
-      {"dalvik.vm.usejitprofiles", "u:object_r:dalvik_prop:s0"},
       {"debug.atrace.tags.enableflags", "u:object_r:debug_prop:s0"},
       {"debug.force_rtl", "u:object_r:debug_prop:s0"},
       {"dev.bootcomplete", "u:object_r:system_prop:s0"},
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 1eec061..f05c0bf 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -535,10 +535,6 @@
     # /data, which in turn can only be loaded when system properties are present.
     trigger post-fs-data
 
-    # APEXes are ready to use. apex-ready is a public trigger similar to apexd.status=ready which
-    # is a system-private property.
-    trigger apex-ready
-
     # Should be before netd, but after apex, properties and logging is available.
     trigger load_bpf_programs
 
@@ -1315,7 +1311,6 @@
 on userspace-reboot-resume
   trigger userspace-reboot-fs-remount
   trigger post-fs-data
-  trigger apex-ready
   trigger zygote-start
   trigger early-boot
   trigger boot
diff --git a/trusty/gatekeeper/TEST_MAPPING b/trusty/gatekeeper/TEST_MAPPING
new file mode 100644
index 0000000..da6c769
--- /dev/null
+++ b/trusty/gatekeeper/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+      {
+        "name": "VtsHalGatekeeperTargetTest"
+      }
+  ]
+}
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/keymaster/TEST_MAPPING b/trusty/keymaster/TEST_MAPPING
new file mode 100644
index 0000000..ae48327
--- /dev/null
+++ b/trusty/keymaster/TEST_MAPPING
@@ -0,0 +1,13 @@
+{
+  "presubmit": [
+      {
+        "name": "RemoteProvisionerUnitTests"
+      },
+      {
+        "name": "VtsAidlKeyMintTargetTest"
+      },
+      {
+        "name": "VtsHalRemotelyProvisionedComponentTargetTest"
+      }
+  ]
+}
diff --git a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
index c6800cd..710be3e 100644
--- a/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
+++ b/trusty/keymaster/keymint/TrustyRemotelyProvisionedComponentDevice.cpp
@@ -85,6 +85,7 @@
     info->rpcAuthorName = std::move(response.rpcAuthorName);
     info->supportedEekCurve = response.supportedEekCurve;
     info->uniqueId = std::move(response.uniqueId);
+    info->supportedNumKeysInCsr = response.supportedNumKeysInCsr;
     return ScopedAStatus::ok();
 }