Merge "Use _Fork()." into main
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 439218d..235fdfd 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -371,6 +371,11 @@
         },
     },
 
+    sanitize: {
+        memtag_heap: true,
+        memtag_stack: true,
+    },
+
     shared_libs: [
         "libbase",
         "libcutils",
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index f396b1d..526e2ca 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -21,6 +21,7 @@
 #include <linux/prctl.h>
 #include <malloc.h>
 #include <pthread.h>
+#include <setjmp.h>
 #include <stdlib.h>
 #include <sys/capability.h>
 #include <sys/mman.h>
@@ -601,6 +602,54 @@
 #endif
 }
 
+__attribute__((noinline)) void mte_illegal_setjmp_helper(jmp_buf& jump_buf) {
+  // This frame is at least 8 bytes for storing and restoring the LR before the
+  // setjmp below. So this can never get an empty stack frame, even if we omit
+  // the frame pointer. So, the SP of this is always less (numerically) than the
+  // calling function frame.
+  setjmp(jump_buf);
+}
+
+TEST_F(CrasherTest, mte_illegal_setjmp) {
+  // This setjmp is illegal because it jumps back into a function that already returned.
+  // Quoting man 3 setjmp:
+  //     If the function which called setjmp() returns before longjmp() is
+  //     called, the behavior is undefined.  Some kind of subtle or
+  //     unsubtle chaos is sure to result.
+  // https://man7.org/linux/man-pages/man3/longjmp.3.html
+#if defined(__aarch64__)
+  if (!mte_supported()) {
+    GTEST_SKIP() << "Requires MTE";
+  }
+
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess([&]() {
+    SetTagCheckingLevelSync();
+    jmp_buf jump_buf;
+    mte_illegal_setjmp_helper(jump_buf);
+    longjmp(jump_buf, 1);
+  });
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGABRT);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+
+  // In our test-case, we have a NEGATIVE stack adjustment, which is being
+  // interpreted as unsigned integer, and thus is "too large".
+  // TODO(fmayer): fix the error message for this
+  ASSERT_MATCH(result, R"(memtag_handle_longjmp: stack adjustment too large)");
+#else
+  GTEST_SKIP() << "Requires aarch64";
+#endif
+}
+
 TEST_F(CrasherTest, mte_async) {
 #if defined(__aarch64__)
   if (!mte_supported()) {
@@ -2647,7 +2696,7 @@
   match_str += format_full_pointer(crash_uptr);
   ASSERT_MATCH(result, match_str);
 
-  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
 
   // Verifies that the fault address error message is at the end of the
   // maps section. To do this, the check below looks for the start of the
@@ -2699,7 +2748,7 @@
   match_str += format_full_pointer(reinterpret_cast<uintptr_t>(middle_ptr));
   ASSERT_MATCH(result, match_str);
 
-  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
 
   match_str = android::base::StringPrintf(
       R"(    %s.*\n--->Fault address falls at %s between mapped regions\n    %s)",
@@ -2737,7 +2786,7 @@
   match_str += format_full_pointer(reinterpret_cast<uintptr_t>(ptr));
   ASSERT_MATCH(result, match_str);
 
-  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->)\n)");
+  ASSERT_MATCH(result, R"(\nmemory map \(.*\): \(fault address prefixed with --->\)\n)");
 
   match_str = android::base::StringPrintf(R"(\n--->%s.*\n)", format_pointer(ptr).c_str());
   ASSERT_MATCH(result, match_str);
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index e261aa3..fee67fdf 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -39,6 +39,9 @@
 #ifndef DM_DEFERRED_REMOVE
 #define DM_DEFERRED_REMOVE (1 << 17)
 #endif
+#ifndef DM_IMA_MEASUREMENT_FLAG
+#define DM_IMA_MEASUREMENT_FLAG (1 << 19)
+#endif
 
 namespace android {
 namespace dm {
@@ -540,6 +543,10 @@
     return GetTable(name, 0, table);
 }
 
+bool DeviceMapper::GetTableStatusIma(const std::string& name, std::vector<TargetInfo>* table) {
+    return GetTable(name, DM_IMA_MEASUREMENT_FLAG, table);
+}
+
 bool DeviceMapper::GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) {
     return GetTable(name, DM_STATUS_TABLE_FLAG, table);
 }
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 22c475f..fa97653 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -78,6 +78,7 @@
     virtual bool LoadTable(const std::string& name, const DmTable& table) = 0;
     virtual bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) = 0;
     virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) = 0;
+    virtual bool GetTableStatusIma(const std::string& name, std::vector<TargetInfo>* table) = 0;
     virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) = 0;
     virtual bool GetDeviceString(const std::string& name, std::string* dev) = 0;
     virtual bool DeleteDeviceIfExists(const std::string& name) = 0;
@@ -267,6 +268,12 @@
     // false.
     bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) override;
 
+    // Query the status of a table, given a device name. The output vector will
+    // contain IMA TargetInfo for each target in the table. If the device does
+    // not exist, or there were too many targets, the call will fail and return
+    // false.
+    bool GetTableStatusIma(const std::string& name, std::vector<TargetInfo>* table) override;
+
     // Identical to GetTableStatus, except also retrives the active table for the device
     // mapper device from the kernel.
     bool GetTableInfo(const std::string& name, std::vector<TargetInfo>* table) override;
diff --git a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
index 5e9f049..90813fe 100644
--- a/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
+++ b/fs_mgr/libsnapshot/include_test/libsnapshot/test_helpers.h
@@ -155,6 +155,9 @@
     virtual bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
         return impl_.GetTableStatus(name, table);
     }
+    virtual bool GetTableStatusIma(const std::string& name, std::vector<TargetInfo>* table) {
+        return impl_.GetTableStatusIma(name, table);
+    }
     virtual bool GetDmDevicePathByName(const std::string& name, std::string* path) {
         return impl_.GetDmDevicePathByName(name, path);
     }
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index de2e528..ea1da4b 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -173,7 +173,7 @@
         batch_size_ = std::max<size_t>(options_.cluster_ops, 1);
         data_vec_.reserve(batch_size_);
         cached_data_.reserve(batch_size_);
