Merge "snapuserd: Use GTEST_SKIP in snapuserd_test." into main
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 13c8d70..5bdc946 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -3302,3 +3302,30 @@
   ASSERT_MATCH(result, ":\\s*This line has a newline.");
   ASSERT_MATCH(result, ":\\s*This is on the next line.");
 }
+
+TEST_F(CrasherTest, log_with_non_utf8) {
+  StartProcess([]() { LOG(FATAL) << "Invalid UTF-8: \xA0\xB0\xC0\xD0 and some other data."; });
+
+  unique_fd output_fd;
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGABRT);
+  int intercept_result;
+  FinishIntercept(&intercept_result);
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  // Verify the abort message is sanitized properly.
+  size_t pos = result.find(
+      "Abort message: 'Invalid UTF-8: "
+      "\x5C\x32\x34\x30\x5C\x32\x36\x30\x5C\x33\x30\x30\x5C\x33\x32\x30 and some other data.'");
+  EXPECT_TRUE(pos != std::string::npos) << "Couldn't find sanitized abort message: " << result;
+
+  // Make sure that the log message is sanitized properly too.
+  EXPECT_TRUE(
+      result.find("Invalid UTF-8: \x5C\x32\x34\x30\x5C\x32\x36\x30\x5C\x33\x30\x30\x5C\x33\x32\x30 "
+                  "and some other data.",
+                  pos + 30) != std::string::npos)
+      << "Couldn't find sanitized log message: " << result;
+}
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index ddc3244..88278ca 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -389,6 +389,13 @@
   return kDebuggerdTombstoneProto;
 }
 
+static const char* get_unwind_type(const debugger_thread_info* thread_info) {
+  if (thread_info->siginfo->si_signo == BIONIC_SIGNAL_DEBUGGER) {
+    return "Unwind request";
+  }
+  return "Crash due to signal";
+}
+
 static int debuggerd_dispatch_pseudothread(void* arg) {
   debugger_thread_info* thread_info = static_cast<debugger_thread_info*>(arg);
 
@@ -502,8 +509,8 @@
 
     execle(CRASH_DUMP_PATH, CRASH_DUMP_NAME, main_tid, pseudothread_tid, debuggerd_dump_type,
            nullptr, nullptr);
-    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "failed to exec crash_dump helper: %s",
-                          strerror(errno));
+    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "%s: failed to exec crash_dump helper: %s",
+                          get_unwind_type(thread_info), strerror(errno));
     return 1;
   }
 
@@ -524,26 +531,30 @@
   } else {
     // Something went wrong, log it.
     if (rc == -1) {
-      async_safe_format_log(ANDROID_LOG_FATAL, "libc", "read of IPC pipe failed: %s",
-                            strerror(errno));
+      async_safe_format_log(ANDROID_LOG_FATAL, "libc", "%s: read of IPC pipe failed: %s",
+                            get_unwind_type(thread_info), strerror(errno));
     } else if (rc == 0) {
       async_safe_format_log(ANDROID_LOG_FATAL, "libc",
-                            "crash_dump helper failed to exec, or was killed");
+                            "%s: crash_dump helper failed to exec, or was killed",
+                            get_unwind_type(thread_info));
     } else if (rc != 1) {
       async_safe_format_log(ANDROID_LOG_FATAL, "libc",
-                            "read of IPC pipe returned unexpected value: %zd", rc);
+                            "%s: read of IPC pipe returned unexpected value: %zd",
+                            get_unwind_type(thread_info), rc);
     } else if (buf[0] != '\1') {
-      async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper reported failure");
+      async_safe_format_log(ANDROID_LOG_FATAL, "libc", "%s: crash_dump helper reported failure",
+                            get_unwind_type(thread_info));
     }
   }
 
   // Don't leave a zombie child.
   int status;
   if (TEMP_FAILURE_RETRY(waitpid(crash_dump_pid, &status, 0)) == -1) {
-    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "failed to wait for crash_dump helper: %s",
-                          strerror(errno));
+    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "%s: failed to wait for crash_dump helper: %s",
+                          get_unwind_type(thread_info), strerror(errno));
   } else if (WIFSTOPPED(status) || WIFSIGNALED(status)) {
-    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "crash_dump helper crashed or stopped");
+    async_safe_format_log(ANDROID_LOG_FATAL, "libc", "%s: crash_dump helper crashed or stopped",
+                          get_unwind_type(thread_info));
   }
 
   if (success) {
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
index 43fb8bd..df22e01 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility_host.h
@@ -29,3 +29,5 @@
 // Number of rows and columns to display in an MTE tag dump.
 constexpr size_t kNumTagColumns = 16;
 constexpr size_t kNumTagRows = 16;
+
+std::string oct_encode(const std::string& data);
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index d59358c..ef303f0 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -34,10 +34,13 @@
 #include <sys/sysinfo.h>
 #include <time.h>
 
+#include <map>
 #include <memory>
 #include <optional>
 #include <set>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include <async_safe/log.h>
 
@@ -463,7 +466,8 @@
   }
   msg.resize(index);
 
