Merge "compare android::Vector and std::vector"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 7dff1b8..ba6df7a 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -337,9 +337,12 @@
             case ADB_AUTH_SIGNATURE: {
                 // TODO: Switch to string_view.
                 std::string signature(p->payload.begin(), p->payload.end());
-                if (adbd_auth_verify(t->token, sizeof(t->token), signature)) {
+                std::string auth_key;
+                if (adbd_auth_verify(t->token, sizeof(t->token), signature, &auth_key)) {
                     adbd_auth_verified(t);
                     t->failed_auth_attempts = 0;
+                    t->auth_key = auth_key;
+                    adbd_notify_framework_connected_key(t);
                 } else {
                     if (t->failed_auth_attempts++ > 256) std::this_thread::sleep_for(1s);
                     send_auth_request(t);
@@ -348,7 +351,8 @@
             }
 
             case ADB_AUTH_RSAPUBLICKEY:
-                adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
+                t->auth_key = std::string(p->payload.data());
+                adbd_auth_confirm_key(t);
                 break;
 #endif
             default:
diff --git a/adb/adb.h b/adb/adb.h
index 352b2fe..c6cb06a 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -33,6 +33,7 @@
 
 constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024;
 constexpr size_t MAX_PAYLOAD = 1024 * 1024;
+constexpr size_t MAX_FRAMEWORK_PAYLOAD = 64 * 1024;
 
 constexpr size_t LINUX_MAX_SOCKET_SIZE = 4194304;
 
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 2fc8478..2be9a76 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -50,8 +50,10 @@
 void adbd_auth_verified(atransport *t);
 
 void adbd_cloexec_auth_socket();
-bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig);
-void adbd_auth_confirm_key(const char* data, size_t len, atransport* t);
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
+                      std::string* auth_key);
+void adbd_auth_confirm_key(atransport* t);
+void adbd_notify_framework_connected_key(atransport* t);
 
 void send_auth_request(atransport *t);
 
diff --git a/adb/daemon/auth.cpp b/adb/daemon/auth.cpp
index 2b8f461..7a3a4f5 100644
--- a/adb/daemon/auth.cpp
+++ b/adb/daemon/auth.cpp
@@ -26,7 +26,9 @@
 #include <resolv.h>
 #include <stdio.h>
 #include <string.h>
+#include <iomanip>
 
+#include <algorithm>
 #include <memory>
 
 #include <android-base/file.h>
@@ -38,22 +40,24 @@
 
 static fdevent* listener_fde = nullptr;
 static fdevent* framework_fde = nullptr;
-static int framework_fd = -1;
+static auto& framework_mutex = *new std::mutex();
+static int framework_fd GUARDED_BY(framework_mutex) = -1;
+static auto& connected_keys GUARDED_BY(framework_mutex) = *new std::vector<std::string>;
 
-static void usb_disconnected(void* unused, atransport* t);
-static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
-static atransport* usb_transport;
+static void adb_disconnected(void* unused, atransport* t);
+static struct adisconnect adb_disconnect = {adb_disconnected, nullptr};
+static atransport* adb_transport;
 static bool needs_retry = false;
 
 bool auth_required = true;
 
-bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) {
+bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig,
+                      std::string* auth_key) {
     static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
 
     for (const auto& path : key_paths) {
         if (access(path, R_OK) == 0) {
             LOG(INFO) << "Loading keys from " << path;
-
             std::string content;
             if (!android::base::ReadFileToString(path, &content)) {
                 PLOG(ERROR) << "Couldn't read " << path;
@@ -61,6 +65,8 @@
             }
 
             for (const auto& line : android::base::Split(content, "\n")) {
+                if (line.empty()) continue;
+                *auth_key = line;
                 // TODO: do we really have to support both ' ' and '\t'?
                 char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
                 if (sep) *sep = '\0';
@@ -88,9 +94,31 @@
             }
         }
     }
+    auth_key->clear();
     return false;
 }
 
+static bool adbd_send_key_message_locked(std::string_view msg_type, std::string_view key)
+        REQUIRES(framework_mutex) {
+    if (framework_fd < 0) {
+        LOG(ERROR) << "Client not connected to send msg_type " << msg_type;
+        return false;
+    }
+    std::string msg = std::string(msg_type) + std::string(key);
+    int msg_len = msg.length();
+    if (msg_len >= static_cast<int>(MAX_FRAMEWORK_PAYLOAD)) {
+        LOG(ERROR) << "Key too long (" << msg_len << ")";
+        return false;
+    }
+
+    LOG(DEBUG) << "Sending '" << msg << "'";
+    if (!WriteFdExactly(framework_fd, msg.c_str(), msg_len)) {
+        PLOG(ERROR) << "Failed to write " << msg_type;
+        return false;
+    }
+    return true;
+}
+
 static bool adbd_auth_generate_token(void* token, size_t token_size) {
     FILE* fp = fopen("/dev/urandom", "re");
     if (!fp) return false;
@@ -99,17 +127,28 @@
     return okay;
 }
 
-static void usb_disconnected(void* unused, atransport* t) {
-    LOG(INFO) << "USB disconnect";
-    usb_transport = nullptr;
+static void adb_disconnected(void* unused, atransport* t) {
+    LOG(INFO) << "ADB disconnect";
+    adb_transport = nullptr;
     needs_retry = false;
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd >= 0) {
+            adbd_send_key_message_locked("DC", t->auth_key);
+        }
+        connected_keys.erase(std::remove(connected_keys.begin(), connected_keys.end(), t->auth_key),
+                             connected_keys.end());
+    }
 }
 
 static void framework_disconnected() {
     LOG(INFO) << "Framework disconnect";
     if (framework_fde) {
         fdevent_destroy(framework_fde);
-        framework_fd = -1;
+        {
+            std::lock_guard<std::mutex> lock(framework_mutex);
+            framework_fd = -1;
+        }
     }
 }
 
@@ -120,41 +159,28 @@
         if (ret <= 0) {
             framework_disconnected();
         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
-            if (usb_transport) {
-                adbd_auth_verified(usb_transport);
+            if (adb_transport) {
+                adbd_auth_verified(adb_transport);
             }
         }
     }
 }
 
-void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) {
-    if (!usb_transport) {
-        usb_transport = t;
-        t->AddDisconnect(&usb_disconnect);
+void adbd_auth_confirm_key(atransport* t) {
+    if (!adb_transport) {
+        adb_transport = t;
+        t->AddDisconnect(&adb_disconnect);
     }
 
-    if (framework_fd < 0) {
-        LOG(ERROR) << "Client not connected";
-        needs_retry = true;
-        return;
-    }
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd < 0) {
+            LOG(ERROR) << "Client not connected";
+            needs_retry = true;
+            return;
+        }
 
-    if (key[len - 1] != '\0') {
-        LOG(ERROR) << "Key must be a null-terminated string";
-        return;
-    }
-
-    char msg[MAX_PAYLOAD_V1];
-    int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
-    if (msg_len >= static_cast<int>(sizeof(msg))) {
-        LOG(ERROR) << "Key too long (" << msg_len << ")";
-        return;
-    }
-    LOG(DEBUG) << "Sending '" << msg << "'";
-
-    if (unix_write(framework_fd, msg, msg_len) == -1) {
-        PLOG(ERROR) << "Failed to write PK";
-        return;
+        adbd_send_key_message_locked("PK", t->auth_key);
     }
 }
 
@@ -165,18 +191,46 @@
         return;
     }
 