-        cached_ops_.reserve(batch_size_);
+        cached_ops_.reserve(batch_size_ * kNonDataOpBufferSize);
     }
 
     if (batch_size_ > 1) {
@@ -342,7 +342,8 @@
     // Allow bigger batch sizes for ops without data. A single CowOperationV3
     // struct uses 14 bytes of memory, even if we cache 200 * 16 ops in memory,
     // it's only ~44K.
-    return cached_data_.size() >= batch_size_ || cached_ops_.size() >= batch_size_ * 16;
+    return cached_data_.size() >= batch_size_ ||
+           cached_ops_.size() >= batch_size_ * kNonDataOpBufferSize;
 }
 
 bool CowWriterV3::ConstructCowOpCompressedBuffers(uint64_t new_block_start, const void* data,
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
index 48eb67b..e2dc698 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.h
@@ -28,6 +28,9 @@
 namespace snapshot {
 
 using namespace android::storage_literals;
+// This is a multiple on top of the number of data ops that can be stored in our cache at once. This
+// is added so that we can cache more non-data ops as it takes up less space.
+static constexpr uint32_t kNonDataOpBufferSize = 16;
 
 class CowWriterV3 : public CowWriterBase {
   public:
diff --git a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
index cf26a16..a4a2c1a 100644
--- a/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
+++ b/fs_mgr/libsnapshot/partition_cow_creator_test.cpp
@@ -39,6 +39,7 @@
 namespace android {
 namespace snapshot {
 
+// @VsrTest = 3.7.6
 class PartitionCowCreatorTest : public ::testing::Test {
   public:
     void SetUp() override {
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index e538d50..47e6ce9 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -104,6 +104,7 @@
 
 void MountMetadata();
 
+// @VsrTest = 3.7.6
 class SnapshotTest : public ::testing::Test {
   public:
     SnapshotTest() : dm_(DeviceMapper::Instance()) {}
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index 50e9f48..5d3f96c 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -52,6 +52,9 @@
 using namespace std::chrono_literals;
 using namespace std::string_literals;
 using namespace android::storage_literals;
+using android::base::LogdLogger;
+using android::base::StderrLogger;
+using android::base::TeeLogger;
 using android::fs_mgr::CreateLogicalPartitionParams;
 using android::fs_mgr::FindPartition;
 using android::fs_mgr::GetPartitionSize;
@@ -461,23 +464,23 @@
 }
 
 bool DumpCmdHandler(int /*argc*/, char** argv) {
-    android::base::InitLogging(argv, &android::base::StderrLogger);
+    android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
     return SnapshotManager::New()->Dump(std::cout);
 }
 
 bool MapCmdHandler(int, char** argv) {
-    android::base::InitLogging(argv, &android::base::StderrLogger);
+    android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
     using namespace std::chrono_literals;
     return SnapshotManager::New()->MapAllSnapshots(5000ms);
 }
 
 bool UnmapCmdHandler(int, char** argv) {
-    android::base::InitLogging(argv, &android::base::StderrLogger);
+    android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
     return SnapshotManager::New()->UnmapAllSnapshots();
 }
 
 bool MergeCmdHandler(int /*argc*/, char** argv) {
-    android::base::InitLogging(argv, &android::base::StderrLogger);
+    android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
     LOG(WARNING) << "Deprecated. Call update_engine_client --merge instead.";
     return false;
 }
diff --git a/fs_mgr/libsnapshot/vts_ota_config_test.cpp b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
index d387eb3..b5618c4 100755
--- a/fs_mgr/libsnapshot/vts_ota_config_test.cpp
+++ b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
@@ -21,6 +21,7 @@
     return android::base::GetIntProperty("ro.vendor.api_level", -1);
 }
 
+// @VsrTest = 3.7.6
 TEST(VAB, Enabled) {
     if (!android::base::GetBoolProperty("ro.build.ab_update", false) && (GetVsrLevel() < __ANDROID_API_T__)) {
         GTEST_SKIP();
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9dc8c24..f843821 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -52,6 +52,7 @@
     std::cerr << "  list <devices | targets> [-v]" << std::endl;
     std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  getuuid <dm-name>" << std::endl;
+    std::cerr << "  ima <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;
@@ -508,7 +509,14 @@
                       << std::endl;
             return -EINVAL;
         }
+    } else if (mode == "ima") {
+        if (!dm.GetTableStatusIma(argv[0], &table)) {
+            std::cerr << "Could not query table status of device \"" << argv[0] << "\"."
+                      << std::endl;
+            return -EINVAL;
+        }
     }
+
     std::cout << "Targets in the device-mapper table for " << argv[0] << ":" << std::endl;
     for (const auto& target : table) {
         std::cout << target.spec.sector_start << "-"
@@ -530,6 +538,10 @@
     return DumpTable("status", argc, argv);
 }
 
+static int ImaCmdHandler(int argc, char** argv) {
+    return DumpTable("ima", argc, argv);
+}
+
 static int ResumeCmdHandler(int argc, char** argv) {
     if (argc != 1) {
         std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
@@ -570,6 +582,7 @@
         {"info", InfoCmdHandler},
         {"table", TableCmdHandler},
         {"status", StatusCmdHandler},
+        {"ima", ImaCmdHandler},
         {"resume", ResumeCmdHandler},
         {"suspend", SuspendCmdHandler},
         // clang-format on
diff --git a/init/Android.bp b/init/Android.bp
index c3abefe..12ca15a 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -162,6 +162,7 @@
     },
     static_libs: [
         "libavb",
+        "libavf_cc_flags",
         "libbootloader_message",
         "libc++fs",
         "libcgrouprc_format",
@@ -359,6 +360,7 @@
     static_libs: [
         "libc++fs",
         "libfs_avb",
+        "libavf_cc_flags",
         "libfs_mgr",
         "libfec",
         "libfec_rs",
@@ -459,7 +461,10 @@
 
 cc_binary {
     name: "init_first_stage.microdroid",
-    defaults: ["init_first_stage_defaults"],
+    defaults: [
+        "avf_build_flags_cc",
+        "init_first_stage_defaults",
+    ],
     cflags: ["-DMICRODROID=1"],
     installable: false,
 }
diff --git a/init/block_dev_initializer.cpp b/init/block_dev_initializer.cpp
index 05e00ed..a686d05 100644
--- a/init/block_dev_initializer.cpp
+++ b/init/block_dev_initializer.cpp
@@ -132,11 +132,19 @@
 bool BlockDevInitializer::InitDmDevice(const std::string& device) {
     const std::string device_name(basename(device.c_str()));
     const std::string syspath = "/sys/block/" + device_name;
+    return InitDevice(syspath, device_name);
+}
+
+bool BlockDevInitializer::InitPlatformDevice(const std::string& dev_name) {
+    return InitDevice("/sys/devices/platform", dev_name);
+}
+
+bool BlockDevInitializer::InitDevice(const std::string& syspath, const std::string& device_name) {
     bool found = false;
 
-    auto uevent_callback = [&device_name, &device, this, &found](const Uevent& uevent) {
+    auto uevent_callback = [&device_name, this, &found](const Uevent& uevent) {
         if (uevent.device_name == device_name) {
-            LOG(VERBOSE) << "Creating device-mapper device : " << device;
+            LOG(VERBOSE) << "Creating device : " << device_name;
             device_handler_->HandleUevent(uevent);
             found = true;
             return ListenerAction::kStop;
@@ -146,13 +154,13 @@
 
     uevent_listener_.RegenerateUeventsForPath(syspath, uevent_callback);
     if (!found) {
-        LOG(INFO) << "dm device '" << device << "' not found in /sys, waiting for its uevent";
+        LOG(INFO) << "device '" << device_name << "' not found in /sys, waiting for its uevent";
         Timer t;
         uevent_listener_.Poll(uevent_callback, 10s);
-        LOG(INFO) << "wait for dm device '" << device << "' returned after " << t;
+        LOG(INFO) << "wait for device '" << device_name << "' returned after " << t;
     }
     if (!found) {
-        LOG(ERROR) << "dm device '" << device << "' not found after polling timeout";
+        LOG(ERROR) << "device '" << device_name << "' not found after polling timeout";
         return false;
     }
     return true;
diff --git a/init/block_dev_initializer.h b/init/block_dev_initializer.h
index ec39ce0..d5b1f60 100644
--- a/init/block_dev_initializer.h
+++ b/init/block_dev_initializer.h
@@ -24,6 +24,7 @@
 namespace android {
 namespace init {
 
+// TODO: should this be renamed to FirstStageDevInitialize?
 class BlockDevInitializer final {
   public:
     BlockDevInitializer();
@@ -32,11 +33,13 @@
     bool InitDmUser(const std::string& name);
     bool InitDevices(std::set<std::string> devices);
     bool InitDmDevice(const std::string& device);
+    bool InitPlatformDevice(const std::string& device);
 
   private:
     ListenerAction HandleUevent(const Uevent& uevent, std::set<std::string>* devices);
 
     bool InitMiscDevice(const std::string& name);
+    bool InitDevice(const std::string& syspath, const std::string& device);
 
     std::unique_ptr<DeviceHandler> device_handler_;
     UeventListener uevent_listener_;
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index c4d0f75..356aaa0 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -37,6 +37,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
+#include <android/avf_cc_flags.h>
 #include <modprobe/modprobe.h>
 #include <private/android_filesystem_config.h>
 
@@ -385,7 +386,12 @@
     // /second_stage_resources is used to preserve files from first to second
     // stage init
     CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
-                    "mode=0755,uid=0,gid=0"))
+                    "mode=0755,uid=0,gid=0"));
+
+    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+        CHECKCALL(mount("tmpfs", "/microdroid_resources", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
+                        "mode=0750,uid=0,gid=0"));
+    }
 #undef CHECKCALL
 
     SetStdioToDevNull(argv);
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index c0b9281..836d536 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -16,6 +16,7 @@
 
 #include "first_stage_mount.h"
 
+#include <signal.h>
 #include <stdlib.h>
 #include <sys/mount.h>
 #include <unistd.h>
@@ -33,6 +34,7 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
+#include <android/avf_cc_flags.h>
 #include <fs_avb/fs_avb.h>
 #include <fs_mgr.h>
 #include <fs_mgr_dm_linear.h>
@@ -272,6 +274,11 @@
     return true;
 }
 
+// TODO: should this be in a library in packages/modules/Virtualization first_stage_init links?
+static bool IsMicrodroidStrictBoot() {
+    return access("/proc/device-tree/chosen/avf,strict-boot", F_OK) == 0;
+}
+
 bool FirstStageMountVBootV2::InitDevices() {
     std::set<std::string> devices;
     GetSuperDeviceName(&devices);
@@ -283,6 +290,14 @@
         return false;
     }
 
+    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+        if (IsMicrodroidStrictBoot()) {
+            if (!block_dev_init_.InitPlatformDevice("open-dice0")) {
+                return false;
+            }
+        }
+    }
+
     if (IsDmLinearEnabled()) {
         auto super_symlink = "/dev/block/by-name/"s + super_partition_name_;
         if (!android::base::Realpath(super_symlink, &super_path_)) {
@@ -527,9 +542,48 @@
     return true;
 }
 
+static bool MaybeDeriveMicrodroidVendorDiceNode(Fstab* fstab) {
+    std::optional<std::string> microdroid_vendor_block_dev;
+    for (auto entry = fstab->begin(); entry != fstab->end(); entry++) {
+        if (entry->mount_point == "/vendor") {
+            microdroid_vendor_block_dev.emplace(entry->blk_device);
+            break;
+        }
+    }
+    if (!microdroid_vendor_block_dev.has_value()) {
+        LOG(VERBOSE) << "No microdroid vendor partition to mount";
+        return true;
+    }
+    // clang-format off
+    const std::array<const char*, 7> args = {
+        "/system/bin/derive_microdroid_vendor_dice_node",
+                "--dice-driver", "/dev/open-dice0",
+                "--microdroid-vendor-disk-image", microdroid_vendor_block_dev->data(),
+                "--output", "/microdroid_resources/dice_chain.raw",
+    };
+    // clang-format-on
+    // ForkExecveAndWaitForCompletion calls waitpid to wait for the fork-ed process to finish.
+    // The first_stage_console adds SA_NOCLDWAIT flag to the SIGCHLD handler, which means that
+    // waitpid will always return -ECHLD. Here we re-register a default handler, so that waitpid
+    // works.
+    LOG(INFO) << "Deriving dice node for microdroid vendor partition";
+    signal(SIGCHLD, SIG_DFL);
+    if (!ForkExecveAndWaitForCompletion(args[0], (char**)args.data())) {
+        LOG(ERROR) << "Failed to derive microdroid vendor dice node";
+        return false;
+    }
+    return true;
+}
+
 bool FirstStageMountVBootV2::MountPartitions() {
     if (!TrySwitchSystemAsRoot()) return false;
 
+    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+        if (!MaybeDeriveMicrodroidVendorDiceNode(&fstab_)) {
+            return false;
+        }
+    }
+
     if (!SkipMountingPartitions(&fstab_, true /* verbose */)) return false;
 
     for (auto current = fstab_.begin(); current != fstab_.end();) {
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 6f8a4de..59e57b9 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -23,6 +23,7 @@
 #include <sys/types.h>
 
 #include <memory>
+#include <unordered_map>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
diff --git a/init/property_service.cpp b/init/property_service.cpp
index bc4ef42..58a0a7f 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -58,6 +58,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <fs_mgr.h>
+#include <private/android_filesystem_config.h>
 #include <property_info_parser/property_info_parser.h>
 #include <property_info_serializer/property_info_serializer.h>
 #include <selinux/android.h>
@@ -117,12 +118,13 @@
 
 static bool persistent_properties_loaded = false;
 
-static int property_set_fd = -1;
 static int from_init_socket = -1;
 static int init_socket = -1;
 static bool accept_messages = false;
 static std::mutex accept_messages_lock;
+static std::mutex selinux_check_access_lock;
 static std::thread property_service_thread;
+static std::thread property_service_for_system_thread;
 
 static std::unique_ptr<PersistWriteThread> persist_write_thread;
 
@@ -167,6 +169,7 @@
     ucred cr = {.pid = 0, .uid = 0, .gid = 0};
     audit_data.cr = &cr;
 
+    auto lock = std::lock_guard{selinux_check_access_lock};
     return selinux_check_access(source_context.c_str(), target_context, "file", "read",
                                 &audit_data) == 0;
 }
@@ -182,10 +185,9 @@
     audit_data.name = name.c_str();
     audit_data.cr = &cr;
 
-    bool has_access = (selinux_check_access(source_context, target_context, "property_service",
-                                            "set", &audit_data) == 0);
-
-    return has_access;
+    auto lock = std::lock_guard{selinux_check_access_lock};
+    return selinux_check_access(source_context, target_context, "property_service", "set",
+                                &audit_data) == 0;
 }
 
 void NotifyPropertyChange(const std::string& name, const std::string& value) {
@@ -400,30 +402,38 @@
         return {PROP_ERROR_INVALID_VALUE};
     }
 
-    prop_info* pi = (prop_info*)__system_property_find(name.c_str());
-    if (pi != nullptr) {
-        // ro.* properties are actually "write-once".
-        if (StartsWith(name, "ro.")) {
-            *error = "Read-only property was already set";
-            return {PROP_ERROR_READ_ONLY_PROPERTY};
-        }
-
-        __system_property_update(pi, value.c_str(), valuelen);
+    if (name == "sys.powerctl") {
+        // No action here - NotifyPropertyChange will trigger the appropriate action, and since this
+        // can come to the second thread, we mustn't call out to the __system_property_* functions
+        // which support multiple readers but only one mutator.
     } else {
-        int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
-        if (rc < 0) {
-            *error = "__system_property_add failed";
-            return {PROP_ERROR_SET_FAILED};
-        }
-    }
+        prop_info* pi = (prop_info*)__system_property_find(name.c_str());
+        if (pi != nullptr) {
+            // ro.* properties are actually "write-once".
+            if (StartsWith(name, "ro.")) {
+                *error = "Read-only property was already set";
+                return {PROP_ERROR_READ_ONLY_PROPERTY};
+            }
 
-    bool need_persist = StartsWith(name, "persist.") || StartsWith(name, "next_boot.");
-    if (socket && persistent_properties_loaded && need_persist) {
-        if (persist_write_thread) {
-            persist_write_thread->Write(name, value, std::move(*socket));
-            return {};
+            __system_property_update(pi, value.c_str(), valuelen);
+        } else {
+            int rc = __system_property_add(name.c_str(), name.size(), value.c_str(), valuelen);
+            if (rc < 0) {
+                *error = "__system_property_add failed";
+                return {PROP_ERROR_SET_FAILED};
+            }
         }
-        WritePersistentProperty(name, value);
+
+        // Don't write properties to disk until after we have read all default
+        // properties to prevent them from being overwritten by default values.
+        bool need_persist = StartsWith(name, "persist.") || StartsWith(name, "next_boot.");
+        if (socket && persistent_properties_loaded && need_persist) {
+            if (persist_write_thread) {
+                persist_write_thread->Write(name, value, std::move(*socket));
+                return {};
+            }
+            WritePersistentProperty(name, value);
+        }
     }
 
     NotifyPropertyChange(name, value);
@@ -584,10 +594,10 @@
     return *ret;
 }
 
-static void handle_property_set_fd() {
+static void handle_property_set_fd(int fd) {
     static constexpr uint32_t kDefaultSocketTimeout = 2000; /* ms */
 
-    int s = accept4(property_set_fd, nullptr, nullptr, SOCK_CLOEXEC);
+    int s = accept4(fd, nullptr, nullptr, SOCK_CLOEXEC);
     if (s == -1) {
         return;
     }
@@ -1090,6 +1100,12 @@
     // required to support.
     constexpr auto VENDOR_API_LEVEL_PROP = "ro.vendor.api_level";
 
+    if (__system_property_find(VENDOR_API_LEVEL_PROP) != nullptr) {
+        // The device already have ro.vendor.api_level in its vendor/build.prop.
+        // Skip initializing the ro.vendor.api_level property.
+        return;
+    }
+
     auto vendor_api_level = GetIntProperty("ro.board.first_api_level", __ANDROID_VENDOR_API_MAX__);
     if (vendor_api_level != __ANDROID_VENDOR_API_MAX__) {
         // Update the vendor_api_level with "ro.board.api_level" only if both "ro.board.api_level"
@@ -1295,7 +1311,7 @@
     mkdir(APPCOMPAT_OVERRIDE_PROP_FOLDERNAME, S_IRWXU | S_IXGRP | S_IXOTH);
     if (!WriteStringToFile(serialized_contexts, APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0444, 0, 0,
                            false)) {
-        PLOG(ERROR) << "Unable to write vendor overrides to file";
+        PLOG(ERROR) << "Unable to write appcompat override property infos to file";
     }
     selinux_android_restorecon(APPCOMPAT_OVERRIDE_PROP_TREE_FILE, 0);
 }
@@ -1432,19 +1448,21 @@
     }
 }
 
-static void PropertyServiceThread() {
+static void PropertyServiceThread(int fd, bool listen_init) {
     Epoll epoll;
     if (auto result = epoll.Open(); !result.ok()) {
         LOG(FATAL) << result.error();
     }
 
-    if (auto result = epoll.RegisterHandler(property_set_fd, handle_property_set_fd);
+    if (auto result = epoll.RegisterHandler(fd, std::bind(handle_property_set_fd, fd));
         !result.ok()) {
         LOG(FATAL) << result.error();
     }
 
-    if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
-        LOG(FATAL) << result.error();
+    if (listen_init) {
+        if (auto result = epoll.RegisterHandler(init_socket, HandleInitSocket); !result.ok()) {
+            LOG(FATAL) << result.error();
+        }
     }
 
     while (true) {
@@ -1493,6 +1511,23 @@
     cv_.notify_all();
 }
 
+void StartThread(const char* name, int mode, int gid, std::thread& t, bool listen_init) {
+    int fd = -1;
+    if (auto result = CreateSocket(name, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
+                                   /*passcred=*/false, /*should_listen=*/false, mode, /*uid=*/0,
+                                   /*gid=*/gid, /*socketcon=*/{});
+        result.ok()) {
+        fd = *result;
+    } else {
+        LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
+    }
+
+    listen(fd, 8);
+
+    auto new_thread = std::thread(PropertyServiceThread, fd, listen_init);
+    t.swap(new_thread);
+}
+
 void StartPropertyService(int* epoll_socket) {
     InitPropertySet("ro.property_service.version", "2");
 
@@ -1504,19 +1539,9 @@
     init_socket = sockets[1];
     StartSendingMessages();
 
-    if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                                   /*passcred=*/false, /*should_listen=*/false, 0666, /*uid=*/0,
-                                   /*gid=*/0, /*socketcon=*/{});
-        result.ok()) {
-        property_set_fd = *result;
-    } else {
-        LOG(FATAL) << "start_property_service socket creation failed: " << result.error();
-    }
-
-    listen(property_set_fd, 8);
-
-    auto new_thread = std::thread{PropertyServiceThread};
-    property_service_thread.swap(new_thread);
+    StartThread(PROP_SERVICE_FOR_SYSTEM_NAME, 0660, AID_SYSTEM, property_service_for_system_thread,
+                true);
+    StartThread(PROP_SERVICE_NAME, 0666, 0, property_service_thread, false);
 
     auto async_persist_writes =
             android::base::GetBoolProperty("ro.property_service.async_persist_writes", false);
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 1a26c4d..150f8f4 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -1083,7 +1083,8 @@
                         return;
                     }
                 }
-            } else if (reboot_target == "quiescent") {
+            } else if (std::find(cmd_params.begin(), cmd_params.end(), "quiescent")
+                    != cmd_params.end()) { // Quiescent can be either subreason or details.
                 bootloader_message boot = {};
                 if (std::string err; !read_bootloader_message(&boot, &err)) {
                     LOG(ERROR) << "Failed to read bootloader message: " << err;
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 1f211dd..e191b60 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -111,97 +111,6 @@
     return true;
 }
 
-// Forks, executes the provided program in the child, and waits for the completion in the parent.
-// Child's stderr is captured and logged using LOG(ERROR).
-bool ForkExecveAndWaitForCompletion(const char* filename, char* const argv[]) {
-    // Create a pipe used for redirecting child process's output.
-    // * pipe_fds[0] is the FD the parent will use for reading.
-    // * pipe_fds[1] is the FD the child will use for writing.
-    int pipe_fds[2];
-    if (pipe(pipe_fds) == -1) {
-        PLOG(ERROR) << "Failed to create pipe";
-        return false;
-    }
-
-    pid_t child_pid = fork();
-    if (child_pid == -1) {
-        PLOG(ERROR) << "Failed to fork for " << filename;
-        return false;
-    }
-
-    if (child_pid == 0) {
-        // fork succeeded -- this is executing in the child process
-
-        // Close the pipe FD not used by this process
-        close(pipe_fds[0]);
-
-        // Redirect stderr to the pipe FD provided by the parent
-        if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
-            PLOG(ERROR) << "Failed to redirect stderr of " << filename;
-            _exit(127);
-            return false;
-        }
-        close(pipe_fds[1]);
-
-        if (execv(filename, argv) == -1) {
-            PLOG(ERROR) << "Failed to execve " << filename;
-            return false;
-        }
-        // Unreachable because execve will have succeeded and replaced this code
-        // with child process's code.
-        _exit(127);
-        return false;
-    } else {
-        // fork succeeded -- this is executing in the original/parent process
-
-        // Close the pipe FD not used by this process
-        close(pipe_fds[1]);
-
-        // Log the redirected output of the child process.
-        // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
-        // As a result, we're buffering all output and logging it in one go at the end of the
-        // invocation, instead of logging it as it comes in.
-        const int child_out_fd = pipe_fds[0];
-        std::string child_output;
-        if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
-            PLOG(ERROR) << "Failed to capture full output of " << filename;
-        }
-        close(child_out_fd);
-        if (!child_output.empty()) {
-            // Log captured output, line by line, because LOG expects to be invoked for each line
-            std::istringstream in(child_output);
-            std::string line;
-            while (std::getline(in, line)) {
-                LOG(ERROR) << filename << ": " << line;
-            }
-        }
-
-        // Wait for child to terminate
-        int status;
-        if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
-            PLOG(ERROR) << "Failed to wait for " << filename;
-            return false;
-        }
-
-        if (WIFEXITED(status)) {
-            int status_code = WEXITSTATUS(status);
-            if (status_code == 0) {
-                return true;
-            } else {
-                LOG(ERROR) << filename << " exited with status " << status_code;
-            }
-        } else if (WIFSIGNALED(status)) {
-            LOG(ERROR) << filename << " killed by signal " << WTERMSIG(status);
-        } else if (WIFSTOPPED(status)) {
-            LOG(ERROR) << filename << " stopped by signal " << WSTOPSIG(status);
-        } else {
-            LOG(ERROR) << "waitpid for " << filename << " returned unexpected status: " << status;
-        }
-
-        return false;
-    }
-}
-
 bool ReadFirstLine(const char* file, std::string* line) {
     line->clear();
 
diff --git a/init/util.cpp b/init/util.cpp
index e760a59..e5efc7d 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/un.h>
+#include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
 
@@ -747,5 +748,96 @@
     return filtered_configs;
 }
 
+// Forks, executes the provided program in the child, and waits for the completion in the parent.
+// Child's stderr is captured and logged using LOG(ERROR).
+bool ForkExecveAndWaitForCompletion(const char* filename, char* const argv[]) {
+    // Create a pipe used for redirecting child process's output.
+    // * pipe_fds[0] is the FD the parent will use for reading.
+    // * pipe_fds[1] is the FD the child will use for writing.
+    int pipe_fds[2];
+    if (pipe(pipe_fds) == -1) {
+        PLOG(ERROR) << "Failed to create pipe";
+        return false;
+    }
+
+    pid_t child_pid = fork();
+    if (child_pid == -1) {
+        PLOG(ERROR) << "Failed to fork for " << filename;
+        return false;
+    }
+
+    if (child_pid == 0) {
+        // fork succeeded -- this is executing in the child process
+
+        // Close the pipe FD not used by this process
+        close(pipe_fds[0]);
+
+        // Redirect stderr to the pipe FD provided by the parent
+        if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
+            PLOG(ERROR) << "Failed to redirect stderr of " << filename;
+            _exit(127);
+            return false;
+        }
+        close(pipe_fds[1]);
+
+        if (execv(filename, argv) == -1) {
+            PLOG(ERROR) << "Failed to execve " << filename;
+            return false;
+        }
+        // Unreachable because execve will have succeeded and replaced this code
+        // with child process's code.
+        _exit(127);
+        return false;
+    } else {
+        // fork succeeded -- this is executing in the original/parent process
+
+        // Close the pipe FD not used by this process
+        close(pipe_fds[1]);
+
+        // Log the redirected output of the child process.
+        // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
+        // As a result, we're buffering all output and logging it in one go at the end of the
+        // invocation, instead of logging it as it comes in.
+        const int child_out_fd = pipe_fds[0];
+        std::string child_output;
+        if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
+            PLOG(ERROR) << "Failed to capture full output of " << filename;
+        }
+        close(child_out_fd);
+        if (!child_output.empty()) {
+            // Log captured output, line by line, because LOG expects to be invoked for each line
+            std::istringstream in(child_output);
+            std::string line;
+            while (std::getline(in, line)) {
+                LOG(ERROR) << filename << ": " << line;
+            }
+        }
+
+        // Wait for child to terminate
+        int status;
+        if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
+            PLOG(ERROR) << "Failed to wait for " << filename;
+            return false;
+        }
+
+        if (WIFEXITED(status)) {
+            int status_code = WEXITSTATUS(status);
+            if (status_code == 0) {
+                return true;
+            } else {
+                LOG(ERROR) << filename << " exited with status " << status_code;
+            }
+        } else if (WIFSIGNALED(status)) {
+            LOG(ERROR) << filename << " killed by signal " << WTERMSIG(status);
+        } else if (WIFSTOPPED(status)) {
+            LOG(ERROR) << filename << " stopped by signal " << WSTOPSIG(status);
+        } else {
+            LOG(ERROR) << "waitpid for " << filename << " returned unexpected status: " << status;
+        }
+
+        return false;
+    }
+}
+
 }  // namespace init
 }  // namespace android
diff --git a/init/util.h b/init/util.h
index 2d02182..aa24123 100644
--- a/init/util.h
+++ b/init/util.h
@@ -117,5 +117,10 @@
 // (.rc == .0rc for ranking purposes)
 std::vector<std::string> FilterVersionedConfigs(const std::vector<std::string>& configs,
                                                   int active_sdk);
+
+// Forks, executes the provided program in the child, and waits for the completion in the parent.
+// Child's stderr is captured and logged using LOG(ERROR).
+bool ForkExecveAndWaitForCompletion(const char* filename, char* const argv[]);
+
 }  // namespace init
 }  // namespace android
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 8ae7d9e..b7752d9 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -116,27 +116,6 @@
     },
 }
 
