Merge "Add v3 to CreateCowWriter" into main
diff --git a/fastboot/README.md b/fastboot/README.md
index 28e623c..6996d4a 100644
--- a/fastboot/README.md
+++ b/fastboot/README.md
@@ -25,7 +25,7 @@
 ## Transport and Framing
 
 1. Host sends a command, which is an ascii string in a single
-   packet no greater than 64 bytes.
+   packet no greater than 4096 bytes.
 
 2. Client response with a single packet no greater than 256 bytes.
    The first four bytes of the response are "OKAY", "FAIL", "DATA",
diff --git a/fs_mgr/clean_scratch_files.rc b/fs_mgr/clean_scratch_files.rc
index 25a7e69..71708f8 100644
--- a/fs_mgr/clean_scratch_files.rc
+++ b/fs_mgr/clean_scratch_files.rc
@@ -1,2 +1,2 @@
-on post-fs-data && property:ro.debuggable=1
+on post-fs-data && property:ro.debuggable=1 && property:ro.boot.dynamic_partitions=true
     exec_background - root root -- /system/bin/clean_scratch_files
diff --git a/fs_mgr/libfiemap/metadata.cpp b/fs_mgr/libfiemap/metadata.cpp
index 22b8afb..0a56f6a 100644
--- a/fs_mgr/libfiemap/metadata.cpp
+++ b/fs_mgr/libfiemap/metadata.cpp
@@ -111,13 +111,7 @@
         return true;
     }
 
-    unique_fd fd(open(metadata_file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY | O_SYNC, 0644));
-    if (fd < 0) {
-        LOG(ERROR) << "open failed: " << metadata_file;
-        return false;
-    }
-
-    if (!WriteToImageFile(fd, *exported.get())) {
+    if (!WriteToImageFile(metadata_file, *exported.get())) {
         LOG(ERROR) << "Unable to save new metadata";
         return false;
     }
diff --git a/fs_mgr/liblp/images.cpp b/fs_mgr/liblp/images.cpp
index 02b64ac..a2dbb10 100644
--- a/fs_mgr/liblp/images.cpp
+++ b/fs_mgr/liblp/images.cpp
@@ -123,13 +123,46 @@
     return true;
 }
 
-bool WriteToImageFile(const std::string& file, const LpMetadata& input) {
-    unique_fd fd(open(file.c_str(), O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_BINARY, 0644));
-    if (fd < 0) {
-        PERROR << __PRETTY_FUNCTION__ << " open failed: " << file;
+#if !defined(_WIN32)
+bool FsyncDirectory(const char* dirname) {
+    android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname, O_RDONLY | O_CLOEXEC)));
+    if (fd == -1) {
+        PLOG(ERROR) << "Failed to open " << dirname;
         return false;
     }
