Merge "libsnapshot: Simplify wipe handling in recovery." into main
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index baddf65..08619b9 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -18,6 +18,7 @@
 #include <dlfcn.h>
 #include <err.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <linux/prctl.h>
 #include <malloc.h>
 #include <pthread.h>
@@ -69,7 +70,6 @@
 #include "crash_test.h"
 #include "debuggerd/handler.h"
 #include "gtest/gtest.h"
-#include "libdebuggerd/utility.h"
 #include "protocol.h"
 #include "tombstoned/tombstoned.h"
 #include "util.h"
@@ -86,6 +86,7 @@
 #define ARCH_SUFFIX ""
 #endif
 
+constexpr size_t kTagGranuleSize = 16;
 constexpr char kWaitForDebuggerKey[] = "debug.debuggerd.wait_for_debugger";
 
 #define TIMEOUT(seconds, expr)                                     \
diff --git a/debuggerd/tombstoned/tombstoned.cpp b/debuggerd/tombstoned/tombstoned.cpp
index fa67d46..2c72379 100644
--- a/debuggerd/tombstoned/tombstoned.cpp
+++ b/debuggerd/tombstoned/tombstoned.cpp
@@ -158,7 +158,7 @@
       }
     }
 
-    return std::move(result);
+    return result;
   }
 
   std::optional<CrashOutput> get_output(DebuggerdDumpType dump_type) {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 3e70f79..76578dd 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -1433,16 +1433,16 @@
 // When multiple fstab records share the same mount_point, it will try to mount each
 // one in turn, and ignore any duplicates after a first successful mount.
 // Returns -1 on error, and  FS_MGR_MNTALL_* otherwise.
-MountAllResult fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
+int fs_mgr_mount_all(Fstab* fstab, int mount_mode) {
     int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
     int error_count = 0;
     CheckpointManager checkpoint_manager;
     AvbUniquePtr avb_handle(nullptr);
     bool wiped = false;
-
     bool userdata_mounted = false;
+
     if (fstab->empty()) {
-        return {FS_MGR_MNTALL_FAIL, userdata_mounted};
+        return FS_MGR_MNTALL_FAIL;
     }
 
     bool scratch_can_be_mounted = true;
@@ -1521,7 +1521,7 @@
                 if (!avb_handle) {
                     LERROR << "Failed to open AvbHandle";
                     set_type_property(encryptable);
-                    return {FS_MGR_MNTALL_FAIL, userdata_mounted};
+                    return FS_MGR_MNTALL_FAIL;
                 }
             }
             if (avb_handle->SetUpAvbHashtree(&current_entry, true /* wait_for_verity_dev */) ==
@@ -1557,7 +1557,7 @@
 
             if (status == FS_MGR_MNTALL_FAIL) {
                 // Fatal error - no point continuing.
-                return {status, userdata_mounted};
+                return status;
             }
 
             if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) {
@@ -1577,7 +1577,7 @@
                                   nullptr)) {
                         LERROR << "Encryption failed";
                         set_type_property(encryptable);
-                        return {FS_MGR_MNTALL_FAIL, userdata_mounted};
+                        return FS_MGR_MNTALL_FAIL;
                     }
                 }
             }
@@ -1696,9 +1696,9 @@
     set_type_property(encryptable);
 
     if (error_count) {
-        return {FS_MGR_MNTALL_FAIL, userdata_mounted};
+        return FS_MGR_MNTALL_FAIL;
     } else {
-        return {encryptable, userdata_mounted};
+        return encryptable;
     }
 }
 
@@ -1735,190 +1735,6 @@
     return ret;
 }
 