-cc_test {
-    name: "libcutils_sockets_test",
-    test_suites: ["device-tests"],
-    static_libs: ["libbase", "libcutils_sockets"],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-
-    srcs: ["sockets_test.cpp"],
-    target: {
-        android: {
-            srcs: [
-                "android_get_control_file_test.cpp",
-                "android_get_control_socket_test.cpp",
-            ],
-        },
-    },
-}
-
 // some files must not be compiled when building against Mingw
 // they correspond to features not used by our host development tools
 // which are also hard or even impossible to port to native Win32
@@ -347,7 +326,10 @@
 
 cc_test {
     name: "KernelLibcutilsTest",
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
     defaults: ["libcutils_test_static_defaults"],
     test_config: "KernelLibcutilsTest.xml",
 }
diff --git a/libcutils/ashmem-dev.cpp b/libcutils/ashmem-dev.cpp
index 410dbfd..46b8ef2 100644
--- a/libcutils/ashmem-dev.cpp
+++ b/libcutils/ashmem-dev.cpp
@@ -301,6 +301,12 @@
         return -1;
     }
 
+    // forbid size changes to match ashmem behaviour
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) == -1) {
+        ALOGE("memfd_create(%s, %zd) F_ADD_SEALS failed: %m", name, size);
+        return -1;
+    }
+
     if (debug_log) {
         ALOGE("memfd_create(%s, %zd) success. fd=%d\n", name, size, fd.get());
     }
