Merge "Add a variant of ReadFstabFromFile for /proc/mounts."
diff --git a/debuggerd/crasher/crasher.cpp b/debuggerd/crasher/crasher.cpp
index 6a19878..12ba502 100644
--- a/debuggerd/crasher/crasher.cpp
+++ b/debuggerd/crasher/crasher.cpp
@@ -148,7 +148,7 @@
 noinline void leak() {
     while (true) {
         void* mapping =
-            mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+            mmap(nullptr, getpagesize(), PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
         static_cast<volatile char*>(mapping)[0] = 'a';
     }
 }
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 4cd6193..52c1c25 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -300,24 +300,7 @@
 }
 
 static void ConsumeFd(unique_fd fd, std::string* output) {
-  constexpr size_t read_length = PAGE_SIZE;
-  std::string result;
-
-  while (true) {
-    size_t offset = result.size();
-    result.resize(result.size() + PAGE_SIZE);
-    ssize_t rc = TEMP_FAILURE_RETRY(read(fd.get(), &result[offset], read_length));
-    if (rc == -1) {
-      FAIL() << "read failed: " << strerror(errno);
-    } else if (rc == 0) {
-      result.resize(result.size() - PAGE_SIZE);
-      break;
-    }
-
-    result.resize(result.size() - PAGE_SIZE + rc);
-  }
-
-  *output = std::move(result);
+  ASSERT_TRUE(android::base::ReadFdToString(fd, output));
 }
 
 class LogcatCollector {
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index c6a535a..1e5365d 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -721,19 +721,19 @@
   }
 
   size_t thread_stack_pages = 8;