-    if (framework_fd >= 0) {
-        LOG(WARNING) << "adb received framework auth socket connection again";
-        framework_disconnected();
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (framework_fd >= 0) {
+            LOG(WARNING) << "adb received framework auth socket connection again";
+            framework_disconnected();
+        }
+
+        framework_fd = s;
+        framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
+        fdevent_add(framework_fde, FDE_READ);
+
+        if (needs_retry) {
+            needs_retry = false;
+            send_auth_request(adb_transport);
+        }
+
+        // if a client connected before the framework was available notify the framework of the
+        // connected key now.
+        if (!connected_keys.empty()) {
+            for (const auto& key : connected_keys) {
+                adbd_send_key_message_locked("CK", key);
+            }
+        }
     }
+}
 
-    framework_fd = s;
-    framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
-    fdevent_add(framework_fde, FDE_READ);
-
-    if (needs_retry) {
-        needs_retry = false;
-        send_auth_request(usb_transport);
+void adbd_notify_framework_connected_key(atransport* t) {
+    if (!adb_transport) {
+        adb_transport = t;
+        t->AddDisconnect(&adb_disconnect);
+    }
+    {
+        std::lock_guard<std::mutex> lock(framework_mutex);
+        if (std::find(connected_keys.begin(), connected_keys.end(), t->auth_key) ==
+            connected_keys.end()) {
+            connected_keys.push_back(t->auth_key);
+        }
+        if (framework_fd >= 0) {
+            adbd_send_key_message_locked("CK", t->auth_key);
+        }
     }
 }
 
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index f4aa9fb..1abae87 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -509,16 +509,14 @@
             }
 
             if (id.direction == TransferDirection::READ) {
-                if (!HandleRead(id, event.res)) {
-                    return;
-                }
+                HandleRead(id, event.res);
             } else {
                 HandleWrite(id);
             }
         }
     }
 
-    bool HandleRead(TransferId id, int64_t size) {
+    void HandleRead(TransferId id, int64_t size) {
         uint64_t read_idx = id.id % kUsbReadQueueDepth;
         IoBlock* block = &read_requests_[read_idx];
         block->pending = false;
@@ -528,7 +526,7 @@
         if (block->id().id != needed_read_id_) {
             LOG(VERBOSE) << "read " << block->id().id << " completed while waiting for "
                          << needed_read_id_;
-            return true;
+            return;
         }
 
         for (uint64_t id = needed_read_id_;; ++id) {
@@ -537,22 +535,15 @@
             if (current_block->pending) {
                 break;
             }
-            if (!ProcessRead(current_block)) {
-                return false;
-            }
+            ProcessRead(current_block);
             ++needed_read_id_;
         }
-
-        return true;
     }
 
-    bool ProcessRead(IoBlock* block) {
+    void ProcessRead(IoBlock* block) {
         if (!block->payload->empty()) {
             if (!incoming_header_.has_value()) {
-                if (block->payload->size() != sizeof(amessage)) {
-                    HandleError("received packet of unexpected length while reading header");
-                    return false;
-                }
+                CHECK_EQ(sizeof(amessage), block->payload->size());
                 amessage msg;
                 memcpy(&msg, block->payload->data(), sizeof(amessage));
                 LOG(DEBUG) << "USB read:" << dump_header(&msg);
@@ -560,10 +551,7 @@
             } else {
                 size_t bytes_left = incoming_header_->data_length - incoming_payload_.size();
                 Block payload = std::move(*block->payload);
-                if (block->payload->size() > bytes_left) {
-                    HandleError("received too many bytes while waiting for payload");
-                    return false;
-                }
+                CHECK_LE(payload.size(), bytes_left);
                 incoming_payload_.append(std::make_unique<Block>(std::move(payload)));
             }
 
@@ -582,7 +570,6 @@
 
         PrepareReadBlock(block, block->id().id + kUsbReadQueueDepth);
         SubmitRead(block);
-        return true;
     }
 
     bool SubmitRead(IoBlock* block) {
diff --git a/adb/transport.h b/adb/transport.h
index 245037e..61a3d9a 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -275,6 +275,9 @@
     std::string device;
     std::string devpath;
 
+    // Used to provide the key to the framework.
+    std::string auth_key;
+
     bool IsTcpDevice() const { return type == kTransportLocal; }
 
 #if ADB_HOST
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 6e11b4e..1605daf 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -120,7 +120,7 @@
   // Catch bogus error checks (i.e.: "!fd" instead of "fd != -1").
   bool operator!() const = delete;
 
-  bool ok() const { return get() != -1; }
+  bool ok() const { return get() >= 0; }
 
   int release() __attribute__((warn_unused_result)) {
     tag(fd_, this, nullptr);
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index cd9fda3..dd24aac 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -1093,8 +1093,8 @@
 void LogBootInfoToStatsd(std::chrono::milliseconds end_time,
                          std::chrono::milliseconds total_duration, int32_t bootloader_duration_ms,
                          double time_since_last_boot_sec) {
-  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "<EMPTY>");
-  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "<EMPTY>");
+  auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "<EMPTY>");
+  auto system_reason = android::base::GetProperty(system_reboot_reason_property, "<EMPTY>");
   android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, reason.c_str(),
                              system_reason.c_str(), end_time.count(), total_duration.count(),
                              (int64_t)bootloader_duration_ms,
diff --git a/fs_mgr/liblp/builder.cpp b/fs_mgr/liblp/builder.cpp
index f8c492d..c5d6a3b 100644
--- a/fs_mgr/liblp/builder.cpp
+++ b/fs_mgr/liblp/builder.cpp
@@ -579,12 +579,38 @@
     return true;
 }
 
-bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size) {
+Interval Interval::Intersect(const Interval& a, const Interval& b) {
+    Interval ret = a;
+    if (a.device_index != b.device_index) {
+        ret.start = ret.end = a.start;  // set length to 0 to indicate no intersection.
+        return ret;
+    }
+    ret.start = std::max(a.start, b.start);
+    ret.end = std::max(ret.start, std::min(a.end, b.end));
+    return ret;
+}
+
+std::vector<Interval> Interval::Intersect(const std::vector<Interval>& a,
+                                          const std::vector<Interval>& b) {
+    std::vector<Interval> ret;
+    for (const Interval& a_interval : a) {
+        for (const Interval& b_interval : b) {
+            auto intersect = Intersect(a_interval, b_interval);
+            if (intersect.length() > 0) ret.emplace_back(std::move(intersect));
+        }
+    }
+    return ret;
+}
+
+bool MetadataBuilder::GrowPartition(Partition* partition, uint64_t aligned_size,
+                                    const std::vector<Interval>& free_region_hint) {
     uint64_t space_needed = aligned_size - partition->size();
     uint64_t sectors_needed = space_needed / LP_SECTOR_SIZE;
     DCHECK(sectors_needed * LP_SECTOR_SIZE == space_needed);
 
     std::vector<Interval> free_regions = GetFreeRegions();
+    if (!free_region_hint.empty())
+        free_regions = Interval::Intersect(free_regions, free_region_hint);
 
     const uint64_t sectors_per_block = geometry_.logical_block_size / LP_SECTOR_SIZE;
     CHECK_NE(sectors_per_block, 0);
@@ -650,7 +676,7 @@
     return true;
 }
 
-std::vector<MetadataBuilder::Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
+std::vector<Interval> MetadataBuilder::PrioritizeSecondHalfOfSuper(
         const std::vector<Interval>& free_list) {
     const auto& super = block_devices_[0];
     uint64_t first_sector = super.first_logical_sector;
@@ -926,7 +952,8 @@
     return true;
 }
 
-bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size) {
+bool MetadataBuilder::ResizePartition(Partition* partition, uint64_t requested_size,
+                                      const std::vector<Interval>& free_region_hint) {
     // Align the space needed up to the nearest sector.
     uint64_t aligned_size = AlignTo(requested_size, geometry_.logical_block_size);
     uint64_t old_size = partition->size();
@@ -936,7 +963,7 @@
     }
 
     if (aligned_size > old_size) {
-        if (!GrowPartition(partition, aligned_size)) {
+        if (!GrowPartition(partition, aligned_size, free_region_hint)) {
             return false;
         }
     } else if (aligned_size < partition->size()) {
diff --git a/fs_mgr/liblp/builder_test.cpp b/fs_mgr/liblp/builder_test.cpp
index c5b4047..bd41f59 100644
--- a/fs_mgr/liblp/builder_test.cpp
+++ b/fs_mgr/liblp/builder_test.cpp
@@ -887,3 +887,38 @@
     std::set<std::string> partitions_to_keep{"system_a", "vendor_a", "product_a"};
     ASSERT_TRUE(builder->ImportPartitions(*on_disk.get(), partitions_to_keep));
 }
+
+// Interval has operator< defined; it is not appropriate to re-define Interval::operator== that
+// compares device index.
+namespace android {
+namespace fs_mgr {
+bool operator==(const Interval& a, const Interval& b) {
+    return a.device_index == b.device_index && a.start == b.start && a.end == b.end;
+}
+}  // namespace fs_mgr
+}  // namespace android
+
+TEST_F(BuilderTest, Interval) {
+    EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 100)).length());
+    EXPECT_EQ(Interval(0, 100, 150),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 150)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 200)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 50, 250)));
+    EXPECT_EQ(Interval(0, 100, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 100, 200)));
+    EXPECT_EQ(Interval(0, 150, 200),
+              Interval::Intersect(Interval(0, 100, 200), Interval(0, 150, 250)));
+    EXPECT_EQ(0u, Interval::Intersect(Interval(0, 100, 200), Interval(0, 200, 250)).length());
+
+    auto v = Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50), Interval(0, 100, 150)},
+                                 std::vector<Interval>{Interval(0, 25, 125)});
+    ASSERT_EQ(2, v.size());
+    EXPECT_EQ(Interval(0, 25, 50), v[0]);
+    EXPECT_EQ(Interval(0, 100, 125), v[1]);
+
+    EXPECT_EQ(0u, Interval::Intersect(std::vector<Interval>{Interval(0, 0, 50)},
+                                      std::vector<Interval>{Interval(0, 100, 150)})
+                          .size());
+}
diff --git a/fs_mgr/liblp/include/liblp/builder.h b/fs_mgr/liblp/include/liblp/builder.h
index 5ab42f5..6f2ab75 100644
--- a/fs_mgr/liblp/include/liblp/builder.h
+++ b/fs_mgr/liblp/include/liblp/builder.h
@@ -138,6 +138,33 @@
     uint64_t size_;
 };
 