@@ -352,14 +358,29 @@
 }
 
 static int memfd_set_prot_region(int fd, int prot) {
-    /* Only proceed if an fd needs to be write-protected */
+    int seals = fcntl(fd, F_GET_SEALS);
+    if (seals == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_GET_SEALS failed: %s\n", fd, prot, strerror(errno));
+        return -1;
+    }
+
     if (prot & PROT_WRITE) {
+        /* Now we want the buffer to be read-write, let's check if the buffer
+         * has been previously marked as read-only before, if so return error
+         */
+        if (seals & F_SEAL_FUTURE_WRITE) {
+            ALOGE("memfd_set_prot_region(%d, %d): region is write protected\n", fd, prot);
+            errno = EINVAL;  // inline with ashmem error code, if already in
+                             // read-only mode
+            return -1;
+        }
         return 0;
     }
 
-    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE) == -1) {
-        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE seal failed: %s\n", fd, prot,
-              strerror(errno));
+    /* We would only allow read-only for any future file operations */
+    if (fcntl(fd, F_ADD_SEALS, F_SEAL_FUTURE_WRITE | F_SEAL_SEAL) == -1) {
+        ALOGE("memfd_set_prot_region(%d, %d): F_SEAL_FUTURE_WRITE | F_SEAL_SEAL seal failed: %s\n",
+              fd, prot, strerror(errno));
         return -1;
     }
 
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index 5d79d6a..d7a90c4 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -41,6 +41,7 @@
                             std::vector<std::string>* post_dependencies);
     void ResetModuleCount() { module_count_ = 0; }
     int GetModuleCount() { return module_count_; }
