Merge "Isolate app profile ref data"
diff --git a/debuggerd/handler/debuggerd_fallback.cpp b/debuggerd/handler/debuggerd_fallback.cpp
index feafa73..f615780 100644
--- a/debuggerd/handler/debuggerd_fallback.cpp
+++ b/debuggerd/handler/debuggerd_fallback.cpp
@@ -87,6 +87,12 @@
 
     // TODO: Create this once and store it in a global?
     unwindstack::UnwinderFromPid unwinder(kMaxFrames, getpid());
+    // Do not use the thread cache here because it will call pthread_key_create
+    // which doesn't work in linker code. See b/189803009.
+    // Use a normal cached object because the process is stopped, and there
+    // is no chance of data changing between reads.
+    auto process_memory = unwindstack::Memory::CreateProcessMemoryCached(getpid());
+    unwinder.SetProcessMemory(process_memory);
     dump_backtrace_thread(output_fd, &unwinder, thread);
   }
   __linker_disable_fallback_allocator();
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index b0639e6..90d91a0 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -109,6 +109,10 @@
     optional_args_.emplace_back("ignore_zero_blocks");
 }
 
+void DmTargetVerity::CheckAtMostOnce() {
+    optional_args_.emplace_back("check_at_most_once");
+}
+
 std::string DmTargetVerity::GetParameterString() const {
     std::string base = android::base::Join(base_args_, " ");
     if (optional_args_.empty()) {
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 478a3c6..9543058 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -127,6 +127,7 @@
     void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start);
     void SetVerityMode(const std::string& mode);
     void IgnoreZeroBlocks();
+    void CheckAtMostOnce();
 
     std::string name() const override { return "verity"; }
     std::string GetParameterString() const override;
diff --git a/fs_mgr/libfs_avb/avb_util.cpp b/fs_mgr/libfs_avb/avb_util.cpp
index 31494c1..e913d50 100644
--- a/fs_mgr/libfs_avb/avb_util.cpp
+++ b/fs_mgr/libfs_avb/avb_util.cpp
@@ -92,6 +92,10 @@
     // Always use ignore_zero_blocks.
     target.IgnoreZeroBlocks();
 
+    if (hashtree_desc.flags & AVB_HASHTREE_DESCRIPTOR_FLAGS_CHECK_AT_MOST_ONCE) {
+        target.CheckAtMostOnce();
+    }
+
     LINFO << "Built verity table: '" << target.GetParameterString() << "'";
 
     return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
diff --git a/fs_mgr/libsnapshot/cow_writer.cpp b/fs_mgr/libsnapshot/cow_writer.cpp
index 51c00a9..0a7ceab 100644
--- a/fs_mgr/libsnapshot/cow_writer.cpp
+++ b/fs_mgr/libsnapshot/cow_writer.cpp
@@ -58,6 +58,12 @@
     return EmitRawBlocks(new_block_start, data, size);
 }
 
+bool AddXorBlocks(uint32_t /*new_block_start*/, const void* /*data*/, size_t /*size*/,
+                  uint32_t /*old_block*/, uint16_t /*offset*/) {
+    LOG(ERROR) << "AddXorBlocks not yet implemented";
+    return false;
+}
+
 bool ICowWriter::AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks) {
     uint64_t last_block = new_block_start + num_blocks - 1;
     if (!ValidateNewBlock(last_block)) {
@@ -70,6 +76,11 @@
     return EmitLabel(label);
 }
 
+bool AddSequenceData(size_t /*num_ops*/, const uint32_t* /*data*/) {
+    LOG(ERROR) << "AddSequenceData not yet implemented";
+    return false;
+}
+
 bool ICowWriter::ValidateNewBlock(uint64_t new_block) {
     if (options_.max_blocks && new_block >= options_.max_blocks.value()) {
         LOG(ERROR) << "New block " << new_block << " exceeds maximum block count "
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
index f43ea68..fbe6461 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/cow_writer.h
@@ -55,12 +55,19 @@
     // Encode a sequence of raw blocks. |size| must be a multiple of the block size.
     bool AddRawBlocks(uint64_t new_block_start, const void* data, size_t size);
 
+    // Add a sequence of xor'd blocks. |size| must be a multiple of the block size.
+    bool AddXorBlocks(uint32_t new_block_start, const void* data, size_t size, uint32_t old_block,
+                      uint16_t offset);
+
     // Encode a sequence of zeroed blocks. |size| must be a multiple of the block size.
     bool AddZeroBlocks(uint64_t new_block_start, uint64_t num_blocks);
 
     // Add a label to the op sequence.
     bool AddLabel(uint64_t label);
 
+    // Add sequence data for op merging. Data is a list of the destination block numbers.
+    bool AddSequenceData(size_t num_ops, const uint32_t* data);
+
     // Flush all pending writes. This must be called before closing the writer
     // to ensure that the correct headers and footers are written.
     virtual bool Finalize() = 0;