-  tombstone->set_abort_message(msg);
+  // Make sure only UTF8 characters are present since abort_message is a string.
+  tombstone->set_abort_message(oct_encode(msg));
 }
 
 static void dump_open_fds(Tombstone* tombstone, const OpenFilesList* open_files) {
@@ -771,7 +775,8 @@
       log_msg->set_tid(log_entry.entry.tid);
       log_msg->set_priority(prio);
       log_msg->set_tag(tag);
-      log_msg->set_message(msg);
+      // Make sure only UTF8 characters are present since message is a string.
+      log_msg->set_message(oct_encode(msg));
     } while ((msg = nl));
   }
   android_logger_list_free(logger_list);
diff --git a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
index fedafc0..e885c5a 100644
--- a/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto_to_text.cpp
@@ -19,9 +19,9 @@
 
 #include <inttypes.h>
 
-#include <charconv>
+#include <algorithm>
 #include <functional>
-#include <limits>
+#include <optional>
 #include <set>
 #include <string>
 #include <unordered_set>
@@ -32,6 +32,7 @@
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
 
+#include "libdebuggerd/utility_host.h"
 #include "tombstone.pb.h"
 
 using android::base::StringAppendF;
@@ -418,27 +419,6 @@
   }
 }
 
-static std::string oct_encode(const std::string& data) {
-  std::string oct_encoded;
-  oct_encoded.reserve(data.size());
-
-  // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
-  // \-123 (and overflow our buffer).
-  for (unsigned char c : data) {
-    if (isprint(c)) {
-      oct_encoded += c;
-    } else {
-      std::string oct_digits("\\\0\0\0", 4);
-      // char is encodable in 3 oct digits
-      static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
-      auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
-      oct_digits.resize(ptr - oct_digits.data());
-      oct_encoded += oct_digits;
-    }
-  }
-  return oct_encoded;
-}
-
 static void print_main_thread(CallbackType callback, SymbolizeCallbackType symbolize,
                               const Tombstone& tombstone, const Thread& thread) {
   print_thread_header(callback, tombstone, thread, true);
diff --git a/debuggerd/libdebuggerd/utility_host.cpp b/debuggerd/libdebuggerd/utility_host.cpp
index 72a560c..4efa03c 100644
--- a/debuggerd/libdebuggerd/utility_host.cpp
+++ b/debuggerd/libdebuggerd/utility_host.cpp
@@ -18,6 +18,8 @@
 
 #include <sys/prctl.h>
 
+#include <charconv>
+#include <limits>
 #include <string>
 
 #include <android-base/stringprintf.h>
@@ -99,3 +101,24 @@
   DESCRIBE_FLAG(PR_PAC_APGAKEY);
   return describe_end(value, desc);
 }