-    return WriteToImageFile(fd, input);
+    if (fsync(fd) == -1) {
+        if (errno == EROFS || errno == EINVAL) {
+            PLOG(WARNING) << "Skip fsync " << dirname
+                          << " on a file system does not support synchronization";
+        } else {
+            PLOG(ERROR) << "Failed to fsync " << dirname;
+            return false;
+        }
+    }
+    return true;
+}
+#endif
+
+bool WriteToImageFile(const std::string& file, const LpMetadata& input) {
+    const auto parent_dir = base::Dirname(file);
+    TemporaryFile tmpfile(parent_dir);
+    if (!WriteToImageFile(tmpfile.fd, input)) {
+        PLOG(ERROR) << "Failed to write geometry data to tmpfile " << tmpfile.path;
+        return false;
+    }
+
+#if !defined(_WIN32)
+    fsync(tmpfile.fd);
+#endif
+    const auto err = rename(tmpfile.path, file.c_str());
+    if (err != 0) {
+        PLOG(ERROR) << "Failed to rename tmp geometry file " << tmpfile.path << " to " << file;
+        return false;
+    }
+#if !defined(_WIN32)
+    FsyncDirectory(parent_dir.c_str());
+#endif
+    return true;
 }
 
 ImageBuilder::ImageBuilder(const LpMetadata& metadata, uint32_t block_size,
@@ -208,7 +241,8 @@
         std::string file_name = "super_" + name + ".img";
         std::string file_path = output_dir + "/" + file_name;
 
-        static const int kOpenFlags = O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
+        static const int kOpenFlags =
+                O_CREAT | O_RDWR | O_TRUNC | O_CLOEXEC | O_NOFOLLOW | O_BINARY;
         unique_fd fd(open(file_path.c_str(), kOpenFlags, 0644));
         if (fd < 0) {
             PERROR << "open failed: " << file_path;
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
index f88406d..6a1dab8 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_core.h
@@ -43,7 +43,6 @@
 #include <libdm/dm.h>
 #include <libsnapshot/cow_reader.h>
 #include <libsnapshot/cow_writer.h>
-#include <liburing.h>
 #include <snapuserd/block_server.h>
 #include <snapuserd/snapuserd_buffer.h>
 #include <snapuserd/snapuserd_kernel.h>
@@ -247,7 +246,6 @@
     bool perform_verification_ = true;
     bool resume_merge_ = false;
 
-    std::unique_ptr<struct io_uring> ring_;
     std::unique_ptr<UpdateVerify> update_verify_;
     std::shared_ptr<IBlockServerOpener> block_server_opener_;
 };
diff --git a/init/persistent_properties.cpp b/init/persistent_properties.cpp
index 8db7267..8efb72c 100644
--- a/init/persistent_properties.cpp
+++ b/init/persistent_properties.cpp
@@ -46,13 +46,6 @@
 
 constexpr const char kLegacyPersistentPropertyDir[] = "/data/property";
 
-void AddPersistentProperty(const std::string& name, const std::string& value,
-                           PersistentProperties* persistent_properties) {
-    auto persistent_property_record = persistent_properties->add_properties();
-    persistent_property_record->set_name(name);
-    persistent_property_record->set_value(value);
-}
-
 Result<PersistentProperties> LoadLegacyPersistentProperties() {
     std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(kLegacyPersistentPropertyDir), closedir);
     if (!dir) {
@@ -161,9 +154,9 @@
         return Error() << "Unable to parse persistent property file: Could not parse protobuf";
     }
     for (auto& prop : persistent_properties.properties()) {
-        if (!StartsWith(prop.name(), "persist.")) {
+        if (!StartsWith(prop.name(), "persist.") && !StartsWith(prop.name(), "next_boot.")) {
             return Error() << "Unable to load persistent property file: property '" << prop.name()
-                           << "' doesn't start with 'persist.'";
+                           << "' doesn't start with 'persist.' or 'next_boot.'";
         }
     }
     return persistent_properties;
@@ -171,6 +164,13 @@
 
 }  // namespace
 
+void AddPersistentProperty(const std::string& name, const std::string& value,
+                           PersistentProperties* persistent_properties) {
+    auto persistent_property_record = persistent_properties->add_properties();
+    persistent_property_record->set_name(name);
+    persistent_property_record->set_value(value);
+}
+
 Result<PersistentProperties> LoadPersistentPropertyFile() {
     auto file_contents = ReadPersistentPropertyFile();
     if (!file_contents.ok()) return file_contents.error();
diff --git a/init/persistent_properties.h b/init/persistent_properties.h
index 3845a0d..a6f80e6 100644
--- a/init/persistent_properties.h
+++ b/init/persistent_properties.h
@@ -25,6 +25,8 @@
 namespace android {
 namespace init {
 
+void AddPersistentProperty(const std::string& name, const std::string& value,
+                           PersistentProperties* persistent_properties);
 PersistentProperties LoadPersistentProperties();
 void WritePersistentProperty(const std::string& name, const std::string& value);
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index cdd0afe..38cbea3 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -412,9 +412,8 @@
         }
     }
 
-    // Don't write properties to disk until after we have read all default
-    // properties to prevent them from being overwritten by default values.
-    if (socket && persistent_properties_loaded && StartsWith(name, "persist.")) {
+    bool need_persist = StartsWith(name, "persist.") || StartsWith(name, "next_boot.");
+    if (socket && persistent_properties_loaded && need_persist) {
         if (persist_write_thread) {
             persist_write_thread->Write(name, value, std::move(*socket));
             return {};
@@ -1398,11 +1397,43 @@
         case InitMessage::kLoadPersistentProperties: {
             load_override_properties();
             // Read persistent properties after all default values have been loaded.
+            // Apply staged and persistent properties
+            bool has_staged_prop = false;
+            auto const staged_prefix = std::string_view("next_boot.");
+            auto const staged_persist_prefix = std::string_view("next_boot.persist.");
+            auto persist_props_map = std::unordered_map<std::string, std::string>();
+
             auto persistent_properties = LoadPersistentProperties();
-            for (const auto& persistent_property_record : persistent_properties.properties()) {
-                InitPropertySet(persistent_property_record.name(),
-                                persistent_property_record.value());
+            for (const auto& property_record : persistent_properties.properties()) {
+                auto const& prop_name = property_record.name();
+                auto const& prop_value = property_record.value();
+
+                if (StartsWith(prop_name, staged_prefix)) {
+                  has_staged_prop = true;
+                  auto actual_prop_name = prop_name.substr(staged_prefix.size());
+                  InitPropertySet(actual_prop_name, prop_value);
+                  if (StartsWith(prop_name, staged_persist_prefix)) {
+                    persist_props_map[actual_prop_name] = prop_value;
+                  }
+                } else if (!persist_props_map.count(prop_name)) {
+                  InitPropertySet(prop_name, prop_value);
+                }
             }
+
+            // Update persist prop file if there are staged props
+            if (has_staged_prop) {
+                PersistentProperties updated_persist_props;
+                for (auto const& [prop_name, prop_value] : persist_props_map) {
+                    AddPersistentProperty(prop_name, prop_value, &updated_persist_props);
+                }
+
+                // write current updated persist prop file
+                auto result = WritePersistentPropertyFile(updated_persist_props);
+                if (!result.ok()) {
+                    LOG(ERROR) << "Could not store persistent property: " << result.error();
+                }
+            }
+
             // Apply debug ramdisk special settings after persistent properties are loaded.
             if (android::base::GetBoolProperty("ro.force.debuggable", false)) {
                 // Always enable usb adb if device is booted with debug ramdisk.
diff --git a/trusty/apploader/fuzz/app_fuzzer.cpp b/trusty/apploader/fuzz/app_fuzzer.cpp
index aa0caca..0a037f9 100644
--- a/trusty/apploader/fuzz/app_fuzzer.cpp
+++ b/trusty/apploader/fuzz/app_fuzzer.cpp
@@ -43,10 +43,6 @@
         {0xb5, 0xe8, 0xa7, 0xe9, 0xef, 0x17, 0x3a, 0x97},
 };
 
-static inline uintptr_t RoundPageUp(uintptr_t val) {
-    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-}
-
 static bool SendLoadMsg(int chan, int dma_buf, size_t dma_buf_size) {
     apploader_header hdr = {
             .cmd = APPLOADER_CMD_LOAD_APPLICATION,
@@ -107,7 +103,7 @@
         android::trusty::fuzz::Abort();
     }
 
-    uint64_t shm_len = size ? RoundPageUp(size) : PAGE_SIZE;
+    uint64_t shm_len = size ? size : 4096;
     BufferAllocator alloc;
     unique_fd dma_buf(alloc.Alloc(kDmabufSystemHeapName, shm_len));
     if (dma_buf < 0) {
diff --git a/trusty/confirmationui/TrustyApp.cpp b/trusty/confirmationui/TrustyApp.cpp
index cee8655..2356eef 100644
--- a/trusty/confirmationui/TrustyApp.cpp
+++ b/trusty/confirmationui/TrustyApp.cpp
@@ -30,10 +30,6 @@
 
 using ::android::base::unique_fd;
 
-static inline uintptr_t RoundPageUp(uintptr_t val) {
-    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-}
-
 ssize_t TrustyApp::TrustyRpc(const uint8_t* obegin, const uint8_t* oend, uint8_t* ibegin,
                              uint8_t* iend) {
     uint32_t olen = oend - obegin;
@@ -99,7 +95,7 @@
         return;
     }
 
-    uint32_t shm_len = RoundPageUp(CONFIRMATIONUI_MAX_MSG_SIZE);
+    uint32_t shm_len = CONFIRMATIONUI_MAX_MSG_SIZE;
     BufferAllocator allocator;
     unique_fd dma_buf(allocator.Alloc("system", shm_len));
     if (dma_buf < 0) {
diff --git a/trusty/coverage/coverage.cpp b/trusty/coverage/coverage.cpp
index 3c6b5c5..8fc2f5c 100644
--- a/trusty/coverage/coverage.cpp
+++ b/trusty/coverage/coverage.cpp
@@ -43,10 +43,6 @@
 using std::to_string;
 using std::unique_ptr;
 
-static inline uintptr_t RoundPageUp(uintptr_t val) {
-    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-}
-
 CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
     : tipc_dev_(std::move(tipc_dev)),
       coverage_srv_fd_(-1),
@@ -136,7 +132,7 @@
         return Error() << "failed to open coverage client: " << ret.error();
     }
     record_len_ = resp.open_args.record_len;
-    shm_len_ = RoundPageUp(record_len_);
+    shm_len_ = record_len_;
 
     BufferAllocator allocator;
 
diff --git a/trusty/fuzz/include/trusty/fuzz/utils.h b/trusty/fuzz/include/trusty/fuzz/utils.h
index c906412..cf4962e 100644
--- a/trusty/fuzz/include/trusty/fuzz/utils.h
+++ b/trusty/fuzz/include/trusty/fuzz/utils.h
@@ -21,7 +21,7 @@
 #include <android-base/result.h>
 #include <android-base/unique_fd.h>
 
-#define TIPC_MAX_MSG_SIZE PAGE_SIZE
+#define TIPC_MAX_MSG_SIZE 4096
 
 namespace android {
 namespace trusty {
diff --git a/trusty/keymaster/include/trusty_keymaster/ipc/trusty_keymaster_ipc.h b/trusty/keymaster/include/trusty_keymaster/ipc/trusty_keymaster_ipc.h
index 16207e6..efad254 100644
--- a/trusty/keymaster/include/trusty_keymaster/ipc/trusty_keymaster_ipc.h
+++ b/trusty/keymaster/include/trusty_keymaster/ipc/trusty_keymaster_ipc.h
@@ -22,9 +22,9 @@
 
 __BEGIN_DECLS
 
-const uint32_t TRUSTY_KEYMASTER_RECV_BUF_SIZE = 2 * PAGE_SIZE;
+const uint32_t TRUSTY_KEYMASTER_RECV_BUF_SIZE = 2 * 4096;
 const uint32_t TRUSTY_KEYMASTER_SEND_BUF_SIZE =
-        (PAGE_SIZE - sizeof(struct keymaster_message) - 16 /* tipc header */);
+        (4096 - sizeof(struct keymaster_message) - 16 /* tipc header */);
 
 int trusty_keymaster_connect(void);
 int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
diff --git a/trusty/libtrusty/tipc-test/tipc_test.c b/trusty/libtrusty/tipc-test/tipc_test.c
index 81c9881..0f50787 100644
--- a/trusty/libtrusty/tipc-test/tipc_test.c
+++ b/trusty/libtrusty/tipc-test/tipc_test.c
@@ -44,6 +44,7 @@
 static const char *closer3_name = "com.android.ipc-unittest.srv.closer3";
 static const char *main_ctrl_name = "com.android.ipc-unittest.ctrl";
 static const char* receiver_name = "com.android.trusty.memref.receiver";
+static const size_t memref_chunk_size = 4096;
 
 static const char* _sopts = "hsvDS:t:r:m:b:";
 /* clang-format off */
@@ -878,7 +879,7 @@
     volatile char* buf = MAP_FAILED;
     BufferAllocator* allocator = NULL;
 
-    const size_t num_pages = 10;
+    const size_t num_chunks = 10;
 
     fd = tipc_connect(dev_name, receiver_name);
     if (fd < 0) {
@@ -894,7 +895,7 @@
         goto cleanup;
     }
 
-    size_t buf_size = PAGE_SIZE * num_pages;
+    size_t buf_size = memref_chunk_size * num_chunks;
     dma_buf = DmabufHeapAlloc(allocator, "system", buf_size, 0, 0 /* legacy align */);
     if (dma_buf < 0) {
         ret = dma_buf;
@@ -927,13 +928,17 @@
     tipc_close(fd);
 
     ret = 0;
-    for (size_t skip = 0; skip < num_pages; skip++) {
-        ret |= strcmp("Hello from Trusty!", (const char*)&buf[skip * PAGE_SIZE]) ? (-1) : 0;
+    for (size_t skip = 0; skip < num_chunks; skip++) {
+        int cmp = strcmp("Hello from Trusty!",
+                         (const char*)&buf[skip * memref_chunk_size]) ? (-1) : 0;
+        if (cmp)
+            fprintf(stderr, "Failed: Unexpected content at page %zu in dmabuf\n", skip);
+        ret |= cmp;
     }
 
 cleanup:
     if (buf != MAP_FAILED) {
-        munmap((char*)buf, PAGE_SIZE);
+        munmap((char*)buf, buf_size);
     }
     close(dma_buf);
     if (allocator) {
diff --git a/trusty/line-coverage/coverage.cpp b/trusty/line-coverage/coverage.cpp
index 57b7025..5f7b3a3 100644
--- a/trusty/line-coverage/coverage.cpp
+++ b/trusty/line-coverage/coverage.cpp
@@ -50,10 +50,6 @@
 using ::android::base::Error;
 using ::std::string;
 
-static inline uintptr_t RoundPageUp(uintptr_t val) {
-    return (val + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-}
-
 CoverageRecord::CoverageRecord(string tipc_dev, struct uuid* uuid)
     : tipc_dev_(std::move(tipc_dev)),
       coverage_srv_fd_(-1),
@@ -129,7 +125,7 @@
         return Error() << "failed to open coverage client: " << ret.error();
     }
     record_len_ = resp.open_args.record_len;
-    shm_len_ = RoundPageUp(record_len_);
+    shm_len_ = record_len_;
 
     BufferAllocator allocator;
 
diff --git a/trusty/utils/acvp/trusty_modulewrapper.cpp b/trusty/utils/acvp/trusty_modulewrapper.cpp
index 85b7159..817b600 100644
--- a/trusty/utils/acvp/trusty_modulewrapper.cpp
+++ b/trusty/utils/acvp/trusty_modulewrapper.cpp
@@ -31,6 +31,7 @@
 #include <sys/mman.h>
 #include <trusty/tipc.h>
 #include <unistd.h>
+#include <algorithm>
 
 #include "acvp_ipc.h"
 
@@ -42,9 +43,6 @@
 using android::base::unique_fd;
 using android::base::WriteFully;
 
-static inline size_t AlignUpToPage(size_t size) {
-    return (size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-}
 
 namespace {
 
@@ -104,15 +102,12 @@
     struct acvp_req request;
     request.num_args = args.size();
 
-    size_t total_args_size = 0;
+    int total_args_size = 0;
     for (auto arg : args) {
         total_args_size += arg.size();
     }
 
-    shm_size_ = ACVP_MIN_SHARED_MEMORY;
-    if (total_args_size > shm_size_) {
-        shm_size_ = AlignUpToPage(total_args_size);
-    }
+    shm_size_ = std::max(ACVP_MIN_SHARED_MEMORY, total_args_size);
     request.buffer_size = shm_size_;
 
     struct iovec iov = {