Merge changes from topic "memcg_v2_soong_flags" into main

* changes:
  Add build flag to split the cgroup v2 hierarchy into apps/system
  Add build flag to force memcg to the v2 cgroup hierarchy
  Use ConvertUid{Pid}ToPath for all path generation
  Fix unused params and remove unneeded cflags
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 235fdfd..2529516 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -373,7 +373,6 @@
 
     sanitize: {
         memtag_heap: true,
-        memtag_stack: true,
     },
 
     shared_libs: [
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 526e2ca..7c52e6e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -610,7 +610,7 @@
   setjmp(jump_buf);
 }
 
-TEST_F(CrasherTest, mte_illegal_setjmp) {
+TEST_F(CrasherTest, DISABLED_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
@@ -1874,8 +1874,8 @@
   StartProcess([&recoverable]() {
     const char* env[] = {"GWP_ASAN_SAMPLE_RATE=1", "GWP_ASAN_PROCESS_SAMPLING=1",
                          "GWP_ASAN_MAX_ALLOCS=40000", nullptr, nullptr};
-    if (recoverable) {
-      env[3] = "GWP_ASAN_RECOVERABLE=true";
+    if (!recoverable) {
+      env[3] = "GWP_ASAN_RECOVERABLE=false";
     }
     std::string test_name = ::testing::UnitTest::GetInstance()->current_test_info()->name();
     test_name = std::regex_replace(test_name, std::regex("run_gwp_asan_test"),
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 25031bf..e26746b 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -108,7 +108,7 @@
                            "persist.device_config.memory_safety_native.permissive.process.%s",
                            getprogname());
   // DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
-  // not async-safe (and this functiong gets used in a signal handler).
+  // not async-safe, and this function gets used in a signal handler.
   return property_parse_bool("persist.sys.mte.permissive") ||
          property_parse_bool("persist.device_config.memory_safety_native.permissive.default") ||
          property_parse_bool(process_sysprop_name) ||
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 12a1ddc..6b9e493 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -1547,9 +1547,14 @@
 
 void reboot_to_userspace_fastboot() {
     fb->RebootTo("fastboot");
+    if (fb->WaitForDisconnect() != fastboot::SUCCESS) {
+        die("Error waiting for USB disconnect.");
+    }
     fb->set_transport(nullptr);
 
-    // Give the current connection time to close.
+    // Not all platforms support WaitForDisconnect. There also isn't a great way to tell whether
+    // or not WaitForDisconnect is supported. So, just wait a bit extra for everyone, in order to
+    // make sure that the device has had time to initiate its reboot and disconnect itself.
     std::this_thread::sleep_for(std::chrono::seconds(1));
 
     fb->set_transport(open_device());
diff --git a/fastboot/fuzzer/Android.bp b/fastboot/fuzzer/Android.bp
index a898070..59533fa 100644
--- a/fastboot/fuzzer/Android.bp
+++ b/fastboot/fuzzer/Android.bp
@@ -55,7 +55,10 @@
     ],
     fuzz_config: {
         cc: [
-            "android-media-fuzzing-reports@google.com",
+            "dvander@google.com",
+            "elsk@google.com",
+            "enh@google.com",
+            "zhangkelvin@google.com",
         ],
         componentid: 533764,
         hotlists: [
diff --git a/fs_mgr/TEST_MAPPING b/fs_mgr/TEST_MAPPING
index 1989a5c..32e8b88 100644
--- a/fs_mgr/TEST_MAPPING
+++ b/fs_mgr/TEST_MAPPING
@@ -25,8 +25,6 @@
     {
       "name": "vab_legacy_tests"
     },
-    // TODO(b/279009697):
-    //{"name": "vabc_legacy_tests"},
     {
       "name": "cow_api_test"
     },
@@ -44,8 +42,6 @@
     {
       "name": "vab_legacy_tests"
     },
-    // TODO(b/279009697):
-    //{"name": "vabc_legacy_tests"}
     {
       "name": "snapuserd_test"
     }
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index 5cc0346..c3ca758 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -71,6 +71,9 @@
         "libbase",
         "liblog",
     ],
+    header_libs: [
+        "libstorage_literals_headers",
+    ],
     srcs: [":libdm_test_srcs"],
     auto_gen_config: true,
     require_root: true,
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index fee67fdf..a963322 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -769,5 +769,25 @@
     return true;
 }
 
+bool DeviceMapper::SendMessage(const std::string& name, uint64_t sector,
+                               const std::string& message) {
+    std::string ioctl_buffer(sizeof(struct dm_ioctl) + sizeof(struct dm_target_msg), 0);
+    ioctl_buffer += message;
+    ioctl_buffer.push_back('\0');
+
+    struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(&ioctl_buffer[0]);
+    InitIo(io, name);
+    io->data_size = ioctl_buffer.size();
+    io->data_start = sizeof(struct dm_ioctl);
+    struct dm_target_msg* msg =
+            reinterpret_cast<struct dm_target_msg*>(&ioctl_buffer[sizeof(struct dm_ioctl)]);
+    msg->sector = sector;
+    if (ioctl(fd_, DM_TARGET_MSG, io)) {
+        PLOG(ERROR) << "DM_TARGET_MSG failed";
+        return false;
+    }
+    return true;
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 1f6bd1a..b5cc9aa 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -298,5 +298,43 @@
     return android::base::Join(argv, " ");
 }
 
+DmTargetThinPool::DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
+                                   const std::string& data_dev, uint64_t data_block_size,
+                                   uint64_t low_water_mark)
+    : DmTarget(start, length),
+      metadata_dev_(metadata_dev),
+      data_dev_(data_dev),
+      data_block_size_(data_block_size),
+      low_water_mark_(low_water_mark) {}
+
+std::string DmTargetThinPool::GetParameterString() const {
+    std::vector<std::string> args{
+            metadata_dev_,
+            data_dev_,
+            std::to_string(data_block_size_),
+            std::to_string(low_water_mark_),
+    };
+    return android::base::Join(args, " ");
+}
+
+bool DmTargetThinPool::Valid() const {
+    // data_block_size: must be between 128 (64KB) and 2097152 (1GB) and a multiple of 128 (64KB)
+    if (data_block_size_ < 128 || data_block_size_ > 2097152) return false;
+    if (data_block_size_ % 128) return false;
+    return true;
+}
+
+DmTargetThin::DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev,
+                           uint64_t dev_id)
+    : DmTarget(start, length), pool_dev_(pool_dev), dev_id_(dev_id) {}
+
+std::string DmTargetThin::GetParameterString() const {
+    std::vector<std::string> args{
+            pool_dev_,
+            std::to_string(dev_id_),
+    };
+    return android::base::Join(args, " ");
+}
+
 }  // namespace dm
 }  // namespace android
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index d043be6..b890f47 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -37,12 +37,14 @@
 #include <gtest/gtest.h>
 #include <libdm/dm.h>
 #include <libdm/loop_control.h>
+#include <storage_literals/storage_literals.h>
 #include "test_util.h"
 #include "utility.h"
 
 using namespace std;
 using namespace std::chrono_literals;
 using namespace android::dm;
+using namespace android::storage_literals;
 using android::base::make_scope_guard;
 using android::base::unique_fd;
 
@@ -773,3 +775,42 @@
     ASSERT_EQ(name, test_name_);
     ASSERT_FALSE(uuid.empty());
 }