+// An interval in the metadata. This is similar to a LinearExtent with one difference.
+// LinearExtent represents a "used" region in the metadata, while Interval can also represent
+// an "unused" region.
+struct Interval {
+    uint32_t device_index;
+    uint64_t start;
+    uint64_t end;
+
+    Interval(uint32_t device_index, uint64_t start, uint64_t end)
+        : device_index(device_index), start(start), end(end) {}
+    uint64_t length() const { return end - start; }
+
+    // Note: the device index is not included in sorting (intervals are
+    // sorted in per-device lists).
+    bool operator<(const Interval& other) const {
+        return (start == other.start) ? end < other.end : start < other.start;
+    }
+
+    // Intersect |a| with |b|.
+    // If no intersection, result has 0 length().
+    static Interval Intersect(const Interval& a, const Interval& b);
+
+    // Intersect two lists of intervals, and store result to |a|.
+    static std::vector<Interval> Intersect(const std::vector<Interval>& a,
+                                           const std::vector<Interval>& b);
+};
+
 class MetadataBuilder {
   public:
     // Construct an empty logical partition table builder given the specified
@@ -244,7 +271,11 @@
     //
     // Note, this is an in-memory operation, and it does not alter the
     // underlying filesystem or contents of the partition on disk.
-    bool ResizePartition(Partition* partition, uint64_t requested_size);
+    //
+    // If |free_region_hint| is not empty, it will only try to allocate extents
+    // in regions within the list.
+    bool ResizePartition(Partition* partition, uint64_t requested_size,
+                         const std::vector<Interval>& free_region_hint = {});
 
     // Return the list of partitions belonging to a group.
     std::vector<Partition*> ListPartitionsInGroup(const std::string& group_name);
@@ -291,6 +322,9 @@
     // Return the name of the block device at |index|.
     std::string GetBlockDevicePartitionName(uint64_t index) const;
 
+    // Return the list of free regions not occupied by extents in the metadata.
+    std::vector<Interval> GetFreeRegions() const;
+
   private:
     MetadataBuilder();
     MetadataBuilder(const MetadataBuilder&) = delete;
@@ -300,7 +334,8 @@
     bool Init(const std::vector<BlockDeviceInfo>& block_devices, const std::string& super_partition,
               uint32_t metadata_max_size, uint32_t metadata_slot_count);
     bool Init(const LpMetadata& metadata);
-    bool GrowPartition(Partition* partition, uint64_t aligned_size);
+    bool GrowPartition(Partition* partition, uint64_t aligned_size,
+                       const std::vector<Interval>& free_region_hint);
     void ShrinkPartition(Partition* partition, uint64_t aligned_size);
     uint64_t AlignSector(const LpMetadataBlockDevice& device, uint64_t sector) const;
     uint64_t TotalSizeOfGroup(PartitionGroup* group) const;
@@ -323,22 +358,6 @@
 
     bool ValidatePartitionGroups() const;
 
-    struct Interval {
-        uint32_t device_index;
-        uint64_t start;
-        uint64_t end;
-
-        Interval(uint32_t device_index, uint64_t start, uint64_t end)
-            : device_index(device_index), start(start), end(end) {}
-        uint64_t length() const { return end - start; }
-
-        // Note: the device index is not included in sorting (intervals are
-        // sorted in per-device lists).
-        bool operator<(const Interval& other) const {
-            return (start == other.start) ? end < other.end : start < other.start;
-        }
-    };
-    std::vector<Interval> GetFreeRegions() const;
     bool IsAnyRegionCovered(const std::vector<Interval>& regions,
                             const LinearExtent& candidate) const;
     bool IsAnyRegionAllocated(const LinearExtent& candidate) const;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 1f3828e..6f0e804 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -329,6 +329,10 @@
     std::string GetSnapshotDeviceName(const std::string& snapshot_name,
                                       const SnapshotStatus& status);
 
+    // Map the base device, COW devices, and snapshot device.
+    bool MapPartitionWithSnapshot(LockedFile* lock, CreateLogicalPartitionParams params,
+                                  std::string* path);
+
     std::string gsid_dir_;
     std::string metadata_dir_;
     std::unique_ptr<IDeviceInfo> device_;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 7f37dc5..7e57421 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -19,6 +19,7 @@
 #include <sys/types.h>
 #include <sys/unistd.h>
 
+#include <optional>
 #include <thread>
 #include <unordered_set>
 
@@ -152,7 +153,13 @@
     auto lock = LockExclusive();
     if (!lock) return false;
 
-    if (ReadUpdateState(lock.get()) != UpdateState::Initiated) {
+    auto update_state = ReadUpdateState(lock.get());
+    if (update_state == UpdateState::Unverified) {
+        LOG(INFO) << "FinishedSnapshotWrites already called before. Ignored.";
+        return true;
+    }
+
+    if (update_state != UpdateState::Initiated) {
         LOG(ERROR) << "Can only transition to the Unverified state from the Initiated state.";
         return false;
     }
@@ -211,8 +218,27 @@
     }
 
     auto cow_name = GetCowName(name);
-    int cow_flags = IImageManager::CREATE_IMAGE_ZERO_FILL;
-    return images_->CreateBackingImage(cow_name, cow_size, cow_flags);
+    int cow_flags = IImageManager::CREATE_IMAGE_DEFAULT;
+    if (!images_->CreateBackingImage(cow_name, cow_size, cow_flags)) {
+        return false;
+    }
+
+    // when the kernel creates a persistent dm-snapshot, it requires a CoW file
+    // to store the modifications. The kernel interface does not specify how
+    // the CoW is used, and there is no standard associated.
+    // By looking at the current implementation, the CoW file is treated as:
+    // - a _NEW_ snapshot if its first 32 bits are zero, so the newly created
+    // dm-snapshot device will look like a perfect copy of the origin device;
+    // - an _EXISTING_ snapshot if the first 32 bits are equal to a
+    // kernel-specified magic number and the CoW file metadata is set as valid,
+    // so it can be used to resume the last state of a snapshot device;
+    // - an _INVALID_ snapshot otherwise.
+    // To avoid zero-filling the whole CoW file when a new dm-snapshot is
+    // created, here we zero-fill only the first 32 bits. This is a temporary
+    // workaround that will be discussed again when the kernel API gets
+    // consolidated.
+    ssize_t dm_snap_magic_size = 4;  // 32 bit
+    return images_->ZeroFillNewImage(cow_name, dm_snap_magic_size);
 }
 
 bool SnapshotManager::MapSnapshot(LockedFile* lock, const std::string& name,
@@ -947,7 +973,7 @@
     // flushed remaining I/O. We could in theory replace with dm-zero (or
     // re-use the table above), but for now it's better to know why this
     // would fail.
-    if (!dm.DeleteDeviceIfExists(dm_name)) {
+    if (dm_name != name && !dm.DeleteDeviceIfExists(dm_name)) {
         LOG(ERROR) << "Unable to delete snapshot device " << dm_name << ", COW cannot be "
                    << "reclaimed until after reboot.";
         return false;
@@ -1102,22 +1128,6 @@
     auto lock = LockExclusive();
     if (!lock) return false;
 
-    std::vector<std::string> snapshot_list;
-    if (!ListSnapshots(lock.get(), &snapshot_list)) {
-        return false;
-    }
-
-    std::unordered_set<std::string> live_snapshots;
-    for (const auto& snapshot : snapshot_list) {
-        SnapshotStatus status;
-        if (!ReadSnapshotStatus(lock.get(), snapshot, &status)) {
-            return false;
-        }
-        if (status.state != SnapshotState::MergeCompleted) {
-            live_snapshots.emplace(snapshot);
-        }
-    }
-
     const auto& opener = device_->GetPartitionOpener();
     uint32_t slot = SlotNumberForSlotSuffix(device_->GetSlotSuffix());
     auto metadata = android::fs_mgr::ReadMetadata(opener, super_device, slot);
@@ -1126,59 +1136,102 @@
         return false;
     }
 
-    // Map logical partitions.
-    auto& dm = DeviceMapper::Instance();
     for (const auto& partition : metadata->partitions) {
-        auto partition_name = GetPartitionName(partition);
-        if (!partition.num_extents) {
-            LOG(INFO) << "Skipping zero-length logical partition: " << partition_name;
-            continue;
-        }
-
-        if (!(partition.attributes & LP_PARTITION_ATTR_UPDATED)) {
-            LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
-                      << partition_name;
-            live_snapshots.erase(partition_name);
-        }
-
         CreateLogicalPartitionParams params = {
                 .block_device = super_device,
                 .metadata = metadata.get(),
                 .partition = &partition,
                 .partition_opener = &opener,
         };
-
-        if (auto iter = live_snapshots.find(partition_name); iter != live_snapshots.end()) {
-            // If the device has a snapshot, it'll need to be writable, and
-            // we'll need to create the logical partition with a marked-up name
-            // (since the snapshot will use the partition name).
-            params.force_writable = true;
-            params.device_name = GetBaseDeviceName(partition_name);
-        }
-
         std::string ignore_path;
-        if (!CreateLogicalPartition(params, &ignore_path)) {
-            LOG(ERROR) << "Could not create logical partition " << partition_name << " as device "
-                       << params.GetDeviceName();
-            return false;
-        }
-        if (!params.force_writable) {
-            // No snapshot.
-            continue;
-        }
-
-        // We don't have ueventd in first-stage init, so use device major:minor
-        // strings instead.
-        std::string base_device;
-        if (!dm.GetDeviceString(params.GetDeviceName(), &base_device)) {
-            LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
-            return false;
-        }
-        if (!MapSnapshot(lock.get(), partition_name, base_device, {}, &ignore_path)) {
-            LOG(ERROR) << "Could not map snapshot for partition: " << partition_name;
+        if (!MapPartitionWithSnapshot(lock.get(), std::move(params), &ignore_path)) {
             return false;
         }
     }
+
+    LOG(INFO) << "Created logical partitions with snapshot.";
+    return true;
+}
+
+bool SnapshotManager::MapPartitionWithSnapshot(LockedFile* lock,
+                                               CreateLogicalPartitionParams params,
+                                               std::string* path) {
+    CHECK(lock);
+    path->clear();
+
+    // Fill out fields in CreateLogicalPartitionParams so that we have more information (e.g. by
+    // reading super partition metadata).
+    CreateLogicalPartitionParams::OwnedData params_owned_data;
+    if (!params.InitDefaults(&params_owned_data)) {
+        return false;
+    }
+
+    if (!params.partition->num_extents) {
+        LOG(INFO) << "Skipping zero-length logical partition: " << params.GetPartitionName();
+        return true;  // leave path empty to indicate that nothing is mapped.
+    }
+
+    // Determine if there is a live snapshot for the SnapshotStatus of the partition; i.e. if the
+    // partition still has a snapshot that needs to be mapped.  If no live snapshot or merge
+    // completed, live_snapshot_status is set to nullopt.
+    std::optional<SnapshotStatus> live_snapshot_status;
+    do {
+        if (!(params.partition->attributes & LP_PARTITION_ATTR_UPDATED)) {
+            LOG(INFO) << "Detected re-flashing of partition, will skip snapshot: "
+                      << params.GetPartitionName();
+            break;
+        }
+        auto file_path = GetSnapshotStatusFilePath(params.GetPartitionName());
+        if (access(file_path.c_str(), F_OK) != 0) {
+            if (errno != ENOENT) {
+                PLOG(INFO) << "Can't map snapshot for " << params.GetPartitionName()
+                           << ": Can't access " << file_path;
+                return false;
+            }
+            break;
+        }
+        live_snapshot_status = std::make_optional<SnapshotStatus>();
+        if (!ReadSnapshotStatus(lock, params.GetPartitionName(), &*live_snapshot_status)) {
+            return false;
+        }
+        // No live snapshot if merge is completed.
+        if (live_snapshot_status->state == SnapshotState::MergeCompleted) {
+            live_snapshot_status.reset();
+        }
+    } while (0);
+
+    if (live_snapshot_status.has_value()) {
+        // dm-snapshot requires the base device to be writable.
+        params.force_writable = true;
+        // Map the base device with a different name to avoid collision.
+        params.device_name = GetBaseDeviceName(params.GetPartitionName());
+    }
+
+    auto& dm = DeviceMapper::Instance();
+    std::string ignore_path;
+    if (!CreateLogicalPartition(params, &ignore_path)) {
+        LOG(ERROR) << "Could not create logical partition " << params.GetPartitionName()
+                   << " as device " << params.GetDeviceName();
+        return false;
+    }
+    if (!live_snapshot_status.has_value()) {
+        return true;
+    }
+
+    // We don't have ueventd in first-stage init, so use device major:minor
+    // strings instead.
+    std::string base_device;
+    if (!dm.GetDeviceString(params.GetDeviceName(), &base_device)) {
+        LOG(ERROR) << "Could not determine major/minor for: " << params.GetDeviceName();
+        return false;
+    }
+    if (!MapSnapshot(lock, params.GetPartitionName(), base_device, {}, path)) {
+        LOG(ERROR) << "Could not map snapshot for partition: " << params.GetPartitionName();
+        return false;
+    }
+
+    LOG(INFO) << "Mapped " << params.GetPartitionName() << " as snapshot device at " << *path;
+
     return true;
 }
 
diff --git a/healthd/Android.mk b/healthd/Android.mk
index b87f3c7..4e34759 100644
--- a/healthd/Android.mk
+++ b/healthd/Android.mk
@@ -23,7 +23,6 @@
     libcharger_sysprop \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libminui \
     libvndksupport \
@@ -77,7 +76,6 @@
     libcharger_sysprop \
     libhidltransport \
     libhidlbase \
-    libhwbinder_noltopgo \
     libhealthstoragedefault \
     libvndksupport \
     libhealthd_charger_nops \
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 7c66de5..d2c73cb 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -80,6 +80,7 @@
 using namespace std::literals::string_literals;
 
 using android::base::Basename;
+using android::base::StringPrintf;
 using android::base::unique_fd;
 using android::fs_mgr::Fstab;
 using android::fs_mgr::ReadFstabFromFile;
@@ -1062,34 +1063,59 @@
     return android::base::GetProperty("ro.crypto.type", "") == "file";
 }
 
-static Result<void> ExecWithRebootOnFailure(const std::string& reboot_reason,
-                                            const BuiltinArguments& args) {
-    auto service = Service::MakeTemporaryOneshotService(args.args);
+static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& args,
+                                              std::function<void(const std::string&)> function) {
+    auto service = Service::MakeTemporaryOneshotService(args);
     if (!service) {
-        return Error() << "Could not create exec service: " << service.error();
+        function("MakeTemporaryOneshotService failed: " + service.error().message());
     }
-    (*service)->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
+    (*service)->AddReapCallback([function](const siginfo_t& siginfo) {
         if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
-            // TODO (b/122850122): support this in gsi
-            if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
-                LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
-                if (auto result = reboot_into_recovery(
-                            {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
-                    !result) {
-                    LOG(FATAL) << "Could not reboot into recovery: " << result.error();
-                }
-            } else {
-                LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
-            }
+            function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
         }
     });
     if (auto result = (*service)->ExecStart(); !result) {
-        return Error() << "Could not start exec service: " << result.error();
+        function("ExecStart failed: " + result.error().message());
     }
     ServiceList::GetInstance().AddService(std::move(*service));
     return {};
 }
 
+static Result<void> do_exec_reboot_on_failure(const BuiltinArguments& args) {
+    auto reboot_reason = args[1];
+    auto reboot = [reboot_reason](const std::string& message) {
+        property_set(LAST_REBOOT_REASON_PROPERTY, reboot_reason);
+        sync();
+        LOG(FATAL) << message << ": rebooting into bootloader, reason: " << reboot_reason;
+    };
+
+    std::vector<std::string> remaining_args(args.begin() + 1, args.end());
+    remaining_args[0] = args[0];
+
+    return ExecWithFunctionOnFailure(remaining_args, reboot);
+}
+
+static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) {
+    auto reboot_reason = vdc_arg + "_failed";
+
+    auto reboot = [reboot_reason](const std::string& message) {
+        // TODO (b/122850122): support this in gsi
+        if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
+            LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
+            if (auto result = reboot_into_recovery(
+                        {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
+                !result) {
+                LOG(FATAL) << "Could not reboot into recovery: " << result.error();
+            }
+        } else {
+            LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
+        }
+    };
+
+    std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg};
+    return ExecWithFunctionOnFailure(args, reboot);
+}
+
 static Result<void> do_installkey(const BuiltinArguments& args) {
     if (!is_file_crypto()) return {};
 
@@ -1097,15 +1123,11 @@
     if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
         return ErrnoError() << "Failed to create " << unencrypted_dir;
     }