+    bool IsBlocklisted(const std::string& module_name);
 
   private:
     std::string MakeCanonical(const std::string& module_path);
@@ -52,7 +53,6 @@
     void AddOption(const std::string& module_name, const std::string& option_name,
                    const std::string& value);
     std::string GetKernelCmdline();
-    bool IsBlocklisted(const std::string& module_name);
 
     bool ParseDepCallback(const std::string& base_path, const std::vector<std::string>& args);
     bool ParseAliasCallback(const std::vector<std::string>& args);
diff --git a/libvendorsupport/include_llndk/android/llndk-versioning.h b/libvendorsupport/include_llndk/android/llndk-versioning.h
index 7c408c9..8ae56d4 100644
--- a/libvendorsupport/include_llndk/android/llndk-versioning.h
+++ b/libvendorsupport/include_llndk/android/llndk-versioning.h
@@ -14,10 +14,9 @@
 
 #pragma once
 
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
+/* As a vendor default header included in all vendor modules, this header MUST NOT include other
+ * header files or any declarations. Only macros are allowed.
+ */
 #if defined(__ANDROID_VENDOR__)
 
 // LLNDK (https://source.android.com/docs/core/architecture/vndk/build-system#ll-ndk) is similar to
@@ -32,17 +31,24 @@
                     "call with '#if (__ANDROID_VENDOR_API__ >= " #vendor_api_level ")'."))) \
             _Pragma("clang diagnostic pop")
 