+
+std::string oct_encode(const std::string& data) {
+  std::string oct_encoded;
+  oct_encoded.reserve(data.size());
+
+  // N.B. the unsigned here is very important, otherwise e.g. \255 would render as
+  // \-123 (and overflow our buffer).
+  for (unsigned char c : data) {
+    if (isprint(c)) {
+      oct_encoded += c;
+    } else {
+      std::string oct_digits("\\\0\0\0", 4);
+      // char is encodable in 3 oct digits
+      static_assert(std::numeric_limits<unsigned char>::max() <= 8 * 8 * 8);
+      auto [ptr, ec] = std::to_chars(oct_digits.data() + 1, oct_digits.data() + 4, c, 8);
+      oct_digits.resize(ptr - oct_digits.data());
+      oct_encoded += oct_digits;
+    }
+  }
+  return oct_encoded;
+}
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index e4d6986..9f52f44 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -822,9 +822,6 @@
     if (read_only) {
         mountflags |= MS_RDONLY;
     }
-    if (!fs_mgr_set_blk_ro(source, read_only)) {
-        PLOG(ERROR) << "Failed to set " << source << " as " << (read_only ? "RO" : "RW");
-    }
     int ret = 0;
     int save_errno = 0;
     int gc_allowance = 0;
@@ -879,6 +876,9 @@
     }
     PINFO << __FUNCTION__ << "(source=" << source << source_missing << ",target=" << target
           << target_missing << ",type=" << entry.fs_type << ")=" << ret;
+    if ((ret == 0) && (mountflags & MS_RDONLY) != 0) {
+        fs_mgr_set_blk_ro(source);
+    }
     if (ret == 0) {
         android::base::SetProperty("ro.boottime.init.mount." + Basename(target),
                                    std::to_string(t.duration().count()));
diff --git a/fs_mgr/libsnapshot/snapuserd/Android.bp b/fs_mgr/libsnapshot/snapuserd/Android.bp
index 97cfe76..639116e 100644
--- a/fs_mgr/libsnapshot/snapuserd/Android.bp
+++ b/fs_mgr/libsnapshot/snapuserd/Android.bp
@@ -89,7 +89,6 @@
         "libprocessgroup_util",
         "libjsoncpp",
     ],
-    include_dirs: ["bionic/libc/kernel"],
     export_include_dirs: ["include"],
     header_libs: [
         "libcutils_headers",
@@ -144,7 +143,6 @@
         "libstorage_literals_headers",
     ],
 
-    include_dirs: ["bionic/libc/kernel"],
     system_shared_libs: [],
 
     // snapuserd is started during early boot by first-stage init. At that