-  void* thread_stack_allocation = mmap(nullptr, PAGE_SIZE * (thread_stack_pages + 2), PROT_NONE,
+  void* thread_stack_allocation = mmap(nullptr, getpagesize() * (thread_stack_pages + 2), PROT_NONE,
                                        MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
   if (thread_stack_allocation == MAP_FAILED) {
     fatal_errno("failed to allocate debuggerd thread stack");
   }
 
-  char* stack = static_cast<char*>(thread_stack_allocation) + PAGE_SIZE;
-  if (mprotect(stack, PAGE_SIZE * thread_stack_pages, PROT_READ | PROT_WRITE) != 0) {
+  char* stack = static_cast<char*>(thread_stack_allocation) + getpagesize();
+  if (mprotect(stack, getpagesize() * thread_stack_pages, PROT_READ | PROT_WRITE) != 0) {
     fatal_errno("failed to mprotect debuggerd thread stack");
   }
 
   // Stack grows negatively, set it to the last byte in the page...
-  stack = (stack + thread_stack_pages * PAGE_SIZE - 1);
+  stack = (stack + thread_stack_pages * getpagesize() - 1);
   // and align it.
   stack -= 15;
   pseudothread_stack = stack;
diff --git a/debuggerd/libdebuggerd/scudo.cpp b/debuggerd/libdebuggerd/scudo.cpp
index 5a62fe1..837f406 100644
--- a/debuggerd/libdebuggerd/scudo.cpp
+++ b/debuggerd/libdebuggerd/scudo.cpp
@@ -22,6 +22,7 @@
 
 #include <android-base/macros.h>
 #include <bionic/macros.h>
+#include <unistd.h>
 
 #include "tombstone.pb.h"
 
@@ -54,21 +55,21 @@
   }
 
   untagged_fault_addr_ = process_info.untagged_fault_address;
-  uintptr_t fault_page = untagged_fault_addr_ & ~(PAGE_SIZE - 1);
+  uintptr_t fault_page = untagged_fault_addr_ & ~(getpagesize() - 1);
 
-  uintptr_t memory_begin = fault_page - PAGE_SIZE * 16;
+  uintptr_t memory_begin = fault_page - getpagesize() * 16;
   if (memory_begin > fault_page) {
     return;
   }
 
-  uintptr_t memory_end = fault_page + PAGE_SIZE * 16;
+  uintptr_t memory_end = fault_page + getpagesize() * 16;
   if (memory_end < fault_page) {
     return;
   }
 
   auto memory = std::make_unique<char[]>(memory_end - memory_begin);
-  for (auto i = memory_begin; i != memory_end; i += PAGE_SIZE) {
-    process_memory->ReadFully(i, memory.get() + i - memory_begin, PAGE_SIZE);
+  for (auto i = memory_begin; i != memory_end; i += getpagesize()) {
+    process_memory->ReadFully(i, memory.get() + i - memory_begin, getpagesize());
   }
 
   auto memory_tags = std::make_unique<char[]>((memory_end - memory_begin) / kTagGranuleSize);
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index dd61272..bbd068b 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -181,6 +181,10 @@
     ramdisk_available: true,
     vendor_ramdisk_available: true,
     recovery_available: true,
+    apex_available: [
+        "//apex_available:anyapex",
+        "//apex_available:platform",
+    ],
     host_supported: true,
     defaults: ["fs_mgr_defaults"],
     srcs: [
@@ -206,6 +210,7 @@
         "libbase_headers",
         "libgsi_headers",
     ],
+    min_sdk_version: "31",
 }
 
 cc_binary {
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 7f4959f..e568a9b 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -613,7 +613,6 @@
 
 // Read the primary superblock from an f2fs filesystem.  On failure return
 // false.  If it's not an f2fs filesystem, also set FS_STAT_INVALID_MAGIC.
-#define F2FS_BLKSIZE 4096
 #define F2FS_SUPER_OFFSET 1024
 static bool read_f2fs_superblock(const std::string& blk_device, int* fs_stat) {
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(blk_device.c_str(), O_RDONLY | O_CLOEXEC)));
@@ -628,7 +627,9 @@
         PERROR << "Can't read '" << blk_device << "' superblock1";
         return false;
     }
-    if (TEMP_FAILURE_RETRY(pread(fd, &sb2, sizeof(sb2), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
+    // F2FS only supports block_size=page_size case. So, it is safe to call
+    // `getpagesize()` and use that as size of super block.
+    if (TEMP_FAILURE_RETRY(pread(fd, &sb2, sizeof(sb2), getpagesize() + F2FS_SUPER_OFFSET)) !=
         sizeof(sb2)) {
         PERROR << "Can't read '" << blk_device << "' superblock2";
         return false;
@@ -652,7 +653,7 @@
         return false;
     }
     if (sb == cpu_to_le32(F2FS_SUPER_MAGIC)) return true;
-    if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), F2FS_BLKSIZE + F2FS_SUPER_OFFSET)) !=
+    if (TEMP_FAILURE_RETRY(pread(fd, &sb, sizeof(sb), getpagesize() + F2FS_SUPER_OFFSET)) !=
         sizeof(sb)) {
         return false;
     }
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 7385f79..622f181 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -32,6 +32,7 @@
 #include <selinux/android.h>
 #include <selinux/label.h>
 #include <selinux/selinux.h>
+#include <string>
 
 #include "fs_mgr_priv.h"
 
@@ -68,6 +69,13 @@
 
     /* Format the partition using the calculated length */
 
+    // EXT4 supports 4K block size on 16K page sizes. A 4K block
+    // size formatted EXT4 partition will mount fine on both 4K and 16K page
+    // size kernels.
+    // However, EXT4 does not support 16K block size on 4K systems.
+    // If we want the same userspace code to work on both 4k/16k kernels,
+    // using a hardcoded 4096 block size is a simple solution. Using
+    // getpagesize() here would work as well, but 4096 is simpler.
     std::string size_str = std::to_string(dev_sz / 4096);
 
     std::vector<const char*> mke2fs_args = {"/system/bin/mke2fs", "-t", "ext4", "-b", "4096"};
@@ -127,7 +135,7 @@
 
     /* Format the partition using the calculated length */
 
-    std::string size_str = std::to_string(dev_sz / 4096);
+    const auto size_str = std::to_string(dev_sz / getpagesize());
 
     std::vector<const char*> args = {"/system/bin/make_f2fs", "-g", "android"};
     if (needs_projid) {
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index f04fc8d..01827d6 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -939,7 +939,9 @@
     auto command = ""s;
     if (!access(kMkF2fs.c_str(), X_OK) && fs_mgr_filesystem_available("f2fs")) {
         fs_type = "f2fs";
-        command = kMkF2fs + " -w 4096 -f -d1 -l" + android::base::Basename(kScratchMountPoint);
+        command = kMkF2fs + " -w ";
+        command += std::to_string(getpagesize());
+        command += " -f -d1 -l" + android::base::Basename(kScratchMountPoint);
     } else if (!access(kMkExt4.c_str(), X_OK) && fs_mgr_filesystem_available("ext4")) {
         fs_type = "ext4";
         command = kMkExt4 + " -F -b 4096 -t ext4 -m 0 -O has_journal -M " + kScratchMountPoint;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
index dd626bc..3a81f63 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_format.h
@@ -166,6 +166,13 @@
 static constexpr uint8_t kCowReadAheadInProgress = 1;
 static constexpr uint8_t kCowReadAheadDone = 2;
 
+static inline uint64_t GetCowOpSourceInfoData(const CowOperation* op) {
+    return op->source;
+}
+static inline bool GetCowOpSourceInfoCompression(const CowOperation* op) {
+    return op->compression != kCowCompressNone;
+}
+
 struct CowFooter {
     CowFooterOperation op;
     uint8_t unused[64];
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
index f599501..f4ce52f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_reader.h
@@ -73,8 +73,20 @@
     // The operation pointer must derive from ICowOpIter::Get().
     virtual ssize_t ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
                              size_t ignore_bytes = 0) = 0;
+
+    // Get the absolute source offset, in bytes, of a CowOperation. Returns
+    // false if the operation does not read from source partitions.
+    virtual bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) = 0;
 };
 
+static constexpr uint64_t GetBlockFromOffset(const CowHeader& header, uint64_t offset) {
+    return offset / header.block_size;
+}
+
+static constexpr uint64_t GetBlockRelativeOffset(const CowHeader& header, uint64_t offset) {
+    return offset % header.block_size;
+}
+
 // Iterate over a sequence of COW operations. The iterator is bidirectional.
 class ICowOpIter {
   public:
@@ -119,6 +131,7 @@
     bool VerifyMergeOps() override;
     bool GetFooter(CowFooter* footer) override;
     bool GetLastLabel(uint64_t* label) override;
+    bool GetSourceOffset(const CowOperation* op, uint64_t* source_offset) override;
 
     // Create a CowOpIter object which contains footer_.num_ops
     // CowOperation objects. Get() returns a unique CowOperation object
@@ -155,6 +168,7 @@
     bool ParseOps(std::optional<uint64_t> label);
     bool PrepMergeOps();
     uint64_t FindNumCopyops();
+    uint8_t GetCompressionType(const CowOperation* op);
 
     android::base::unique_fd owned_fd_;
     android::base::borrowed_fd fd_;
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
index 4ac89ae..489669a 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/cow_reader.cpp
@@ -312,19 +312,15 @@
     std::unordered_map<uint64_t, const CowOperation*> overwritten_blocks;
     while (!itr->AtEnd()) {
         const auto& op = itr->Get();
-        uint64_t block;
-        bool offset;
-        if (op->type == kCowCopyOp) {
-            block = op->source;
-            offset = false;
-        } else if (op->type == kCowXorOp) {
-            block = op->source / header_.block_size;
-            offset = (op->source % header_.block_size) != 0;
-        } else {
+        uint64_t offset;
+        if (!GetSourceOffset(op, &offset)) {
             itr->Next();
             continue;
         }
 
+        uint64_t block = GetBlockFromOffset(header_, offset);
+        bool misaligned = (GetBlockRelativeOffset(header_, offset) != 0);
+
         const CowOperation* overwrite = nullptr;
         if (overwritten_blocks.count(block)) {
             overwrite = overwritten_blocks[block];
@@ -332,7 +328,7 @@
                        << op << "\noverwritten by previously merged op:\n"
                        << *overwrite;
         }
-        if (offset && overwritten_blocks.count(block + 1)) {
+        if (misaligned && overwritten_blocks.count(block + 1)) {
             overwrite = overwritten_blocks[block + 1];
             LOG(ERROR) << "Invalid Sequence! Block needed for op:\n"
                        << op << "\noverwritten by previously merged op:\n"
@@ -521,7 +517,7 @@
         case kCowSequenceOp:
         case kCowReplaceOp:
         case kCowXorOp:
-            return GetRawBytes(op->source, buffer, len, read);
+            return GetRawBytes(GetCowOpSourceInfoData(op), buffer, len, read);
         default:
             LOG(ERROR) << "Cannot get raw bytes of non-data op: " << *op;
             return false;
@@ -578,10 +574,14 @@
     size_t remaining_;
 };
 
+uint8_t CowReader::GetCompressionType(const CowOperation* op) {
+    return op->compression;
+}
+
 ssize_t CowReader::ReadData(const CowOperation* op, void* buffer, size_t buffer_size,
                             size_t ignore_bytes) {
     std::unique_ptr<IDecompressor> decompressor;
-    switch (op->compression) {
+    switch (GetCompressionType(op)) {
         case kCowCompressNone:
             break;
         case kCowCompressGz:
@@ -601,7 +601,7 @@
             }
             break;
         default:
-            LOG(ERROR) << "Unknown compression type: " << op->compression;
+            LOG(ERROR) << "Unknown compression type: " << GetCompressionType(op);
             return -1;
     }
 
@@ -609,7 +609,7 @@
     if (op->type == kCowXorOp) {
         offset = data_loc_->at(op->new_block);
     } else {
-        offset = op->source;
+        offset = GetCowOpSourceInfoData(op);
     }
 
     if (!decompressor) {
@@ -622,5 +622,18 @@
     return decompressor->Decompress(buffer, buffer_size, header_.block_size, ignore_bytes);
 }
 
+bool CowReader::GetSourceOffset(const CowOperation* op, uint64_t* source_offset) {
+    switch (op->type) {
+        case kCowCopyOp:
+            *source_offset = GetCowOpSourceInfoData(op) * header_.block_size;
+            return true;
+        case kCowXorOp:
+            *source_offset = GetCowOpSourceInfoData(op);
+            return true;
+        default:
+            return false;
+    }
+}
+
 }  // namespace snapshot
 }  // namespace android
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
index f9cdbc0..a3e40d9 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/snapshot_reader.cpp
@@ -155,7 +155,12 @@
         }
 
         if (op) {
-            chunk = op->source;
+            uint64_t source_offset;
+            if (!cow_->GetSourceOffset(op, &source_offset)) {
+                LOG(ERROR) << "GetSourceOffset failed in CompressedSnapshotReader for op: " << *op;
+                return false;
+            }
+            chunk = GetBlockFromOffset(cow_->GetHeader(), source_offset);
         }
 
         off64_t offset = (chunk * block_size_) + start_offset;
@@ -179,7 +184,12 @@
             return -1;
         }
 
-        off64_t offset = op->source + start_offset;
+        uint64_t source_offset;
+        if (!cow_->GetSourceOffset(op, &source_offset)) {
+            LOG(ERROR) << "GetSourceOffset failed in CompressedSnapshotReader for op: " << *op;
+            return false;
+        }
+        off64_t offset = source_offset + start_offset;
 
         std::string data(bytes_to_read, '\0');
         if (!android::base::ReadFullyAtOffset(fd, data.data(), data.size(), offset)) {
diff --git a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
index 120b2c0..31b9a58 100644
--- a/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
+++ b/fs_mgr/libsnapshot/libsnapshot_cow/test_v2.cpp
@@ -145,7 +145,7 @@
     op = iter->Get();
 
     ASSERT_EQ(op->type, kCowReplaceOp);
-    ASSERT_EQ(op->compression, kCowCompressNone);
+    ASSERT_FALSE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->data_length, 4096);
     ASSERT_EQ(op->new_block, 50);
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -224,10 +224,10 @@
     op = iter->Get();
 
     ASSERT_EQ(op->type, kCowXorOp);
-    ASSERT_EQ(op->compression, kCowCompressNone);
+    ASSERT_FALSE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->data_length, 4096);
     ASSERT_EQ(op->new_block, 50);
-    ASSERT_EQ(op->source, 98314);  // 4096 * 24 + 10
+    ASSERT_EQ(GetCowOpSourceInfoData(op), 98314);  // 4096 * 24 + 10
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
     ASSERT_EQ(sink, data);
 
@@ -283,7 +283,7 @@
     std::string sink(data.size(), '\0');
 
     ASSERT_EQ(op->type, kCowReplaceOp);
-    ASSERT_EQ(op->compression, kCowCompressGz);
+    ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->data_length, 56);  // compressed!
     ASSERT_EQ(op->new_block, 50);
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -339,7 +339,7 @@
             total_blocks += 1;
             std::string sink(xor_data.size(), '\0');
             ASSERT_EQ(op->new_block, 50);