+
+TEST_F(DmTest, ThinProvisioning) {
+    if (!DeviceMapper::Instance().GetTargetByName("thin-pool", nullptr)) GTEST_SKIP();
+
+    constexpr uint64_t MetaSize = 2_MiB;
+    constexpr uint64_t DataSize = 64_MiB;
+    constexpr uint64_t ThinSize = 1_TiB;
+
+    // Prepare two loop devices for meta and data devices.
+    TemporaryFile meta;
+    ASSERT_GE(meta.fd, 0);
+    ASSERT_EQ(0, ftruncate64(meta.fd, MetaSize));
+    TemporaryFile data;
+    ASSERT_GE(data.fd, 0);
+    ASSERT_EQ(0, ftruncate64(data.fd, DataSize));
+
+    LoopDevice loop_meta(meta.fd, 10s);
+    ASSERT_TRUE(loop_meta.valid());
+    LoopDevice loop_data(data.fd, 10s);
+    ASSERT_TRUE(loop_data.valid());
+
+    // Create a thin-pool
+    DmTable poolTable;
+    poolTable.Emplace<DmTargetThinPool>(0, DataSize / kSectorSize, loop_meta.device(),
+                                        loop_data.device(), 128, 0);
+    TempDevice pool("pool", poolTable);
+    ASSERT_TRUE(pool.valid());
+
+    // Create a thin volume
+    uint64_t thin_volume_id = 0;
+    ASSERT_TRUE(DeviceMapper::Instance().SendMessage(
+            "pool", 0, "create_thin " + std::to_string(thin_volume_id)));
+
+    // Use a thin volume to create a 1T device
+    DmTable thinTable;
+    thinTable.Emplace<DmTargetThin>(0, ThinSize / kSectorSize, pool.path(), thin_volume_id);
+    TempDevice thin("thin", thinTable);
+    ASSERT_TRUE(thin.valid());
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index fa97653..43d84f9 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -307,6 +307,9 @@
 
     bool GetDeviceNameAndUuid(dev_t dev, std::string* name, std::string* uuid);
 
+    // Send |message| to target, pointed by |name| and |sector|. Use 0 if |sector| is not needed.
+    bool SendMessage(const std::string& name, uint64_t sector, const std::string& message);
+
   private:
     // Maximum possible device mapper targets registered in the kernel.
     // This is only used to read the list of targets from kernel so we allocate
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 97f3c13..c49fc5e 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -349,6 +349,35 @@
     std::string GetParameterString() const override { return ""; }
 };
 
+class DmTargetThinPool final : public DmTarget {
+  public:
+    DmTargetThinPool(uint64_t start, uint64_t length, const std::string& metadata_dev,
+                     const std::string& data_dev, uint64_t data_block_size,
+                     uint64_t low_water_mark);
+
+    std::string name() const override { return "thin-pool"; }
+    std::string GetParameterString() const override;
+    bool Valid() const override;
+
+  private:
+    std::string metadata_dev_;
+    std::string data_dev_;
+    uint64_t data_block_size_;
+    uint64_t low_water_mark_;
+};
+
+class DmTargetThin final : public DmTarget {
+  public:
+    DmTargetThin(uint64_t start, uint64_t length, const std::string& pool_dev, uint64_t dev_id);
+
+    std::string name() const override { return "thin"; }
+    std::string GetParameterString() const override;
+
+  private:
+    std::string pool_dev_;
+    uint64_t dev_id_;
+};
+
 }  // namespace dm
 }  // namespace android
 
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
index ac04245..21dc666 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_compress.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <memory>
-#include <vector>
 #include "libsnapshot/cow_format.h"
 
 namespace android {
@@ -25,27 +24,30 @@
 
 class ICompressor {
   public:
-    explicit ICompressor(uint32_t compression_level, uint32_t block_size)
+    explicit ICompressor(const int32_t compression_level, const uint32_t block_size)
         : compression_level_(compression_level), block_size_(block_size) {}
 
     virtual ~ICompressor() {}
     // Factory methods for compression methods.
-    static std::unique_ptr<ICompressor> Gz(uint32_t compression_level, const int32_t block_size);
-    static std::unique_ptr<ICompressor> Brotli(uint32_t compression_level,
-                                               const int32_t block_size);
-    static std::unique_ptr<ICompressor> Lz4(uint32_t compression_level, const int32_t block_size);
-    static std::unique_ptr<ICompressor> Zstd(uint32_t compression_level, const int32_t block_size);
+    static std::unique_ptr<ICompressor> Gz(const int32_t compression_level,
+                                           const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Brotli(const int32_t compression_level,
+                                               const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Lz4(const int32_t compression_level,
+                                            const uint32_t block_size);
+    static std::unique_ptr<ICompressor> Zstd(const int32_t compression_level,
+                                             const uint32_t block_size);
 
     static std::unique_ptr<ICompressor> Create(CowCompression compression,
-                                               const int32_t block_size);
+                                               const uint32_t block_size);
 
-    uint32_t GetCompressionLevel() const { return compression_level_; }
+    int32_t GetCompressionLevel() const { return compression_level_; }
     uint32_t GetBlockSize() const { return block_size_; }
     [[nodiscard]] virtual std::vector<uint8_t> Compress(const void* data, size_t length) const = 0;
 
   private:
-    uint32_t compression_level_;
-    uint32_t block_size_;
+    const int32_t compression_level_;
+    const uint32_t block_size_;
 };
 }  // namespace snapshot
 }  // namespace android
\ No newline at end of file
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index 6865b19..6a7153d 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -293,7 +293,7 @@
 };
 struct CowCompression {
     CowCompressionAlgorithm algorithm = kCowCompressNone;
-    uint32_t compression_level = 0;
+    int32_t compression_level = 0;
 };
 
 static constexpr uint8_t kCowReadAheadNotStarted = 0;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
index 0205f50..bff5257 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_compress.cpp
@@ -17,6 +17,7 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#include <cstdint>
 #include <limits>
 #include <memory>
 #include <queue>