-    return ExecWithRebootOnFailure(
-        "enablefilecrypto_failed",
-        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context});
+    return ExecVdcRebootOnFailure("enablefilecrypto");
 }
 
 static Result<void> do_init_user0(const BuiltinArguments& args) {
-    return ExecWithRebootOnFailure(
-        "init_user0_failed",
-        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
+    return ExecVdcRebootOnFailure("init_user0");
 }
 
 static Result<void> do_mark_post_data(const BuiltinArguments& args) {
@@ -1180,6 +1202,7 @@
         {"enable",                  {1,     1,    {false,  do_enable}}},
         {"exec",                    {1,     kMax, {false,  do_exec}}},
         {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
+        {"exec_reboot_on_failure",  {2,     kMax, {false,  do_exec_reboot_on_failure}}},
         {"exec_start",              {1,     1,    {false,  do_exec_start}}},
         {"export",                  {2,     2,    {false,  do_export}}},
         {"hostname",                {1,     1,    {true,   do_hostname}}},
diff --git a/init/check_builtins.cpp b/init/check_builtins.cpp
index 771f1d7..2efaeea 100644
--- a/init/check_builtins.cpp
+++ b/init/check_builtins.cpp
@@ -81,6 +81,15 @@
     return check_exec(std::move(args));
 }
 
+Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
+    BuiltinArguments remaining_args(args.context);
+
+    remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
+    remaining_args.args[0] = args[0];
+
+    return check_exec(remaining_args);
+}
+
 Result<void> check_interface_restart(const BuiltinArguments& args) {
     if (auto result = IsKnownInterface(args[1]); !result) {
         return result.error();
diff --git a/init/check_builtins.h b/init/check_builtins.h
index 4ff0d0c..fb34556 100644
--- a/init/check_builtins.h
+++ b/init/check_builtins.h
@@ -25,6 +25,7 @@
 Result<void> check_chown(const BuiltinArguments& args);
 Result<void> check_exec(const BuiltinArguments& args);
 Result<void> check_exec_background(const BuiltinArguments& args);
+Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args);
 Result<void> check_interface_restart(const BuiltinArguments& args);
 Result<void> check_interface_start(const BuiltinArguments& args);
 Result<void> check_interface_stop(const BuiltinArguments& args);
diff --git a/libappfuse/FuseBridgeLoop.cc b/libappfuse/FuseBridgeLoop.cc
index f1ca446..f71d0c3 100644
--- a/libappfuse/FuseBridgeLoop.cc
+++ b/libappfuse/FuseBridgeLoop.cc
@@ -86,6 +86,7 @@
         const bool proxy_read_ready = last_proxy_events_.events & EPOLLIN;
         const bool proxy_write_ready = last_proxy_events_.events & EPOLLOUT;
 
+        last_state_ = state_;
         last_device_events_.events = 0;
         last_proxy_events_.events = 0;
 
diff --git a/libcutils/ashmem-host.cpp b/libcutils/ashmem-host.cpp
index 32446d4..6c7655a 100644
--- a/libcutils/ashmem-host.cpp
+++ b/libcutils/ashmem-host.cpp
@@ -34,6 +34,29 @@
 
 #include <utils/Compat.h>
 
+static bool ashmem_validate_stat(int fd, struct stat* buf) {
+    int result = fstat(fd, buf);
+    if (result == -1) {
+        return false;
+    }
+
+    /*
+     * Check if this is an "ashmem" region.
+     * TODO: This is very hacky, and can easily break.
+     * We need some reliable indicator.
+     */
+    if (!(buf->st_nlink == 0 && S_ISREG(buf->st_mode))) {
+        errno = ENOTTY;
+        return false;
+    }
+    return true;
+}
+
+int ashmem_valid(int fd) {
+    struct stat buf;
+    return ashmem_validate_stat(fd, &buf);
+}
+
 int ashmem_create_region(const char* /*ignored*/, size_t size) {
     char pattern[PATH_MAX];
     snprintf(pattern, sizeof(pattern), "/tmp/android-ashmem-%d-XXXXXXXXX", getpid());
@@ -65,18 +88,7 @@
 int ashmem_get_size_region(int fd)
 {
     struct stat buf;
-    int result = fstat(fd, &buf);
-    if (result == -1) {
-        return -1;
-    }
-
-    /*
-     * Check if this is an "ashmem" region.
-     * TODO: This is very hacky, and can easily break.
-     * We need some reliable indicator.
-     */
-    if (!(buf.st_nlink == 0 && S_ISREG(buf.st_mode))) {
-        errno = ENOTTY;
+    if (!ashmem_validate_stat(fd, &buf)) {
         return -1;
     }
 
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index f6cae36..4f07456 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -69,10 +69,11 @@
 
 /*
  * native_handle_create
- * 
+ *
  * creates a native_handle_t and initializes it. must be destroyed with
- * native_handle_delete().
- * 
+ * native_handle_delete(). Note that numFds must be <= NATIVE_HANDLE_MAX_FDS,
+ * numInts must be <= NATIVE_HANDLE_MAX_INTS, and both must be >= 0.
+ *
  */
 native_handle_t* native_handle_create(int numFds, int numInts);
 
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 45a9bc9..5a73dc0 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -1747,22 +1747,21 @@
 
   return count;
 }
-
-// meant to be handed to ASSERT_TRUE / EXPECT_TRUE only to expand the message
-static testing::AssertionResult IsOk(bool ok, std::string& message) {
-  return ok ? testing::AssertionSuccess()
-            : (testing::AssertionFailure() << message);
-}
 #endif  // TEST_PREFIX
 
 TEST(liblog, enoent) {
 #ifdef TEST_PREFIX
+  if (getuid() != 0) {
+    GTEST_SKIP() << "Skipping test, must be run as root.";
+    return;
+  }
+
   TEST_PREFIX
   log_time ts(CLOCK_MONOTONIC);
   EXPECT_LT(0, __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)));
   EXPECT_EQ(SUPPORTS_END_TO_END, count_matching_ts(ts));
 
-  // This call will fail if we are setuid(AID_SYSTEM), beware of any
+  // This call will fail unless we are root, beware of any
   // test prior to this one playing with setuid and causing interference.
   // We need to run before these tests so that they do not interfere with
   // this test.
@@ -1774,20 +1773,7 @@
   // liblog.android_logger_get_ is one of those tests that has no recourse
   // and that would be adversely affected by emptying the log if it was run
   // right after this test.
-  if (getuid() != AID_ROOT) {
-    fprintf(
-        stderr,
-        "WARNING: test conditions request being run as root and not AID=%d\n",
-        getuid());
-    if (!__android_log_is_debuggable()) {
-      fprintf(
-          stderr,
-          "WARNING: can not run test on a \"user\" build, bypassing test\n");
-      return;
-    }
-  }
-
-  system((getuid() == AID_ROOT) ? "stop logd" : "su 0 stop logd");
+  system("stop logd");
   usleep(1000000);
 
   // A clean stop like we are testing returns -ENOENT, but in the _real_
@@ -1799,19 +1785,15 @@
   std::string content = android::base::StringPrintf(
       "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
       ret, (ret <= 0) ? strerror(-ret) : "(content sent)");
-  EXPECT_TRUE(
-      IsOk((ret == -ENOENT) || (ret == -ENOTCONN) || (ret == -ECONNREFUSED),
-           content));
+  EXPECT_TRUE(ret == -ENOENT || ret == -ENOTCONN || ret == -ECONNREFUSED) << content;
   ret = __android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts));
   content = android::base::StringPrintf(
       "__android_log_btwrite(0, EVENT_TYPE_LONG, &ts, sizeof(ts)) = %d %s\n",
       ret, (ret <= 0) ? strerror(-ret) : "(content sent)");
-  EXPECT_TRUE(
-      IsOk((ret == -ENOENT) || (ret == -ENOTCONN) || (ret == -ECONNREFUSED),
-           content));
+  EXPECT_TRUE(ret == -ENOENT || ret == -ENOTCONN || ret == -ECONNREFUSED) << content;
   EXPECT_EQ(0, count_matching_ts(ts));
 
-  system((getuid() == AID_ROOT) ? "start logd" : "su 0 start logd");
+  system("start logd");
   usleep(1000000);
 
   EXPECT_EQ(0, count_matching_ts(ts));
diff --git a/libmemunreachable/Android.bp b/libmemunreachable/Android.bp
index d864d1b..f20df19 100644
--- a/libmemunreachable/Android.bp
+++ b/libmemunreachable/Android.bp
@@ -113,7 +113,7 @@
     static_libs: ["libmemunreachable"],
     shared_libs: [
         "libbinder",
-        "libhwbinder",
+        "libhidlbase",
         "libutils",
     ],
     test_suites: ["device-tests"],
diff --git a/libstats/statsd_writer.c b/libstats/statsd_writer.c
index b778f92..b1c05ea 100644
--- a/libstats/statsd_writer.c
+++ b/libstats/statsd_writer.c
@@ -109,6 +109,11 @@
         if (sock < 0) {
             ret = -errno;
         } else {
+            int sndbuf = 1 * 1024 * 1024;  // set max send buffer size 1MB
+            socklen_t bufLen = sizeof(sndbuf);
+            // SO_RCVBUF does not have an effect on unix domain socket, but SO_SNDBUF does.
+            // Proceed to connect even setsockopt fails.
+            setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, bufLen);
             struct sockaddr_un un;
             memset(&un, 0, sizeof(struct sockaddr_un));
             un.sun_family = AF_UNIX;
diff --git a/libsystem/include/system/graphics-base-v1.2.h b/libsystem/include/system/graphics-base-v1.2.h
new file mode 100644
index 0000000..2194f5e
--- /dev/null
+++ b/libsystem/include/system/graphics-base-v1.2.h
@@ -0,0 +1,31 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+// Source: android.hardware.graphics.common@1.2
+// Location: hardware/interfaces/graphics/common/1.2/
+
+#ifndef HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
+#define HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    HAL_HDR_HDR10_PLUS = 4,
+} android_hdr_v1_2_t;
+
+typedef enum {
+    HAL_DATASPACE_DISPLAY_BT2020 = 142999552 /* ((STANDARD_BT2020 | TRANSFER_SRGB) | RANGE_FULL) */,
+    HAL_DATASPACE_DYNAMIC_DEPTH = 4098 /* 0x1002 */,
+    HAL_DATASPACE_JPEG_APP_SEGMENTS = 4099 /* 0x1003 */,
+    HAL_DATASPACE_HEIF = 4100 /* 0x1004 */,
+} android_dataspace_v1_2_t;
+
+typedef enum {
+    HAL_PIXEL_FORMAT_HSV_888 = 55 /* 0x37 */,
+} android_pixel_format_v1_2_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // HIDL_GENERATED_ANDROID_HARDWARE_GRAPHICS_COMMON_V1_2_EXPORTED_CONSTANTS_H_
diff --git a/libsystem/include/system/graphics-base.h b/libsystem/include/system/graphics-base.h
index ea92007..92ee077 100644
--- a/libsystem/include/system/graphics-base.h
+++ b/libsystem/include/system/graphics-base.h
@@ -3,5 +3,6 @@
 
 #include "graphics-base-v1.0.h"
 #include "graphics-base-v1.1.h"