-            ASSERT_EQ(op->source, 98314);  // 4096 * 24 + 10
+            ASSERT_EQ(GetCowOpSourceInfoData(op), 98314);  // 4096 * 24 + 10
             ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
             ASSERT_EQ(sink, xor_data);
         }
@@ -528,7 +528,7 @@
     std::string sink(data.size(), '\0');
 
     ASSERT_EQ(op->type, kCowReplaceOp);
-    ASSERT_EQ(op->compression, kCowCompressGz);
+    ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->data_length, 56);  // compressed!
     ASSERT_EQ(op->new_block, 50);
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -546,7 +546,7 @@
 
     sink = {};
     sink.resize(data2.size(), '\0');
-    ASSERT_EQ(op->compression, kCowCompressGz);
+    ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->data_length, 41);  // compressed!
     ASSERT_EQ(op->new_block, 51);
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
@@ -591,7 +591,7 @@
 
     auto op = iter->Get();
     ASSERT_EQ(op->type, kCowReplaceOp);
-    ASSERT_EQ(op->compression, kCowCompressGz);
+    ASSERT_TRUE(GetCowOpSourceInfoCompression(op));
     ASSERT_EQ(op->new_block, 51);
     ASSERT_TRUE(ReadData(reader, op, sink.data(), sink.size()));
 }
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
index da9bd11..978a7f2 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd.cpp
@@ -508,7 +508,7 @@
             // the merge of operations are done based on the ops present
             // in the file.
             //===========================================================