-static std::chrono::milliseconds GetMillisProperty(const std::string& name,
-                                                   std::chrono::milliseconds default_value) {
-    auto value = GetUintProperty(name, static_cast<uint64_t>(default_value.count()));
-    return std::chrono::milliseconds(std::move(value));
-}
-
-static bool fs_mgr_unmount_all_data_mounts(const std::string& data_block_device) {
-    LINFO << __FUNCTION__ << "(): about to umount everything on top of " << data_block_device;
-    Timer t;
-    auto timeout = GetMillisProperty("init.userspace_reboot.userdata_remount.timeoutmillis", 5s);
-    while (true) {
-        bool umount_done = true;
-        Fstab proc_mounts;
-        if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
-            LERROR << __FUNCTION__ << "(): Can't read /proc/mounts";
-            return false;
-        }
-        // Now proceed with other bind mounts on top of /data.
-        for (const auto& entry : proc_mounts) {
-            std::string block_device;
-            if (StartsWith(entry.blk_device, "/dev/block") &&
-                !Realpath(entry.blk_device, &block_device)) {
-                PWARNING << __FUNCTION__ << "(): failed to realpath " << entry.blk_device;
-                block_device = entry.blk_device;
-            }
-            if (data_block_device == block_device) {
-                if (umount2(entry.mount_point.c_str(), 0) != 0) {
-                    PERROR << __FUNCTION__ << "(): Failed to umount " << entry.mount_point;
-                    umount_done = false;
-                }
-            }
-        }
-        if (umount_done) {
-            LINFO << __FUNCTION__ << "(): Unmounting /data took " << t;
-            return true;
-        }
-        if (t.duration() > timeout) {
-            LERROR << __FUNCTION__ << "(): Timed out unmounting all mounts on "
-                   << data_block_device;
-            Fstab remaining_mounts;
-            if (!ReadFstabFromFile("/proc/mounts", &remaining_mounts)) {
-                LERROR << __FUNCTION__ << "(): Can't read /proc/mounts";
-            } else {
-                LERROR << __FUNCTION__ << "(): Following mounts remaining";
-                for (const auto& e : remaining_mounts) {
-                    LERROR << __FUNCTION__ << "(): mount point: " << e.mount_point
-                           << " block device: " << e.blk_device;
-                }
-            }
-            return false;
-        }
-        std::this_thread::sleep_for(50ms);
-    }
-}
-
-static bool UnwindDmDeviceStack(const std::string& block_device,
-                                std::vector<std::string>* dm_stack) {
-    if (!StartsWith(block_device, "/dev/block/")) {
-        LWARNING << block_device << " is not a block device";
-        return false;
-    }
-    std::string current = block_device;
-    DeviceMapper& dm = DeviceMapper::Instance();
-    while (true) {
-        dm_stack->push_back(current);
-        if (!dm.IsDmBlockDevice(current)) {
-            break;
-        }
-        auto parent = dm.GetParentBlockDeviceByPath(current);
-        if (!parent) {
-            return false;
-        }
-        current = *parent;
-    }
-    return true;
-}
-
-FstabEntry* fs_mgr_get_mounted_entry_for_userdata(Fstab* fstab,
-                                                  const std::string& data_block_device) {
-    std::vector<std::string> dm_stack;
-    if (!UnwindDmDeviceStack(data_block_device, &dm_stack)) {
-        LERROR << "Failed to unwind dm-device stack for " << data_block_device;
-        return nullptr;
-    }
-    for (auto& entry : *fstab) {
-        if (entry.mount_point != "/data") {
-            continue;
-        }
-        std::string block_device;
-        if (entry.fs_mgr_flags.logical) {
-            if (!fs_mgr_update_logical_partition(&entry)) {
-                LERROR << "Failed to update logic partition " << entry.blk_device;
-                continue;
-            }
-            block_device = entry.blk_device;
-        } else if (!Realpath(entry.blk_device, &block_device)) {
-            PWARNING << "Failed to realpath " << entry.blk_device;
-            block_device = entry.blk_device;
-        }
-        if (std::find(dm_stack.begin(), dm_stack.end(), block_device) != dm_stack.end()) {
-            return &entry;
-        }
-    }
-    LERROR << "Didn't find entry that was used to mount /data onto " << data_block_device;
-    return nullptr;
-}
-
-// TODO(b/143970043): return different error codes based on which step failed.
-int fs_mgr_remount_userdata_into_checkpointing(Fstab* fstab) {
-    Fstab proc_mounts;
-    if (!ReadFstabFromFile("/proc/mounts", &proc_mounts)) {
-        LERROR << "Can't read /proc/mounts";
-        return -1;
-    }
-    auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data");
-    if (mounted_entry == nullptr) {
-        LERROR << "/data is not mounted";
-        return -1;
-    }
-    std::string block_device;
-    if (!Realpath(mounted_entry->blk_device, &block_device)) {
-        PERROR << "Failed to realpath " << mounted_entry->blk_device;
-        return -1;
-    }
-    auto fstab_entry = fs_mgr_get_mounted_entry_for_userdata(fstab, block_device);
-    if (fstab_entry == nullptr) {
-        LERROR << "Can't find /data in fstab";
-        return -1;
-    }
-    bool force_umount = GetBoolProperty("sys.init.userdata_remount.force_umount", false);
-    if (force_umount) {
-        LINFO << "Will force an umount of userdata even if it's not required";
-    }
-    if (!force_umount && !SupportsCheckpoint(fstab_entry)) {
-        LINFO << "Userdata doesn't support checkpointing. Nothing to do";
-        return 0;
-    }
-    CheckpointManager checkpoint_manager;
-    if (!force_umount && !checkpoint_manager.NeedsCheckpoint()) {
-        LINFO << "Checkpointing not needed. Don't remount";
-        return 0;
-    }
-    if (!force_umount && fstab_entry->fs_mgr_flags.checkpoint_fs) {
-        // Userdata is f2fs, simply remount it.
-        if (!checkpoint_manager.Update(fstab_entry)) {
-            LERROR << "Failed to remount userdata in checkpointing mode";
-            return -1;
-        }
-        if (mount(block_device.c_str(), fstab_entry->mount_point.c_str(), "none",
-                  MS_REMOUNT | fstab_entry->flags, fstab_entry->fs_options.c_str()) != 0) {
-            PERROR << "Failed to remount userdata in checkpointing mode";
-            return -1;
-        }
-    } else {
-        LINFO << "Unmounting /data before remounting into checkpointing mode";
-        if (!fs_mgr_unmount_all_data_mounts(block_device)) {
-            LERROR << "Failed to umount /data";
-            return -1;
-        }
-        DeviceMapper& dm = DeviceMapper::Instance();
-        while (dm.IsDmBlockDevice(block_device)) {
-            auto next_device = dm.GetParentBlockDeviceByPath(block_device);
-            auto name = dm.GetDmDeviceNameByPath(block_device);
-            if (!name) {
-                LERROR << "Failed to get dm-name for " << block_device;
-                return -1;
-            }
-            LINFO << "Deleting " << block_device << " named " << *name;
-            if (!dm.DeleteDevice(*name, 3s)) {
-                return -1;
-            }
-            if (!next_device) {
-                LERROR << "Failed to find parent device for " << block_device;
-            }
-            block_device = *next_device;
-        }
-        LINFO << "Remounting /data";
-        // TODO(b/143970043): remove this hack after fs_mgr_mount_all is refactored.
-        auto result = fs_mgr_mount_all(fstab, MOUNT_MODE_ONLY_USERDATA);
-        return result.code == FS_MGR_MNTALL_FAIL ? -1 : 0;
-    }
-    return 0;
-}
-
 // wrapper to __mount() and expects a fully prepared fstab_rec,
 // unlike fs_mgr_do_mount which does more things with avb / verity etc.
 int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& alt_mount_point) {
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 2e1cf76..af5ae2d 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -58,13 +58,8 @@
 #define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4
 #define FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE 0
 #define FS_MGR_MNTALL_FAIL (-1)
-
-struct MountAllResult {
-    // One of the FS_MGR_MNTALL_* returned code defined above.
-    int code;
-    // Whether userdata was mounted as a result of |fs_mgr_mount_all| call.
-    bool userdata_mounted;
-};
+// fs_mgr_mount_all() updates fstab entries that reference device-mapper.
+int fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode);
 
 struct HashtreeInfo {
     // The hash algorithm used to build the merkle tree.
@@ -75,13 +70,6 @@
     bool check_at_most_once;
 };
 
-// fs_mgr_mount_all() updates fstab entries that reference device-mapper.
-// Returns a |MountAllResult|. The first element is one of the FS_MNG_MNTALL_* return codes
-// defined above, and the second element tells whether this call to fs_mgr_mount_all was responsible
-// for mounting userdata. Later is required for init to correctly enqueue fs-related events as part
-// of userdata remount during userspace reboot.
-MountAllResult fs_mgr_mount_all(android::fs_mgr::Fstab* fstab, int mount_mode);
-
 #define FS_MGR_DOMNT_FAILED (-1)
 #define FS_MGR_DOMNT_BUSY (-2)
 #define FS_MGR_DOMNT_SUCCESS 0
@@ -127,11 +115,6 @@
 // it destroys verity devices from device mapper after the device is unmounted.
 int fs_mgr_umount_all(android::fs_mgr::Fstab* fstab);
 
-// Finds a entry in |fstab| that was used to mount a /data on |data_block_device|.
-android::fs_mgr::FstabEntry* fs_mgr_get_mounted_entry_for_userdata(
-        android::fs_mgr::Fstab* fstab, const std::string& data_block_device);
-int fs_mgr_remount_userdata_into_checkpointing(android::fs_mgr::Fstab* fstab);
-
 // Finds the dm_bow device on which this block device is stacked, or returns
 // empty string
 std::string fs_mgr_find_bow_device(const std::string& block_device);
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index c29da17..16c247f 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2835,7 +2835,6 @@
     // that is fixed, don't call GTEST_SKIP here, but instead call GTEST_SKIP in individual test
     // suites.
     RETURN_IF_NON_VIRTUAL_AB_MSG("Virtual A/B is not enabled, skipping global setup.\n");