-// For the vendor libraries, __INTRODUCED_IN must be ignored because they are only for NDKs but not
-// for LLNDKs.
-#undef __INTRODUCED_IN
-#define __INTRODUCED_IN(x)
+// Use this macro as an `if` statement to call an API that are available to both NDK and LLNDK.
+// This returns true for the vendor modules if the vendor_api_level is less than or equal to the
+// ro.board.api_level.
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
+    constexpr(__ANDROID_VENDOR_API__ >= vendor_api_level)
 
 #else  // __ANDROID_VENDOR__
 
-// For non-vendor libraries, __INTRODUCED_IN_LLNDK must be ignored because it must not change
-// symbols of NDK or the system side of the treble boundary.
-#define __INTRODUCED_IN_LLNDK(vendor_api_level)
+// __INTRODUCED_IN_LLNDK is for LLNDK only but not for NDK. Ignore this for non-vendor modules.
+// It leaves a no-op annotation for ABI analysis.
+#if !defined(__INTRODUCED_IN_LLNDK)
+#define __INTRODUCED_IN_LLNDK(vendor_api_level) \
+    __attribute__((annotate("introduced_in_llndk=" #vendor_api_level)))
+#endif
+
+// For non-vendor modules, API_LEVEL_AT_LEAST is replaced with __builtin_available(sdk_api_level) to
+// guard the API for __INTRODUCED_IN.
+#define API_LEVEL_AT_LEAST(sdk_api_level, vendor_api_level) \
+    (__builtin_available(android sdk_api_level, *))
 
 #endif  // __ANDROID_VENDOR__
-
-__END_DECLS
diff --git a/rootdir/Android.bp b/rootdir/Android.bp
index c8a3cd6..6a3484e 100644
--- a/rootdir/Android.bp
+++ b/rootdir/Android.bp
@@ -71,3 +71,33 @@
     src: "adb_debug.prop",
     debug_ramdisk: true,
 }
+
+prebuilt_etc {
+    name: "init.zygote64.rc",
+    src: "init.zygote64.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "init.zygote32.rc",
+    src: "init.zygote32.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "init.zygote64_32.rc",
+    src: "init.zygote64_32.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "init.usb.rc",
+    src: "init.usb.rc",
+    sub_dir: "init/hw",
+}
+
+prebuilt_etc {
+    name: "init.usb.configfs.rc",
+    src: "init.usb.configfs.rc",
+    sub_dir: "init/hw",
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 8a2ed9f..ec203f9 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -247,6 +247,7 @@
     write /dev/blkio/background/blkio.bfq.weight 10
     write /dev/blkio/blkio.group_idle 0
     write /dev/blkio/background/blkio.group_idle 0
+    write /dev/blkio/blkio.prio.class promote-to-rt
     write /dev/blkio/background/blkio.prio.class restrict-to-be
 
     restorecon_recursive /mnt
@@ -303,6 +304,9 @@
     mkdir /mnt/runtime/full 0755 root root
     mkdir /mnt/runtime/full/self 0755 root root
 
+    # For Pre-reboot Dexopt
+    mkdir /mnt/pre_reboot_dexopt 0755 artd artd
+
     # Symlink to keep legacy apps working in multi-user world
     symlink /storage/self/primary /mnt/sdcard
     symlink /mnt/user/0/primary /mnt/runtime/default/self/primary
@@ -1358,3 +1362,16 @@
   write /sys/kernel/mm/lru_gen/enabled 5
 on property:persist.device_config.mglru_native.lru_gen_config=all
   write /sys/kernel/mm/lru_gen/enabled 7
+
+# Allow other processes to run `snapshotctl` through `init`. This requires
+# `set_prop` permission on `snapshotctl_prop`.
+on property:sys.snapshotctl.map=requested
+    # "root" is needed to talk to gsid and pass its check on uid.
+    # "system" is needed to write to "/dev/socket/snapuserd" to talk to
+    # snapuserd.
+    exec - root root system -- /system/bin/snapshotctl map
+    setprop sys.snapshotctl.map "finished"
+
+on property:sys.snapshotctl.unmap=requested
+    exec - root root system -- /system/bin/snapshotctl unmap
+    setprop sys.snapshotctl.unmap "finished"
diff --git a/toolbox/modprobe.cpp b/toolbox/modprobe.cpp
index 17d4e31..45dd9b8 100644
--- a/toolbox/modprobe.cpp
+++ b/toolbox/modprobe.cpp
@@ -112,6 +112,7 @@
     android::base::SetMinimumLogSeverity(android::base::INFO);
 
     std::vector<std::string> modules;
+    std::string modules_load_file;
     std::string module_parameters;
     std::string mods;
     std::vector<std::string> mod_dirs;
@@ -119,7 +120,7 @@
     bool blocklist = false;
     int rv = EXIT_SUCCESS;
 
-    int opt;
+    int opt, fd;
     int option_index = 0;
     // NB: We have non-standard short options -l and -D to make it easier for
     // OEMs to transition from toybox.
@@ -144,16 +145,19 @@
                 // is supported here by default, ignore flag if no argument.
                 check_mode();
                 if (optarg == NULL) break;
-                if (!android::base::ReadFileToString(optarg, &mods)) {
+
+                // Since libmodprobe doesn't fail when the modules load file
+                // doesn't exist, let's check that here so that we don't
+                // silently fail.
+                fd = open(optarg, O_RDONLY | O_CLOEXEC | O_BINARY);
+                if (fd == -1) {
                     PLOG(ERROR) << "Failed to open " << optarg;
-                    rv = EXIT_FAILURE;
+                    return EXIT_FAILURE;
                 }
-                for (auto mod : android::base::Split(stripComments(mods), "\n")) {
-                    mod = android::base::Trim(mod);
-                    if (mod == "") continue;
-                    if (std::find(modules.begin(), modules.end(), mod) != modules.end()) continue;
-                    modules.emplace_back(mod);
-                }
+                close(fd);
+
+                mod_dirs.emplace_back(android::base::Dirname(optarg));
+                modules_load_file = android::base::Basename(optarg);
                 break;
             case 'b':
                 blocklist = true;
@@ -233,30 +237,39 @@
     LOG(DEBUG) << "mode is " << mode;
     LOG(DEBUG) << "mod_dirs is: " << android::base::Join(mod_dirs, " ");
     LOG(DEBUG) << "modules is: " << android::base::Join(modules, " ");
+    LOG(DEBUG) << "modules load file is: " << modules_load_file;
     LOG(DEBUG) << "module parameters is: " << android::base::Join(module_parameters, " ");
 
     if (modules.empty()) {
         if (mode == ListModulesMode) {
             // emulate toybox modprobe list with no pattern (list all)
             modules.emplace_back("*");
-        } else {
+        } else if (modules_load_file.empty()) {
             LOG(ERROR) << "No modules given.";
             print_usage();
             return EXIT_FAILURE;
         }
     }
-    if (parameter_count && modules.size() > 1) {
+    if (parameter_count && (modules.size() > 1 || !modules_load_file.empty())) {
         LOG(ERROR) << "Only one module may be loaded when specifying module parameters.";
         print_usage();
         return EXIT_FAILURE;
     }
 
-    Modprobe m(mod_dirs, "modules.load", blocklist);
+    Modprobe m(mod_dirs, modules_load_file.empty() ? "modules.load" : modules_load_file, blocklist);
+    if (mode == AddModulesMode && !modules_load_file.empty()) {
+        if (!m.LoadListedModules(false)) {
+            PLOG(ERROR) << "Failed to load all the modules from " << modules_load_file;
+            return EXIT_FAILURE;
+        }
+        /* Fall-through to load modules provided on the command line (if any)*/
+    }
 
     for (const auto& module : modules) {
         switch (mode) {
             case AddModulesMode:
                 if (!m.LoadWithAliases(module, true, module_parameters)) {
+                    if (m.IsBlocklisted(module)) continue;
                     PLOG(ERROR) << "Failed to load module " << module;
                     rv = EXIT_FAILURE;
                 }
diff --git a/trusty/metrics/include/trusty/metrics/tipc.h b/trusty/metrics/include/trusty/metrics/tipc.h
index b29628e..e2cf57b 100644
--- a/trusty/metrics/include/trusty/metrics/tipc.h
+++ b/trusty/metrics/include/trusty/metrics/tipc.h
@@ -39,14 +39,17 @@
  * repository. They must be kept in sync.
  */
 
-#define METRICS_PORT "com.android.trusty.metrics"
+#define METRICS_PORT "com.android.trusty.metrics.consumer"
+
+#define UUID_STR_SIZE (37)
 
 /**
  * enum metrics_cmd - command identifiers for metrics interface
- * @METRICS_CMD_RESP_BIT:          message is a response
- * @METRICS_CMD_REQ_SHIFT:         number of bits used by @METRICS_CMD_RESP_BIT
- * @METRICS_CMD_REPORT_EVENT_DROP: report gaps in the event stream
- * @METRICS_CMD_REPORT_CRASH:      report an app crash event
+ * @METRICS_CMD_RESP_BIT:             message is a response
+ * @METRICS_CMD_REQ_SHIFT:            number of bits used by @METRICS_CMD_RESP_BIT
+ * @METRICS_CMD_REPORT_EVENT_DROP:    report gaps in the event stream
+ * @METRICS_CMD_REPORT_CRASH:         report an app crash event
+ * @METRICS_CMD_REPORT_STORAGE_ERROR: report trusty storage error
  */
 enum metrics_cmd {
     METRICS_CMD_RESP_BIT = 1,
@@ -54,6 +57,7 @@
 
     METRICS_CMD_REPORT_EVENT_DROP = (1 << METRICS_CMD_REQ_SHIFT),
     METRICS_CMD_REPORT_CRASH = (2 << METRICS_CMD_REQ_SHIFT),
+    METRICS_CMD_REPORT_STORAGE_ERROR = (3 << METRICS_CMD_REQ_SHIFT),
 };
 
 /**
@@ -90,17 +94,70 @@
 /**
  * struct metrics_report_crash_req - arguments of %METRICS_CMD_REPORT_CRASH
  *                                   requests
- * @app_id_len: length of app ID that follows this structure
+ * @app_id: uuid of the app that crashed
  * @crash_reason: architecture-specific code representing the reason for the
  *                crash
  */
 struct metrics_report_crash_req {
-    uint32_t app_id_len;
+    char app_id[UUID_STR_SIZE];
     uint32_t crash_reason;
 } __attribute__((__packed__));
 
-#define METRICS_MAX_APP_ID_LEN 256
+enum TrustyStorageErrorType {
+  TRUSTY_STORAGE_ERROR_UNKNOWN = 0,
+  TRUSTY_STORAGE_ERROR_SUPERBLOCK_INVALID = 1,
+  TRUSTY_STORAGE_ERROR_BLOCK_MAC_MISMATCH = 2,
+  TRUSTY_STORAGE_ERROR_BLOCK_HEADER_INVALID = 3,
+  TRUSTY_STORAGE_ERROR_RPMB_COUNTER_MISMATCH = 4,
+  TRUSTY_STORAGE_ERROR_RPMB_COUNTER_MISMATCH_RECOVERED = 5,
+  TRUSTY_STORAGE_ERROR_RPMB_COUNTER_READ_FAILURE = 6,
+  TRUSTY_STORAGE_ERROR_RPMB_MAC_MISMATCH = 7,
+  TRUSTY_STORAGE_ERROR_RPMB_ADDR_MISMATCH = 8,
+  TRUSTY_STORAGE_ERROR_RPMB_FAILURE_RESPONSE = 9,
+  TRUSTY_STORAGE_ERROR_RPMB_UNKNOWN = 10,
+  TRUSTY_STORAGE_ERROR_RPMB_SCSI_ERROR = 11,
+  TRUSTY_STORAGE_ERROR_IO_ERROR = 12,
+  TRUSTY_STORAGE_ERROR_PROXY_COMMUNICATION_FAILURE = 13,
+};
 
-#define METRICS_MAX_MSG_SIZE                                                \
-    (sizeof(struct metrics_req) + sizeof(struct metrics_report_crash_req) + \
-     METRICS_MAX_APP_ID_LEN)
+enum TrustyFileSystem {
+  TRUSTY_FS_UNKNOWN = 0,
+  TRUSTY_FS_TP = 1,
+  TRUSTY_FS_TD = 2,
+  TRUSTY_FS_TDP = 3,
+  TRUSTY_FS_TDEA = 4,
+  TRUSTY_FS_NSP = 5,
+};
+
+enum TrustyBlockType {
+  TRUSTY_BLOCKTYPE_UNKNOWN = 0,
+  TRUSTY_BLOCKTYPE_FILES_ROOT = 1,
+  TRUSTY_BLOCKTYPE_FREE_ROOT = 2,
+  TRUSTY_BLOCKTYPE_FILES_INTERNAL = 3,
+  TRUSTY_BLOCKTYPE_FREE_INTERNAL = 4,
+  TRUSTY_BLOCKTYPE_FILE_ENTRY = 5,
+  TRUSTY_BLOCKTYPE_FILE_BLOCK_MAP = 6,
+  TRUSTY_BLOCKTYPE_FILE_DATA = 7,
+  TRUSTY_BLOCKTYPE_CHECKPOINT_ROOT = 8,
+  TRUSTY_BLOCKTYPE_CHECKPOINT_FILES_ROOT = 9,
+  TRUSTY_BLOCKTYPE_CHECKPOINT_FREE_ROOT = 10,
+};
+
+struct metrics_report_storage_error_req {
+    enum TrustyStorageErrorType error;
+    char app_id[UUID_STR_SIZE];
+    char client_app_id[UUID_STR_SIZE];
+    uint32_t write;
+    enum TrustyFileSystem file_system;
+    uint64_t file_path_hash;
+    enum TrustyBlockType block_type;
+    uint64_t repair_counter;
+} __attribute__((__packed__));
+
+struct metrics_msg {
+    struct metrics_req req;
+    union {
+        struct metrics_report_crash_req crash_args;
+        struct metrics_report_storage_error_req storage_args;
+    };
+} __attribute__((__packed__));
\ No newline at end of file
diff --git a/trusty/metrics/metrics.cpp b/trusty/metrics/metrics.cpp
index 3ac128a..d2f0b0a 100644
--- a/trusty/metrics/metrics.cpp
+++ b/trusty/metrics/metrics.cpp
@@ -78,9 +78,8 @@
         return Error() << "connection to Metrics TA has not been initialized yet";
     }
 
-    uint8_t msg[METRICS_MAX_MSG_SIZE];
-
-    auto rc = read(metrics_fd_, msg, sizeof(msg));
+    struct metrics_msg metrics_msg;
+    int rc = read(metrics_fd_, &metrics_msg, sizeof(metrics_msg));
     if (rc < 0) {
         return ErrnoError() << "failed to read metrics message";
     }
@@ -89,23 +88,14 @@
     if (msg_len < sizeof(metrics_req)) {
         return Error() << "message too small: " << rc;
     }
-    auto req = reinterpret_cast<metrics_req*>(msg);
-    size_t offset = sizeof(metrics_req);
+    uint32_t cmd = metrics_msg.req.cmd;
     uint32_t status = METRICS_NO_ERROR;
 
-    switch (req->cmd) {
+    switch (cmd) {
         case METRICS_CMD_REPORT_CRASH: {
-            if (msg_len < offset + sizeof(metrics_report_crash_req)) {
-                return Error() << "message too small: " << rc;
-            }
-            auto crash_args = reinterpret_cast<metrics_report_crash_req*>(msg + offset);
-            offset += sizeof(metrics_report_crash_req);
-
-            if (msg_len < offset + crash_args->app_id_len) {
-                return Error() << "message too small: " << rc;
-            }
-            auto app_id_ptr = reinterpret_cast<char*>(msg + offset);
-            std::string app_id(app_id_ptr, crash_args->app_id_len);
+            struct metrics_report_crash_req crash_args = metrics_msg.crash_args;
+            auto app_id_ptr = crash_args.app_id;
+            std::string app_id(app_id_ptr, UUID_STR_SIZE);
 
             HandleCrash(app_id);
             break;
@@ -121,7 +111,7 @@
     }
 
     metrics_resp resp = {
-            .cmd = req->cmd | METRICS_CMD_RESP_BIT,
+            .cmd = cmd | METRICS_CMD_RESP_BIT,
             .status = status,
     };