-            uint64_t block_source = cow_op->source;
+            uint64_t block_source = GetCowOpSourceInfoData(cow_op);
             if (prev_id.has_value()) {
                 if (dest_blocks.count(cow_op->new_block) || source_blocks.count(block_source)) {
                     break;
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
index a32c2bf..d5fbe91 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_readahead.cpp
@@ -172,7 +172,7 @@
 }
 
 void ReadAheadThread::CheckOverlap(const CowOperation* cow_op) {
-    uint64_t source_block = cow_op->source;
+    uint64_t source_block = GetCowOpSourceInfoData(cow_op);
     if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block)) {
         overlap_ = true;
     }
@@ -191,7 +191,7 @@
         // Get the first block with offset
         const CowOperation* cow_op = GetRAOpIter();
         CHECK_NE(cow_op, nullptr);
-        *source_offset = cow_op->source;
+        *source_offset = GetCowOpSourceInfoData(cow_op);
         if (cow_op->type == kCowCopyOp) {
             *source_offset *= BLOCK_SZ;
         }
@@ -210,7 +210,7 @@
         while (!RAIterDone() && num_ops) {
             const CowOperation* op = GetRAOpIter();
             CHECK_NE(op, nullptr);
-            uint64_t next_offset = op->source;
+            uint64_t next_offset = GetCowOpSourceInfoData(op);
             if (op->type == kCowCopyOp) {
                 next_offset *= BLOCK_SZ;
             }
diff --git a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
index 922df34..559dcc7 100644
--- a/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/dm-snapshot-merge/snapuserd_worker.cpp
@@ -115,12 +115,13 @@
         SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get payload buffer";
         return false;
     }
-    SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
-                    << " Source: " << cow_op->source;
-    uint64_t offset = cow_op->source;
-    if (cow_op->type == kCowCopyOp) {
-        offset *= BLOCK_SZ;
+    uint64_t offset;
+    if (!reader_->GetSourceOffset(cow_op, &offset)) {
+        SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get source offset";
+        return false;
     }
+    SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
+                    << " Source: " << offset;
     if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ, offset)) {
         SNAP_PLOG(ERROR) << "Copy op failed. Read from backing store: " << backing_store_device_
                          << "at block :" << offset / BLOCK_SZ << " offset:" << offset % BLOCK_SZ;
@@ -508,7 +509,7 @@
                 if (read_ahead_buffer_map.find(cow_op->new_block) == read_ahead_buffer_map.end()) {
                     SNAP_LOG(ERROR)
                             << " Block: " << cow_op->new_block << " not found in read-ahead cache"
-                            << " Source: " << cow_op->source;
+                            << " Op: " << *cow_op;
                     return -1;
                 }
                 // If this is a final block merged in the read-ahead buffer
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
index 7858216..44b7319 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
@@ -94,12 +94,13 @@
         SNAP_LOG(ERROR) << "ReadFromBaseDevice: Failed to get payload buffer";
         return false;
     }