@@ -226,7 +224,6 @@
         "libz",
     ],
     include_dirs: [
-        "bionic/libc/kernel",
         ".",
     ],
     header_libs: [
@@ -324,7 +321,6 @@
         "libz",
     ],
     include_dirs: [
-        "bionic/libc/kernel",
         ".",
     ],
     header_libs: [
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
index 486548c..a0c5c66 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/merge_worker.cpp
@@ -582,7 +582,6 @@
     pthread_setname_np(pthread_self(), "MergeWorker");
 
     if (!snapuserd_->WaitForMergeBegin()) {
-        SNAP_LOG(ERROR) << "Merge terminated early...";
         return true;
     }
     auto merge_thread_priority = android::base::GetUintProperty<uint32_t>(
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
index 9a1d441..3007d45 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -702,7 +702,7 @@
     // window. If there is a crash during this time frame, merge should resume
     // based on the contents of the scratch space.
     if (!snapuserd_->WaitForMergeReady()) {
-        SNAP_LOG(ERROR) << "ReadAhead failed to wait for merge ready";
+        SNAP_LOG(VERBOSE) << "ReadAhead failed to wait for merge ready";
         return false;
     }
 
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_transitions.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_transitions.cpp
index 2ad4ea1..714c641 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_transitions.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_transitions.cpp
@@ -202,7 +202,7 @@
     cv.wait(lock, [this]() -> bool { return MergeInitiated() || IsMergeBeginError(io_state_); });
 
     if (IsMergeBeginError(io_state_)) {
-        SNAP_LOG(ERROR) << "WaitForMergeBegin failed with state: " << io_state_;
+        SNAP_LOG(VERBOSE) << "WaitForMergeBegin failed with state: " << io_state_;
         return false;
     }
 
@@ -276,7 +276,9 @@
         if (io_state_ == MERGE_IO_TRANSITION::MERGE_FAILED ||
             io_state_ == MERGE_IO_TRANSITION::MERGE_COMPLETE ||
             io_state_ == MERGE_IO_TRANSITION::IO_TERMINATED) {
-            SNAP_LOG(ERROR) << "Wait for merge ready failed: " << io_state_;
+            if (io_state_ == MERGE_IO_TRANSITION::MERGE_FAILED) {
+                SNAP_LOG(ERROR) << "Wait for merge ready failed: " << io_state_;
+            }
             return false;
         }
         return true;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
index 7c99085..b300a70 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_verify.h
@@ -62,8 +62,8 @@
      * (/proc/pressure/{cpu,memory}; and monitoring the Inactive(file) and
      * Active(file) pages from /proc/meminfo.
      *
-     * Additionally, for low memory devices, it is advisible to use O_DIRECT
-     * fucntionality for source block device.
+     * Additionally, for low memory devices, it is advisable to use O_DIRECT
+     * functionality for source block device.
      */
     int kMinThreadsToVerify = 1;
     int kMaxThreadsToVerify = 3;
diff --git a/init/devices.cpp b/init/devices.cpp
index 2cdecec..fafa58f 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -193,9 +193,11 @@
     BlockDeviceInfo info;
 
     if (!boot_part_uuid_.empty()) {
-        // Only use the more specific "MMC" or "SCSI" match if a partition UUID
-        // was passed. Old bootloaders that aren't passing the partition UUID
-        // instead pass the path to the closest "platform" device. It would
+        // Only use the more specific "MMC" / "NVME" / "SCSI" match if a
+        // partition UUID was passed.
+        //
+        // Old bootloaders that aren't passing the partition UUID instead
+        // pass the path to the closest "platform" device. It would
         // break them if we chose this deeper (more specific) path.
         //
         // When we have a UUID we _want_ the more specific path since it can
@@ -204,6 +206,8 @@
         // classify them both the same by using the path to the USB controller.
         if (FindMmcDevice(uevent_path, &info.str)) {
             info.type = "mmc";
+        } else if (FindNvmeDevice(uevent_path, &info.str)) {
+            info.type = "nvme";
         } else if (FindScsiDevice(uevent_path, &info.str)) {
             info.type = "scsi";
         }
@@ -325,6 +329,14 @@
     return FindSubsystemDevice(path, mmc_device_path, subsystem_paths);
 }
 
+bool DeviceHandler::FindNvmeDevice(const std::string& path, std::string* nvme_device_path) const {
+    const std::set<std::string> subsystem_paths = {
+            sysfs_mount_point_ + "/class/nvme",
+    };
+
+    return FindSubsystemDevice(path, nvme_device_path, subsystem_paths);
+}
+
 bool DeviceHandler::FindScsiDevice(const std::string& path, std::string* scsi_device_path) const {
     const std::set<std::string> subsystem_paths = {
             sysfs_mount_point_ + "/bus/scsi",
diff --git a/init/devices.h b/init/devices.h
index 67a3d00..b8f8e54 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -151,6 +151,7 @@
                              const std::set<std::string>& subsystem_paths) const;
     bool FindPlatformDevice(const std::string& path, std::string* platform_device_path) const;
     bool FindMmcDevice(const std::string& path, std::string* mmc_device_path) const;
+    bool FindNvmeDevice(const std::string& path, std::string* nvme_device_path) const;
     bool FindScsiDevice(const std::string& path, std::string* scsi_device_path) const;
     std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
         const std::string& path, const std::vector<std::string>& links) const;
diff --git a/init/init.cpp b/init/init.cpp
index 17498da..5b0b0dd 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -315,8 +315,7 @@
         if (apex_info_list.has_value()) {
             std::vector<std::string> subcontext_apexes;
             for (const auto& info : apex_info_list->getApexInfo()) {
-                if (info.hasPreinstalledModulePath() &&
-                    subcontext->PathMatchesSubcontext(info.getPreinstalledModulePath())) {
+                if (subcontext->PartitionMatchesSubcontext(info.getPartition())) {
                     subcontext_apexes.push_back(info.getModuleName());
                 }
             }
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 6a095fb..3fe448f 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -263,6 +263,10 @@
     return false;
 }
 
+bool Subcontext::PartitionMatchesSubcontext(const std::string& partition) const {
+    return std::find(partitions_.begin(), partitions_.end(), partition) != partitions_.end();
+}
+
 void Subcontext::SetApexList(std::vector<std::string>&& apex_list) {
     apex_list_ = std::move(apex_list);
 }
@@ -352,12 +356,13 @@
     }
 
     if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_P__) {
-        subcontext.reset(
-                new Subcontext(std::vector<std::string>{"/vendor", "/odm"}, kVendorContext));
+        subcontext.reset(new Subcontext(std::vector<std::string>{"/vendor", "/odm"},
+                                        std::vector<std::string>{"VENDOR", "ODM"}, kVendorContext));
     }
 }
+
 void InitializeHostSubcontext(std::vector<std::string> vendor_prefixes) {
-    subcontext.reset(new Subcontext(vendor_prefixes, kVendorContext, /*host=*/true));
+    subcontext.reset(new Subcontext(vendor_prefixes, {}, kVendorContext, /*host=*/true));
 }
 
 Subcontext* GetSubcontext() {
diff --git a/init/subcontext.h b/init/subcontext.h
index 93ebace..23c4a24 100644
--- a/init/subcontext.h
+++ b/init/subcontext.h
@@ -36,8 +36,10 @@
 
 class Subcontext {
   public:
-    Subcontext(std::vector<std::string> path_prefixes, std::string_view context, bool host = false)
+    Subcontext(std::vector<std::string> path_prefixes, std::vector<std::string> partitions,
+               std::string_view context, bool host = false)
         : path_prefixes_(std::move(path_prefixes)),
+          partitions_(std::move(partitions)),
           context_(context.begin(), context.end()),
           pid_(0) {
         if (!host) {
@@ -49,6 +51,7 @@
     Result<std::vector<std::string>> ExpandArgs(const std::vector<std::string>& args);
     void Restart();
     bool PathMatchesSubcontext(const std::string& path) const;
+    bool PartitionMatchesSubcontext(const std::string& partition) const;
     void SetApexList(std::vector<std::string>&& apex_list);
 
     const std::string& context() const { return context_; }
@@ -59,6 +62,7 @@
     Result<SubcontextReply> TransmitMessage(const SubcontextCommand& subcontext_command);
 
     std::vector<std::string> path_prefixes_;
+    std::vector<std::string> partitions_;
     std::vector<std::string> apex_list_;
     std::string context_;
     pid_t pid_;
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
index ccef2f3..172ee31 100644
--- a/init/subcontext_benchmark.cpp
+++ b/init/subcontext_benchmark.cpp
@@ -33,7 +33,7 @@
         return;
     }
 
-    auto subcontext = Subcontext({"path"}, context);
+    auto subcontext = Subcontext({"path"}, {"partition"}, context);
     free(context);
 
     while (state.KeepRunning()) {
diff --git a/init/subcontext_test.cpp b/init/subcontext_test.cpp
index da1f455..85a2f2a 100644
--- a/init/subcontext_test.cpp
+++ b/init/subcontext_test.cpp
@@ -41,7 +41,7 @@
 
 template <typename F>
 void RunTest(F&& test_function) {
-    auto subcontext = Subcontext({"dummy_path"}, kTestContext);
+    auto subcontext = Subcontext({"dummy_path"}, {"dummy_partition"}, kTestContext);
     ASSERT_NE(0, subcontext.pid());
 
     test_function(subcontext);
@@ -177,6 +177,19 @@
     });
 }
 
+TEST(subcontext, PartitionMatchesSubcontext) {
+    RunTest([](auto& subcontext) {
+        static auto& existent_partition = "dummy_partition";
+        static auto& non_existent_partition = "not_dummy_partition";
+
+        auto existent_result = subcontext.PartitionMatchesSubcontext(existent_partition);
+        auto non_existent_result = subcontext.PartitionMatchesSubcontext(non_existent_partition);
+
+        ASSERT_TRUE(existent_result);
+        ASSERT_FALSE(non_existent_result);
+    });
+}
+
 BuiltinFunctionMap BuildTestFunctionMap() {
     // For CheckDifferentPid
     auto do_return_pids_as_error = [](const BuiltinArguments& args) -> Result<void> {
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index b0bddf5..2aaafbe 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -143,6 +143,7 @@
 #define AID_PRNG_SEEDER 1092         /* PRNG seeder daemon */
 #define AID_UPROBESTATS 1093         /* uid for uprobestats */
 #define AID_CROS_EC 1094             /* uid for accessing ChromeOS EC (cros_ec) */
+#define AID_MMD 1095                 /* uid for memory management daemon */
 // Additions to this file must be made in AOSP, *not* in internal branches.
 // You will also need to update expect_ids() in bionic/tests/grp_pwd_test.cpp.
 
diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h
index 8057757..6a026a7 100644
--- a/libprocessgroup/include/processgroup/processgroup.h
+++ b/libprocessgroup/include/processgroup/processgroup.h
@@ -16,7 +16,6 @@
 
 #pragma once
 
-#include <sys/cdefs.h>
 #include <sys/types.h>
 #include <initializer_list>
 #include <span>
@@ -24,10 +23,7 @@
 #include <string_view>
 #include <vector>
 
-__BEGIN_DECLS
-
-static constexpr const char* CGROUPV2_HIERARCHY_NAME = "cgroup2";
-[[deprecated]] static constexpr const char* CGROUPV2_CONTROLLER_NAME = "cgroup2";
+static constexpr std::string CGROUPV2_HIERARCHY_NAME = "cgroup2";
 
 bool CgroupsAvailable();
 bool CgroupGetControllerPath(const std::string& cgroup_name, std::string* path);
@@ -40,8 +36,6 @@
 bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
 bool SetUserProfiles(uid_t uid, const std::vector<std::string>& profiles);
 
-__END_DECLS
-
 bool SetTaskProfiles(pid_t tid, std::initializer_list<std::string_view> profiles,
                      bool use_fd_cache = false);
 bool SetProcessProfiles(uid_t uid, pid_t pid, std::initializer_list<std::string_view> profiles);
@@ -51,14 +45,11 @@
 bool SetProcessProfiles(uid_t uid, pid_t pid, std::span<const std::string_view> profiles);
 #endif
 
-__BEGIN_DECLS
 
 #ifndef __ANDROID_VNDK__
 
 bool SetProcessProfilesCached(uid_t uid, pid_t pid, const std::vector<std::string>& profiles);
 
-[[deprecated]] static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc";
-
 bool UsePerAppMemcg();
 
 // Drop the fd cache of cgroup path. It is used for when resource caching is enabled and a process
@@ -99,5 +90,3 @@
 bool isProfileValidForProcess(const std::string& profile_name, uid_t uid, pid_t pid);
 
 #endif // __ANDROID_VNDK__
-
-__END_DECLS
diff --git a/libprocessgroup/setup/cgroup_map_write.cpp b/libprocessgroup/setup/cgroup_map_write.cpp
index d05bf24..c4e1fb6 100644
--- a/libprocessgroup/setup/cgroup_map_write.cpp
+++ b/libprocessgroup/setup/cgroup_map_write.cpp
@@ -222,7 +222,7 @@
     const CgroupController* controller = descriptor.controller();
 
     if (controller->version() == 2) {
-        if (!strcmp(controller->name(), CGROUPV2_HIERARCHY_NAME)) {
+        if (controller->name() == CGROUPV2_HIERARCHY_NAME) {
             return MountV2CgroupController(descriptor);
         } else {
             return ActivateV2CgroupController(descriptor);
diff --git a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc
index ca6132e..410e10a 100644
--- a/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc
+++ b/trusty/keymint/android.hardware.security.keymint-service.rust.trusty.system.nonsecure.rc
@@ -11,7 +11,7 @@
 # Only starts the non-secure KeyMint HALs when the KeyMint VM feature is enabled
 # TODO(b/357821690): Start the KeyMint HALs when the KeyMint VM is ready once the Trusty VM
 # has a mechanism to notify the host.
-on late-fs && property:ro.hardware.security.keymint.trusty.system=1 && \
+on late-fs && property:ro.hardware.trusty.security_vm.keymint.enabled=1 && \
    property:trusty.security_vm.vm_cid=*
     setprop system.keymint.trusty_ipc_dev VSOCK:${trusty.security_vm.vm_cid}:1
     start system.keymint.rust-trusty.nonsecure
diff --git a/trusty/utils/rpmb_dev/Android.bp b/trusty/utils/rpmb_dev/Android.bp
index 13f151d..ef23cc5 100644
--- a/trusty/utils/rpmb_dev/Android.bp
+++ b/trusty/utils/rpmb_dev/Android.bp
@@ -49,3 +49,12 @@
         "rpmb_dev.system.rc",
     ],
 }
+
+cc_binary {
+    name: "rpmb_dev.wv.system",
+    defaults: ["rpmb_dev.cc_defaults"],
+    system_ext_specific: true,
+    init_rc: [
+        "rpmb_dev.wv.system.rc",
+    ],
+}
diff --git a/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc b/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc
new file mode 100644
index 0000000..3e7f8b4
--- /dev/null
+++ b/trusty/utils/rpmb_dev/rpmb_dev.wv.system.rc
@@ -0,0 +1,62 @@
+service storageproxyd_wv_system /system_ext/bin/storageproxyd.system \
+        -d ${storageproxyd_wv_system.trusty_ipc_dev:-/dev/trusty-ipc-dev0} \
+        -r /dev/socket/rpmb_mock_wv_system \
+        -p /data/secure_storage_wv_system \
+        -t sock
+    disabled
+    class hal
+    user system
+    group system
+
+service rpmb_mock_init_wv_system /system_ext/bin/rpmb_dev.wv.system \
+        --dev /mnt/secure_storage_rpmb_wv_system/persist/RPMB_DATA --init --size 2048
+    disabled
+    user system
+    group system
+    oneshot
+
+service rpmb_mock_wv_system /system_ext/bin/rpmb_dev.wv.system \
+        --dev /mnt/secure_storage_rpmb_wv_system/persist/RPMB_DATA \
+        --sock rpmb_mock_wv_system
+    disabled
+    user system
+    group system
+    socket rpmb_mock_wv_system stream 660 system system
+
+# storageproxyd
+on boot && \
+    property:trusty.widevine_vm.nonsecure_vm_ready=1 && \
+    property:storageproxyd_wv_system.trusty_ipc_dev=*
+    wait /dev/socket/rpmb_mock_wv_system
+    enable storageproxyd_wv_system
+
+
+# RPMB Mock
+on early-boot && \
+    property:ro.hardware.security.trusty.widevine_vm.system=1 && \
+    property:trusty.widevine_vm.vm_cid=* && \
+    property:ro.boot.vendor.apex.com.android.services.widevine=\
+com.android.services.widevine.cf_guest_trusty_nonsecure
+    # Create a persistent location for the RPMB data
+    # (work around lack of RPMb block device on CF).
+    # file contexts secure_storage_rpmb_system_file
+    # (only used on Cuttlefish as this is non secure)
+    mkdir /metadata/secure_storage_rpmb_wv_system 0770 system system
+    mkdir /mnt/secure_storage_rpmb_wv_system 0770 system system
+    symlink /metadata/secure_storage_rpmb_wv_system \
+            /mnt/secure_storage_rpmb_wv_system/persist
+    # Create a system persist directory in /metadata
+    # (work around lack of dedicated system persist partition).
+    # file contexts secure_storage_persist_system_file
+    mkdir /metadata/secure_storage_persist_wv_system 0770 system system
+    mkdir /mnt/secure_storage_persist_wv_system 0770 system system
+    symlink /metadata/secure_storage_persist_wv_system \
+            /mnt/secure_storage_persist_wv_system/persist
+    # file contexts secure_storage_system_file
+    mkdir /data/secure_storage_wv_system 0770 root system
+    symlink /mnt/secure_storage_persist_wv_system/persist \
+            /data/secure_storage_wv_system/persist
+    chown root system /data/secure_storage_wv_system/persist
+    setprop storageproxyd_wv_system.trusty_ipc_dev VSOCK:${trusty.widevine_vm.vm_cid}:1
+    exec_start rpmb_mock_init_wv_system
+    start rpmb_mock_wv_system