Merge "Remove String16::remove."
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index eb3738e..5b04111 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -514,6 +514,38 @@
 #endif
 }
 
+TEST_P(SizeParamCrasherTest, mte_oob_uaf) {
+#if defined(__aarch64__)
+  if (!mte_supported()) {
+    GTEST_SKIP() << "Requires MTE";
+  }
+
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess([&]() {
+    SetTagCheckingLevelSync();
+    volatile int* p = (volatile int*)malloc(GetParam());
+    free((void *)p);
+    p[-1] = 42;
+  });
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+
+  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\))");
+  ASSERT_NOT_MATCH(result, R"(Cause: \[MTE\]: Use After Free, 4 bytes left)");
+#else
+  GTEST_SKIP() << "Requires aarch64";
+#endif
+}
+
 TEST_P(SizeParamCrasherTest, mte_overflow) {
 #if defined(__aarch64__)
   if (!mte_supported()) {
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index e0cc662..ad903ce 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -106,9 +106,9 @@
     unwindstack::MapInfo* map_info = maps->Find(sp);
     if (map_info == nullptr) {
       return "stack pointer is in a non-existent map; likely due to stack overflow.";
-    } else if ((map_info->flags & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
+    } else if ((map_info->flags() & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
       return "stack pointer is not in a rw map; likely due to stack overflow.";
-    } else if ((sp - map_info->start) <= kMaxDifferenceBytes) {
+    } else if ((sp - map_info->start()) <= kMaxDifferenceBytes) {
       return "stack pointer is close to top of stack; likely stack overflow.";
     }
   }
@@ -137,7 +137,7 @@
   } else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
     uint64_t fault_addr = reinterpret_cast<uint64_t>(si->si_addr);
     unwindstack::MapInfo* map_info = maps->Find(fault_addr);
-    if (map_info != nullptr && map_info->flags == PROT_EXEC) {
+    if (map_info != nullptr && map_info->flags() == PROT_EXEC) {
       cause = "execute-only (no-read) memory access error; likely due to data in .text.";
     } else {
       cause = get_stack_overflow_cause(fault_addr, regs->sp(), maps);
@@ -244,7 +244,7 @@
        "memory map (%zu entr%s):",
        maps->Total(), maps->Total() == 1 ? "y" : "ies");
   if (print_fault_address_marker) {
-    if (maps->Total() != 0 && addr < maps->Get(0)->start) {
+    if (maps->Total() != 0 && addr < maps->Get(0)->start()) {
       _LOG(log, logtype::MAPS, "\n--->Fault address falls at %s before any mapped regions\n",
            get_addr_string(addr).c_str());
       print_fault_address_marker = false;
@@ -261,37 +261,37 @@
   for (auto const& map_info : *maps) {
     line = "    ";
     if (print_fault_address_marker) {
-      if (addr < map_info->start) {
+      if (addr < map_info->start()) {
         _LOG(log, logtype::MAPS, "--->Fault address falls at %s between mapped regions\n",
              get_addr_string(addr).c_str());
         print_fault_address_marker = false;
-      } else if (addr >= map_info->start && addr < map_info->end) {
+      } else if (addr >= map_info->start() && addr < map_info->end()) {
         line = "--->";
         print_fault_address_marker = false;
       }
     }
-    line += get_addr_string(map_info->start) + '-' + get_addr_string(map_info->end - 1) + ' ';
-    if (map_info->flags & PROT_READ) {
+    line += get_addr_string(map_info->start()) + '-' + get_addr_string(map_info->end() - 1) + ' ';
+    if (map_info->flags() & PROT_READ) {
       line += 'r';
     } else {
       line += '-';
     }
-    if (map_info->flags & PROT_WRITE) {
+    if (map_info->flags() & PROT_WRITE) {
       line += 'w';
     } else {
       line += '-';
     }
-    if (map_info->flags & PROT_EXEC) {
+    if (map_info->flags() & PROT_EXEC) {
       line += 'x';
     } else {
       line += '-';
     }
-    line += StringPrintf("  %8" PRIx64 "  %8" PRIx64, map_info->offset,
-                         map_info->end - map_info->start);
+    line += StringPrintf("  %8" PRIx64 "  %8" PRIx64, map_info->offset(),
+                         map_info->end() - map_info->start());
     bool space_needed = true;
-    if (!map_info->name.empty()) {
+    if (!map_info->name().empty()) {
       space_needed = false;
-      line += "  " + map_info->name;
+      line += "  " + map_info->name();
       std::string build_id = map_info->GetPrintableBuildID();
       if (!build_id.empty()) {
         line += " (BuildId: " + build_id + ")";
@@ -369,8 +369,8 @@
     std::string label{"memory near "s + reg_name};
     if (maps) {
       unwindstack::MapInfo* map_info = maps->Find(untag_address(reg_value));
-      if (map_info != nullptr && !map_info->name.empty()) {
-        label += " (" + map_info->name + ")";
+      if (map_info != nullptr && !map_info->name().empty()) {
+        label += " (" + map_info->name() + ")";
       }
     }
     dump_memory(log, memory, reg_value, label);
diff --git a/debuggerd/libdebuggerd/tombstone_proto.cpp b/debuggerd/libdebuggerd/tombstone_proto.cpp
index d4a35b3..abd1f12 100644
--- a/debuggerd/libdebuggerd/tombstone_proto.cpp
+++ b/debuggerd/libdebuggerd/tombstone_proto.cpp
@@ -102,9 +102,9 @@
     unwindstack::MapInfo* map_info = maps->Find(sp);
     if (map_info == nullptr) {
       return "stack pointer is in a non-existent map; likely due to stack overflow.";
-    } else if ((map_info->flags & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
+    } else if ((map_info->flags() & (PROT_READ | PROT_WRITE)) != (PROT_READ | PROT_WRITE)) {
       return "stack pointer is not in a rw map; likely due to stack overflow.";
-    } else if ((sp - map_info->start) <= kMaxDifferenceBytes) {
+    } else if ((sp - map_info->start()) <= kMaxDifferenceBytes) {
       return "stack pointer is close to top of stack; likely stack overflow.";
     }
   }
@@ -221,7 +221,7 @@
     }
   } else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
     unwindstack::MapInfo* map_info = maps->Find(fault_addr);
-    if (map_info != nullptr && map_info->flags == PROT_EXEC) {
+    if (map_info != nullptr && map_info->flags() == PROT_EXEC) {
       cause = "execute-only (no-read) memory access error; likely due to data in .text.";
     } else {
       cause = get_stack_overflow_cause(fault_addr, main_thread.registers->sp(), maps);
@@ -359,7 +359,7 @@
           dump.set_register_name(name);
           unwindstack::MapInfo* map_info = maps->Find(untag_address(value));
           if (map_info) {
-            dump.set_mapping_name(map_info->name);
+            dump.set_mapping_name(map_info->name());
           }
 
           char buf[256];
@@ -426,21 +426,21 @@
 
   for (const auto& map_info : *maps) {
     auto* map = tombstone->add_memory_mappings();
-    map->set_begin_address(map_info->start);
-    map->set_end_address(map_info->end);
-    map->set_offset(map_info->offset);
+    map->set_begin_address(map_info->start());
+    map->set_end_address(map_info->end());
+    map->set_offset(map_info->offset());
 
-    if (map_info->flags & PROT_READ) {
+    if (map_info->flags() & PROT_READ) {
       map->set_read(true);
     }
-    if (map_info->flags & PROT_WRITE) {
+    if (map_info->flags() & PROT_WRITE) {
       map->set_write(true);
     }
-    if (map_info->flags & PROT_EXEC) {
+    if (map_info->flags() & PROT_EXEC) {
       map->set_execute(true);
     }
 
-    map->set_mapping_name(map_info->name);
+    map->set_mapping_name(map_info->name());
 
     std::string build_id = map_info->GetPrintableBuildID();
     if (!build_id.empty()) {
diff --git a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
index 17f4c4e..1c95cf0 100644
--- a/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
+++ b/fs_mgr/libfs_avb/tests/fs_avb_test_util.cpp
@@ -122,6 +122,7 @@
                                                  const size_t padding_size) {
     VBMetaImage vbmeta_image;
     vbmeta_image.path = test_dir_.Append(output_file_name);
+    GTEST_LOG_(INFO) << "ExtractVBMetaImage: " << image_path << " to " << output_file_name;
     EXPECT_COMMAND(0,
                    "avbtool extract_vbmeta_image"
                    " --image %s"
diff --git a/fs_mgr/libsnapshot/cow_reader.cpp b/fs_mgr/libsnapshot/cow_reader.cpp
index 35a02e6..2349e4a 100644
--- a/fs_mgr/libsnapshot/cow_reader.cpp
+++ b/fs_mgr/libsnapshot/cow_reader.cpp
@@ -377,7 +377,6 @@
               });
 
     if (header_.num_merge_ops > 0) {
-        CHECK(ops_->size() >= header_.num_merge_ops);
         ops_->erase(ops_.get()->begin(), ops_.get()->begin() + header_.num_merge_ops);
     }
 
diff --git a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
index 313eb64..3888eb1 100644
--- a/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/cow_snapuserd_test.cpp
@@ -96,7 +96,8 @@
 class CowSnapuserdTest final {
   public:
     bool Setup();
-    bool SetupCopyOverlap();
+    bool SetupCopyOverlap_1();
+    bool SetupCopyOverlap_2();
     bool Merge();
     void ValidateMerge();
     void ReadSnapshotDeviceAndValidate();
@@ -115,7 +116,9 @@
     void StartMerge();
 
     void CreateCowDevice();
-    void CreateCowDeviceWithCopyOverlap();
+    void CreateCowDeviceWithCopyOverlap_1();
+    void CreateCowDeviceWithCopyOverlap_2();
+    bool SetupDaemon();
     void CreateBaseDevice();
     void InitCowDevice();
     void SetDeviceControlName();
@@ -193,10 +196,19 @@
     return setup_ok_;
 }
 
-bool CowSnapuserdTest::SetupCopyOverlap() {
+bool CowSnapuserdTest::SetupCopyOverlap_1() {
     CreateBaseDevice();
-    CreateCowDeviceWithCopyOverlap();
+    CreateCowDeviceWithCopyOverlap_1();
+    return SetupDaemon();
+}
 
+bool CowSnapuserdTest::SetupCopyOverlap_2() {
+    CreateBaseDevice();
+    CreateCowDeviceWithCopyOverlap_2();
+    return SetupDaemon();
+}
+
+bool CowSnapuserdTest::SetupDaemon() {
     SetDeviceControlName();
 
     StartSnapuserdDaemon();
@@ -275,7 +287,59 @@
     ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 3), size_), 0);
 }
 
-void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap() {
+void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_2() {
+    std::string path = android::base::GetExecutableDirectory();
+    cow_system_ = std::make_unique<TemporaryFile>(path);
+
+    CowOptions options;
+    options.compression = "gz";
+    CowWriter writer(options);
+
+    ASSERT_TRUE(writer.Initialize(cow_system_->fd));
+
+    size_t num_blocks = size_ / options.block_size;
+    size_t x = num_blocks;
+    size_t blk_src_copy = 0;
+
+    // Create overlapping copy operations
+    while (1) {
+        ASSERT_TRUE(writer.AddCopy(blk_src_copy, blk_src_copy + 1));
+        x -= 1;
+        if (x == 1) {
+            break;
+        }
+        blk_src_copy += 1;
+    }
+
+    // Flush operations
+    ASSERT_TRUE(writer.Finalize());
+
+    // Construct the buffer required for validation
+    orig_buffer_ = std::make_unique<uint8_t[]>(total_base_size_);
+
+    // Read the entire base device
+    ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), total_base_size_, 0),
+              true);
+
+    // Merged operations required for validation
+    int block_size = 4096;
+    x = num_blocks;
+    loff_t src_offset = block_size;
+    loff_t dest_offset = 0;
+
+    while (1) {
+        memmove((char*)orig_buffer_.get() + dest_offset, (char*)orig_buffer_.get() + src_offset,
+                block_size);
+        x -= 1;
+        if (x == 1) {
+            break;
+        }
+        src_offset += block_size;
+        dest_offset += block_size;
+    }
+}
+
+void CowSnapuserdTest::CreateCowDeviceWithCopyOverlap_1() {
     std::string path = android::base::GetExecutableDirectory();
     cow_system_ = std::make_unique<TemporaryFile>(path);
 
@@ -770,19 +834,19 @@
 
             de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
             ASSERT_EQ(de->old_chunk, 21);
-            ASSERT_EQ(de->new_chunk, 536);
-            offset += sizeof(struct disk_exception);
-
-            de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
-            ASSERT_EQ(de->old_chunk, 22);
             ASSERT_EQ(de->new_chunk, 537);
             offset += sizeof(struct disk_exception);
 
             de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
-            ASSERT_EQ(de->old_chunk, 23);
+            ASSERT_EQ(de->old_chunk, 22);
             ASSERT_EQ(de->new_chunk, 538);
             offset += sizeof(struct disk_exception);
 
+            de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
+            ASSERT_EQ(de->old_chunk, 23);
+            ASSERT_EQ(de->new_chunk, 539);
+            offset += sizeof(struct disk_exception);
+
             // End of metadata
             de = reinterpret_cast<struct disk_exception*>((char*)buffer + offset);
             ASSERT_EQ(de->old_chunk, 0);
@@ -821,9 +885,17 @@
     harness.Shutdown();
 }
 
-TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST) {
+TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_1) {
     CowSnapuserdTest harness;
-    ASSERT_TRUE(harness.SetupCopyOverlap());
+    ASSERT_TRUE(harness.SetupCopyOverlap_1());
+    ASSERT_TRUE(harness.Merge());
+    harness.ValidateMerge();
+    harness.Shutdown();
+}
+
+TEST(Snapuserd_Test, Snapshot_COPY_Overlap_TEST_2) {
+    CowSnapuserdTest harness;
+    ASSERT_TRUE(harness.SetupCopyOverlap_2());
     ASSERT_TRUE(harness.Merge());
     harness.ValidateMerge();
     harness.Shutdown();
@@ -831,7 +903,7 @@
 
 TEST(Snapuserd_Test, Snapshot_COPY_Overlap_Merge_Resume_TEST) {
     CowSnapuserdTest harness;
-    ASSERT_TRUE(harness.SetupCopyOverlap());
+    ASSERT_TRUE(harness.SetupCopyOverlap_1());
     harness.MergeInterrupt();
     harness.ValidateMerge();
     harness.Shutdown();
diff --git a/fs_mgr/libsnapshot/snapuserd.cpp b/fs_mgr/libsnapshot/snapuserd.cpp
index 2ccc750..03c2ef6 100644
--- a/fs_mgr/libsnapshot/snapuserd.cpp
+++ b/fs_mgr/libsnapshot/snapuserd.cpp
@@ -90,7 +90,10 @@
 }
 
 bool Snapuserd::GetRABuffer(std::unique_lock<std::mutex>* lock, uint64_t block, void* buffer) {
-    CHECK(lock->owns_lock());
+    if (!lock->owns_lock()) {
+        SNAP_LOG(ERROR) << "GetRABuffer - Lock not held";
+        return false;
+    }
     std::unordered_map<uint64_t, void*>::iterator it = read_ahead_buffer_map_.find(block);
 
     // This will be true only for IO's generated as part of reading a root
@@ -344,7 +347,10 @@
         return false;
     }
 
-    CHECK(header.block_size == BLOCK_SZ);
+    if (!(header.block_size == BLOCK_SZ)) {
+        SNAP_LOG(ERROR) << "Invalid header block size found: " << header.block_size;
+        return false;
+    }
 
     reader_->InitializeMerge();
     SNAP_LOG(DEBUG) << "Merge-ops: " << header.num_merge_ops;
@@ -437,6 +443,7 @@
     int num_ra_ops_per_iter = ((GetBufferDataSize()) / BLOCK_SZ);
     std::optional<chunk_t> prev_id = {};
     std::map<uint64_t, const CowOperation*> map;
+    std::set<uint64_t> dest_blocks;
     size_t pending_copy_ops = exceptions_per_area_ - num_ops;
     uint64_t total_copy_ops = reader_->total_copy_ops();
 
@@ -555,10 +562,15 @@
                 if (diff != 1) {
                     break;
                 }
+
+                if (dest_blocks.count(cow_op->new_block) || map.count(cow_op->source) > 0) {
+                    break;
+                }
             }
             metadata_found = true;
             pending_copy_ops -= 1;
             map[cow_op->new_block] = cow_op;
+            dest_blocks.insert(cow_op->source);
             prev_id = cow_op->new_block;
             cowop_riter_->Next();
         } while (!cowop_riter_->Done() && pending_copy_ops);
@@ -604,7 +616,11 @@
                     SNAP_LOG(DEBUG) << "ReadMetadata() completed; Number of Areas: " << vec_.size();
                 }
 
-                CHECK(pending_copy_ops == 0);
+                if (!(pending_copy_ops == 0)) {
+                    SNAP_LOG(ERROR)
+                            << "Invalid pending_copy_ops: expected: 0 found: " << pending_copy_ops;
+                    return false;
+                }
                 pending_copy_ops = exceptions_per_area_;
             }
 
@@ -620,6 +636,7 @@
             }
         }
         map.clear();
+        dest_blocks.clear();
         prev_id.reset();
     }
 
diff --git a/fs_mgr/libsnapshot/snapuserd_readahead.cpp b/fs_mgr/libsnapshot/snapuserd_readahead.cpp
index 09ee2f2..16d5919 100644
--- a/fs_mgr/libsnapshot/snapuserd_readahead.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_readahead.cpp
@@ -257,7 +257,12 @@
             // Verify that we have covered all the ops which were re-constructed
             // from COW device - These are the ops which are being
             // re-constructed after crash.
-            CHECK(num_ops == 0);
+            if (!(num_ops == 0)) {
+                SNAP_LOG(ERROR) << "ReconstructDataFromCow failed. Not all ops recoverd "
+                                << " Pending ops: " << num_ops;
+                snapuserd_->ReadAheadIOFailed();
+                return false;
+            }
             break;
         }
     }
@@ -370,8 +375,6 @@
         bm->file_offset = 0;
 
         buffer_offset += io_size;
-        CHECK(offset == buffer_offset);
-        CHECK((file_offset - snapuserd_->GetBufferDataOffset()) == offset);
     }
 
     snapuserd_->SetTotalRaBlocksMerged(total_blocks_merged);
diff --git a/fs_mgr/libsnapshot/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd_server.cpp
index ff8a259..8339690 100644
--- a/fs_mgr/libsnapshot/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_server.cpp
@@ -191,7 +191,7 @@
         }
         case DaemonOperations::DETACH: {
             terminating_ = true;
-            return Sendmsg(fd, "success");
+            return true;
         }
         default: {
             LOG(ERROR) << "Received unknown message type from client";
@@ -378,7 +378,10 @@
 }
 
 bool SnapuserdServer::StartHandler(const std::shared_ptr<DmUserHandler>& handler) {
-    CHECK(!handler->snapuserd()->IsAttached());
+    if (handler->snapuserd()->IsAttached()) {
+        LOG(ERROR) << "Handler already attached";
+        return false;
+    }
 
     handler->snapuserd()->AttachControlDevice();
 
diff --git a/fs_mgr/libsnapshot/snapuserd_worker.cpp b/fs_mgr/libsnapshot/snapuserd_worker.cpp
index 9f42ab8..7e0f493 100644
--- a/fs_mgr/libsnapshot/snapuserd_worker.cpp
+++ b/fs_mgr/libsnapshot/snapuserd_worker.cpp
@@ -57,7 +57,9 @@
 }
 
 struct dm_user_header* BufferSink::GetHeaderPtr() {
-    CHECK(sizeof(struct dm_user_header) <= buffer_size_);
+    if (!(sizeof(struct dm_user_header) <= buffer_size_)) {
+        return nullptr;
+    }
     char* buf = reinterpret_cast<char*>(GetBufPtr());
     struct dm_user_header* header = (struct dm_user_header*)(&(buf[0]));
     return header;
@@ -111,7 +113,6 @@
 // the header, zero out the remaining block.
 void WorkerThread::ConstructKernelCowHeader() {
     void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
-    CHECK(buffer != nullptr);
 
     memset(buffer, 0, BLOCK_SZ);
 
@@ -137,7 +138,10 @@
 
 bool WorkerThread::ReadFromBaseDevice(const CowOperation* cow_op) {
     void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
-    CHECK(buffer != nullptr);
+    if (buffer == nullptr) {
+        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;
     if (!android::base::ReadFullyAtOffset(backing_store_fd_, buffer, BLOCK_SZ,
@@ -152,7 +156,10 @@
 
 bool WorkerThread::GetReadAheadPopulatedBuffer(const CowOperation* cow_op) {
     void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
-    CHECK(buffer != nullptr);
+    if (buffer == nullptr) {
+        SNAP_LOG(ERROR) << "GetReadAheadPopulatedBuffer: Failed to get payload buffer";
+        return false;
+    }
 
     if (!snapuserd_->GetReadAheadPopulatedBuffer(cow_op->new_block, buffer)) {
         return false;
@@ -178,14 +185,20 @@
 bool WorkerThread::ProcessZeroOp() {
     // Zero out the entire block
     void* buffer = bufsink_.GetPayloadBuffer(BLOCK_SZ);
-    CHECK(buffer != nullptr);
+    if (buffer == nullptr) {
+        SNAP_LOG(ERROR) << "ProcessZeroOp: Failed to get payload buffer";
+        return false;
+    }
 
     memset(buffer, 0, BLOCK_SZ);
     return true;
 }
 
 bool WorkerThread::ProcessCowOp(const CowOperation* cow_op) {
-    CHECK(cow_op != nullptr);
+    if (cow_op == nullptr) {
+        SNAP_LOG(ERROR) << "ProcessCowOp: Invalid cow_op";
+        return false;
+    }
 
     switch (cow_op->type) {
         case kCowReplaceOp: {
@@ -216,7 +229,8 @@
                     << " Aligned sector: " << it->first;
 
     if (!ProcessCowOp(it->second)) {
-        SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed of size: " << size;
+        SNAP_LOG(ERROR) << "ReadUnalignedSector: " << sector << " failed of size: " << size
+                        << " Aligned sector: " << it->first;
         return -1;
     }
 
@@ -261,7 +275,10 @@
     it = std::lower_bound(chunk_vec.begin(), chunk_vec.end(), std::make_pair(sector, nullptr),
                           Snapuserd::compare);
 
-    CHECK(it != chunk_vec.end());
+    if (!(it != chunk_vec.end())) {
+        SNAP_LOG(ERROR) << "ReadData: Sector " << sector << " not found in chunk_vec";
+        return -1;
+    }
 
     // We didn't find the required sector; hence find the previous sector
     // as lower_bound will gives us the value greater than
@@ -334,7 +351,10 @@
     }
 
     void* buffer = bufsink_.GetPayloadBuffer(size);
-    CHECK(buffer != nullptr);
+    if (buffer == nullptr) {
+        SNAP_LOG(ERROR) << "ZerofillDiskExceptions: Failed to get payload buffer";
+        return false;
+    }
 
     memset(buffer, 0, size);
     return true;
@@ -364,10 +384,17 @@
     if (divresult.quot < vec.size()) {
         size = exceptions_per_area_ * sizeof(struct disk_exception);
 
-        CHECK(read_size == size);
+        if (read_size != size) {
+            SNAP_LOG(ERROR) << "ReadDiskExceptions: read_size: " << read_size
+                            << " does not match with size: " << size;
+            return false;
+        }
 
         void* buffer = bufsink_.GetPayloadBuffer(size);
-        CHECK(buffer != nullptr);
+        if (buffer == nullptr) {
+            SNAP_LOG(ERROR) << "ReadDiskExceptions: Failed to get payload buffer of size: " << size;
+            return false;
+        }
 
         memcpy(buffer, vec[divresult.quot].get(), size);
     } else {
@@ -390,8 +417,19 @@
 
         // Unmerged op by the kernel
         if (merged_de->old_chunk != 0 || merged_de->new_chunk != 0) {
-            CHECK(merged_de->old_chunk == cow_de->old_chunk);
-            CHECK(merged_de->new_chunk == cow_de->new_chunk);
+            if (!(merged_de->old_chunk == cow_de->old_chunk)) {
+                SNAP_LOG(ERROR) << "GetMergeStartOffset: merged_de->old_chunk: "
+                                << merged_de->old_chunk
+                                << "cow_de->old_chunk: " << cow_de->old_chunk;
+                return -1;
+            }
+
+            if (!(merged_de->new_chunk == cow_de->new_chunk)) {
+                SNAP_LOG(ERROR) << "GetMergeStartOffset: merged_de->new_chunk: "
+                                << merged_de->new_chunk
+                                << "cow_de->new_chunk: " << cow_de->new_chunk;
+                return -1;
+            }
 
             offset += sizeof(struct disk_exception);
             *unmerged_exceptions += 1;
@@ -401,8 +439,6 @@
         break;
     }
 
-    CHECK(!(*unmerged_exceptions == exceptions_per_area_));
-
     SNAP_LOG(DEBUG) << "Unmerged_Exceptions: " << *unmerged_exceptions << " Offset: " << offset;
     return offset;
 }
@@ -421,8 +457,15 @@
         struct disk_exception* cow_de =
                 reinterpret_cast<struct disk_exception*>((char*)unmerged_buffer + offset);
 
-        CHECK(merged_de->new_chunk == 0);
-        CHECK(merged_de->old_chunk == 0);
+        if (!(merged_de->new_chunk == 0)) {
+            SNAP_LOG(ERROR) << "GetNumberOfMergedOps: Invalid new-chunk: " << merged_de->new_chunk;
+            return -1;
+        }
+
+        if (!(merged_de->old_chunk == 0)) {
+            SNAP_LOG(ERROR) << "GetNumberOfMergedOps: Invalid old-chunk: " << merged_de->old_chunk;
+            return -1;
+        }
 
         if (cow_de->new_chunk != 0) {
             merged_ops_cur_iter += 1;
@@ -430,11 +473,18 @@
             auto it = std::lower_bound(chunk_vec.begin(), chunk_vec.end(),
                                        std::make_pair(ChunkToSector(cow_de->new_chunk), nullptr),
                                        Snapuserd::compare);
-            CHECK(it != chunk_vec.end());
-            CHECK(it->first == ChunkToSector(cow_de->new_chunk));
+
+            if (!(it != chunk_vec.end())) {
+                SNAP_LOG(ERROR) << "Sector not found: " << ChunkToSector(cow_de->new_chunk);
+                return -1;
+            }
+
+            if (!(it->first == ChunkToSector(cow_de->new_chunk))) {
+                SNAP_LOG(ERROR) << "Invalid sector: " << ChunkToSector(cow_de->new_chunk);
+                return -1;
+            }
             const CowOperation* cow_op = it->second;
 
-            CHECK(cow_op != nullptr);
             if (snapuserd_->IsReadAheadFeaturePresent() && cow_op->type == kCowCopyOp) {
                 *copy_op = true;
                 // Every single copy operation has to come from read-ahead
@@ -453,7 +503,6 @@
                 }
             }
 
-            CHECK(cow_op->new_block == cow_de->old_chunk);
             // zero out to indicate that operation is merged.
             cow_de->old_chunk = 0;
             cow_de->new_chunk = 0;
@@ -463,7 +512,6 @@
             //
             // If the op was merged in previous cycle, we don't have
             // to count them.
-            CHECK(cow_de->new_chunk == 0);
             break;
         } else {
             SNAP_LOG(ERROR) << "Error in merge operation. Found invalid metadata: "
@@ -488,18 +536,33 @@
 
     // ChunkID to vector index
     lldiv_t divresult = lldiv(chunk, stride);
-    CHECK(divresult.quot < vec.size());
+
+    if (!(divresult.quot < vec.size())) {
+        SNAP_LOG(ERROR) << "ProcessMergeComplete: Invalid chunk: " << chunk
+                        << " Metadata-Index: " << divresult.quot << " Area-size: " << vec.size();
+        return false;
+    }
+
     SNAP_LOG(DEBUG) << "ProcessMergeComplete: chunk: " << chunk
                     << " Metadata-Index: " << divresult.quot;
 
     int unmerged_exceptions = 0;
     loff_t offset = GetMergeStartOffset(buffer, vec[divresult.quot].get(), &unmerged_exceptions);
 
+    if (offset < 0) {
+        SNAP_LOG(ERROR) << "GetMergeStartOffset failed: unmerged_exceptions: "
+                        << unmerged_exceptions;
+        return false;
+    }
+
     int merged_ops_cur_iter = GetNumberOfMergedOps(buffer, vec[divresult.quot].get(), offset,
                                                    unmerged_exceptions, &copy_op, &commit);
 
     // There should be at least one operation merged in this cycle
-    CHECK(merged_ops_cur_iter > 0);
+    if (!(merged_ops_cur_iter > 0)) {
+        SNAP_LOG(ERROR) << "Merge operation failed: " << merged_ops_cur_iter;
+        return false;
+    }
 
     if (copy_op) {
         if (commit) {
@@ -570,8 +633,12 @@
     // REQ_PREFLUSH flag set. Snapuser daemon doesn't have anything
     // to flush per se; hence, just respond back with a success message.
     if (header->sector == 0) {
-        CHECK(header->len == 0);
-        header->type = DM_USER_RESP_SUCCESS;
+        if (!(header->len == 0)) {
+            header->type = DM_USER_RESP_ERROR;
+        } else {
+            header->type = DM_USER_RESP_SUCCESS;
+        }
+
         if (!WriteDmUserPayload(0)) {
             return false;
         }
@@ -581,33 +648,37 @@
     std::vector<std::pair<sector_t, const CowOperation*>>& chunk_vec = snapuserd_->GetChunkVec();
     size_t remaining_size = header->len;
     size_t read_size = std::min(PAYLOAD_SIZE, remaining_size);
-    CHECK(read_size == BLOCK_SZ) << "DmuserWriteRequest: read_size: " << read_size;
 
-    CHECK(header->sector > 0);
     chunk_t chunk = SectorToChunk(header->sector);
     auto it = std::lower_bound(chunk_vec.begin(), chunk_vec.end(),
                                std::make_pair(header->sector, nullptr), Snapuserd::compare);
 
     bool not_found = (it == chunk_vec.end() || it->first != header->sector);
-    CHECK(not_found);
 
-    void* buffer = bufsink_.GetPayloadBuffer(read_size);
-    CHECK(buffer != nullptr);
-    header->type = DM_USER_RESP_SUCCESS;
+    if (not_found) {
+        void* buffer = bufsink_.GetPayloadBuffer(read_size);
+        if (buffer == nullptr) {
+            SNAP_LOG(ERROR) << "DmuserWriteRequest: Failed to get payload buffer of size: "
+                            << read_size;
+            header->type = DM_USER_RESP_ERROR;
+        } else {
+            header->type = DM_USER_RESP_SUCCESS;
 
-    if (!ReadDmUserPayload(buffer, read_size)) {
-        SNAP_LOG(ERROR) << "ReadDmUserPayload failed for chunk id: " << chunk
-                        << "Sector: " << header->sector;
-        header->type = DM_USER_RESP_ERROR;
-    }
+            if (!ReadDmUserPayload(buffer, read_size)) {
+                SNAP_LOG(ERROR) << "ReadDmUserPayload failed for chunk id: " << chunk
+                                << "Sector: " << header->sector;
+                header->type = DM_USER_RESP_ERROR;
+            }
 
-    if (header->type == DM_USER_RESP_SUCCESS && !ProcessMergeComplete(chunk, buffer)) {
-        SNAP_LOG(ERROR) << "ProcessMergeComplete failed for chunk id: " << chunk
-                        << "Sector: " << header->sector;
-        header->type = DM_USER_RESP_ERROR;
+            if (header->type == DM_USER_RESP_SUCCESS && !ProcessMergeComplete(chunk, buffer)) {
+                SNAP_LOG(ERROR) << "ProcessMergeComplete failed for chunk id: " << chunk
+                                << "Sector: " << header->sector;
+                header->type = DM_USER_RESP_ERROR;
+            }
+        }
     } else {
-        SNAP_LOG(DEBUG) << "ProcessMergeComplete success for chunk id: " << chunk
-                        << "Sector: " << header->sector;
+        SNAP_LOG(ERROR) << "DmuserWriteRequest: Invalid sector received: header->sector";
+        header->type = DM_USER_RESP_ERROR;
     }
 
     if (!WriteDmUserPayload(0)) {
@@ -636,7 +707,6 @@
         // never see multiple IO requests. Additionally this IO
         // will always be a single 4k.
         if (header->sector == 0) {
-            CHECK(read_size == BLOCK_SZ) << " Sector 0 read request of size: " << read_size;
             ConstructKernelCowHeader();
             SNAP_LOG(DEBUG) << "Kernel header constructed";
         } else {
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 83174ef..eb2919b 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -325,14 +325,14 @@
     TemporaryFile tf;
     ASSERT_TRUE(tf.fd != -1);
     std::string fstab_contents = R"fs(
-source /            ext4    ro,barrier=1                    wait,slotselect,avb
+source /            ext4    ro,barrier=1                    wait,avb
 source /metadata    ext4    noatime,nosuid,nodev,discard    wait,formattable
 
 source /data        f2fs    noatime,nosuid,nodev,discard,reserve_root=32768,resgid=1065,fsync_mode=nobarrier    latemount,wait,check,fileencryption=ice,keydirectory=/metadata/vold/metadata_encryption,quota,formattable,sysfs_path=/sys/devices/platform/soc/1d84000.ufshc,reservedsize=128M
 
 source /misc        emmc    defaults                        defaults
 
-source /vendor/firmware_mnt    vfat    ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0    wait,slotselect
+source /vendor/firmware_mnt    vfat    ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0    wait
 
 source auto         vfat    defaults                        voldmanaged=usb:auto
 source none         swap    defaults                        zramsize=1073741824,max_comp_streams=8
@@ -412,8 +412,8 @@
     ASSERT_TRUE(tf.fd != -1);
     std::string fstab_contents = R"fs(
 source none0       swap   defaults      wait,check,nonremovable,recoveryonly,verifyatboot,verify
-source none1       swap   defaults      avb,noemulatedsd,notrim,formattable,slotselect,nofail
-source none2       swap   defaults      first_stage_mount,latemount,quota,logical,slotselect_other
+source none1       swap   defaults      avb,noemulatedsd,notrim,formattable,nofail
+source none2       swap   defaults      first_stage_mount,latemount,quota,logical
 source none3       swap   defaults      checkpoint=block
 source none4       swap   defaults      checkpoint=fs
 source none5       swap   defaults      defaults
@@ -445,7 +445,6 @@
         flags.no_emulated_sd = true;
         flags.no_trim = true;
         flags.formattable = true;
-        flags.slot_select = true;
         flags.no_fail = true;
         EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
@@ -458,7 +457,6 @@
         flags.late_mount = true;
         flags.quota = true;
         flags.logical = true;
-        flags.slot_select_other = true;
         EXPECT_TRUE(CompareFlags(flags, entry->fs_mgr_flags));
     }
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 9f1ebcf..ff9da42 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -94,6 +94,12 @@
 
 namespace android {
 namespace init {
+constexpr auto FINGERPRINT_PROP = "ro.build.fingerprint";
+constexpr auto LEGACY_FINGERPRINT_PROP = "ro.build.legacy.fingerprint";
+constexpr auto ID_PROP = "ro.build.id";
+constexpr auto LEGACY_ID_PROP = "ro.build.legacy.id";
+constexpr auto VBMETA_DIGEST_PROP = "ro.boot.vbmeta.digest";
+constexpr auto DIGEST_SIZE_USED = 8;
 
 static bool persistent_properties_loaded = false;
 
@@ -857,15 +863,33 @@
     }
 }
 
-// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
-static void property_derive_build_fingerprint() {
-    std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
-    if (!build_fingerprint.empty()) {
+static void property_initialize_build_id() {
+    std::string build_id = GetProperty(ID_PROP, "");
+    if (!build_id.empty()) {
         return;
     }
 
+    std::string legacy_build_id = GetProperty(LEGACY_ID_PROP, "");
+    std::string vbmeta_digest = GetProperty(VBMETA_DIGEST_PROP, "");
+    if (vbmeta_digest.size() < DIGEST_SIZE_USED) {
+        LOG(ERROR) << "vbmeta digest size too small " << vbmeta_digest;
+        // Still try to set the id field in the unexpected case.
+        build_id = legacy_build_id;
+    } else {
+        // Derive the ro.build.id by appending the vbmeta digest to the base value.
+        build_id = legacy_build_id + "." + vbmeta_digest.substr(0, DIGEST_SIZE_USED);
+    }
+
+    std::string error;
+    auto res = PropertySet(ID_PROP, build_id, &error);
+    if (res != PROP_SUCCESS) {
+        LOG(ERROR) << "Failed to set " << ID_PROP << " to " << build_id;
+    }
+}
+
+static std::string ConstructBuildFingerprint(bool legacy) {
     const std::string UNKNOWN = "unknown";
-    build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
+    std::string build_fingerprint = GetProperty("ro.product.brand", UNKNOWN);
     build_fingerprint += '/';
     build_fingerprint += GetProperty("ro.product.name", UNKNOWN);
     build_fingerprint += '/';
@@ -873,7 +897,10 @@
     build_fingerprint += ':';
     build_fingerprint += GetProperty("ro.build.version.release_or_codename", UNKNOWN);
     build_fingerprint += '/';
-    build_fingerprint += GetProperty("ro.build.id", UNKNOWN);
+
+    std::string build_id =
+            legacy ? GetProperty(LEGACY_ID_PROP, UNKNOWN) : GetProperty(ID_PROP, UNKNOWN);
+    build_fingerprint += build_id;
     build_fingerprint += '/';
     build_fingerprint += GetProperty("ro.build.version.incremental", UNKNOWN);
     build_fingerprint += ':';
@@ -881,13 +908,49 @@
     build_fingerprint += '/';
     build_fingerprint += GetProperty("ro.build.tags", UNKNOWN);
 
-    LOG(INFO) << "Setting property 'ro.build.fingerprint' to '" << build_fingerprint << "'";
+    return build_fingerprint;
+}
+
+// Derive the legacy build fingerprint if we overwrite the build id at runtime.
+static void property_derive_legacy_build_fingerprint() {
+    std::string legacy_build_fingerprint = GetProperty(LEGACY_FINGERPRINT_PROP, "");
+    if (!legacy_build_fingerprint.empty()) {
+        return;
+    }
+
+    // The device doesn't have a legacy build id, skipping the legacy fingerprint.
+    std::string legacy_build_id = GetProperty(LEGACY_ID_PROP, "");
+    if (legacy_build_id.empty()) {
+        return;
+    }
+
+    legacy_build_fingerprint = ConstructBuildFingerprint(true /* legacy fingerprint */);
+    LOG(INFO) << "Setting property '" << LEGACY_FINGERPRINT_PROP << "' to '"
+              << legacy_build_fingerprint << "'";
 
     std::string error;
-    uint32_t res = PropertySet("ro.build.fingerprint", build_fingerprint, &error);
+    uint32_t res = PropertySet(LEGACY_FINGERPRINT_PROP, legacy_build_fingerprint, &error);
     if (res != PROP_SUCCESS) {
-        LOG(ERROR) << "Error setting property 'ro.build.fingerprint': err=" << res << " (" << error
-                   << ")";
+        LOG(ERROR) << "Error setting property '" << LEGACY_FINGERPRINT_PROP << "': err=" << res
+                   << " (" << error << ")";
+    }
+}
+
+// If the ro.build.fingerprint property has not been set, derive it from constituent pieces
+static void property_derive_build_fingerprint() {
+    std::string build_fingerprint = GetProperty("ro.build.fingerprint", "");
+    if (!build_fingerprint.empty()) {
+        return;
+    }
+
+    build_fingerprint = ConstructBuildFingerprint(false /* legacy fingerprint */);
+    LOG(INFO) << "Setting property '" << FINGERPRINT_PROP << "' to '" << build_fingerprint << "'";
+
+    std::string error;
+    uint32_t res = PropertySet(FINGERPRINT_PROP, build_fingerprint, &error);
+    if (res != PROP_SUCCESS) {
+        LOG(ERROR) << "Error setting property '" << FINGERPRINT_PROP << "': err=" << res << " ("
+                   << error << ")";
     }
 }
 
@@ -1035,7 +1098,9 @@
     }
 
     property_initialize_ro_product_props();
+    property_initialize_build_id();
     property_derive_build_fingerprint();
+    property_derive_legacy_build_fingerprint();
     property_initialize_ro_cpu_abilist();
 
     update_sys_usb_config();
diff --git a/init/property_service_test.cpp b/init/property_service_test.cpp
index c6dcfa2..ac6b7b2 100644
--- a/init/property_service_test.cpp
+++ b/init/property_service_test.cpp
@@ -23,6 +23,7 @@
 
 #include <android-base/properties.h>
 #include <android-base/scopeguard.h>
+#include <android-base/strings.h>
 #include <gtest/gtest.h>
 
 using android::base::GetProperty;
@@ -90,5 +91,39 @@
     EXPECT_FALSE(SetProperty("sys.powerctl", "reboot,userspace"));
 }
 
+TEST(property_service, check_fingerprint_with_legacy_build_id) {
+    std::string legacy_build_id = GetProperty("ro.build.legacy.id", "");
+    if (legacy_build_id.empty()) {
+        GTEST_SKIP() << "Skipping test, legacy build id isn't set.";
+    }
+
+    std::string vbmeta_digest = GetProperty("ro.boot.vbmeta.digest", "");
+    ASSERT_GE(vbmeta_digest.size(), 8u);
+    std::string build_id = GetProperty("ro.boot.build.id", "");
+    // Check that the build id is constructed with the prefix of vbmeta digest
+    std::string expected_build_id = legacy_build_id + "." + vbmeta_digest.substr(0, 8);
+    ASSERT_EQ(expected_build_id, build_id);
+    // Check that the fingerprint is constructed with the expected format.
+    std::string fingerprint = GetProperty("ro.build.fingerprint", "");
+    std::vector<std::string> fingerprint_fields = {
+            GetProperty("ro.product.brand", ""),
+            "/",
+            GetProperty("ro.product.name", ""),
+            "/",
+            GetProperty("ro.product.device", ""),
+            ":",
+            GetProperty("ro.build.version.release_or_codename", ""),
+            "/",
+            expected_build_id,
+            "/",
+            GetProperty("ro.build.version.incremental", ""),
+            ":",
+            GetProperty("ro.build.type", ""),
+            "/",
+            GetProperty("ro.build.tags", "")};
+
+    ASSERT_EQ(android::base::Join(fingerprint_fields, ""), fingerprint);
+}
+
 }  // namespace init
 }  // namespace android
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 6395567..13e4c02 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -275,12 +275,6 @@
 }
 
 cc_fuzz {
-    name: "libutils_fuzz_stopwatch",
-    defaults: ["libutils_fuzz_defaults"],
-    srcs: ["StopWatch_fuzz.cpp"],
-}
-
-cc_fuzz {
     name: "libutils_fuzz_refbase",
     defaults: ["libutils_fuzz_defaults"],
     srcs: ["RefBase_fuzz.cpp"],
diff --git a/libutils/README b/libutils/README
deleted file mode 100644
index 01741e0..0000000
--- a/libutils/README
+++ /dev/null
@@ -1,289 +0,0 @@
-Android Utility Function Library
-================================
-
-
-If you need a feature that is native to Linux but not present on other
-platforms, construct a platform-dependent implementation that shares
-the Linux interface.  That way the actual device runs as "light" as
-possible.
-
-If that isn't feasible, create a system-independent interface and hide
-the details.
-
-The ultimate goal is *not* to create a super-duper platform abstraction
-layer.  The goal is to provide an optimized solution for Linux with
-reasonable implementations for other platforms.
-
-
-
-Resource overlay
-================
-
-
-Introduction
-------------
-
-Overlay packages are special .apk files which provide no code but
-additional resource values (and possibly new configurations) for
-resources in other packages. When an application requests resources,
-the system will return values from either the application's original
-package or any associated overlay package. Any redirection is completely
-transparent to the calling application.
-
-Resource values have the following precedence table, listed in
-descending precedence.
-
- * overlay package, matching config (eg res/values-en-land)
-
- * original package, matching config
-
- * overlay package, no config (eg res/values)
-
- * original package, no config
-
-During compilation, overlay packages are differentiated from regular
-packages by passing the -o flag to aapt.
-
-
-Background
-----------
-
-This section provides generic background material on resources in
-Android.
-
-
-How resources are bundled in .apk files
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Android .apk files are .zip files, usually housing .dex code,
-certificates and resources, though packages containing resources but
-no code are possible. Resources can be divided into the following
-categories; a `configuration' indicates a set of phone language, display
-density, network operator, etc.
-
- * assets: uncompressed, raw files packaged as part of an .apk and
-           explicitly referenced by filename. These files are
-           independent of configuration.
-
- * res/drawable: bitmap or xml graphics. Each file may have different
-                 values depending on configuration.
-
- * res/values: integers, strings, etc. Each resource may have different
-               values depending on configuration.
-
-Resource meta information and information proper is stored in a binary
-format in a named file resources.arsc, bundled as part of the .apk.
-
-Resource IDs and lookup
-~~~~~~~~~~~~~~~~~~~~~~~
-During compilation, the aapt tool gathers application resources and
-generates a resources.arsc file. Each resource name is assigned an
-integer ID 0xppttiii (translated to a symbolic name via R.java), where
-
- * pp: corresponds to the package namespace (details below).
-
- * tt: corresponds to the resource type (string, int, etc). Every
-       resource of the same type within the same package has the same
-       tt value, but depending on available types, the actual numerical
-       value may be different between packages.
-
- * iiii: sequential number, assigned in the order resources are found.
-
-Resource values are specified paired with a set of configuration
-constraints (the default being the empty set), eg res/values-sv-port
-which imposes restrictions on language (Swedish) and display orientation
-(portrait). During lookup, every constraint set is matched against the
-current configuration, and the value corresponding to the best matching
-constraint set is returned (ResourceTypes.{h,cpp}).
-
-Parsing of resources.arsc is handled by ResourceTypes.cpp; this utility
-is governed by AssetManager.cpp, which tracks loaded resources per
-process.
-
-Assets are looked up by path and filename in AssetManager.cpp. The path
-to resources in res/drawable are located by ResourceTypes.cpp and then
-handled like assets by AssetManager.cpp. Other resources are handled
-solely by ResourceTypes.cpp.
-
-Package ID as namespace
-~~~~~~~~~~~~~~~~~~~~~~~
-The pp part of a resource ID defines a namespace. Android currently
-defines two namespaces:
-
- * 0x01: system resources (pre-installed in framework-res.apk)
-
- * 0x7f: application resources (bundled in the application .apk)
-
-ResourceTypes.cpp supports package IDs between 0x01 and 0x7f
-(inclusive); values outside this range are invalid.
-
-Each running (Dalvik) process is assigned a unique instance of
-AssetManager, which in turn keeps a forest structure of loaded
-resource.arsc files. Normally, this forest is structured as follows,
-where mPackageMap is the internal vector employed in ResourceTypes.cpp.
-
-mPackageMap[0x00] -> system package
-mPackageMap[0x01] -> NULL
-mPackageMap[0x02] -> NULL
-...
-mPackageMap[0x7f - 2] -> NULL
-mPackageMap[0x7f - 1] -> application package
-
-
-
-The resource overlay extension
-------------------------------
-
-The resource overlay mechanism aims to (partly) shadow and extend
-existing resources with new values for defined and new configurations.
-Technically, this is achieved by adding resource-only packages (called
-overlay packages) to existing resource namespaces, like so:
-
-mPackageMap[0x00] -> system package -> system overlay package
-mPackageMap[0x01] -> NULL
-mPackageMap[0x02] -> NULL
-...
-mPackageMap[0x7f - 2] -> NULL
-mPackageMap[0x7f - 1] -> application package -> overlay 1 -> overlay 2
-
-The use of overlay resources is completely transparent to
-applications; no additional resource identifiers are introduced, only
-configuration/value pairs. Any number of overlay packages may be loaded
-at a time; overlay packages are agnostic to what they target -- both
-system and application resources are fair game.
-
-The package targeted by an overlay package is called the target or
-original package.
-
-Resource overlay operates on symbolic resources names. Hence, to
-override the string/str1 resources in a package, the overlay package
-would include a resource also named string/str1. The end user does not
-have to worry about the numeric resources IDs assigned by aapt, as this
-is resolved automatically by the system.
-
-As of this writing, the use of resource overlay has not been fully
-explored. Until it has, only OEMs are trusted to use resource overlay.
-For this reason, overlay packages must reside in /system/overlay.
-
-
-Resource ID mapping
-~~~~~~~~~~~~~~~~~~~
-Resource identifiers must be coherent within the same namespace (ie
-PackageGroup in ResourceTypes.cpp). Calling applications will refer to
-resources using the IDs defined in the original package, but there is no
-guarantee aapt has assigned the same ID to the corresponding resource in
-an overlay package. To translate between the two, a resource ID mapping
-{original ID -> overlay ID} is created during package installation
-(PackageManagerService.java) and used during resource lookup. The
-mapping is stored in /data/resource-cache, with a @idmap file name
-suffix.
-
-The idmap file format is documented in a separate section, below.
-
-
-Package management
-~~~~~~~~~~~~~~~~~~
-Packages are managed by the PackageManagerService. Addition and removal
-of packages are monitored via the inotify framework, exposed via
-android.os.FileObserver.
-
-During initialization of a Dalvik process, ActivityThread.java requests
-the process' AssetManager (by proxy, via AssetManager.java and JNI)
-to load a list of packages. This list includes overlay packages, if
-present.
-
-When a target package or a corresponding overlay package is installed,
-the target package's process is stopped and a new idmap is generated.
-This is similar to how applications are stopped when their packages are
-upgraded.
-
-
-Creating overlay packages
--------------------------
-
-Overlay packages should contain no code, define (some) resources with
-the same type and name as in the original package, and be compiled with
-the -o flag passed to aapt.
-
-The aapt -o flag instructs aapt to create an overlay package.
-Technically, this means the package will be assigned package id 0x00.
-
-There are no restrictions on overlay packages names, though the naming
-convention <original.package.name>.overlay.<name> is recommended.
-
-
-Example overlay package
-~~~~~~~~~~~~~~~~~~~~~~~
-
-To overlay the resource bool/b in package com.foo.bar, to be applied
-when the display is in landscape mode, create a new package with
-no source code and a single .xml file under res/values-land, with
-an entry for bool/b. Compile with aapt -o and place the results in
-/system/overlay by adding the following to Android.mk:
-
-LOCAL_AAPT_FLAGS := -o com.foo.bar
-LOCAL_MODULE_PATH := $(TARGET_OUT)/overlay
-
-
-The ID map (idmap) file format
-------------------------------
-
-The idmap format is designed for lookup performance. However, leading
-and trailing undefined overlay values are discarded to reduce the memory
-footprint.
-
-
-idmap grammar
-~~~~~~~~~~~~~
-All atoms (names in square brackets) are uint32_t integers. The
-idmap-magic constant spells "idmp" in ASCII. Offsets are given relative
-to the data_header, not to the beginning of the file.
-
-map          := header data
-header       := idmap-magic <crc32-original-pkg> <crc32-overlay-pkg>
-idmap-magic  := <0x706d6469>
-data         := data_header type_block+
-data_header  := <m> header_block{m}
-header_block := <0> | <type_block_offset>
-type_block   := <n> <id_offset> entry{n}
-entry        := <resource_id_in_target_package>
-
-
-idmap example
-~~~~~~~~~~~~~
-Given a pair of target and overlay packages with CRC sums 0x216a8fe2
-and 0x6b9beaec, each defining the following resources
-
-Name          Target package  Overlay package
-string/str0   0x7f010000      -
-string/str1   0x7f010001      0x7f010000
-string/str2   0x7f010002      -
-string/str3   0x7f010003      0x7f010001
-string/str4   0x7f010004      -
-bool/bool0    0x7f020000      -
-integer/int0  0x7f030000      0x7f020000
-integer/int1  0x7f030001      -
-
-the corresponding resource map is
-
-0x706d6469 0x216a8fe2 0x6b9beaec 0x00000003 \
-0x00000004 0x00000000 0x00000009 0x00000003 \
-0x00000001 0x7f010000 0x00000000 0x7f010001 \
-0x00000001 0x00000000 0x7f020000
-
-or, formatted differently
-
-0x706d6469  # magic: all idmap files begin with this constant
-0x216a8fe2  # CRC32 of the resources.arsc file in the original package
-0x6b9beaec  # CRC32 of the resources.arsc file in the overlay package
-0x00000003  # header; three types (string, bool, integer) in the target package
-0x00000004  #   header_block for type 0 (string) is located at offset 4
-0x00000000  #   no bool type exists in overlay package -> no header_block
-0x00000009  #   header_block for type 2 (integer) is located at offset 9
-0x00000003  # header_block for string; overlay IDs span 3 elements
-0x00000001  #   the first string in target package is entry 1 == offset
-0x7f010000  #   target 0x7f01001 -> overlay 0x7f010000
-0x00000000  #   str2 not defined in overlay package
-0x7f010001  #   target 0x7f010003 -> overlay 0x7f010001
-0x00000001  # header_block for integer; overlay IDs span 1 element
-0x00000000  #   offset == 0
-0x7f020000  #   target 0x7f030000 -> overlay 0x7f020000
diff --git a/libutils/StopWatch.cpp b/libutils/StopWatch.cpp
index d01865e..28e2d76 100644
--- a/libutils/StopWatch.cpp
+++ b/libutils/StopWatch.cpp
@@ -26,58 +26,26 @@
 
 #include <utils/Log.h>
 
-/*****************************************************************************/
-
 namespace android {
 
 StopWatch::StopWatch(const char* name, int clock) : mName(name), mClock(clock) {
     reset();
 }
 
-StopWatch::~StopWatch()
-{
-    nsecs_t elapsed = elapsedTime();
-    const int n = mNumLaps;
-    ALOGD("StopWatch %s (us): %" PRId64 " ", mName, ns2us(elapsed));
-    for (int i=0 ; i<n ; i++) {
-        const nsecs_t soFar = mLaps[i].soFar;
-        const nsecs_t thisLap = mLaps[i].thisLap;
-        ALOGD(" [%d: %" PRId64 ", %" PRId64, i, ns2us(soFar), ns2us(thisLap));
-    }
+StopWatch::~StopWatch() {
+    ALOGD("StopWatch %s (us): %" PRId64 " ", name(), ns2us(elapsedTime()));
 }
 
-const char* StopWatch::name() const
-{
+const char* StopWatch::name() const {
     return mName;
 }
 
-nsecs_t StopWatch::lap()
-{
-    nsecs_t elapsed = elapsedTime();
-    if (mNumLaps >= 8) {
-        elapsed = 0;
-    } else {
-        const int n = mNumLaps;
-        mLaps[n].soFar   = elapsed;
-        mLaps[n].thisLap = n ? (elapsed - mLaps[n-1].soFar) : elapsed;
-        mNumLaps = n+1;
-    }
-    return elapsed;
-}
-
-nsecs_t StopWatch::elapsedTime() const
-{
+nsecs_t StopWatch::elapsedTime() const {
     return systemTime(mClock) - mStartTime;
 }
 
-void StopWatch::reset()
-{
-    mNumLaps = 0;
+void StopWatch::reset() {
     mStartTime = systemTime(mClock);
 }
 
-
-/*****************************************************************************/
-
-}; // namespace android
-
+}  // namespace android
diff --git a/libutils/StopWatch_fuzz.cpp b/libutils/StopWatch_fuzz.cpp
deleted file mode 100644
index 63d8a28..0000000
--- a/libutils/StopWatch_fuzz.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "fuzzer/FuzzedDataProvider.h"
-#include "utils/StopWatch.h"
-
-static constexpr int MAX_OPERATIONS = 100;
-static constexpr int MAX_NAME_LEN = 2048;
-
-static const std::vector<std::function<void(android::StopWatch)>> operations = {
-        [](android::StopWatch stopWatch) -> void { stopWatch.reset(); },
-        [](android::StopWatch stopWatch) -> void { stopWatch.lap(); },
-        [](android::StopWatch stopWatch) -> void { stopWatch.elapsedTime(); },
-        [](android::StopWatch stopWatch) -> void { stopWatch.name(); },
-};
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-    FuzzedDataProvider dataProvider(data, size);
-    std::string nameStr = dataProvider.ConsumeRandomLengthString(MAX_NAME_LEN);
-    int clockVal = dataProvider.ConsumeIntegral<int>();
-    android::StopWatch stopWatch = android::StopWatch(nameStr.c_str(), clockVal);
-    std::vector<uint8_t> opsToRun = dataProvider.ConsumeRemainingBytes<uint8_t>();
-    int opsRun = 0;
-    for (auto it : opsToRun) {
-        if (opsRun++ >= MAX_OPERATIONS) {
-            break;
-        }
-        it = it % operations.size();
-        operations[it](stopWatch);
-    }
-    return 0;
-}
diff --git a/libutils/include/utils/StopWatch.h b/libutils/include/utils/StopWatch.h
index 9b14ac8..4e53eda 100644
--- a/libutils/include/utils/StopWatch.h
+++ b/libutils/include/utils/StopWatch.h
@@ -14,46 +14,30 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_STOPWATCH_H
-#define ANDROID_STOPWATCH_H
+#pragma once
 
 #include <stdint.h>
 #include <sys/types.h>
 
 #include <utils/Timers.h>
 
-// ---------------------------------------------------------------------------
-
 namespace android {
 
-class StopWatch
-{
-public:
-  StopWatch(const char* name, int clock = SYSTEM_TIME_MONOTONIC);
-  ~StopWatch();
+class StopWatch {
+  public:
+    StopWatch(const char* name, int clock = SYSTEM_TIME_MONOTONIC);
+    ~StopWatch();
 
-  const char* name() const;
-  nsecs_t lap();
-  nsecs_t elapsedTime() const;
+    const char* name() const;
+    nsecs_t elapsedTime() const;
 
-  void reset();
+    void reset();
 
-private:
-    const char*     mName;
-    int             mClock;
-    
-    struct lap_t {
-        nsecs_t     soFar;
-        nsecs_t     thisLap;
-    };
-    
-    nsecs_t         mStartTime;
-    lap_t           mLaps[8];
-    int             mNumLaps;
+  private:
+    const char* mName;
+    int mClock;
+
+    nsecs_t mStartTime;
 };
 
 }  // namespace android
-
-// ---------------------------------------------------------------------------
-
-#endif // ANDROID_STOPWATCH_H