-    RETURN_IF_VENDOR_ON_ANDROID_S_MSG("Test not enabled for Vendor on Android S.\n");
 
     std::vector<std::string> paths = {
             // clang-format off
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index c0af5c5..013df35 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/socket.h>
+#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <unistd.h>
 
@@ -35,9 +36,6 @@
 #include <snapuserd/snapuserd_client.h>
 #include "snapuserd_server.h"
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
 namespace android {
 namespace snapshot {
 
diff --git a/fs_mgr/tests/AndroidTest.xml b/fs_mgr/tests/AndroidTest.xml
index de835b3..1c06ebd 100644
--- a/fs_mgr/tests/AndroidTest.xml
+++ b/fs_mgr/tests/AndroidTest.xml
@@ -16,6 +16,7 @@
     <option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
     <option name="config-descriptor:metadata" key="parameter" value="multi_abi" />
     <option name="config-descriptor:metadata" key="parameter" value="secondary_user" />
+    <option name="config-descriptor:metadata" key="parameter" value="secondary_user_on_secondary_display" />
     <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
         <option name="cleanup" value="true" />
         <option name="push" value="CtsFsMgrTestCases->/data/local/tmp/CtsFsMgrTestCases" />
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 322bf1b..bd3d6b5 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -1062,23 +1062,6 @@
             << "Default fstab doesn't contain /data entry";
 }
 
-TEST(fs_mgr, UserdataMountedFromDefaultFstab) {
-    if (getuid() != 0) {
-        GTEST_SKIP() << "Must be run as root.";
-        return;
-    }
-    Fstab fstab;
-    ASSERT_TRUE(ReadDefaultFstab(&fstab)) << "Failed to read default fstab";
-    Fstab proc_mounts;
-    ASSERT_TRUE(ReadFstabFromFile("/proc/mounts", &proc_mounts)) << "Failed to read /proc/mounts";
-    auto mounted_entry = GetEntryForMountPoint(&proc_mounts, "/data");
-    ASSERT_NE(mounted_entry, nullptr) << "/data is not mounted";
-    std::string block_device;
-    ASSERT_TRUE(android::base::Realpath(mounted_entry->blk_device, &block_device));
-    ASSERT_NE(nullptr, fs_mgr_get_mounted_entry_for_userdata(&fstab, block_device))
-            << "/data wasn't mounted from default fstab";
-}
-
 TEST(fs_mgr, ReadFstabFromFile_FsMgrOptions_Readahead_Size_KB) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 606ea8c..122adb7 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -606,8 +606,6 @@
     return Error() << "Invalid code: " << code;
 }
 
-static int initial_mount_fstab_return_code = -1;
-
 /* <= Q: mount_all <fstab> [ <path> ]* [--<options>]*
  * >= R: mount_all [ <fstab> ] [--<options>]*
  *
@@ -648,19 +646,10 @@
         import_late(mount_all->rc_paths);
     }
 
-    if (mount_fstab_result.userdata_mounted) {
-        // This call to fs_mgr_mount_all mounted userdata. Keep the result in
-        // order for userspace reboot to correctly remount userdata.
-        LOG(INFO) << "Userdata mounted using "
-                  << (mount_all->fstab_path.empty() ? "(default fstab)" : mount_all->fstab_path)
-                  << " result : " << mount_fstab_result.code;
-        initial_mount_fstab_return_code = mount_fstab_result.code;
-    }
-
     if (queue_event) {
         /* queue_fs_event will queue event based on mount_fstab return code
          * and return processed return code*/
-        auto queue_fs_result = queue_fs_event(mount_fstab_result.code);
+        auto queue_fs_result = queue_fs_event(mount_fstab_result);
         if (!queue_fs_result.ok()) {
             return Error() << "queue_fs_event() failed: " << queue_fs_result.error();
         }
@@ -1148,29 +1137,19 @@
 }
 
 static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) {
-    bool should_reboot_into_recovery = true;
     auto reboot_reason = vdc_arg + "_failed";
-    if (android::sysprop::InitProperties::userspace_reboot_in_progress().value_or(false)) {
-        should_reboot_into_recovery = false;
-        reboot_reason = "userspace_failed," + vdc_arg;
-    }
 
-    auto reboot = [reboot_reason, should_reboot_into_recovery](const std::string& message) {
+    auto reboot = [reboot_reason](const std::string& message) {
         // TODO (b/122850122): support this in gsi
-        if (should_reboot_into_recovery) {
-            if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) {
-                LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
-                if (auto result = reboot_into_recovery(
-                            {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
-                    !result.ok()) {
-                    LOG(FATAL) << "Could not reboot into recovery: " << result.error();
-                }
-            } else {
-                LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
+        if (IsFbeEnabled() && !android::gsi::IsGsiRunning()) {
+            LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
+            if (auto result = reboot_into_recovery(
+                        {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+                !result.ok()) {
+                LOG(FATAL) << "Could not reboot into recovery: " << result.error();
             }
         } else {
-            LOG(ERROR) << message << ": rebooting, reason: " << reboot_reason;
-            trigger_shutdown("reboot," + reboot_reason);
+            LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
         }
     };
 
@@ -1178,29 +1157,6 @@
     return ExecWithFunctionOnFailure(args, reboot);
 }
 
-static Result<void> do_remount_userdata(const BuiltinArguments& args) {
-    if (initial_mount_fstab_return_code == -1) {
-        return Error() << "Calling remount_userdata too early";
-    }
-    Fstab fstab;
-    if (!ReadDefaultFstab(&fstab)) {
-        // TODO(b/135984674): should we reboot here?
-        return Error() << "Failed to read fstab";
-    }
-    // TODO(b/135984674): check that fstab contains /data.
-    if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) {
-        std::string proc_mounts_output;
-        android::base::ReadFileToString("/proc/mounts", &proc_mounts_output, true);
-        android::base::WriteStringToFile(proc_mounts_output,
-                                         "/metadata/userspacereboot/mount_info.txt");
-        trigger_shutdown("reboot,mount_userdata_failed");
-    }
-    if (auto result = queue_fs_event(initial_mount_fstab_return_code); !result.ok()) {
-        return Error() << "queue_fs_event() failed: " << result.error();
-    }
-    return {};
-}
-
 static Result<void> do_installkey(const BuiltinArguments& args) {
     if (!is_file_crypto()) return {};
 
@@ -1361,7 +1317,6 @@
         {"umount_all",              {0,     1,    {false,  do_umount_all}}},
         {"update_linker_config",    {0,     0,    {false,  do_update_linker_config}}},
         {"readahead",               {1,     2,    {true,   do_readahead}}},
-        {"remount_userdata",        {0,     0,    {false,  do_remount_userdata}}},
         {"restart",                 {1,     2,    {false,  do_restart}}},
         {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
         {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
diff --git a/init/init.cpp b/init/init.cpp
index 19e909f..4878660 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -26,13 +26,11 @@
 #include <sys/eventfd.h>
 #include <sys/mount.h>
 #include <sys/signalfd.h>
+#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/utsname.h>
 #include <unistd.h>
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
 #include <filesystem>
 #include <fstream>
 #include <functional>
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 0d6eb15..96a9cd4 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -31,14 +31,12 @@
 #include <sys/mman.h>
 #include <sys/poll.h>
 #include <sys/select.h>
+#include <sys/system_properties.h>
 #include <sys/types.h>
 #include <sys/un.h>
 #include <unistd.h>
 #include <wchar.h>
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
 #include <map>
 #include <memory>
 #include <mutex>
@@ -102,7 +100,6 @@
 using android::properties::ParsePropertyInfoFile;
 using android::properties::PropertyInfoAreaFile;
 using android::properties::PropertyInfoEntry;
-using android::sysprop::InitProperties::is_userspace_reboot_supported;
 
 namespace android {
 namespace init {
@@ -569,8 +566,8 @@
         }
         LOG(INFO) << "Received sys.powerctl='" << value << "' from pid: " << cr.pid
                   << process_log_string;
-        if (value == "reboot,userspace" && !is_userspace_reboot_supported().value_or(false)) {
-            *error = "Userspace reboot is not supported by this device";
+        if (value == "reboot,userspace") {
+            *error = "Userspace reboot is deprecated.";
             return {PROP_ERROR_INVALID_VALUE};
         }
     }
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index 5f34cc4..c12ff72 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -16,11 +16,9 @@
 
 #include <errno.h>
 #include <sys/socket.h>
+#include <sys/system_properties.h>
 #include <sys/un.h>
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
 #include <android-base/properties.h>
 #include <android-base/scopeguard.h>
 #include <android-base/strings.h>
@@ -82,12 +80,6 @@
         GTEST_SKIP() << "Skipping test, must be run as root.";
         return;
     }
-    const std::string original_value = GetProperty("init.userspace_reboot.is_supported", "");
-    auto guard = android::base::make_scope_guard([&original_value]() {
-        SetProperty("init.userspace_reboot.is_supported", original_value);
-    });
-
-    ASSERT_TRUE(SetProperty("init.userspace_reboot.is_supported", "false"));
     EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace"));
 }
 
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 150f8f4..66ee977 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -87,16 +87,6 @@
 
 static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
 
-static std::set<std::string> GetPostDataDebuggingServices() {
-    std::set<std::string> ret;
-    for (const auto& s : ServiceList::GetInstance()) {
-        if (kDebuggingServices.count(s->name()) && s->is_post_data()) {
-            ret.insert(s->name());
-        }
-    }
-    return ret;
-}
-
 static void PersistRebootReason(const char* reason, bool write_to_property) {
     if (write_to_property) {
         SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
@@ -810,196 +800,6 @@
     }
 }
 
-static void LeaveShutdown() {
-    LOG(INFO) << "Leaving shutdown mode";
-    shutting_down = false;
-    StartSendingMessages();
-}
-
-static std::chrono::milliseconds GetMillisProperty(const std::string& name,
-                                                   std::chrono::milliseconds default_value) {
-    auto value = GetUintProperty(name, static_cast<uint64_t>(default_value.count()));
-    return std::chrono::milliseconds(std::move(value));
-}
-
-static Result<void> DoUserspaceReboot() {
-    LOG(INFO) << "Userspace reboot initiated";
-    // An ugly way to pass a more precise reason on why fallback to hard reboot was triggered.
-    std::string sub_reason = "";
-    auto guard = android::base::make_scope_guard([&sub_reason] {
-        // Leave shutdown so that we can handle a full reboot.
-        LeaveShutdown();
-        trigger_shutdown("reboot,userspace_failed,shutdown_aborted," + sub_reason);
-    });
-    // Triggering userspace-reboot-requested will result in a bunch of setprop
-    // actions. We should make sure, that all of them are propagated before
-    // proceeding with userspace reboot. Synchronously setting sys.init.userspace_reboot.in_progress
-    // property is not perfect, but it should do the trick.
-    if (!android::sysprop::InitProperties::userspace_reboot_in_progress(true)) {
-        sub_reason = "setprop";
-        return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
-    }
-    EnterShutdown();
-    if (!SetProperty("sys.powerctl", "")) {
-        sub_reason = "resetprop";
-        return Error() << "Failed to reset sys.powerctl property";
-    }
-    std::set<std::string> stop_first;
-    // Remember the services that were enabled. We will need to manually enable them again otherwise
-    // triggers like class_start won't restart them.
-    std::set<std::string> were_enabled;
-    for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
-        if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
-            stop_first.insert(s->name());
-        }
-        // TODO(ioffe): we should also filter out temporary services here.
-        if (s->is_post_data() && s->IsEnabled()) {
-            were_enabled.insert(s->name());
-        }
-    }
-    {
-        Timer sync_timer;
-        LOG(INFO) << "sync() before terminating services...";
-        sync();
-        LOG(INFO) << "sync() took " << sync_timer;
-    }
-    auto sigterm_timeout = GetMillisProperty("init.userspace_reboot.sigterm.timeoutmillis", 5s);
-    auto sigkill_timeout = GetMillisProperty("init.userspace_reboot.sigkill.timeoutmillis", 10s);
-    LOG(INFO) << "Timeout to terminate services: " << sigterm_timeout.count() << "ms "
-              << "Timeout to kill services: " << sigkill_timeout.count() << "ms";
-    std::string services_file_name = "/metadata/userspacereboot/services.txt";
-    const int flags = O_RDWR | O_CREAT | O_SYNC | O_APPEND | O_CLOEXEC;
-    StopServicesAndLogViolations(stop_first, sigterm_timeout, true /* SIGTERM */);
-    if (int r = StopServicesAndLogViolations(stop_first, sigkill_timeout, false /* SIGKILL */);
-        r > 0) {
-        auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
-        android::base::WriteStringToFd("Post-data services still running: \n", fd);
-        for (const auto& s : ServiceList::GetInstance()) {
-            if (s->IsRunning() && stop_first.count(s->name())) {
-                android::base::WriteStringToFd(s->name() + "\n", fd);
-            }
-        }
-        sub_reason = "sigkill";
-        return Error() << r << " post-data services are still running";
-    }
-    if (auto result = KillZramBackingDevice(); !result.ok()) {
-        sub_reason = "zram";
-        return result;
-    }
-    if (auto result = CallVdc("volume", "reset"); !result.ok()) {
-        sub_reason = "vold_reset";
-        return result;
-    }
-    const auto& debugging_services = GetPostDataDebuggingServices();
-    if (int r = StopServicesAndLogViolations(debugging_services, sigkill_timeout,
-                                             false /* SIGKILL */);
-        r > 0) {
-        auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
-        android::base::WriteStringToFd("Debugging services still running: \n", fd);
-        for (const auto& s : ServiceList::GetInstance()) {
-            if (s->IsRunning() && debugging_services.count(s->name())) {
-                android::base::WriteStringToFd(s->name() + "\n", fd);
-            }
-        }
-        sub_reason = "sigkill_debug";
-        return Error() << r << " debugging services are still running";
-    }
-    {
-        Timer sync_timer;
-        LOG(INFO) << "sync() after stopping services...";
-        sync();
-        LOG(INFO) << "sync() took " << sync_timer;
-    }
-    if (auto result = UnmountAllApexes(); !result.ok()) {
-        sub_reason = "apex";
-        return result;
-    }
-    if (!SwitchToMountNamespaceIfNeeded(NS_BOOTSTRAP).ok()) {
-        sub_reason = "ns_switch";
-        return Error() << "Failed to switch to bootstrap namespace";
-    }
-    ActionManager::GetInstance().RemoveActionIf([](const auto& action) -> bool {
-        if (action->IsFromApex()) {
-            std::string trigger_name = action->BuildTriggersString();
-            LOG(INFO) << "Removing action (" << trigger_name << ") from (" << action->filename()
-                      << ":" << action->line() << ")";
-            return true;
-        }
-        return false;
-    });
-    // Remove services that were defined in an APEX
-    ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
-        if (s->is_from_apex()) {
-            LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
-            return true;
-        }
-        return false;
-    });
-    // Re-enable services
-    for (const auto& s : ServiceList::GetInstance()) {
-        if (were_enabled.count(s->name())) {
-            LOG(INFO) << "Re-enabling service '" << s->name() << "'";
-            s->Enable();
-        }
-    }
-    ServiceList::GetInstance().ResetState();
-    LeaveShutdown();
-    ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
-    guard.Disable();  // Go on with userspace reboot.
-    return {};
-}
-
-static void UserspaceRebootWatchdogThread() {
-    auto started_timeout = GetMillisProperty("init.userspace_reboot.started.timeoutmillis", 10s);
-    if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", started_timeout)) {
-        LOG(ERROR) << "Userspace reboot didn't start in " << started_timeout.count()
-                   << "ms. Switching to full reboot";
-        // Init might be wedged, don't try to write reboot reason into a persistent property and do
-        // a dirty reboot.
-        PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_start", false);
-        RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_start");
-    }
-    LOG(INFO) << "Starting userspace reboot watchdog";
-    auto watchdog_timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min);
-    LOG(INFO) << "UserspaceRebootWatchdog timeout: " << watchdog_timeout.count() << "ms";
-    if (!WaitForProperty("sys.boot_completed", "1", watchdog_timeout)) {
-        LOG(ERROR) << "Failed to boot in " << watchdog_timeout.count()
-                   << "ms. Switching to full reboot";
-        // In this case device is in a boot loop. Only way to recover is to do dirty reboot.
-        // Since init might be wedged, don't try to write reboot reason into a persistent property.
-        PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_boot", false);
-        RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_boot");
-    }
-    LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
-}
-
-static void HandleUserspaceReboot() {
-    if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) {
-        LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it";
-        return;
-    }
-    // Spinnig up a separate thread will fail the setns call later in the boot sequence.
-    // Fork a new process to monitor userspace reboot while we are investigating a better solution.
-    pid_t pid = fork();
-    if (pid < 0) {
-        PLOG(ERROR) << "Failed to fork process for userspace reboot watchdog. Switching to full "
-                    << "reboot";
-        trigger_shutdown("reboot,userspace_failed,watchdog_fork");
-        return;
-    }
-    if (pid == 0) {
-        // Child
-        UserspaceRebootWatchdogThread();
-        _exit(EXIT_SUCCESS);
-    }
-    LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger";
-    auto& am = ActionManager::GetInstance();
-    am.ClearQueue();
-    am.QueueEventTrigger("userspace-reboot-requested");
-    auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); };
-    am.QueueBuiltinAction(handler, "userspace-reboot");
-}
-
 /**
  * Check if "command" field is set in bootloader message.
  *
@@ -1030,7 +830,6 @@
     std::string reboot_target = "";
     bool run_fsck = false;
     bool command_invalid = false;
-    bool userspace_reboot = false;
 
     if (cmd_params[0] == "shutdown") {
         cmd = ANDROID_RB_POWEROFF;
@@ -1051,8 +850,8 @@
         if (cmd_params.size() >= 2) {
             reboot_target = cmd_params[1];
             if (reboot_target == "userspace") {
-                LOG(INFO) << "Userspace reboot requested";
-                userspace_reboot = true;
+                LOG(ERROR) << "Userspace reboot is deprecated.";
+                return;
             }
             // adb reboot fastboot should boot into bootloader for devices not
             // supporting logical partitions.
@@ -1130,11 +929,6 @@
     // messages, etc) from properties during reboot.
     StopSendingMessages();
 
-    if (userspace_reboot) {
-        HandleUserspaceReboot();
-        return;
-    }
-
     LOG(INFO) << "Clear action queue and start shutdown trigger";
     ActionManager::GetInstance().ClearQueue();
     // Queue shutdown trigger first
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 3af92bb..efba9f6 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -87,6 +87,25 @@
     return info.param;
 }
 
-INSTANTIATE_TEST_CASE_P(DeathTest, InitKillServicesTest,
-                        ::testing::Values("lmkd", "ueventd", "hwservicemanager", "servicemanager"),
-                        PrintName);
+INSTANTIATE_TEST_CASE_P(
+        DeathTest, InitKillServicesTest,
+        ::testing::Values(
+                // clang-format off
+
+// TODO: we may want a more automatic way of testing this for services based on some
+// criteria (e.g. not disabled), but for now adding core services one at a time
+
+// BEGIN INTERNAL ONLY MERGE GUARD (add things here if internal only, move down later)
+// END INTERNAL ONLY MERGE GUARD
+
+// BEGIN AOSP ONLY (add things here if adding to AOSP)
+    "lmkd",
+    "ueventd",
+    "hwservicemanager",
+    "servicemanager",
+    "system_suspend"
+// END AOSP ONLY
+
+                // clang-format on
+                ),
+        PrintName);
diff --git a/libcutils/properties.cpp b/libcutils/properties.cpp
index 03f0496..d3a2b50 100644
--- a/libcutils/properties.cpp
+++ b/libcutils/properties.cpp
@@ -93,8 +93,7 @@
 
 #if __has_include(<sys/system_properties.h>)
 
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 
 struct callback_data {
     void (*callback)(const char* name, const char* value, void* cookie);
diff --git a/libcutils/trace-dev.inc b/libcutils/trace-dev.inc
index 3bc6dc3..c911b4f 100644
--- a/libcutils/trace-dev.inc
+++ b/libcutils/trace-dev.inc
@@ -36,8 +36,7 @@
 #include <log/log_properties.h>
 
 #if defined(__BIONIC__)
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
+#include <sys/system_properties.h>
 #endif
 
 /**
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index 52b5afe..fb01cfd 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -38,26 +38,26 @@
 static constexpr const char* CGROUP_TASKS_FILE = "/tasks";
 static constexpr const char* CGROUP_TASKS_FILE_V2 = "/cgroup.threads";
 
-uint32_t CgroupController::version() const {
+uint32_t CgroupControllerWrapper::version() const {
     CHECK(HasValue());
     return ACgroupController_getVersion(controller_);
 }
 
-const char* CgroupController::name() const {
+const char* CgroupControllerWrapper::name() const {
     CHECK(HasValue());
     return ACgroupController_getName(controller_);
 }
 
-const char* CgroupController::path() const {
+const char* CgroupControllerWrapper::path() const {
     CHECK(HasValue());
     return ACgroupController_getPath(controller_);
 }
 
-bool CgroupController::HasValue() const {
+bool CgroupControllerWrapper::HasValue() const {
     return controller_ != nullptr;
 }
 
-bool CgroupController::IsUsable() {
+bool CgroupControllerWrapper::IsUsable() {
     if (!HasValue()) return false;
 
     if (state_ == UNKNOWN) {
@@ -72,7 +72,7 @@
     return state_ == USABLE;
 }
 
-std::string CgroupController::GetTasksFilePath(const std::string& rel_path) const {
+std::string CgroupControllerWrapper::GetTasksFilePath(const std::string& rel_path) const {
     std::string tasks_path = path();
 
     if (!rel_path.empty()) {
@@ -81,8 +81,8 @@
     return (version() == 1) ? tasks_path + CGROUP_TASKS_FILE : tasks_path + CGROUP_TASKS_FILE_V2;
 }
 
-std::string CgroupController::GetProcsFilePath(const std::string& rel_path, uid_t uid,
-                                               pid_t pid) const {
+std::string CgroupControllerWrapper::GetProcsFilePath(const std::string& rel_path, uid_t uid,
+                                                      pid_t pid) const {
     std::string proc_path(path());
     proc_path.append("/").append(rel_path);
     proc_path = regex_replace(proc_path, std::regex("<uid>"), std::to_string(uid));
@@ -91,7 +91,7 @@
     return proc_path.append(CGROUP_PROCS_FILE);
 }
 
-bool CgroupController::GetTaskGroup(pid_t tid, std::string* group) const {
+bool CgroupControllerWrapper::GetTaskGroup(pid_t tid, std::string* group) const {
     std::string file_name = StringPrintf("/proc/%d/cgroup", tid);
     std::string content;
     if (!android::base::ReadFileToString(file_name, &content)) {
@@ -175,40 +175,40 @@
     }
 }
 
-CgroupController CgroupMap::FindController(const std::string& name) const {
+CgroupControllerWrapper CgroupMap::FindController(const std::string& name) const {
     if (!loaded_) {
         LOG(ERROR) << "CgroupMap::FindController called for [" << getpid()
                    << "] failed, RC file was not initialized properly";
-        return CgroupController(nullptr);
+        return CgroupControllerWrapper(nullptr);
     }
 
     auto controller_count = ACgroupFile_getControllerCount();
     for (uint32_t i = 0; i < controller_count; ++i) {
         const ACgroupController* controller = ACgroupFile_getController(i);
         if (name == ACgroupController_getName(controller)) {
-            return CgroupController(controller);
+            return CgroupControllerWrapper(controller);
         }
     }
 
-    return CgroupController(nullptr);
+    return CgroupControllerWrapper(nullptr);
 }
 
-CgroupController CgroupMap::FindControllerByPath(const std::string& path) const {
+CgroupControllerWrapper CgroupMap::FindControllerByPath(const std::string& path) const {
     if (!loaded_) {
         LOG(ERROR) << "CgroupMap::FindControllerByPath called for [" << getpid()
                    << "] failed, RC file was not initialized properly";
-        return CgroupController(nullptr);
+        return CgroupControllerWrapper(nullptr);
     }
 
     auto controller_count = ACgroupFile_getControllerCount();
     for (uint32_t i = 0; i < controller_count; ++i) {
         const ACgroupController* controller = ACgroupFile_getController(i);
         if (StartsWith(path, ACgroupController_getPath(controller))) {
-            return CgroupController(controller);
+            return CgroupControllerWrapper(controller);
         }
     }
 
-    return CgroupController(nullptr);
+    return CgroupControllerWrapper(nullptr);
 }
 
 int CgroupMap::ActivateControllers(const std::string& path) const {
diff --git a/libprocessgroup/cgroup_map.h b/libprocessgroup/cgroup_map.h
index 31925d5..3642794 100644
--- a/libprocessgroup/cgroup_map.h
+++ b/libprocessgroup/cgroup_map.h
@@ -23,10 +23,10 @@
 #include <android/cgrouprc.h>
 
 // Convenient wrapper of an ACgroupController pointer.
-class CgroupController {
+class CgroupControllerWrapper {
   public:
     // Does not own controller
-    explicit CgroupController(const ACgroupController* controller)
+    explicit CgroupControllerWrapper(const ACgroupController* controller)
         : controller_(controller) {}
 
     uint32_t version() const;
@@ -53,12 +53,9 @@
 
 class CgroupMap {
   public:
-    // Selinux policy ensures only init process can successfully use this function
-    static bool SetupCgroups();
-
     static CgroupMap& GetInstance();
-    CgroupController FindController(const std::string& name) const;
-    CgroupController FindControllerByPath(const std::string& path) const;
+    CgroupControllerWrapper FindController(const std::string& name) const;
+    CgroupControllerWrapper FindControllerByPath(const std::string& path) const;
     int ActivateControllers(const std::string& path) const;
 
   private:
diff --git a/libprocessgroup/cgrouprc/Android.bp b/libprocessgroup/cgrouprc/Android.bp
index 7522cfe..cb91247 100644
--- a/libprocessgroup/cgrouprc/Android.bp
+++ b/libprocessgroup/cgrouprc/Android.bp
@@ -32,8 +32,8 @@
         symbol_file: "libcgrouprc.map.txt",
     },
     srcs: [
-        "cgroup_controller.cpp",
-        "cgroup_file.cpp",
+        "a_cgroup_controller.cpp",
+        "a_cgroup_file.cpp",
     ],
     cflags: [
         "-Wall",
diff --git a/libprocessgroup/cgrouprc/cgroup_controller.cpp b/libprocessgroup/cgrouprc/a_cgroup_controller.cpp
similarity index 100%
rename from libprocessgroup/cgrouprc/cgroup_controller.cpp
rename to libprocessgroup/cgrouprc/a_cgroup_controller.cpp
diff --git a/libprocessgroup/cgrouprc/cgroup_file.cpp b/libprocessgroup/cgrouprc/a_cgroup_file.cpp
similarity index 100%
rename from libprocessgroup/cgrouprc/cgroup_file.cpp
rename to libprocessgroup/cgrouprc/a_cgroup_file.cpp
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp
index 387c104..83a2258 100644
--- a/libprocessgroup/processgroup.cpp
+++ b/libprocessgroup/processgroup.cpp
@@ -94,7 +94,7 @@
 }
 
 static bool CgroupGetMemcgAppsPath(std::string* path) {
-    CgroupController controller = CgroupMap::GetInstance().FindController("memory");
+    CgroupControllerWrapper controller = CgroupMap::GetInstance().FindController("memory");
 
     if (!controller.HasValue()) {
         return false;
diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp
index 4870548..67ecc1d 100644
--- a/libprocessgroup/task_profiles.cpp
+++ b/libprocessgroup/task_profiles.cpp
@@ -123,8 +123,8 @@
     return file_name_;
 }
 
-void ProfileAttribute::Reset(const CgroupController& controller, const std::string& file_name,
-                             const std::string& file_v2_name) {
+void ProfileAttribute::Reset(const CgroupControllerWrapper& controller,
+                             const std::string& file_name, const std::string& file_v2_name) {
     controller_ = controller;
     file_name_ = file_name;
     file_v2_name_ = file_v2_name;
@@ -333,7 +333,7 @@
     return optional_;
 }
 
-SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p)
+SetCgroupAction::SetCgroupAction(const CgroupControllerWrapper& c, const std::string& p)
     : controller_(c), path_(p) {
     FdCacheHelper::Init(controller_.GetTasksFilePath(path_), fd_[ProfileAction::RCT_TASK]);
     // uid and pid don't matter because IsAppDependentPath ensures the path doesn't use them
diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h
index 184e9e3..abb3ca5 100644
--- a/libprocessgroup/task_profiles.h
+++ b/libprocessgroup/task_profiles.h
@@ -32,9 +32,9 @@
 class IProfileAttribute {
   public:
     virtual ~IProfileAttribute() = 0;
-    virtual void Reset(const CgroupController& controller, const std::string& file_name,
+    virtual void Reset(const CgroupControllerWrapper& controller, const std::string& file_name,
                        const std::string& file_v2_name) = 0;
-    virtual const CgroupController* controller() const = 0;
+    virtual const CgroupControllerWrapper* controller() const = 0;
     virtual const std::string& file_name() const = 0;
     virtual bool GetPathForProcess(uid_t uid, pid_t pid, std::string* path) const = 0;
     virtual bool GetPathForTask(pid_t tid, std::string* path) const = 0;
@@ -46,14 +46,14 @@
     // Cgroup attributes may have different names in the v1 and v2 hierarchies. If `file_v2_name` is
     // not empty, `file_name` is the name for the v1 hierarchy and `file_v2_name` is the name for
     // the v2 hierarchy. If `file_v2_name` is empty, `file_name` is used for both hierarchies.
-    ProfileAttribute(const CgroupController& controller, const std::string& file_name,
+    ProfileAttribute(const CgroupControllerWrapper& controller, const std::string& file_name,
                      const std::string& file_v2_name)
         : controller_(controller), file_name_(file_name), file_v2_name_(file_v2_name) {}
     ~ProfileAttribute() = default;
 
-    const CgroupController* controller() const override { return &controller_; }
+    const CgroupControllerWrapper* controller() const override { return &controller_; }
     const std::string& file_name() const override;
-    void Reset(const CgroupController& controller, const std::string& file_name,
+    void Reset(const CgroupControllerWrapper& controller, const std::string& file_name,
                const std::string& file_v2_name) override;
 
     bool GetPathForProcess(uid_t uid, pid_t pid, std::string* path) const override;
@@ -61,7 +61,7 @@
     bool GetPathForUID(uid_t uid, std::string* path) const override;
 
   private:
-    CgroupController controller_;
+    CgroupControllerWrapper controller_;
     std::string file_name_;
     std::string file_v2_name_;
 };
@@ -142,7 +142,7 @@
 // Set cgroup profile element
 class SetCgroupAction : public ProfileAction {
   public:
-    SetCgroupAction(const CgroupController& c, const std::string& p);
+    SetCgroupAction(const CgroupControllerWrapper& c, const std::string& p);
 
     const char* Name() const override { return "SetCgroup"; }
     bool ExecuteForProcess(uid_t uid, pid_t pid) const override;
@@ -152,10 +152,10 @@
     bool IsValidForProcess(uid_t uid, pid_t pid) const override;
     bool IsValidForTask(pid_t tid) const override;
 
-    const CgroupController* controller() const { return &controller_; }
+    const CgroupControllerWrapper* controller() const { return &controller_; }
 
   private:
-    CgroupController controller_;
+    CgroupControllerWrapper controller_;
     std::string path_;
     android::base::unique_fd fd_[ProfileAction::RCT_COUNT];
     mutable std::mutex fd_mutex_;
diff --git a/libprocessgroup/task_profiles_test.cpp b/libprocessgroup/task_profiles_test.cpp
index d19da2b..dff6d67 100644
--- a/libprocessgroup/task_profiles_test.cpp
+++ b/libprocessgroup/task_profiles_test.cpp
@@ -102,10 +102,10 @@
   public:
     ProfileAttributeMock(const std::string& file_name) : file_name_(file_name) {}
     ~ProfileAttributeMock() override = default;
-    void Reset(const CgroupController&, const std::string&, const std::string&) override {
+    void Reset(const CgroupControllerWrapper&, const std::string&, const std::string&) override {
         CHECK(false);
     }
-    const CgroupController* controller() const override {
+    const CgroupControllerWrapper* controller() const override {
         CHECK(false);
         return {};
     }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b804c1b..e867998 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -620,7 +620,6 @@
     mkdir /metadata/bootstat 0750 system log
     mkdir /metadata/ota 0750 root system
     mkdir /metadata/ota/snapshots 0750 root system
-    mkdir /metadata/userspacereboot 0770 root system
     mkdir /metadata/watchdog 0770 root system
 
     mkdir /metadata/apex 0700 root system
@@ -648,6 +647,14 @@
     chmod 0755 /sys/kernel/tracing
     chmod 0755 /sys/kernel/debug/tracing
 
+    # Early HALs may use early VM. Mount /mnt/vm before starting such HALs.
+    mkdir /mnt/vm 0755 root root
+    mount tmpfs tmpfs /mnt/vm nosuid nodev noexec rw
+    restorecon /mnt/vm
+    chown system system /mnt/vm
+    chmod 0770 /mnt/vm
+    mkdir /mnt/vm/early 0770 system system
+
     # HALs required before storage encryption can get unlocked (FBE)
     class_start early_hal
 
@@ -1323,46 +1330,6 @@
 on init && property:ro.debuggable=1
     start console
 
-on userspace-reboot-requested
-  # TODO(b/135984674): reset all necessary properties here.
-  setprop sys.boot_completed ""
-  setprop dev.bootcomplete ""
-  setprop sys.init.updatable_crashing ""
-  setprop sys.init.updatable_crashing_process_name ""
-  setprop sys.user.0.ce_available ""
-  setprop sys.shutdown.requested ""
-  setprop service.bootanim.exit ""
-  setprop service.bootanim.progress ""
-
-on userspace-reboot-fs-remount
-  # Make sure that vold is running.
-  # This is mostly a precaution measure in case vold for some reason wasn't running when
-  # userspace reboot was initiated.
-  start vold
-  exec - system system -- /system/bin/vdc checkpoint resetCheckpoint
-  exec - system system -- /system/bin/vdc checkpoint markBootAttempt
-  # Unmount /data_mirror mounts in the reverse order of corresponding mounts.
-  umount /data_mirror/data_ce/null/0
-  umount /data_mirror/data_ce/null
-  umount /data_mirror/data_de/null
-  umount /data_mirror/storage_area/0
-  umount /data_mirror/storage_area
-  umount /data_mirror/cur_profiles
-  umount /data_mirror/ref_profiles
-  umount /data_mirror
-  remount_userdata
-  start bootanim
-
-on userspace-reboot-resume
-  trigger userspace-reboot-fs-remount
-  trigger post-fs-data
-  trigger zygote-start
-  trigger early-boot
-  trigger boot
-
-on property:sys.boot_completed=1 && property:sys.init.userspace_reboot.in_progress=1
-  setprop sys.init.userspace_reboot.in_progress ""
-
 # Multi-Gen LRU Experiment
 on property:persist.device_config.mglru_native.lru_gen_config=none
   write /sys/kernel/mm/lru_gen/enabled 0
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index dde784e..b30d6d0 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -139,7 +139,3 @@
 on property:sys.usb.typec.power_role=sink
     write /sys/class/dual_role_usb/otg_default/power_role ${sys.usb.typec.power_role}
     setprop sys.usb.typec.state ${sys.usb.typec.power_role}
-
-on userspace-reboot-requested
-  setprop sys.usb.config ""
-  setprop sys.usb.state ""
diff --git a/trusty/libtrusty/trusty.c b/trusty/libtrusty/trusty.c
index f44f8b4..63262a0 100644
--- a/trusty/libtrusty/trusty.c
+++ b/trusty/libtrusty/trusty.c
@@ -23,16 +23,161 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
 #include <unistd.h>
 
+#include <linux/vm_sockets.h> /* must be after sys/socket.h */
 #include <log/log.h>
 
 #include <trusty/ipc.h>
 