@@ -57,7 +58,7 @@
 }
 
 std::unique_ptr<ICompressor> ICompressor::Create(CowCompression compression,
-                                                 const int32_t block_size) {
+                                                 const uint32_t block_size) {
     switch (compression.algorithm) {
         case kCowCompressLz4:
             return ICompressor::Lz4(compression.compression_level, block_size);
@@ -101,7 +102,7 @@
 
 class GzCompressor final : public ICompressor {
   public:
-    GzCompressor(uint32_t compression_level, const uint32_t block_size)
+    GzCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -122,7 +123,7 @@
 
 class Lz4Compressor final : public ICompressor {
   public:
-    Lz4Compressor(uint32_t compression_level, const uint32_t block_size)
+    Lz4Compressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -154,7 +155,7 @@
 
 class BrotliCompressor final : public ICompressor {
   public:
-    BrotliCompressor(uint32_t compression_level, const uint32_t block_size)
+    BrotliCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size){};
 
     std::vector<uint8_t> Compress(const void* data, size_t length) const override {
@@ -180,7 +181,7 @@
 
 class ZstdCompressor final : public ICompressor {
   public:
-    ZstdCompressor(uint32_t compression_level, const uint32_t block_size)
+    ZstdCompressor(int32_t compression_level, const uint32_t block_size)
         : ICompressor(compression_level, block_size),
           zstd_context_(ZSTD_createCCtx(), ZSTD_freeCCtx) {
         ZSTD_CCtx_setParameter(zstd_context_.get(), ZSTD_c_compressionLevel, compression_level);
@@ -318,22 +319,23 @@
     }
 }
 
-std::unique_ptr<ICompressor> ICompressor::Brotli(uint32_t compression_level,
-                                                 const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Brotli(const int32_t compression_level,
+                                                 const uint32_t block_size) {
     return std::make_unique<BrotliCompressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Gz(uint32_t compression_level, const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Gz(const int32_t compression_level,
+                                             const uint32_t block_size) {
     return std::make_unique<GzCompressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Lz4(uint32_t compression_level,
-                                              const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Lz4(const int32_t compression_level,
+                                              const uint32_t block_size) {
     return std::make_unique<Lz4Compressor>(compression_level, block_size);
 }
 
-std::unique_ptr<ICompressor> ICompressor::Zstd(uint32_t compression_level,
-                                               const int32_t block_size) {
+std::unique_ptr<ICompressor> ICompressor::Zstd(const int32_t compression_level,
+                                               const uint32_t block_size) {
     return std::make_unique<ZstdCompressor>(compression_level, block_size);
 }
 
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
index d0864e0..0993dba 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v2.cpp
@@ -134,7 +134,7 @@
         return false;
     }
     if (parts.size() > 1) {
-        if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
+        if (!android::base::ParseInt(parts[1], &compression_.compression_level)) {
             LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
             return false;
         }
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
index 73deafb..95398e4 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/writer_v3.cpp
@@ -149,7 +149,7 @@
     }
 
     if (parts.size() > 1) {
-        if (!android::base::ParseUint(parts[1], &compression_.compression_level)) {
+        if (!android::base::ParseInt(parts[1], &compression_.compression_level)) {
             LOG(ERROR) << "failed to parse compression level invalid type: " << parts[1];
             return false;
         }
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index de91bd2..7ca53ad 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -24,7 +24,6 @@
 #include <filesystem>
 #include <optional>
 #include <thread>
-#include <unordered_set>
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
@@ -46,7 +45,6 @@
 #include <android/snapshot/snapshot.pb.h>
 #include <libsnapshot/snapshot_stats.h>
 #include "device_info.h"
-#include "libsnapshot_cow/parser_v2.h"
 #include "partition_cow_creator.h"
 #include "snapshot_metadata_updater.h"
 #include "utility.h"
@@ -3309,7 +3307,7 @@
             compression_algorithm = "gz";
         }
         LOG(INFO) << "using compression algorithm: " << compression_algorithm
-                   << ", max compressible block size: " << compression_factor;
+                  << ", max compressible block size: " << compression_factor;
     }
 
     PartitionCowCreator cow_creator{
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 8d0c898..80dad17 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -2883,7 +2883,16 @@
     ::testing::AddGlobalTestEnvironment(new ::android::snapshot::SnapshotTestEnvironment());
     gflags::ParseCommandLineFlags(&argc, &argv, false);
 
-    android::base::SetProperty("ctl.stop", "snapuserd");
+    bool vab_legacy = false;
+    if (FLAGS_force_mode == "vab-legacy") {
+        vab_legacy = true;
+    }
+
+    if (!vab_legacy) {
+        // This is necessary if the configuration we're testing doesn't match the device.
+        android::base::SetProperty("ctl.stop", "snapuserd");
+        android::snapshot::KillSnapuserd();
+    }
 
     std::unordered_set<std::string> modes = {"", "vab-legacy"};
     if (modes.count(FLAGS_force_mode) == 0) {
@@ -2891,13 +2900,12 @@
         return 1;
     }
 
-    // This is necessary if the configuration we're testing doesn't match the device.
-    android::snapshot::KillSnapuserd();
-
     int ret = RUN_ALL_TESTS();
 
     android::base::SetProperty("snapuserd.test.io_uring.force_disable", "0");
 
-    android::snapshot::KillSnapuserd();
+    if (!vab_legacy) {
+        android::snapshot::KillSnapuserd();
+    }
     return ret;
 }
diff --git a/fs_mgr/libsnapshot/snapshotctl.cpp b/fs_mgr/libsnapshot/snapshotctl.cpp
index 5d3f96c..192e1d6 100644
--- a/fs_mgr/libsnapshot/snapshotctl.cpp
+++ b/fs_mgr/libsnapshot/snapshotctl.cpp
@@ -47,7 +47,9 @@
 
 #include "partition_cow_creator.h"
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 #include <BootControlClient.h>
+#endif
 
 using namespace std::chrono_literals;
 using namespace std::string_literals;
@@ -92,6 +94,7 @@
 namespace android {
 namespace snapshot {
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 class MapSnapshots {
   public:
     MapSnapshots(std::string path = "");
@@ -462,6 +465,7 @@
     }
     return true;
 }
+#endif
 
 bool DumpCmdHandler(int /*argc*/, char** argv) {
     android::base::InitLogging(argv, TeeLogger(LogdLogger(), &StderrLogger));
@@ -485,6 +489,7 @@
     return false;
 }
 
+#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 bool GetVerityPartitions(std::vector<std::string>& partitions) {
     auto& dm = android::dm::DeviceMapper::Instance();
     auto dm_block_devices = dm.FindDmPartitions();
@@ -637,7 +642,6 @@
     return cow.FinishSnapshotWrites();
 }
 
-#ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
 bool CreateTestUpdate(SnapshotManager* sm) {
     chromeos_update_engine::DeltaArchiveManifest manifest;
 
@@ -761,13 +765,13 @@
         {"map", MapCmdHandler},
 #ifdef SNAPSHOTCTL_USERDEBUG_OR_ENG
         {"test-blank-ota", TestOtaHandler},
-#endif
-        {"unmap", UnmapCmdHandler},
         {"apply-update", ApplyUpdate},
         {"map-snapshots", MapPrecreatedSnapshots},
         {"unmap-snapshots", UnMapPrecreatedSnapshots},
         {"delete-snapshots", DeletePrecreatedSnapshots},
         {"revert-snapshots", RemovePrecreatedSnapshots},
+#endif
+        {"unmap", UnmapCmdHandler},
         // clang-format on
 };
 
diff --git a/fs_mgr/tests/vts_fs_test.cpp b/fs_mgr/tests/vts_fs_test.cpp
index 9503072..f55cadb 100644
--- a/fs_mgr/tests/vts_fs_test.cpp
+++ b/fs_mgr/tests/vts_fs_test.cpp
@@ -74,6 +74,7 @@
     ASSERT_EQ(access("/sys/fs/erofs", F_OK), 0);
 }
 
+// @VsrTest = 3.7.10
 TEST(fs, PartitionTypes) {
     // Requirements only apply to Android 13+, 5.10+ devices.
     int vsr_level = GetVsrLevel();
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index f843821..00f8038 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -50,6 +50,7 @@
     std::cerr << "  create <dm-name> [-ro] <targets...>" << std::endl;
     std::cerr << "  delete <dm-name>" << std::endl;
     std::cerr << "  list <devices | targets> [-v]" << std::endl;
+    std::cerr << "  message <dm-name> <sector> <message>" << std::endl;
     std::cerr << "  getpath <dm-name>" << std::endl;
     std::cerr << "  getuuid <dm-name>" << std::endl;
     std::cerr << "  ima <dm-name>" << std::endl;
@@ -203,6 +204,46 @@
             return std::make_unique<DmTargetUser>(start_sector, num_sectors, control_device);
         } else if (target_type == "error") {
             return std::make_unique<DmTargetError>(start_sector, num_sectors);
+        } else if (target_type == "thin-pool") {
+            if (!HasArgs(4)) {
+                std::cerr << "Expected \"thin-pool\" <metadata dev> <data dev> <data block size> "
+                             "<low water mark> <feature args>"
+                          << std::endl;
+                return nullptr;
+            }
+
+            std::string metadata_dev = NextArg();
+            std::string data_dev = NextArg();
+            std::string data_block_size_str = NextArg();
+            std::string low_water_mark_str = NextArg();
+
+            uint64_t data_block_size;
+            if (!android::base::ParseUint(data_block_size_str, &data_block_size)) {
+                std::cerr << "Data block size must be an unsigned integer.\n";
+                return nullptr;
+            }
+            uint64_t low_water_mark;
+            if (!android::base::ParseUint(low_water_mark_str, &low_water_mark)) {
+                std::cerr << "Low water mark must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetThinPool>(start_sector, num_sectors, metadata_dev,
+                                                      data_dev, data_block_size, low_water_mark);
+        } else if (target_type == "thin") {
+            if (!HasArgs(2)) {
+                std::cerr << "Expected \"thin\" <pool dev> <dev id>" << std::endl;
+                return nullptr;
+            }
+
+            std::string pool_dev = NextArg();
+            std::string dev_id_str = NextArg();
+
+            uint64_t dev_id;
+            if (!android::base::ParseUint(dev_id_str, &dev_id)) {
+                std::cerr << "Dev id must be an unsigned integer.\n";
+                return nullptr;
+            }
+            return std::make_unique<DmTargetThin>(start_sector, num_sectors, pool_dev, dev_id);
         } else {
             std::cerr << "Unrecognized target type: " << target_type << std::endl;
             return nullptr;
@@ -417,6 +458,24 @@
     return -EINVAL;
 }
 
+static int DmMessageCmdHandler(int argc, char** argv) {
+    if (argc != 3) {
+        std::cerr << "Usage: dmctl message <name> <sector> <message>" << std::endl;
+        return -EINVAL;
+    }
+    uint64_t sector;
+    if (!android::base::ParseUint(argv[1], &sector)) {
+        std::cerr << "Invalid argument for sector: " << argv[1] << std::endl;
+        return -EINVAL;
+    }
+    DeviceMapper& dm = DeviceMapper::Instance();
+    if (!dm.SendMessage(argv[0], sector, argv[2])) {
+        std::cerr << "Could not send message to " << argv[0] << std::endl;
+        return -EINVAL;
+    }
+    return 0;
+}
+
 static int HelpCmdHandler(int /* argc */, char** /* argv */) {
     Usage();
     return 0;
@@ -576,6 +635,7 @@
         {"delete", DmDeleteCmdHandler},
         {"replace", DmReplaceCmdHandler},
         {"list", DmListCmdHandler},
+        {"message", DmMessageCmdHandler},
         {"help", HelpCmdHandler},
         {"getpath", GetPathCmdHandler},
         {"getuuid", GetUuidCmdHandler},
diff --git a/init/Android.bp b/init/Android.bp
index d4b7fab..ff82f7f 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -255,7 +255,10 @@
 
 cc_library_static {
     name: "libinit.microdroid",
-    defaults: ["libinit_defaults"],
+    defaults: [
+        "avf_build_flags_cc",
+        "libinit_defaults",
+    ],
     cflags: ["-DMICRODROID=1"],
 }
 
@@ -315,7 +318,10 @@
 
 cc_binary {
     name: "init_second_stage.microdroid",
-    defaults: ["init_second_stage_defaults"],
+    defaults: [
+        "avf_build_flags_cc",
+        "init_second_stage_defaults",
+    ],
     static_libs: ["libinit.microdroid"],
     cflags: ["-DMICRODROID=1"],
     installable: false,
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 836d536..ae216c6 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -396,9 +396,10 @@
     use_snapuserd_ = sm->IsSnapuserdRequired();
     if (use_snapuserd_) {
         if (sm->UpdateUsesUserSnapshots()) {
-            LaunchFirstStageSnapuserd(SnapshotDriver::DM_USER);
+            LaunchFirstStageSnapuserd();
         } else {
-            LaunchFirstStageSnapuserd(SnapshotDriver::DM_SNAPSHOT);
+            LOG(FATAL) << "legacy virtual-ab is no longer supported";
+            return false;
         }
     }
 
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 59e57b9..1d17e3c 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -236,6 +236,9 @@
                            persistent_properties->mutable_properties()->end(),
                            [&name](const auto& record) { return record.name() == name; });
     if (it != persistent_properties->mutable_properties()->end()) {
+        if (it->value() == value) {
+            return;
+        }
         it->set_name(name);
         it->set_value(value);
     } else {
diff --git a/init/persistent_properties_test.cpp b/init/persistent_properties_test.cpp
index 5763050..97865d7 100644
--- a/init/persistent_properties_test.cpp
+++ b/init/persistent_properties_test.cpp
@@ -17,6 +17,9 @@
 #include "persistent_properties.h"
 
 #include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #include <vector>
 
@@ -155,6 +158,31 @@
     EXPECT_FALSE(it == read_back_properties.properties().end());
 }
 
+TEST(persistent_properties, NopUpdateDoesntWriteFile) {
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    persistent_property_filename = tf.path;
+
+    auto last_modified = [&tf]() -> time_t {
+        struct stat buf;
+        EXPECT_EQ(fstat(tf.fd, &buf), 0);
+        return buf.st_mtime;
+    };
+
+    std::vector<std::pair<std::string, std::string>> persistent_properties = {
+            {"persist.sys.locale", "en-US"},
+            {"persist.sys.timezone", "America/Los_Angeles"},
+    };
+    ASSERT_RESULT_OK(
+            WritePersistentPropertyFile(VectorToPersistentProperties(persistent_properties)));
+
+    time_t t = last_modified();
+    sleep(2);
+    WritePersistentProperty("persist.sys.locale", "en-US");
+    // Ensure that the file was not modified
+    ASSERT_EQ(last_modified(), t);
+}
+
 TEST(persistent_properties, RejectNonPersistProperty) {
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
diff --git a/init/selinux.cpp b/init/selinux.cpp
index e191b60..c2d9b8d 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -66,6 +66,7 @@
 #include <android-base/result.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <android/avf_cc_flags.h>
 #include <fs_avb/fs_avb.h>
 #include <fs_mgr.h>
 #include <libgsi/libgsi.h>
@@ -702,6 +703,15 @@
 
     SelinuxSetEnforcement();
 
+    if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
+        // We run restorecon of /microdroid_resources while we are still in kernel context to avoid
+        // granting init `tmpfs:file relabelfrom` capability.
+        const int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
+        if (selinux_android_restorecon("/microdroid_resources", flags) == -1) {
+            PLOG(FATAL) << "restorecon of /microdroid_resources failed";
+        }
+    }
+
     // We're in the kernel domain and want to transition to the init domain.  File systems that
     // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
     // but other file systems do.  In particular, this is needed for ramdisks such as the
diff --git a/init/service.cpp b/init/service.cpp
index eb24dd5..31308a0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -355,20 +355,35 @@
     // If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
+    constexpr const char native_watchdog_reboot_time[] = "persist.init.svc.last_fatal_reboot_epoch";
+    uint64_t throttle_window =
+            std::chrono::duration_cast<std::chrono::seconds>(std::chrono::hours(24)).count();
     if (((flags_ & SVC_CRITICAL) || is_process_updatable) && !(flags_ & SVC_RESTART) &&
         !was_last_exit_ok_) {
         bool boot_completed = GetBoolProperty("sys.boot_completed", false);
         if (now < time_crashed_ + fatal_crash_window_ || !boot_completed) {
             if (++crash_count_ > 4) {
-                auto exit_reason = boot_completed ?
-                    "in " + std::to_string(fatal_crash_window_.count()) + " minutes" :
-                    "before boot completed";
+                auto exit_reason =
+                        boot_completed
+                                ? "in " + std::to_string(fatal_crash_window_.count()) + " minutes"
+                                : "before boot completed";
                 if (flags_ & SVC_CRITICAL) {
                     if (!GetBoolProperty("init.svc_debug.no_fatal." + name_, false)) {
-                        // Aborts into `fatal_reboot_target_'.
-                        SetFatalRebootTarget(fatal_reboot_target_);
-                        LOG(FATAL) << "critical process '" << name_ << "' exited 4 times "
-                                   << exit_reason;
+                        uint64_t epoch_time =
+                                std::chrono::duration_cast<std::chrono::seconds>(
+                                        std::chrono::system_clock::now().time_since_epoch())
+                                        .count();
+                        // Do not reboot again If it was already initiated in the last 24hrs
+                        if (epoch_time - GetIntProperty(native_watchdog_reboot_time, 0) >
+                            throttle_window) {
+                            SetProperty(native_watchdog_reboot_time, std::to_string(epoch_time));
+                            // Aborts into `fatal_reboot_target_'.
+                            SetFatalRebootTarget(fatal_reboot_target_);
+                            LOG(FATAL) << "critical process '" << name_ << "' exited 4 times "
+                                       << exit_reason;
+                        } else {
+                            LOG(INFO) << "Reboot already performed in last 24hrs because of crash.";
+                        }
                     }
                 } else {
                     LOG(ERROR) << "process with updatable components '" << name_
diff --git a/init/snapuserd_transition.cpp b/init/snapuserd_transition.cpp
index dea7af9..9e3ff41 100644
--- a/init/snapuserd_transition.cpp
+++ b/init/snapuserd_transition.cpp
@@ -62,7 +62,7 @@
 static constexpr char kSnapuserdLabel[] = "u:object_r:snapuserd_exec:s0";
 static constexpr char kSnapuserdSocketLabel[] = "u:object_r:snapuserd_socket:s0";
 
-void LaunchFirstStageSnapuserd(SnapshotDriver driver) {
+void LaunchFirstStageSnapuserd() {
     SocketDescriptor socket_desc;
     socket_desc.name = android::snapshot::kSnapuserdSocket;
     socket_desc.type = SOCK_STREAM;
@@ -85,22 +85,13 @@
     if (pid == 0) {
         socket->Publish();
 
-        if (driver == SnapshotDriver::DM_USER) {
-            char arg0[] = "/system/bin/snapuserd";
-            char arg1[] = "-user_snapshot";
-            char* const argv[] = {arg0, arg1, nullptr};
-            if (execv(arg0, argv) < 0) {
-                PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
-            }
-            _exit(127);
-        } else {
-            char arg0[] = "/system/bin/snapuserd";
-            char* const argv[] = {arg0, nullptr};
-            if (execv(arg0, argv) < 0) {
-                PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
-            }
-            _exit(127);
+        char arg0[] = "/system/bin/snapuserd";
+        char arg1[] = "-user_snapshot";
+        char* const argv[] = {arg0, arg1, nullptr};
+        if (execv(arg0, argv) < 0) {
+            PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
         }
+        _exit(127);
     }
 
     auto client = SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 10s);
diff --git a/init/snapuserd_transition.h b/init/snapuserd_transition.h
index 557d105..e86e8da 100644
--- a/init/snapuserd_transition.h
+++ b/init/snapuserd_transition.h
@@ -29,13 +29,8 @@
 namespace android {
 namespace init {
 
-enum class SnapshotDriver {
-    DM_SNAPSHOT,
-    DM_USER,
-};
-
 // Fork and exec a new copy of snapuserd.
-void LaunchFirstStageSnapuserd(SnapshotDriver driver);
+void LaunchFirstStageSnapuserd();
 
 class SnapuserdSelinuxHelper final {
     using SnapshotManager = android::snapshot::SnapshotManager;
diff --git a/init/test_kill_services/Android.bp b/init/test_kill_services/Android.bp
index 37361a8..ada87d8 100644
--- a/init/test_kill_services/Android.bp
+++ b/init/test_kill_services/Android.bp
@@ -10,7 +10,10 @@
 cc_test {
     name: "init_kill_services_test",
     srcs: ["init_kill_services_test.cpp"],
-    shared_libs: ["libbase"],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+    ],
     test_suites: ["general-tests"],
 
     // TODO(b/153565474): switch back to auto-generation
diff --git a/init/test_kill_services/init_kill_services_test.cpp b/init/test_kill_services/init_kill_services_test.cpp
index 510ad8a..3af92bb 100644
--- a/init/test_kill_services/init_kill_services_test.cpp
+++ b/init/test_kill_services/init_kill_services_test.cpp
@@ -18,15 +18,20 @@
 
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <hidl/ServiceManagement.h>
 
 #include <iostream>
 
 using ::android::base::GetProperty;
 using ::android::base::SetProperty;
 using ::android::base::WaitForProperty;
+using ::android::hardware::isHidlSupported;
 using std::literals::chrono_literals::operator""s;
 
 void ExpectKillingServiceRecovers(const std::string& service_name) {
+    if (!isHidlSupported() && service_name == "hwservicemanager") {
+        GTEST_SKIP() << "No HIDL support on device so hwservicemanager will not be running";
+    }
     LOG(INFO) << "before we say hi to " << service_name << ", I can't have apexd around!";
 
     // b/280514080 - servicemanager will restart apexd, and apexd will restart the
diff --git a/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
index 333e61c..67c7514 100644
--- a/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
+++ b/libcutils/abi-dumps/arm64/source-based/libcutils.so.lsdump
@@ -290,6 +290,9 @@
    "name" : "fs_write_atomic_int"
   },
   {
+   "name" : "get_fs_config"
+  },
+  {
    "name" : "hashmapCreate"
   },
   {
@@ -1274,6 +1277,27 @@
    "source_file" : "system/core/libcutils/include/cutils/fs.h"
   },
   {
+   "function_name" : "get_fs_config",
+   "linker_set_key" : "get_fs_config",
+   "parameters" :
+   [
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIb"
+    },
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIP9fs_config"
+    }
+   ],
+   "return_type" : "_ZTIb",
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
    "function_name" : "hashmapCreate",
    "linker_set_key" : "hashmapCreate",
    "parameters" :
@@ -2392,6 +2416,15 @@
   },
   {
    "alignment" : 8,
+   "linker_set_key" : "_ZTIP9fs_config",
+   "name" : "fs_config *",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTIP9fs_config",
+   "size" : 8,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
+   "alignment" : 8,
    "linker_set_key" : "_ZTIP9str_parms",
    "name" : "str_parms *",
    "referenced_type" : "_ZTI9str_parms",
@@ -2684,6 +2717,37 @@
    "self_type" : "_ZTI5cnode",
    "size" : 40,
    "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+  },
+  {
+   "alignment" : 8,
+   "fields" :
+   [
+    {
+     "field_name" : "uid",
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "gid",
+     "field_offset" : 32,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "mode",
+     "field_offset" : 64,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "capabilities",
+     "field_offset" : 128,
+     "referenced_type" : "_ZTIm"
+    }
+   ],
+   "linker_set_key" : "_ZTI9fs_config",
+   "name" : "fs_config",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTI9fs_config",
+   "size" : 24,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
   }
  ],
  "rvalue_reference_types" : []
diff --git a/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
index f612fb9..f75240c 100644
--- a/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
+++ b/libcutils/abi-dumps/arm_arm64/source-based/libcutils.so.lsdump
@@ -300,6 +300,9 @@
    "name" : "fs_write_atomic_int"
   },
   {
+   "name" : "get_fs_config"
+  },
+  {
    "name" : "hashmapCreate"
   },
   {
@@ -1284,6 +1287,27 @@
    "source_file" : "system/core/libcutils/include/cutils/fs.h"
   },
   {
+   "function_name" : "get_fs_config",
+   "linker_set_key" : "get_fs_config",
+   "parameters" :
+   [
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIb"
+    },
+    {
+     "referenced_type" : "_ZTIPKc"
+    },
+    {
+     "referenced_type" : "_ZTIP9fs_config"
+    }
+   ],
+   "return_type" : "_ZTIb",
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
    "function_name" : "hashmapCreate",
    "linker_set_key" : "hashmapCreate",
    "parameters" :
@@ -2402,6 +2426,15 @@
   },
   {
    "alignment" : 4,
+   "linker_set_key" : "_ZTIP9fs_config",
+   "name" : "fs_config *",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTIP9fs_config",
+   "size" : 4,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
+  },
+  {
+   "alignment" : 4,
    "linker_set_key" : "_ZTIP9str_parms",
    "name" : "str_parms *",
    "referenced_type" : "_ZTI9str_parms",
@@ -2694,6 +2727,37 @@
    "self_type" : "_ZTI5cnode",
    "size" : 20,
    "source_file" : "system/core/libcutils/include/cutils/config_utils.h"
+  },
+  {
+   "alignment" : 8,
+   "fields" :
+   [
+    {
+     "field_name" : "uid",
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "gid",
+     "field_offset" : 32,
+     "referenced_type" : "_ZTIj"
+    },
+    {
+     "field_name" : "mode",
+     "field_offset" : 64,
+     "referenced_type" : "_ZTIt"
+    },
+    {
+     "field_name" : "capabilities",
+     "field_offset" : 128,
+     "referenced_type" : "_ZTIy"
+    }
+   ],
+   "linker_set_key" : "_ZTI9fs_config",
+   "name" : "fs_config",
+   "referenced_type" : "_ZTI9fs_config",
+   "self_type" : "_ZTI9fs_config",
+   "size" : 24,
+   "source_file" : "system/core/libcutils/include/private/fs_config.h"
   }
  ],
  "rvalue_reference_types" : []
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 919be2f..5efe209 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -91,7 +91,7 @@
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/bin" },
     { 00751, AID_ROOT,         AID_SHELL,        0, "vendor/apex/*/bin" },
     { 00755, AID_ROOT,         AID_SHELL,        0, "vendor" },
-    { 00755, AID_ROOT,         AID_ROOT,         0, 0 },
+    {},
         // clang-format on
 };
 #ifndef __ANDROID_VNDK__
@@ -218,17 +218,32 @@
     { 00640, AID_ROOT,      AID_SHELL,     0, "fstab.*" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "init*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "odm/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "odm/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "product/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "product/apex/*bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "product/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/xbin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/apex/*/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system_ext/apex/*/bin/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "system_ext/priv-app/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/apex/*bin/*" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "vendor/xbin/*" },
-    { 00644, AID_ROOT,      AID_ROOT,      0, 0 },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/framework/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/app/*" },
+    { 00644, AID_ROOT,      AID_ROOT,      0, "vendor/priv-app/*" },
+    {},
         // clang-format on
 };
 #ifndef __ANDROID_VNDK__
@@ -318,8 +333,8 @@
 auto __for_testing_only__fs_config_cmp = fs_config_cmp;
 #endif
 
-void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
-               unsigned* mode, uint64_t* capabilities) {
+bool get_fs_config(const char* path, bool dir, const char* target_out_path,
+                   struct fs_config* fs_conf) {
     const struct fs_path_config* pc;
     size_t which, plen;
 
@@ -362,11 +377,11 @@
             if (fs_config_cmp(dir, prefix, len, path, plen)) {
                 free(prefix);
                 close(fd);
-                *uid = header.uid;
-                *gid = header.gid;
-                *mode = (*mode & (~07777)) | header.mode;
-                *capabilities = header.capabilities;
-                return;
+                fs_conf->uid = header.uid;
+                fs_conf->gid = header.gid;
+                fs_conf->mode = header.mode;
+                fs_conf->capabilities = header.capabilities;
+                return true;
             }
             free(prefix);
         }
@@ -375,11 +390,28 @@
 
     for (pc = dir ? android_dirs : android_files; pc->prefix; pc++) {
         if (fs_config_cmp(dir, pc->prefix, strlen(pc->prefix), path, plen)) {
-            break;
+            fs_conf->uid = pc->uid;
+            fs_conf->gid = pc->gid;
+            fs_conf->mode = pc->mode;
+            fs_conf->capabilities = pc->capabilities;
+            return true;
         }
     }
-    *uid = pc->uid;
-    *gid = pc->gid;
-    *mode = (*mode & (~07777)) | pc->mode;
-    *capabilities = pc->capabilities;
+    return false;
+}
+
+void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
+               unsigned* mode, uint64_t* capabilities) {
+    struct fs_config conf;
+    if (get_fs_config(path, dir, target_out_path, &conf)) {
+        *uid = conf.uid;
+        *gid = conf.gid;
+        *mode = (*mode & S_IFMT) | conf.mode;
+        *capabilities = conf.capabilities;
+    } else {
+        *uid = AID_ROOT;
+        *gid = AID_ROOT;
+        *mode = (*mode & S_IFMT) | (dir ? 0755 : 0644);
+        *capabilities = 0;
+    }
 }
diff --git a/libcutils/include/private/fs_config.h b/libcutils/include/private/fs_config.h
index 45f46e5..9a727bc 100644
--- a/libcutils/include/private/fs_config.h
+++ b/libcutils/include/private/fs_config.h
@@ -21,8 +21,11 @@
 
 #pragma once
 
+#include <fcntl.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/cdefs.h>
+#include <unistd.h>
 
 #include <linux/capability.h>
 
@@ -30,17 +33,27 @@
 
 __BEGIN_DECLS
 
-/*
- * Used in:
- *  build/tools/fs_config/fs_config.c
- *  build/tools/fs_get_stats/fs_get_stats.c
- *  system/extras/ext4_utils/make_ext4fs_main.c
- *  external/squashfs-tools/squashfs-tools/android.c
- *  system/core/cpio/mkbootfs.c
- *  system/core/adb/file_sync_service.cpp
- *  system/extras/ext4_utils/canned_fs_config.c
- */
+/* This API is deprecated. New users should call get_fs_config. */
 void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid,
                unsigned* mode, uint64_t* capabilities);
 
+struct fs_config {
+  uid_t uid;
+  gid_t gid;
+  mode_t mode;
+  uint64_t capabilities;
+};
+
+/*
+ * If a file system configuration was found for the specified path, store it to *conf.
+ * Returns whether a file system configuration was found.
+ *
+ * dir: Whether path refers to a directory.
+ * target_out_path: Path to the base directory to read the file system configuration from, or a null
+ * pointer to use the root directory as the base. Host code should pass $ANDROID_PRODUCT_OUT or
+ * equivalent, and device code should pass a null pointer.
+ */
+bool get_fs_config(const char* path, bool dir, const char* target_out_path,
+                   struct fs_config* conf);
+
 __END_DECLS
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index fe827eb..029f4a7 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -89,7 +89,8 @@
 // The following four functions may be used via weak symbol references from libutils.
 // Clients assume that if any of these symbols are available, then deleteStack() is.
 
-#ifdef WEAKS_AVAILABLE
+// Apple and Windows does not support this, so only compile on other platforms.
+#if !defined(__APPLE__) && !defined(_WIN32)
 
 CallStack::CallStackUPtr CallStack::getCurrentInternal(int ignoreDepth) {
     CallStack::CallStackUPtr stack(new CallStack());
@@ -110,6 +111,6 @@
     delete stack;
 }
 
-#endif // WEAKS_AVAILABLE
+#endif  // !defined(__APPLE__) && !defined(_WIN32)
 
 }; // namespace android
diff --git a/libutils/CallStack_test.cpp b/libutils/CallStack_test.cpp
index 2cfaf61..7afc2c3 100644
--- a/libutils/CallStack_test.cpp
+++ b/libutils/CallStack_test.cpp
@@ -18,10 +18,16 @@
 
 #include <thread>
 
+#include <android-base/test_utils.h>
 #include <android-base/threads.h>
 #include <gtest/gtest.h>
 #include <utils/CallStack.h>
 
+#if defined(__ANDROID__)
+#include <log/log.h>
+#include <log/log_read.h>
+#endif
+
 __attribute__((__noinline__)) extern "C" void CurrentCaller(android::String8& backtrace) {
     android::CallStack cs;
     cs.update();
@@ -61,3 +67,38 @@
 
     ASSERT_NE(-1, cs.toString().find("(ThreadBusyWait")) << "Full backtrace:\n" << cs.toString();
 }
+
+#if defined(__ANDROID__)
+TEST(CallStackTest, log_stack) {
+    android::CallStack::logStack("callstack_test");
+    auto logger_list = android_logger_list_open(android_name_to_log_id("main"),
+                                                ANDROID_LOG_NONBLOCK, 1000, getpid());
+    ASSERT_NE(nullptr, logger_list);
+    std::string log;
+    while (true) {
+        log_msg log_msg;
+        auto ret = android_logger_list_read(logger_list, &log_msg);
+        if (ret == -EAGAIN) {
+            break;
+        }
+        ASSERT_GT(ret, 0);
+        if (log_msg.msg() == nullptr) {
+            continue;
+        }
+        // First get the tag.
+        char* msg = &log_msg.msg()[1];
+        if (std::string(msg) != "callstack_test") {
+            continue;
+        }
+        // Now move past the tag.
+        msg = &msg[strlen(msg) + 1];
+        log += msg;
+        log += '\n';
+    }
+    ASSERT_NE("", log) << "No messages found in the log from the test.";
+    // Look for a backtrace line such as:
+    //   #00 pc 00000000000536e4  libutils_test (testing::Test::Run()+436)
+    ASSERT_MATCH(log, "#\\d+ pc \\d+");
+    android_logger_list_close(logger_list);
+}
+#endif
diff --git a/libvendorsupport/include_llndk/android/llndk-versioning.h b/libvendorsupport/include_llndk/android/llndk-versioning.h
index 58cd18d..cf82fb7 100644
--- a/libvendorsupport/include_llndk/android/llndk-versioning.h
+++ b/libvendorsupport/include_llndk/android/llndk-versioning.h
@@ -14,22 +14,18 @@
 
 #pragma once
 
-/* 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
 // NDK, but uses its own versioning of YYYYMM format for vendor builds. The LLNDK symbols are
-// enabled when the vendor api level is equal to or newer than the ro.board.api_level.
-#define __INTRODUCED_IN_LLNDK(vendor_api_level)                                             \
-    _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wgcc-compat\"")   \
-            __attribute__((enable_if(                                                       \
-                    __ANDROID_VENDOR_API__ >= vendor_api_level,                             \
-                    "available in vendor API level " #vendor_api_level " that "             \
-                    "is newer than the current vendor API level. Guard the API "            \
-                    "call with '#if (__ANDROID_VENDOR_API__ >= " #vendor_api_level ")'."))) \
-            _Pragma("clang diagnostic pop")
+// enabled when the vendor api level is equal to or newer than the ro.board.api_level. These symbols
+// must be annotated in map.txt files with the `# llndk=YYYYMM` annotation. They also must be marked
+// with `__INTRODUCED_IN_LLNDK(YYYYMM)` in the header files. 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
+
+#if defined(__ANDROID_VENDOR__)
 
 // 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
@@ -39,13 +35,6 @@
 
 #else  // __ANDROID_VENDOR__
 
-// __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.
 #if !defined(API_LEVEL_AT_LEAST)
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 7444f96..593bb1e 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -223,13 +223,6 @@
 	$(hide) sed -i -e 's?%EXPORT_GLOBAL_HWASAN_OPTIONS%?$(EXPORT_GLOBAL_HWASAN_OPTIONS)?g' $@
 	$(hide) sed -i -e 's?%EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE%?$(EXPORT_GLOBAL_SCUDO_ALLOCATION_RING_BUFFER_SIZE)?g' $@
 
-# Append PLATFORM_VNDK_VERSION to base name.
-define append_vndk_version
-$(strip \
-  $(basename $(1)).$(PLATFORM_VNDK_VERSION)$(suffix $(1)) \
-)
-endef
-
 #######################################
 # sanitizer.libraries.txt
 include $(CLEAR_VARS)
diff --git a/rootdir/etc/linker.config.json b/rootdir/etc/linker.config.json
index d72ac66..8b3542f 100644
--- a/rootdir/etc/linker.config.json
+++ b/rootdir/etc/linker.config.json
@@ -9,8 +9,6 @@
     "libnativehelper.so",
     "libnativeloader.so",
     "libsigchain.so",
-    // TODO(b/122876336): Remove libpac.so once it's migrated to Webview
-    "libpac.so",
     // TODO(b/120786417 or b/134659294): libicuuc.so
     // and libicui18n.so are kept for app compat.
     "libicui18n.so",
@@ -32,6 +30,8 @@
   ],
   "provideLibs": [
     "libaptX_encoder.so",
-    "libaptXHD_encoder.so"
+    "libaptXHD_encoder.so",
+    "libEGL.so",
+    "libGLESv2.so"
   ]
 }
diff --git a/rootdir/init.rc b/rootdir/init.rc
index d4cd4b8..1af46c1 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -648,6 +648,8 @@
     mkdir /metadata/aconfig 0775 root system
     mkdir /metadata/aconfig/flags 0770 root system
     mkdir /metadata/aconfig/boot 0775 root system
+
+    mkdir /metadata/aconfig_test_missions 0775 root system
     exec_start aconfigd-init
     start aconfigd
 
@@ -1031,7 +1033,7 @@
     perform_apex_config
 
     # Create directories for boot animation.
-    mkdir /data/misc/bootanim 0755 system system encryption=DeleteIfNecessary
+    mkdir /data/misc/bootanim 0755 system system
 
     exec_start derive_sdk
 
diff --git a/toolbox/OWNERS b/toolbox/OWNERS
index 5e2c581..898ddce 100644
--- a/toolbox/OWNERS
+++ b/toolbox/OWNERS
@@ -1,2 +1,3 @@
 include platform/system/core:/janitors/OWNERS
 per-file modprobe.c=willmcvicker@google.com,dvander@google.com
+per-file getevent.c=file:platform/frameworks/base:/INPUT_OWNERS
diff --git a/toolbox/getevent.c b/toolbox/getevent.c
index f65bb20..7b896e9 100644
--- a/toolbox/getevent.c
+++ b/toolbox/getevent.c
@@ -441,7 +441,7 @@
     if(res < (int)sizeof(*event)) {
         if(errno == EINTR)
             return 0;
-        fprintf(stderr, "could not get event, %s\n", strerror(errno));
+        fprintf(stderr, "could not get inotify events, %s\n", strerror(errno));
         return 1;
     }
     //printf("got %d bytes of event information\n", res);
@@ -664,7 +664,7 @@
                 if(ufds[i].revents & POLLIN) {
                     res = read(ufds[i].fd, &event, sizeof(event));
                     if(res < (int)sizeof(event)) {
-                        fprintf(stderr, "could not get event\n");
+                        fprintf(stderr, "could not get evdev event, %s\n", strerror(errno));
                         return 1;
                     }
                     if(get_time) {
diff --git a/trusty/keymint/src/keymint_hal_main.rs b/trusty/keymint/src/keymint_hal_main.rs
index eda986a..ef0c598 100644
--- a/trusty/keymint/src/keymint_hal_main.rs
+++ b/trusty/keymint/src/keymint_hal_main.rs
@@ -82,7 +82,7 @@
 }
 
 fn main() {
-    if let Err(e) = inner_main() {
+    if let Err(HalServiceError(e)) = inner_main() {
         panic!("HAL service failed: {:?}", e);
     }
 }
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index dabe118..3cf0c05 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -37,7 +37,7 @@
 #define BENCH_RESULT_TPL                                    \
 "{"                                                         \
 "    \"schema_version\": 3,"                                \
-"    \"suite_name\": \"crypto\","                           \
+"    \"suite_name\": \"tipc\","                           \
 "    \"bench_name\": \"%s\","                               \
 "    \"results\": ["                                        \
 "        {"                                                 \
@@ -1041,7 +1041,7 @@
     }
     avg /= params->bench;
 
-    fprintf(stderr, BENCH_RESULT_TPL, params->test_name, min, max, avg, cold, min, max, avg, cold);
+    printf(BENCH_RESULT_TPL, params->test_name, min, max, avg, cold, min, max, avg, cold);
     return rc;
 }
 
diff --git a/trusty/secretkeeper/src/hal_main.rs b/trusty/secretkeeper/src/hal_main.rs
index df30493..b31db13 100644
--- a/trusty/secretkeeper/src/hal_main.rs
+++ b/trusty/secretkeeper/src/hal_main.rs
@@ -91,7 +91,7 @@
 }
 
 fn main() {
-    if let Err(e) = inner_main() {
+    if let Err(HalServiceError(e)) = inner_main() {
         panic!("HAL service failed: {:?}", e);
     }
 }