+#include "graphics-base-v1.2.h"
 
 #endif  // SYSTEM_CORE_GRAPHICS_BASE_H_
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 14246ae..da18af6 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -153,12 +153,12 @@
     shared_libs: [
         "libunwindstack",
     ],
+    relative_install_path: "libunwindstack_test",
 }
 
-cc_test {
-    name: "libunwindstack_test",
+cc_defaults {
+    name: "libunwindstack_testlib_flags",
     defaults: ["libunwindstack_flags"],
-    isolated: true,
 
     srcs: [
         "tests/ArmExidxDecodeTest.cpp",
@@ -183,7 +183,6 @@
         "tests/ElfTestUtils.cpp",
         "tests/IsolatedSettings.cpp",
         "tests/JitDebugTest.cpp",
-        "tests/LocalUnwinderTest.cpp",
         "tests/LogFake.cpp",
         "tests/MapInfoCreateMemoryTest.cpp",
         "tests/MapInfoGetBuildIDTest.cpp",
@@ -253,11 +252,28 @@
         "tests/files/offline/straddle_arm/*",
         "tests/files/offline/straddle_arm64/*",
     ],
+}
+
+cc_test {
+    name: "libunwindstack_test",
+    defaults: ["libunwindstack_testlib_flags"],
+    isolated: true,
+
+    srcs: [
+        "tests/LocalUnwinderTest.cpp",
+    ],
     required: [
         "libunwindstack_local",
     ],
 }
 
+// Skip LocalUnwinderTest until atest understands required properly.
+cc_test {
+    name: "libunwindstack_unit_test",
+    defaults: ["libunwindstack_testlib_flags"],
+    isolated: true,
+}
+
 //-------------------------------------------------------------------------
 // Tools
 //-------------------------------------------------------------------------
diff --git a/libunwindstack/TEST_MAPPING b/libunwindstack/TEST_MAPPING
new file mode 100644
index 0000000..55771c0
--- /dev/null
+++ b/libunwindstack/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "libunwindstack_unit_test"
+    }
+  ]
+}
diff --git a/libunwindstack/tests/LocalUnwinderTest.cpp b/libunwindstack/tests/LocalUnwinderTest.cpp
index 56a18cd..9936f7a 100644
--- a/libunwindstack/tests/LocalUnwinderTest.cpp
+++ b/libunwindstack/tests/LocalUnwinderTest.cpp
@@ -170,10 +170,10 @@
 
   std::string testlib(testing::internal::GetArgvs()[0]);
   auto const value = testlib.find_last_of('/');