-    SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
-                    << " Source: " << cow_op->source;
-    uint64_t offset = cow_op->source;
-    if (cow_op->type == kCowCopyOp) {
-        offset *= BLOCK_SZ;
+    uint64_t offset;
+    if (!reader_->GetSourceOffset(cow_op, &offset)) {
+        SNAP_LOG(ERROR) << "ReadFromSourceDevice: Failed to get source offset";
+        return false;
     }
+    SNAP_LOG(DEBUG) << " ReadFromBaseDevice...: new-block: " << cow_op->new_block
+                    << " Op: " << *cow_op;
     if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ, offset)) {
         std::string op;
         if (cow_op->type == kCowCopyOp)
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
index af24286..399f7b8 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.cpp
@@ -34,14 +34,17 @@
 }
 
 void ReadAhead::CheckOverlap(const CowOperation* cow_op) {
-    uint64_t source_block = cow_op->source;
-    uint64_t source_offset = 0;
-    if (cow_op->type == kCowXorOp) {
-        source_block /= BLOCK_SZ;
-        source_offset = cow_op->source % BLOCK_SZ;
+    uint64_t source_offset;
+    if (!reader_->GetSourceOffset(cow_op, &source_offset)) {
+        SNAP_LOG(ERROR) << "ReadAhead operation has no source offset: " << *cow_op;
+        return;
     }
+
+    uint64_t source_block = GetBlockFromOffset(header_, source_offset);
+    bool misaligned = (GetBlockRelativeOffset(header_, source_offset) != 0);
+
     if (dest_blocks_.count(cow_op->new_block) || source_blocks_.count(source_block) ||
-        (source_offset > 0 && source_blocks_.count(source_block + 1))) {
+        (misaligned && source_blocks_.count(source_block + 1))) {
         overlap_ = true;
     }
 
@@ -66,11 +69,12 @@
 
     // Get the first block with offset
     const CowOperation* cow_op = GetRAOpIter();
-    *source_offset = cow_op->source;
 
-    if (cow_op->type == kCowCopyOp) {
-        *source_offset *= BLOCK_SZ;
-    } else if (cow_op->type == kCowXorOp) {
+    if (!reader_->GetSourceOffset(cow_op, source_offset)) {
+        SNAP_LOG(ERROR) << "PrepareNextReadAhead operation has no source offset: " << *cow_op;
+        return nr_consecutive;
+    }
+    if (cow_op->type == kCowXorOp) {
         xor_op_vec.push_back(cow_op);
     }
 
@@ -88,10 +92,10 @@
      */
     while (!RAIterDone() && num_ops) {
         const CowOperation* op = GetRAOpIter();
-        uint64_t next_offset = op->source;
-
-        if (cow_op->type == kCowCopyOp) {
-            next_offset *= BLOCK_SZ;
+        uint64_t next_offset;
+        if (!reader_->GetSourceOffset(op, &next_offset)) {
+            SNAP_LOG(ERROR) << "PrepareNextReadAhead operation has no source offset: " << *cow_op;
+            break;
         }
 
         // Check for consecutive blocks
@@ -803,6 +807,7 @@
     if (!reader_->InitForMerge(std::move(cow_fd_))) {
         return false;
     }
+    header_ = reader_->GetHeader();
     return true;
 }
 
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
index 5e94de0..d3ba126 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_readahead.h
@@ -85,6 +85,7 @@
 
     std::shared_ptr<SnapshotHandler> snapuserd_;
     std::unique_ptr<CowReader> reader_;
+    CowHeader header_;
 
     std::unordered_set<uint64_t> dest_blocks_;
     std::unordered_set<uint64_t> source_blocks_;
diff --git a/init/Android.bp b/init/Android.bp
index f62d7b7..1af398a 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -214,8 +214,8 @@
     visibility: [":__subpackages__"],
 }
 
-cc_library_static {
-    name: "libinit",
+cc_defaults {
+    name: "libinit_defaults",
     recovery_available: true,
     defaults: [
         "init_defaults",
@@ -228,7 +228,6 @@
     ],
     whole_static_libs: [
         "libcap",
-        "libcom.android.sysprop.apex",
         "libcom.android.sysprop.init",
     ],
     header_libs: ["bootimg_headers"],
@@ -252,10 +251,17 @@
             ],
         },
     },
-    visibility: [
-        "//system/apex/apexd",
-        "//frameworks/native/cmds/installd",
-    ],
+}
+
+cc_library_static {
+    name: "libinit",
+    defaults: ["libinit_defaults"],
+}
+
+cc_library_static {
+    name: "libinit.microdroid",
+    defaults: ["libinit_defaults"],
+    cflags: ["-DMICRODROID=1"],
 }
 
 phony {
@@ -270,7 +276,6 @@
     recovery_available: true,
     stem: "init",
     defaults: ["init_defaults"],
-    static_libs: ["libinit"],
     srcs: ["main.cpp"],
     symlinks: ["ueventd"],
     target: {
@@ -309,12 +314,14 @@
 cc_binary {
     name: "init_second_stage",
     defaults: ["init_second_stage_defaults"],
+    static_libs: ["libinit"],
 }
 
 cc_binary {
     name: "init_second_stage.microdroid",
     defaults: ["init_second_stage_defaults"],
-    cflags: ["-DMICRODROID"],
+    static_libs: ["libinit.microdroid"],
+    cflags: ["-DMICRODROID=1"],
     installable: false,
     visibility: ["//packages/modules/Virtualization/microdroid"],
 }
@@ -460,7 +467,7 @@
 cc_binary {
     name: "init_first_stage.microdroid",
     defaults: ["init_first_stage_defaults"],
-    cflags: ["-DMICRODROID"],
+    cflags: ["-DMICRODROID=1"],
     installable: false,
 }
 
diff --git a/init/fuzzer/Android.bp b/init/fuzzer/Android.bp
index c21a196..856ca8c 100644
--- a/init/fuzzer/Android.bp
+++ b/init/fuzzer/Android.bp
@@ -18,7 +18,7 @@
 }
 
 cc_defaults {
-    name: "libinit_defaults",
+    name: "libinit_fuzzer_defaults",
     static_libs: [
         "libc++fs",
         "liblmkd_utils",
@@ -53,7 +53,7 @@
     ],
     shared_libs: ["libhidlmetadata",],
     defaults: [
-        "libinit_defaults",
+        "libinit_fuzzer_defaults",
     ],
 }
 
@@ -62,7 +62,7 @@
     srcs: [
         "init_property_fuzzer.cpp",
     ],
-    defaults: ["libinit_defaults"],
+    defaults: ["libinit_fuzzer_defaults"],
 }
 
 cc_fuzz {
@@ -71,6 +71,6 @@
         "init_ueventHandler_fuzzer.cpp",
     ],
     defaults: [
-        "libinit_defaults",
+        "libinit_fuzzer_defaults",
     ],
 }
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index fead371..5b53d50 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -21,7 +21,6 @@
 #include <string>
 #include <vector>
 
