Merge "remove healthd.rc"
diff --git a/debuggerd/client/debuggerd_client.cpp b/debuggerd/client/debuggerd_client.cpp
index b302918..c9e097e 100644
--- a/debuggerd/client/debuggerd_client.cpp
+++ b/debuggerd/client/debuggerd_client.cpp
@@ -216,7 +216,7 @@
       log_error(output_fd, 0,
                 "received packet of unexpected length from tombstoned while reading %s response: "
                 "expected %zd, received %zd",
-                kind, sizeof(response), rc);
+                kind, sizeof(*response), rc);
       return false;
     }
     return true;
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index e4d68f8..8e6abdf 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -190,6 +190,7 @@
 static void print_thread_backtrace(CallbackType callback, const Tombstone& tombstone,
                                    const Thread& thread, bool should_log) {
   CBS("");
+  CB(should_log, "%d total frames", thread.current_backtrace().size());
   CB(should_log, "backtrace:");
   if (!thread.backtrace_note().empty()) {
     CB(should_log, "  NOTE: %s",
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 42269fe..d7d2091 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1600,10 +1600,10 @@
 
     // Change the slot first, so we boot into the correct recovery image when
     // using fastbootd.
-    if (fp_->slot == "all") {
+    if (fp_->slot_override == "all") {
         set_active("a");
     } else {
-        set_active(fp_->slot);
+        set_active(fp_->slot_override);
     }
 
     DetermineSlot();
@@ -1654,17 +1654,17 @@
 }
 
 void FlashAllTool::DetermineSlot() {
-    if (fp_->slot.empty()) {
+    if (fp_->slot_override.empty()) {
         fp_->current_slot = get_current_slot();
     } else {
-        fp_->current_slot = fp_->slot;
+        fp_->current_slot = fp_->slot_override;
     }
 
     if (fp_->skip_secondary) {
         return;
     }
-    if (fp_->slot != "" && fp_->slot != "all") {
-        fp_->secondary_slot = get_other_slot(fp_->slot);
+    if (fp_->slot_override != "" && fp_->slot_override != "all") {
+        fp_->secondary_slot = get_other_slot(fp_->slot_override);
     } else {
         fp_->secondary_slot = get_other_slot();
     }
@@ -1678,7 +1678,7 @@
 
 void FlashAllTool::CollectImages() {
     for (size_t i = 0; i < images.size(); ++i) {
-        std::string slot = fp_->slot;
+        std::string slot = fp_->slot_override;
         if (images[i].IsSecondary()) {
             if (fp_->skip_secondary) {
                 continue;
@@ -2017,7 +2017,6 @@
     std::unique_ptr<FlashingPlan> fp = std::make_unique<FlashingPlan>();
 
     int longindex;
-    std::string slot_override;
     std::string next_active;
 
     g_boot_img_hdr.kernel_addr = 0x00008000;
@@ -2090,7 +2089,7 @@
             } else if (name == "skip-secondary") {
                 fp->skip_secondary = true;
             } else if (name == "slot") {
-                slot_override = optarg;
+                fp->slot_override = optarg;
             } else if (name == "dtb-offset") {
                 g_boot_img_hdr.dtb_addr = strtoul(optarg, 0, 16);
             } else if (name == "tags-offset") {
@@ -2182,12 +2181,12 @@
 
     const double start = now();
 
-    if (slot_override != "") slot_override = verify_slot(slot_override);
+    if (fp->slot_override != "") fp->slot_override = verify_slot(fp->slot_override);
     if (next_active != "") next_active = verify_slot(next_active, false);
 
     if (fp->wants_set_active) {
         if (next_active == "") {
-            if (slot_override == "") {
+            if (fp->slot_override == "") {
                 std::string current_slot;
                 if (fb->GetVar("current-slot", &current_slot) == fastboot::SUCCESS) {
                     if (current_slot[0] == '_') current_slot.erase(0, 1);
@@ -2196,7 +2195,7 @@
                     fp->wants_set_active = false;
                 }
             } else {
-                next_active = verify_slot(slot_override, false);
+                next_active = verify_slot(fp->slot_override, false);
             }
         }
     }
@@ -2221,7 +2220,7 @@
 
                 fb->Erase(partition);
             };
-            do_for_partitions(partition, slot_override, erase, true);
+            do_for_partitions(partition, fp->slot_override, erase, true);
         } else if (android::base::StartsWith(command, "format")) {
             // Parsing for: "format[:[type][:[size]]]"
             // Some valid things:
@@ -2241,7 +2240,7 @@
             auto format = [&](const std::string& partition) {
                 fb_perform_format(partition, 0, type_override, size_override, fp->fs_options);
             };
-            do_for_partitions(partition, slot_override, format, true);
+            do_for_partitions(partition, fp->slot_override, format, true);
         } else if (command == "signature") {
             std::string filename = next_arg(&args);
             std::vector<char> data;
@@ -2255,7 +2254,7 @@
             if (args.size() == 1) {
                 std::string reboot_target = next_arg(&args);
                 reboot_task = std::make_unique<RebootTask>(fp.get(), reboot_target);
-            } else {
+            } else if (!fp->skip_reboot) {
                 reboot_task = std::make_unique<RebootTask>(fp.get());
             }
             if (!args.empty()) syntax_error("junk after reboot command");
@@ -2286,7 +2285,7 @@
             }
             if (fname.empty()) die("cannot determine image filename for '%s'", pname.c_str());
 
-            FlashTask task(slot_override, pname, fname, is_vbmeta_partition(pname));
+            FlashTask task(fp->slot_override, pname, fname, is_vbmeta_partition(pname));
             task.Run();
         } else if (command == "flash:raw") {
             std::string partition = next_arg(&args);
@@ -2300,9 +2299,9 @@
             auto flashraw = [&data](const std::string& partition) {
                 fb->FlashPartition(partition, data);
             };
-            do_for_partitions(partition, slot_override, flashraw, true);
+            do_for_partitions(partition, fp->slot_override, flashraw, true);
         } else if (command == "flashall") {
-            if (slot_override == "all") {
+            if (fp->slot_override == "all") {
                 fprintf(stderr,
                         "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
                 fp->skip_secondary = true;
@@ -2310,9 +2309,11 @@
             } else {
                 do_flashall(fp.get());
             }
-            reboot_task = std::make_unique<RebootTask>(fp.get());
+            if (!fp->skip_reboot) {
+                reboot_task = std::make_unique<RebootTask>(fp.get());
+            }
         } else if (command == "update") {
-            bool slot_all = (slot_override == "all");
+            bool slot_all = (fp->slot_override == "all");
             if (slot_all) {
                 fprintf(stderr,
                         "Warning: slot set to 'all'. Secondary slots will not be flashed.\n");
@@ -2322,7 +2323,9 @@
                 filename = next_arg(&args);
             }
             do_update(filename.c_str(), fp.get());
-            reboot_task = std::make_unique<RebootTask>(fp.get());
+            if (!fp->skip_reboot) {
+                reboot_task = std::make_unique<RebootTask>(fp.get());
+            }
         } else if (command == FB_CMD_SET_ACTIVE) {
             std::string slot = verify_slot(next_arg(&args), false);
             fb->SetActive(slot);
@@ -2361,7 +2364,7 @@
             std::string partition = next_arg(&args);
             std::string size = next_arg(&args);
             std::unique_ptr<ResizeTask> resize_task =
-                    std::make_unique<ResizeTask>(fp.get(), partition, size, slot_override);
+                    std::make_unique<ResizeTask>(fp.get(), partition, size, fp->slot_override);
             resize_task->Run();
         } else if (command == "gsi") {
             std::string arg = next_arg(&args);
@@ -2379,7 +2382,7 @@
             } else {
                 image = next_arg(&args);
             }
-            do_wipe_super(image, slot_override);
+            do_wipe_super(image, fp->slot_override);
         } else if (command == "snapshot-update") {
             std::string arg;
             if (!args.empty()) {
@@ -2392,7 +2395,7 @@
         } else if (command == FB_CMD_FETCH) {
             std::string partition = next_arg(&args);
             std::string outfile = next_arg(&args);
-            do_fetch(partition, slot_override, outfile);
+            do_fetch(partition, fp->slot_override, outfile);
         } else {
             syntax_error("unknown command %s", command.c_str());
         }
@@ -2411,7 +2414,7 @@
     if (fp->wants_set_active) {
         fb->SetActive(next_active);
     }
-    if (reboot_task && !fp->skip_reboot) {
+    if (reboot_task) {
         reboot_task->Run();
     }
     fprintf(stderr, "Finished. Total time: %.3fs\n", (now() - start));
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index c954487..6462a4f 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -80,7 +80,7 @@
     bool skip_secondary = false;
     bool force_flash = false;
 
-    std::string slot;
+    std::string slot_override;
     std::string current_slot;
     std::string secondary_slot;
     fastboot::FastBootDriver* fb;
diff --git a/fastboot/task.cpp b/fastboot/task.cpp
index 9d4cb75..de48a16 100644
--- a/fastboot/task.cpp
+++ b/fastboot/task.cpp
@@ -42,8 +42,8 @@
     do_for_partitions(pname_, slot_, flash, true);
 }
 
-RebootTask::RebootTask(FlashingPlan* fp) : fp_(fp){};
-RebootTask::RebootTask(FlashingPlan* fp, const std::string& reboot_target)
+RebootTask::RebootTask(const FlashingPlan* fp) : fp_(fp){};
+RebootTask::RebootTask(const FlashingPlan* fp, const std::string& reboot_target)
     : reboot_target_(reboot_target), fp_(fp){};
 
 void RebootTask::Run() {
@@ -95,7 +95,7 @@
         LOG(VERBOSE) << "Cannot optimize flashing super on non-AB device";
         return nullptr;
     }
-    if (fp->slot == "all") {
+    if (fp->slot_override == "all") {
         LOG(VERBOSE) << "Cannot optimize flashing super for all slots";
         return nullptr;
     }
@@ -153,7 +153,7 @@
                                                   partition_size);
 }
 
-UpdateSuperTask::UpdateSuperTask(FlashingPlan* fp) : fp_(fp) {}
+UpdateSuperTask::UpdateSuperTask(const FlashingPlan* fp) : fp_(fp) {}
 
 void UpdateSuperTask::Run() {
     unique_fd fd = fp_->source->OpenFile("super_empty.img");
@@ -177,7 +177,7 @@
     fp_->fb->RawCommand(command, "Updating super partition");
 }
 
-ResizeTask::ResizeTask(FlashingPlan* fp, const std::string& pname, const std::string& size,
+ResizeTask::ResizeTask(const FlashingPlan* fp, const std::string& pname, const std::string& size,
                        const std::string& slot)
     : fp_(fp), pname_(pname), size_(size), slot_(slot) {}
 
@@ -190,13 +190,13 @@
     do_for_partitions(pname_, slot_, resize_partition, false);
 }
 
-DeleteTask::DeleteTask(FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
+DeleteTask::DeleteTask(const FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
 
 void DeleteTask::Run() {
     fp_->fb->DeletePartition(pname_);
 }
 
-WipeTask::WipeTask(FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
+WipeTask::WipeTask(const FlashingPlan* fp, const std::string& pname) : fp_(fp), pname_(pname){};
 
 void WipeTask::Run() {
     std::string partition_type;
diff --git a/fastboot/task.h b/fastboot/task.h
index e89f85b..e80f88d 100644
--- a/fastboot/task.h
+++ b/fastboot/task.h
@@ -46,8 +46,8 @@
 
 class RebootTask : public Task {
   public:
-    RebootTask(FlashingPlan* fp);
-    RebootTask(FlashingPlan* fp, const std::string& reboot_target);
+    RebootTask(const FlashingPlan* fp);
+    RebootTask(const FlashingPlan* fp, const std::string& reboot_target);
     void Run() override;
 
   private:
@@ -73,7 +73,7 @@
 
 class UpdateSuperTask : public Task {
   public:
-    UpdateSuperTask(FlashingPlan* fp);
+    UpdateSuperTask(const FlashingPlan* fp);
     void Run() override;
 
   private:
@@ -82,7 +82,7 @@
 
 class ResizeTask : public Task {
   public:
-    ResizeTask(FlashingPlan* fp, const std::string& pname, const std::string& size,
+    ResizeTask(const FlashingPlan* fp, const std::string& pname, const std::string& size,
                const std::string& slot);
     void Run() override;
 
@@ -95,7 +95,7 @@
 
 class DeleteTask : public Task {
   public:
-    DeleteTask(FlashingPlan* _fp, const std::string& _pname);
+    DeleteTask(const FlashingPlan* _fp, const std::string& _pname);
     void Run() override;
 
   private:
@@ -105,7 +105,7 @@
 
 class WipeTask : public Task {
   public:
-    WipeTask(FlashingPlan* fp, const std::string& pname);
+    WipeTask(const FlashingPlan* fp, const std::string& pname);
     void Run() override;
 
   private:
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 7fcaac5..1e03683 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -164,7 +164,7 @@
 }
 
 cc_test {
-    name: "cow_snapuserd_test",
+    name: "snapuserd_test_legacy",
     defaults: [
         "fs_mgr_defaults",
         "libsnapshot_cow_defaults",
@@ -216,16 +216,17 @@
     ],
     static_libs: [
         "libbrotli",
+        "libcutils_sockets",
+        "libdm",
+        "libext4_utils",
+        "libfs_mgr",
+        "libgflags",
         "libgtest",
         "libsnapshot_cow",
         "libsnapshot_snapuserd",
-        "libcutils_sockets",
-        "libz",
-        "libfs_mgr",
-        "libdm",
-        "libext4_utils",
+        "libsnapuserd",
         "liburing",
-        "libgflags",
+        "libz",
     ],
     include_dirs: ["bionic/libc/kernel"],
     header_libs: [
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index 0557214..36dad33 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -110,7 +110,7 @@
     for (int i = arg_start; i < argc; i++) {
         auto parts = android::base::Split(argv[i], ",");
         if (parts.size() != 4) {
-            LOG(ERROR) << "Malformed message, expected three sub-arguments.";
+            LOG(ERROR) << "Malformed message, expected four sub-arguments.";
             return false;
         }
         auto handler = user_server_.AddHandler(parts[0], parts[1], parts[2], parts[3]);
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
index c5150c4..bdba5c0 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/handler_manager.cpp
@@ -25,6 +25,9 @@
 
 static constexpr uint8_t kMaxMergeThreads = 2;
 
+HandlerThread::HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd)
+    : snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
+
 void HandlerThread::FreeResources() {
     // Each worker thread holds a reference to snapuserd.
     // Clear them so that all the resources
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
index 2c201ff..25ce0ae 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.cpp
@@ -433,11 +433,6 @@
     struct utsname uts;
     unsigned int major, minor;
 
-    if (android::base::GetBoolProperty("snapuserd.test.io_uring.force_disable", false)) {
-        SNAP_LOG(INFO) << "io_uring disabled for testing";
-        return false;
-    }
-
     if ((uname(&uts) != 0) || (sscanf(uts.release, "%u.%u", &major, &minor) != 2)) {
         SNAP_LOG(ERROR) << "Could not parse the kernel version from uname. "
                         << " io_uring not supported";
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 d87990a..c953f1a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -83,9 +83,6 @@
     handlers_->JoinAllThreads();
 }
 
-HandlerThread::HandlerThread(std::shared_ptr<SnapshotHandler> snapuserd)
-    : snapuserd_(snapuserd), misc_name_(snapuserd_->GetMiscName()) {}
-
 bool UserSnapshotServer::Sendmsg(android::base::borrowed_fd fd, const std::string& msg) {
     ssize_t ret = TEMP_FAILURE_RETRY(send(fd.get(), msg.data(), msg.size(), MSG_NOSIGNAL));
     if (ret < 0) {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
index 1421403..57f9e7a 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp
@@ -37,9 +37,9 @@
 #include <libdm/dm.h>
 #include <libdm/loop_control.h>
 #include <libsnapshot/cow_writer.h>
-#include <snapuserd/snapuserd_client.h>
 #include <storage_literals/storage_literals.h>
 
+#include "handler_manager.h"
 #include "snapuserd_core.h"
 
 DEFINE_string(force_config, "", "Force testing mode with iouring disabled");
@@ -54,8 +54,6 @@
 using namespace android::dm;
 using namespace std;
 
-static constexpr char kSnapuserdSocketTest[] = "snapuserdTest";
-
 class Tempdevice {
   public:
     Tempdevice(const std::string& name, const DmTable& table)
@@ -68,15 +66,15 @@
     }
     ~Tempdevice() {
         if (valid_) {
-            dm_.DeleteDevice(name_);
+            dm_.DeleteDeviceIfExists(name_);
         }
     }
     bool Destroy() {
         if (!valid_) {
-            return false;
+            return true;
         }
         valid_ = false;
-        return dm_.DeleteDevice(name_);
+        return dm_.DeleteDeviceIfExists(name_);
     }
     const std::string& path() const { return path_; }
     const std::string& name() const { return name_; }
@@ -138,7 +136,6 @@
     void SetDeviceControlName();
     void InitDaemon();
     void CreateDmUserDevice();
-    void StartSnapuserdDaemon();
 
     unique_ptr<LoopDevice> base_loop_;
     unique_ptr<Tempdevice> dmuser_dev_;
@@ -148,9 +145,9 @@
 
     unique_fd base_fd_;
     std::unique_ptr<TemporaryFile> cow_system_;
-    std::unique_ptr<SnapuserdClient> client_;
     std::unique_ptr<uint8_t[]> orig_buffer_;
     std::unique_ptr<uint8_t[]> merged_buffer_;
+    SnapshotHandlerManager handlers_;
     bool setup_ok_ = false;
     bool merge_ok_ = false;
     size_t size_ = 100_MiB;
@@ -180,9 +177,9 @@
     ASSERT_TRUE(dmuser_dev_->Destroy());
 
     auto misc_device = "/dev/dm-user/" + system_device_ctrl_name_;
-    ASSERT_TRUE(client_->WaitForDeviceDelete(system_device_ctrl_name_));
+    ASSERT_TRUE(handlers_.DeleteHandler(system_device_ctrl_name_));
     ASSERT_TRUE(android::fs_mgr::WaitForFileDeleted(misc_device, 10s));
-    ASSERT_TRUE(client_->DetachSnapuserd());
+    handlers_.TerminateMergeThreads();
 }
 
 bool SnapuserdTest::SetupDefault() {
@@ -217,8 +214,6 @@
 bool SnapuserdTest::SetupDaemon() {
     SetDeviceControlName();
 
-    StartSnapuserdDaemon();
-
     CreateDmUserDevice();
     InitCowDevice();
     InitDaemon();
@@ -228,20 +223,6 @@
     return setup_ok_;
 }
 
-void SnapuserdTest::StartSnapuserdDaemon() {
-    pid_t pid = fork();
-    ASSERT_GE(pid, 0);
-    if (pid == 0) {
-        std::string arg0 = "/system/bin/snapuserd";
-        std::string arg1 = "-socket="s + kSnapuserdSocketTest;
-        char* const argv[] = {arg0.data(), arg1.data(), nullptr};
-        ASSERT_GE(execv(arg0.c_str(), argv), 0);
-    } else {
-        client_ = SnapuserdClient::Connect(kSnapuserdSocketTest, 10s);
-        ASSERT_NE(client_, nullptr);
-    }
-}
-
 void SnapuserdTest::CreateBaseDevice() {
     unique_fd rnd_fd;
 
@@ -606,9 +587,17 @@
 }
 
 void SnapuserdTest::InitCowDevice() {
-    uint64_t num_sectors = client_->InitDmUserCow(system_device_ctrl_name_, cow_system_->path,
-                                                  base_loop_->device(), base_loop_->device());
-    ASSERT_NE(num_sectors, 0);
+    bool use_iouring = true;
+    if (FLAGS_force_config == "iouring_disabled") {
+        use_iouring = false;
+    }
+
+    auto handler =
+            handlers_.AddHandler(system_device_ctrl_name_, cow_system_->path, base_loop_->device(),
+                                 base_loop_->device(), 1, use_iouring, false);
+    ASSERT_NE(handler, nullptr);
+    ASSERT_NE(handler->snapuserd(), nullptr);
+    ASSERT_NE(handler->snapuserd()->GetNumSectors(), 0);
 }
 
 void SnapuserdTest::SetDeviceControlName() {
@@ -646,13 +635,12 @@
 }
 
 void SnapuserdTest::InitDaemon() {
-    bool ok = client_->AttachDmUser(system_device_ctrl_name_);
-    ASSERT_TRUE(ok);
+    ASSERT_TRUE(handlers_.StartHandler(system_device_ctrl_name_));
 }
 
 void SnapuserdTest::CheckMergeCompletion() {
     while (true) {
-        double percentage = client_->GetMergePercent();
+        double percentage = handlers_.GetMergePercentage();
         if ((int)percentage == 100) {
             break;
         }
@@ -667,8 +655,6 @@
 
     SetDeviceControlName();
 
-    StartSnapuserdDaemon();
-
     CreateDmUserDevice();
     InitCowDevice();
     InitDaemon();
@@ -684,8 +670,7 @@
 }
 
 void SnapuserdTest::StartMerge() {
-    bool ok = client_->InitiateMerge(system_device_ctrl_name_);
-    ASSERT_TRUE(ok);
+    ASSERT_TRUE(handlers_.InitiateMerge(system_device_ctrl_name_));
 }
 
 void SnapuserdTest::ValidateMerge() {
@@ -699,7 +684,6 @@
     Shutdown();
     std::this_thread::sleep_for(500ms);
     SetDeviceControlName();
-    StartSnapuserdDaemon();
     CreateDmUserDevice();
     InitCowDevice();
     InitDaemon();
@@ -859,20 +843,5 @@
 
     gflags::ParseCommandLineFlags(&argc, &argv, false);
 
-    android::base::SetProperty("ctl.stop", "snapuserd");
-
-    if (FLAGS_force_config == "iouring_disabled") {
-        if (!android::base::SetProperty("snapuserd.test.io_uring.force_disable", "1")) {
-            return testing::AssertionFailure()
-                   << "Failed to disable property: snapuserd.test.io_uring.disabled";
-        }
-    }
-
-    int ret = RUN_ALL_TESTS();
-
-    if (FLAGS_force_config == "iouring_disabled") {
-        android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
-    }
-
-    return ret;
+    return RUN_ALL_TESTS();
 }
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 10efd0c..7273087 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -53,6 +53,7 @@
     std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  getuuid <dm-name>" << std::endl;
     std::cerr << "  info <dm-name>" << std::endl;
+    std::cerr << "  replace <dm-name> <targets...>" << std::endl;
     std::cerr << "  status <dm-name>" << std::endl;
     std::cerr << "  resume <dm-name>" << std::endl;
     std::cerr << "  suspend <dm-name>" << std::endl;
diff --git a/init/README.md b/init/README.md
index b006365..6bdff4a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -642,17 +642,17 @@
   the current SELinux policy or its parent if not specified in the policy. If
   the directory exists, its security context will not be changed (even if
   different from the policy).
-
-  > _action_ can be one of:
-  * `None`: take no encryption action; directory will be encrypted if parent is.
-  * `Require`: encrypt directory, abort boot process if encryption fails
-  * `Attempt`: try to set an encryption policy, but continue if it fails
-  * `DeleteIfNecessary`: recursively delete directory if necessary to set
-  encryption policy.
-
-  > _key_ can be one of:
-  * `ref`: use the systemwide DE key
-  * `per_boot_ref`: use the key freshly generated on each boot.
+>
+> _action_ can be one of:
+>  * `None`: take no encryption action; directory will be encrypted if parent is.
+>  * `Require`: encrypt directory, abort boot process if encryption fails
+>  * `Attempt`: try to set an encryption policy, but continue if it fails
+>  * `DeleteIfNecessary`: recursively delete directory if necessary to set
+>  encryption policy.
+>
+> _key_ can be one of:
+>  * `ref`: use the systemwide DE key
+>  * `per_boot_ref`: use the key freshly generated on each boot.
 
 `mount_all [ <fstab> ] [--<option>]`
 > Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 305bf95..0fc3ffc 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -204,6 +204,10 @@
         GTEST_SKIP() << "Must run on userdebug/eng builds. b/262090304";
         return;
     }
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string init_script = R"init(
 service console /system/bin/sh
     class core
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 062ed39..907eb80 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -761,15 +761,7 @@
 
 constexpr size_t kKlogMessageSize = 1024;
 
-void SelinuxAvcLog(char* buf, size_t buf_len) {
-    CHECK_GT(buf_len, 0u);
-
-    size_t str_len = strnlen(buf, buf_len);
-    // trim newline at end of string
-    if (buf[str_len - 1] == '\n') {
-        buf[str_len - 1] = '\0';
-    }
-
+void SelinuxAvcLog(char* buf) {
     struct NetlinkMessage {
         nlmsghdr hdr;
         char buf[kKlogMessageSize];
@@ -835,8 +827,17 @@
     if (length_written <= 0) {
         return 0;
     }
+
+    // libselinux log messages usually contain a new line character, while
+    // Android LOG() does not expect it. Remove it to avoid empty lines in
+    // the log buffers.
+    size_t str_len = strlen(buf);
+    if (buf[str_len - 1] == '\n') {
+        buf[str_len - 1] = '\0';
+    }
+
     if (type == SELINUX_AVC) {
-        SelinuxAvcLog(buf, sizeof(buf));
+        SelinuxAvcLog(buf);
     } else {
         android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
     }
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index a6835fc..e46774b 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -83,6 +83,8 @@
     { 00751, AID_ROOT,         AID_SHELL,        0, "product/apex/*/bin" },
     { 00777, AID_ROOT,         AID_ROOT,         0, "sdcard" },
     { 00751, AID_ROOT,         AID_SDCARD_R,     0, "storage" },
+    { 00750, AID_ROOT,         AID_SYSTEM,       0, "system/apex/com.android.tethering/bin/for-system" },
+    { 00750, AID_ROOT,         AID_SYSTEM,       0, "system/apex/com.android.tethering.inprocess/bin/for-system" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "system/bin" },
     { 00755, AID_ROOT,         AID_ROOT,         0, "system/etc/ppp" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "system/vendor" },
@@ -194,6 +196,8 @@
 
     // the following files have enhanced capabilities and ARE included
     // in user builds.
+    { 06755, AID_CLAT,      AID_CLAT,      0, "system/apex/com.android.tethering/bin/for-system/clatd" },
+    { 06755, AID_CLAT,      AID_CLAT,      0, "system/apex/com.android.tethering.inprocess/bin/for-system/clatd" },
     { 00700, AID_SYSTEM,    AID_SHELL,     CAP_MASK_LONG(CAP_BLOCK_SUSPEND),
                                               "system/bin/inputflinger" },
     { 00750, AID_ROOT,      AID_SHELL,     CAP_MASK_LONG(CAP_SETUID) |
diff --git a/libprocessgroup/task_profiles_test.cpp b/libprocessgroup/task_profiles_test.cpp
index 09ac44c..c449e95 100644
--- a/libprocessgroup/task_profiles_test.cpp
+++ b/libprocessgroup/task_profiles_test.cpp
@@ -43,7 +43,7 @@
     }
     struct mntent* mnt;
     while ((mnt = getmntent(mnts.get()))) {
-        if (strcmp(mnt->mnt_fsname, "cgroup2") == 0) {
+        if (strcmp(mnt->mnt_type, "cgroup2") == 0) {
             return true;
         }
     }