-  if (value == std::string::npos) {
-    testlib = "../";
+  if (value != std::string::npos) {
+    testlib = testlib.substr(0, value + 1);
   } else {
-    testlib = testlib.substr(0, value + 1) + "../";
+    testlib = "";
   }
   testlib += "libunwindstack_local.so";
 
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 42af751..d17da12 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -1433,8 +1433,8 @@
     set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
 
     inc_killcnt(procp->oomadj);
-    ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
-        taskname, pid, uid, procp->oomadj, tasksize * page_k);
+    ALOGE("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB", taskname, pid, uid, procp->oomadj,
+          tasksize * page_k);
 
     TRACE_KILL_END();
 
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 2fa110b..df1d929 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -233,18 +233,7 @@
 LOCAL_POST_INSTALL_CMD += && ln -sf /apex/com.android.i18n/etc/icu $(TARGET_OUT)/usr/icu
 
 # TODO(b/124106384): Clean up compat symlinks for ART binaries.
-ART_BINARIES := \
-  dalvikvm \
-  dalvikvm32 \
-  dalvikvm64 \
-  dex2oat \
-  dexdiag \
-  dexdump \
-  dexlist \
-  dexoptanalyzer \
-  oatdump \
-  profman \
-
+ART_BINARIES := dalvikvm dex2oat
 LOCAL_POST_INSTALL_CMD += && mkdir -p $(TARGET_OUT)/bin
 $(foreach b,$(ART_BINARIES), \
   $(eval LOCAL_POST_INSTALL_CMD += \
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index c8c6387..e1da587 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -190,6 +190,7 @@
 namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
 
 namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
 
 namespace.media.links = default,neuralnetworks
 namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
@@ -723,6 +724,7 @@
 namespace.media.asan.search.paths = /apex/com.android.media/${LIB}
 
 namespace.media.permitted.paths = /apex/com.android.media/${LIB}/extractors
+namespace.media.asan.permitted.paths = /apex/com.android.media/${LIB}/extractors
 
 namespace.media.links = default,neuralnetworks
 namespace.media.link.default.shared_libs  = %LLNDK_LIBRARIES%
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index d8f6095..27e855f 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
index 20905bf..b565340 100644
--- a/rootdir/etc/public.libraries.iot.txt
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -2,6 +2,7 @@
 libandroid.so
 libandroidthings.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 4ece5b5..7cbda08 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/init.rc b/rootdir/init.rc
index bb36139..afa1a86 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -431,10 +431,6 @@
     # HALs required before storage encryption can get unlocked (FBE/FDE)
     class_start early_hal
 
-    # Check and mark a successful boot, before mounting userdata with mount_all.
-    # No-op for non-A/B device.
-    exec_start update_verifier_nonencrypted
-
 on post-fs-data
     mark_post_data
 
@@ -669,16 +665,22 @@
 # It is recommended to put unnecessary data/ initialization from post-fs-data
 # to start-zygote in device's init.rc to unblock zygote start.
 on zygote-start && property:ro.crypto.state=unencrypted
+    # A/B update verifier that marks a successful boot.
+    exec_start update_verifier_nonencrypted
     start netd
     start zygote
     start zygote_secondary
 
 on zygote-start && property:ro.crypto.state=unsupported
+    # A/B update verifier that marks a successful boot.
+    exec_start update_verifier_nonencrypted
     start netd
     start zygote
     start zygote_secondary
 
 on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
+    # A/B update verifier that marks a successful boot.
+    exec_start update_verifier_nonencrypted
     start netd
     start zygote
     start zygote_secondary
@@ -702,6 +704,12 @@
     chown root system /sys/module/lowmemorykiller/parameters/minfree
     chmod 0664 /sys/module/lowmemorykiller/parameters/minfree
 
+    # System server manages zram writeback
+    chown root system /sys/block/zram0/idle
+    chmod 0664 /sys/block/zram0/idle
+    chown root system /sys/block/zram0/writeback
+    chmod 0664 /sys/block/zram0/writeback
+
     # Tweak background writeout
     write /proc/sys/vm/dirty_expire_centisecs 200
     write /proc/sys/vm/dirty_background_ratio  5
@@ -801,6 +809,8 @@
     trigger zygote-start
 
 on property:vold.decrypt=trigger_restart_min_framework
+    # A/B update verifier that marks a successful boot.
+    exec_start update_verifier
     class_start main
 
 on property:vold.decrypt=trigger_restart_framework
diff --git a/rootdir/init.usb.rc b/rootdir/init.usb.rc
index f0681d2..b6cba90 100644
--- a/rootdir/init.usb.rc
+++ b/rootdir/init.usb.rc
@@ -14,7 +14,7 @@
 # adbd is controlled via property triggers in init.<platform>.usb.rc
 service adbd /system/bin/adbd --root_seclabel=u:r:su:s0
     class core
-    socket adbd stream 660 system system
+    socket adbd seqpacket 660 system system
     disabled
     seclabel u:r:adbd:s0
 
diff --git a/rootdir/init.zygote32.rc b/rootdir/init.zygote32.rc
index f8e680d..bf3fb42 100644
--- a/rootdir/init.zygote32.rc
+++ b/rootdir/init.zygote32.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote32_64.rc b/rootdir/init.zygote32_64.rc
index 0235370..1bab588 100644
--- a/rootdir/init.zygote32_64.rc
+++ b/rootdir/init.zygote32_64.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -20,6 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
-    socket blastula_pool_secondary stream 660 root system
+    socket usap_pool_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 3f3cc15..6fa210a 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index fae38c9..48461ec 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -4,7 +4,7 @@
     user root
     group root readproc reserved_disk
     socket zygote stream 660 root system
-    socket blastula_pool stream 660 root system
+    socket usap_pool_primary stream 660 root system
     onrestart write /sys/android_power/request_state wake
     onrestart write /sys/power/state on
     onrestart restart audioserver
@@ -20,6 +20,6 @@
     user root
     group root readproc reserved_disk
     socket zygote_secondary stream 660 root system
-    socket blastula_pool_secondary stream 660 root system
+    socket usap_pool_secondary stream 660 root system
     onrestart restart zygote
     writepid /dev/cpuset/foreground/tasks