+static const char* strip_prefix(const char* str, const char* prefix) {
+    size_t prefix_len = strlen(prefix);
+    if (strncmp(str, prefix, prefix_len) == 0) {
+        return str + prefix_len;
+    } else {
+        return NULL;
+    }
+}
+
+static bool use_vsock_connection = false;
+static int tipc_vsock_connect(const char* type_cid_port_str, const char* srv_name) {
+    int ret;
+    const char* cid_port_str;
+    char* port_str;
+    char* end_str;
+    int socket_type;
+    if ((cid_port_str = strip_prefix(type_cid_port_str, "STREAM:"))) {
+        socket_type = SOCK_STREAM;
+    } else if ((cid_port_str = strip_prefix(type_cid_port_str, "SEQPACKET:"))) {
+        socket_type = SOCK_SEQPACKET;
+    } else {
+        /*
+         * Default to SOCK_STREAM if neither type is specified.
+         *
+         * TODO: use SOCK_SEQPACKET by default instead of SOCK_STREAM when SOCK_SEQPACKET is fully
+         * supported since it matches tipc better. At the moment SOCK_SEQPACKET is not supported by
+         * crosvm. It is also significantly slower since the Linux kernel implementation (as of
+         * v6.7-rc1) sends credit update packets every time it receives a data packet while the
+         * SOCK_STREAM version skips these unless the remaining buffer space is "low".
+         */
+        socket_type = SOCK_STREAM;
+        cid_port_str = type_cid_port_str;
+    }
+    long cid = strtol(cid_port_str, &port_str, 0);
+    if (port_str[0] != ':') {
+        ALOGE("%s: invalid VSOCK str, \"%s\", need cid:port missing : after cid\n", __func__,
+              cid_port_str);
+        return -EINVAL;
+    }
+    long port = strtol(port_str + 1, &end_str, 0);
+    if (end_str[0] != '\0') {
+        ALOGE("%s: invalid VSOCK str, \"%s\", need cid:port got %ld:%ld\n", __func__, cid_port_str,
+              cid, port);
+        return -EINVAL;
+    }
+    int fd = socket(AF_VSOCK, socket_type, 0);
+    if (fd < 0) {
+        ret = -errno;
+        ALOGE("%s: can't get vsock %ld:%ld socket for tipc service \"%s\" (err=%d)\n", __func__,
+              cid, port, srv_name, errno);
+        return ret < 0 ? ret : -1;
+    }
+    struct timeval connect_timeout = {.tv_sec = 60, .tv_usec = 0};
+    ret = setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_CONNECT_TIMEOUT, &connect_timeout,
+                     sizeof(connect_timeout));
+    if (ret) {
+        ALOGE("%s: vsock %ld:%ld: Failed to set connect timeout (err=%d)\n", __func__, cid, port,
+              errno);
+        /* failed to set longer timeout, but try to connect anyway */
+    }
+    struct sockaddr_vm sa = {
+            .svm_family = AF_VSOCK,
+            .svm_port = port,
+            .svm_cid = cid,
+    };
+    int retry = 10;
+    do {
+        ret = TEMP_FAILURE_RETRY(connect(fd, (struct sockaddr*)&sa, sizeof(sa)));
+        if (ret && (errno == ENODEV || errno == ESOCKTNOSUPPORT) && --retry) {
+            /*
+             * The kernel returns ESOCKTNOSUPPORT instead of ENODEV if the socket type is
+             * SOCK_SEQPACKET and the guest CID we are trying to connect to is not ready yet.
+             */
+            ALOGE("%s: Can't connect to vsock %ld:%ld for tipc service \"%s\" (err=%d) %d retries "
+                  "remaining\n",
+                  __func__, cid, port, srv_name, errno, retry);
+            sleep(1);
+        } else {
+            retry = 0;
+        }
+    } while (retry);
+    if (ret) {
+        ret = -errno;
+        ALOGE("%s: Can't connect to vsock %ld:%ld for tipc service \"%s\" (err=%d)\n", __func__,
+              cid, port, srv_name, errno);
+        close(fd);
+        return ret < 0 ? ret : -1;
+    }
+    /*
+     * TODO: Current vsock tipc bridge in trusty expects a port name in the
+     * first packet. We need to replace this with a protocol that also does DICE
+     * based authentication.
+     */
+    ret = TEMP_FAILURE_RETRY(write(fd, srv_name, strlen(srv_name)));
+    if (ret != strlen(srv_name)) {
+        ret = -errno;
+        ALOGE("%s: vsock %ld:%ld: failed to send tipc service name \"%s\" (err=%d)\n", __func__,
+              cid, port, srv_name, errno);
+        close(fd);
+        return ret < 0 ? ret : -1;
+    }
+    /*
+     * Work around lack of seq packet support. Read a status byte to prevent
+     * the caller from sending more data until srv_name has been read.
+     */
+    int8_t status;
+    ret = TEMP_FAILURE_RETRY(read(fd, &status, sizeof(status)));
+    if (ret != sizeof(status)) {
+        ALOGE("%s: vsock %ld:%ld: failed to read status byte for connect to tipc service name "
+              "\"%s\" (err=%d)\n",
+              __func__, cid, port, srv_name, errno);
+        close(fd);
+        return ret < 0 ? ret : -1;
+    }
+    use_vsock_connection = true;
+    return fd;
+}
+
+static size_t tipc_vsock_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shms,
+                              int shmcnt) {
+    int ret;
+
+    (void)shms;
+    if (shmcnt != 0) {
+        ALOGE("%s: vsock does not yet support passing fds\n", __func__);
+        return -ENOTSUP;
+    }
+    ret = TEMP_FAILURE_RETRY(writev(fd, iov, iovcnt));
+    if (ret < 0) {
+        ret = -errno;
+        ALOGE("%s: failed to send message (err=%d)\n", __func__, errno);
+        return ret < 0 ? ret : -1;
+    }
+
+    return ret;
+}
+
 int tipc_connect(const char* dev_name, const char* srv_name) {
     int fd;
     int rc;
 
+    const char* type_cid_port_str = strip_prefix(dev_name, "VSOCK:");
+    if (type_cid_port_str) {
+        return tipc_vsock_connect(type_cid_port_str, srv_name);
+    }
+
     fd = TEMP_FAILURE_RETRY(open(dev_name, O_RDWR));
     if (fd < 0) {
         rc = -errno;
@@ -54,6 +199,9 @@
 
 ssize_t tipc_send(int fd, const struct iovec* iov, int iovcnt, struct trusty_shm* shms,
                   int shmcnt) {
+    if (use_vsock_connection) {
+        return tipc_vsock_send(fd, iov, iovcnt, shms, shmcnt);
+    }
     struct tipc_send_msg_req req;
     req.iov = (__u64)iov;
     req.iov_cnt = (__u64)iovcnt;