-#include <ApexProperties.sysprop.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
@@ -30,16 +29,6 @@
 
 #include "util.h"
 
-#ifndef RECOVERY
-#define ACTIVATE_FLATTENED_APEX 1
-#endif
-
-#ifdef ACTIVATE_FLATTENED_APEX
-#include <apex_manifest.pb.h>
-#include <com_android_apex.h>
-#include <selinux/android.h>
-#endif  // ACTIVATE_FLATTENED_APEX
-
 namespace android {
 namespace init {
 namespace {
@@ -77,15 +66,9 @@
     return ret;
 }
 
-static bool IsApexUpdatable() {
-    static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
-    return updatable;
-}
-
 // In case we have two sets of APEXes (non-updatable, updatable), we need two separate mount
 // namespaces.
 static bool NeedsTwoMountNamespaces() {
-    if (!IsApexUpdatable()) return false;
     if (IsRecoveryMode()) return false;
     // In microdroid, there's only one set of APEXes in built-in directories include block devices.
     if (IsMicrodroid()) return false;
@@ -193,7 +176,7 @@
 // Switch the mount namespace of the current process from bootstrap to default OR from default to
 // bootstrap. If the current mount namespace is neither bootstrap nor default, keep it that way.
 Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace) {
-    if (IsRecoveryMode() || !IsApexUpdatable()) {
+    if (IsRecoveryMode()) {
         // we don't have multiple namespaces in recovery mode or if apex is not updatable
         return {};
     }
diff --git a/init/selinux.cpp b/init/selinux.cpp
index a936532..e0ef491 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -300,8 +300,6 @@
 }
 
 constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
-constexpr const char kMicrodroidPrecompiledSepolicy[] =
-        "/system/etc/selinux/microdroid_precompiled_sepolicy";
 
 bool IsSplitPolicyDevice() {
     return access(plat_policy_cil_file, R_OK) != -1;
@@ -499,19 +497,14 @@
 
 bool OpenMonolithicPolicy(PolicyFile* policy_file) {
     static constexpr char kSepolicyFile[] = "/sepolicy";
-    // In Microdroid the precompiled sepolicy is located on /system, since there is no vendor code.
-    // TODO(b/287206497): refactor once we start conditionally compiling init for Microdroid.
-    std::string monolithic_policy_file = access(kMicrodroidPrecompiledSepolicy, R_OK) == 0
-                                                 ? kMicrodroidPrecompiledSepolicy
-                                                 : kSepolicyFile;
 
-    LOG(INFO) << "Opening SELinux policy from monolithic file " << monolithic_policy_file;
-    policy_file->fd.reset(open(monolithic_policy_file.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    LOG(INFO) << "Opening SELinux policy from monolithic file " << kSepolicyFile;
+    policy_file->fd.reset(open(kSepolicyFile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
     if (policy_file->fd < 0) {
         PLOG(ERROR) << "Failed to open monolithic SELinux policy";
         return false;
     }
-    policy_file->path = monolithic_policy_file;
+    policy_file->path = kSepolicyFile;
     return true;
 }
 
@@ -858,6 +851,10 @@
 }
 
 int SelinuxGetVendorAndroidVersion() {
+    if (IsMicrodroid()) {
+        // As of now Microdroid doesn't have any vendor code.
+        return __ANDROID_API_FUTURE__;
+    }
     static int vendor_android_version = [] {
         if (!IsSplitPolicyDevice()) {
             // If this device does not split sepolicy files, it's not a Treble device and therefore,
@@ -961,6 +958,26 @@
     }
 }
 
+// Encapsulates steps to load SELinux policy in Microdroid.
+// So far the process is very straightforward - just load the precompiled policy from /system.
+void LoadSelinuxPolicyMicrodroid() {
+    constexpr const char kMicrodroidPrecompiledSepolicy[] =
+            "/system/etc/selinux/microdroid_precompiled_sepolicy";
+
+    LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
+    unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
+    if (policy_fd < 0) {
+        PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
+    }
+
+    std::string policy;
+    if (!android::base::ReadFdToString(policy_fd, &policy)) {
+        PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
+    }
+
+    LoadSelinuxPolicy(policy);
+}
+
 // The SELinux setup process is carefully orchestrated around snapuserd. Policy
 // must be loaded off dynamic partitions, and during an OTA, those partitions
 // cannot be read without snapuserd. But, with kernel-privileged snapuserd
@@ -976,20 +993,9 @@
 //  (5) Re-launch snapuserd and attach it to the dm-user devices from step (2).
 //
 // After this sequence, it is safe to enable enforcing mode and continue booting.
-int SetupSelinux(char** argv) {
-    SetStdioToDevNull(argv);
-    InitKernelLogging(argv);
-
-    if (REBOOT_BOOTLOADER_ON_PANIC) {
-        InstallRebootSignalHandlers();
-    }
-
-    boot_clock::time_point start_time = boot_clock::now();
-
+void LoadSelinuxPolicyAndroid() {
     MountMissingSystemPartitions();
 
-    SelinuxSetupKernelLogging();
-
     LOG(INFO) << "Opening SELinux policy";
 
     PrepareApexSepolicy();
@@ -1001,9 +1007,8 @@
 
     auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
     if (snapuserd_helper) {
-        // Kill the old snapused to avoid audit messages. After this we cannot
-        // read from /system (or other dynamic partitions) until we call
-        // FinishTransition().
+        // Kill the old snapused to avoid audit messages. After this we cannot read from /system
+        // (or other dynamic partitions) until we call FinishTransition().
         snapuserd_helper->StartTransition();
     }
 
@@ -1021,6 +1026,26 @@
     if (selinux_android_restorecon("/dev/selinux/", SELINUX_ANDROID_RESTORECON_RECURSE) == -1) {
         PLOG(FATAL) << "restorecon failed of /dev/selinux failed";
     }
+}
+
+int SetupSelinux(char** argv) {
+    SetStdioToDevNull(argv);
+    InitKernelLogging(argv);
+
+    if (REBOOT_BOOTLOADER_ON_PANIC) {
+        InstallRebootSignalHandlers();
+    }
+
+    boot_clock::time_point start_time = boot_clock::now();
+
+    SelinuxSetupKernelLogging();
+
+    // TODO(b/287206497): refactor into different headers to only include what we need.
+    if (IsMicrodroid()) {
+        LoadSelinuxPolicyMicrodroid();
+    } else {
+        LoadSelinuxPolicyAndroid();
+    }
 
     SelinuxSetEnforcement();
 
diff --git a/init/service.cpp b/init/service.cpp
index 2945708..a0b3478 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -50,7 +50,6 @@
 #endif
 
 #ifdef INIT_FULL_SOURCES
-#include <ApexProperties.sysprop.h>
 #include <android/api-level.h>
 
 #include "mount_namespace.h"
@@ -323,7 +322,7 @@
     }
 
 #if INIT_FULL_SOURCES
-    static bool is_apex_updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+    static bool is_apex_updatable = true;
 #else
     static bool is_apex_updatable = false;
 #endif
diff --git a/init/util.cpp b/init/util.cpp
index bc8ea6e..d0478e8 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -732,11 +732,6 @@
     is_default_mount_namespace_ready = true;
 }
 
-bool IsMicrodroid() {
-    static bool is_microdroid = android::base::GetProperty("ro.hardware", "") == "microdroid";
-    return is_microdroid;
-}
-
 bool Has32BitAbi() {
     static bool has = !android::base::GetProperty("ro.product.cpu.abilist32", "").empty();
     return has;
diff --git a/init/util.h b/init/util.h
index e58e70e..3f0a4e0 100644
--- a/init/util.h
+++ b/init/util.h
@@ -105,7 +105,14 @@
 bool IsDefaultMountNamespaceReady();
 void SetDefaultMountNamespaceReady();
 
-bool IsMicrodroid();
+inline constexpr bool IsMicrodroid() {
+#ifdef MICRODROID
+    return MICRODROID;
+#else
+    return false;
+#endif
+}
+
 bool Has32BitAbi();
 
 std::string GetApexNameFromFileName(const std::string& path);
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index 3867f34..7f57637 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -89,6 +89,36 @@
 #error ATRACE_TAG must be defined to be one of the tags defined in cutils/trace.h
 #endif
 
+/** Internal implementation detail. Do not use. */
+void atrace_begin_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_end_body();
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_begin_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_async_for_track_end_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_body(const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_instant_for_track_body(const char*, const char*);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int_body(const char*, int32_t);
+
+/** Internal implementation detail. Do not use. */
+void atrace_int64_body(const char*, int64_t);
+
 /**
  * Opens the trace file for writing and reads the property for initial tags.
  * The atrace.tags.enableflags property sets the tags to trace.
@@ -159,7 +189,6 @@
 static inline void atrace_begin(uint64_t tag, const char* name)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_begin_body(const char*);
         atrace_begin_body(name);
     }
 }
@@ -172,7 +201,6 @@
 static inline void atrace_end(uint64_t tag)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_end_body();
         atrace_end_body();
     }
 }
@@ -190,7 +218,6 @@
         int32_t cookie)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_begin_body(const char*, int32_t);
         atrace_async_begin_body(name, cookie);
     }
 }
@@ -203,7 +230,6 @@
 static inline void atrace_async_end(uint64_t tag, const char* name, int32_t cookie)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_end_body(const char*, int32_t);
         atrace_async_end_body(name, cookie);
     }
 }
@@ -221,7 +247,6 @@
 static inline void atrace_async_for_track_begin(uint64_t tag, const char* track_name,
                                                 const char* name, int32_t cookie) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_for_track_begin_body(const char*, const char*, int32_t);
         atrace_async_for_track_begin_body(track_name, name, cookie);
     }
 }
@@ -235,7 +260,6 @@
 static inline void atrace_async_for_track_end(uint64_t tag, const char* track_name,
                                               int32_t cookie) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_async_for_track_end_body(const char*, int32_t);
         atrace_async_for_track_end_body(track_name, cookie);
     }
 }
@@ -252,7 +276,6 @@
 #define ATRACE_INSTANT(name) atrace_instant(ATRACE_TAG, name)
 static inline void atrace_instant(uint64_t tag, const char* name) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_instant_body(const char*);
         atrace_instant_body(name);
     }
 }
@@ -269,7 +292,6 @@
 static inline void atrace_instant_for_track(uint64_t tag, const char* track_name,
                                             const char* name) {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_instant_for_track_body(const char*, const char*);
         atrace_instant_for_track_body(track_name, name);
     }
 }
@@ -282,7 +304,6 @@
 static inline void atrace_int(uint64_t tag, const char* name, int32_t value)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_int_body(const char*, int32_t);
         atrace_int_body(name, value);
     }
 }
@@ -295,7 +316,6 @@
 static inline void atrace_int64(uint64_t tag, const char* name, int64_t value)
 {
     if (CC_UNLIKELY(atrace_is_tag_enabled(tag))) {
-        void atrace_int64_body(const char*, int64_t);
         atrace_int64_body(name, value);
     }
 }
diff --git a/libcutils/trace-host.cpp b/libcutils/trace-host.cpp
index e9f58c3..2bf57eb 100644
--- a/libcutils/trace-host.cpp
+++ b/libcutils/trace-host.cpp
@@ -20,7 +20,6 @@
 int                     atrace_marker_fd     = -1;
 uint64_t                atrace_enabled_tags  = 0;
 
-void atrace_set_debuggable(bool /*debuggable*/) {}
 void atrace_set_tracing_enabled(bool /*enabled*/) {}
 void atrace_update_tags() { }
 void atrace_setup() { }
diff --git a/libmodprobe/libmodprobe.cpp b/libmodprobe/libmodprobe.cpp
index 858b955..5023c79 100644
--- a/libmodprobe/libmodprobe.cpp
+++ b/libmodprobe/libmodprobe.cpp
@@ -230,7 +230,7 @@
     }
 
     std::vector<std::string> lines = android::base::Split(cfg_contents, "\n");
-    for (const std::string line : lines) {
+    for (const auto& line : lines) {
         if (line.empty() || line[0] == '#') {
             continue;
         }
@@ -421,7 +421,8 @@
     }
 
     if (strict && !module_loaded) {
-        LOG(ERROR) << "LoadWithAliases was unable to load " << module_name;
+        LOG(ERROR) << "LoadWithAliases was unable to load " << module_name
+                   << ", tried: " << android::base::Join(modules_to_load, ", ");
         return false;
     }
     return true;
@@ -524,11 +525,8 @@
 
         std::lock_guard guard(module_loaded_lock_);
         // Remove loaded module form mod_with_deps and soft dependencies of other modules
-        for (const auto& module_loaded : module_loaded_) {
-            if (mod_with_deps.find(module_loaded) != mod_with_deps.end()) {
-                mod_with_deps.erase(module_loaded);
-            }
-        }
+        for (const auto& module_loaded : module_loaded_)
+            mod_with_deps.erase(module_loaded);
 
         // Remove loaded module form dependencies of other modules which are not loaded yet
         for (const auto& module_loaded_path : module_loaded_paths_) {
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index 94a1dc4..c4519e3 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -84,7 +84,7 @@
 }
 
 bool Modprobe::ModuleExists(const std::string& module_name) {
-    struct stat fileStat;
+    struct stat fileStat {};
     if (blocklist_enabled && module_blocklist_.count(module_name)) {
         LOG(INFO) << "module " << module_name << " is blocklisted";
         return false;
@@ -95,7 +95,7 @@
         return false;
     }
     if (stat(deps.front().c_str(), &fileStat)) {
-        LOG(INFO) << "module " << module_name << " does not exist";
+        PLOG(INFO) << "module " << module_name << " can't be loaded; can't access " << deps.front();
         return false;
     }
     if (!S_ISREG(fileStat.st_mode)) {
diff --git a/libstats/pull_rust/Android.bp b/libstats/pull_rust/Android.bp
index 85a38f8..4609e6b 100644
--- a/libstats/pull_rust/Android.bp
+++ b/libstats/pull_rust/Android.bp
@@ -28,7 +28,6 @@
     ],
     source_stem: "bindings",
     bindgen_flags: [
-        "--size_t-is-usize",
         "--allowlist-function=AStatsEventList_addStatsEvent",
         "--allowlist-function=AStatsEvent_.*",
         "--allowlist-function=AStatsManager_.*",
diff --git a/libutils/include/utils/Vector.h b/libutils/include/utils/Vector.h
index be35ea2..d5db3cb 100644
--- a/libutils/include/utils/Vector.h
+++ b/libutils/include/utils/Vector.h
@@ -67,13 +67,10 @@
     virtual                 ~Vector();
 
     /*! copy operator */
-            const Vector<TYPE>&     operator = (const Vector<TYPE>& rhs) const;
-            Vector<TYPE>&           operator = (const Vector<TYPE>& rhs);
+    Vector<TYPE>& operator=(const Vector<TYPE>& rhs);        // NOLINT(cert-oop54-cpp)
+    Vector<TYPE>& operator=(const SortedVector<TYPE>& rhs);  // NOLINT(cert-oop54-cpp)
 
-            const Vector<TYPE>&     operator = (const SortedVector<TYPE>& rhs) const;
-            Vector<TYPE>&           operator = (const SortedVector<TYPE>& rhs);
-
-            /*
+    /*
      * empty the vector
      */
 
@@ -248,27 +245,18 @@
     finish_vector();
 }
 
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) {
-    VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(const Vector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(rhs);
     return *this;
 }
 
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const Vector<TYPE>& rhs) const {
-    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
-    return *this;
-}
-
-template<class TYPE> inline
-Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) {
-    VectorImpl::operator = (static_cast<const VectorImpl&>(rhs));
-    return *this;
-}
-
-template<class TYPE> inline
-const Vector<TYPE>& Vector<TYPE>::operator = (const SortedVector<TYPE>& rhs) const {
-    VectorImpl::operator = (rhs);
+template <class TYPE>
+inline Vector<TYPE>& Vector<TYPE>::operator=(
+        const SortedVector<TYPE>& rhs)  // NOLINT(cert-oop54-cpp)
+{
+    VectorImpl::operator=(static_cast<const VectorImpl&>(rhs));
     return *this;
 }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 5344368..a8b78d5 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -1129,7 +1129,7 @@
     write /dev/sys/fs/by-name/userdata/iostat_enable 1
 
     # set readahead multiplier for POSIX_FADV_SEQUENTIAL files
-    write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 16
+    write /dev/sys/fs/by-name/userdata/seq_file_ra_mul 128
 
     # limit discard size to 128MB in order to avoid long IO latency
     # for filesystem tuning first (dm or sda)