Merge "init: Statically link libbootloader_message."
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index 299b5d4..845b303 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -367,8 +367,6 @@
   adb logcat -b all ${timestamp} |
   grep bootstat[^e] |
   grep -v -F "bootstat: Service started: /system/bin/bootstat --record_boot_complete${match}
-bootstat: Failed to read /data/misc/bootstat/post_decrypt_time_elapsed: No such file or directory
-bootstat: Failed to parse boot time record: /data/misc/bootstat/post_decrypt_time_elapsed
 bootstat: Service started: /system/bin/bootstat --record_boot_reason
 bootstat: Service started: /system/bin/bootstat --set_system_boot_reason
 bootstat: Service started: /system/bin/bootstat --record_time_since_factory_reset
@@ -388,7 +386,6 @@
 init    : processing action (sys.boot_completed=1 && sys.bootstat.first_boot_completed=0) from (/system/etc/init/bootstat.rc
  (/system/bin/bootstat --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
  (/system/bin/bootstat --set_system_boot_reason --record_boot_complete --record_boot_reason --record_time_since_factory_reset -l)'
- (/system/bin/bootstat -r post_decrypt_time_elapsed)'
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_complete' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
 init    : Command 'exec - system log -- /system/bin/bootstat --record_boot_reason' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
 init    : Command 'exec - system log -- /system/bin/bootstat --record_time_since_factory_reset' action=sys.boot_completed=1 && sys.bootstat.first_boot_completed=0 (/system/etc/init/bootstat.rc:
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index 589b99a..844357c 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -67,15 +67,9 @@
     {"boot_complete",
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE}},
-    {"boot_decryption_complete",
-     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
-      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_ENCRYPTION}},
     {"boot_complete_no_encryption",
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_NO_ENCRYPTION}},
-    {"boot_complete_post_decrypt",
-     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
-      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__BOOT_COMPLETE_POST_DECRYPT}},
     {"factory_reset_boot_complete",
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE}},
@@ -83,22 +77,12 @@
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::
           BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_NO_ENCRYPTION}},
-    {"factory_reset_boot_complete_post_decrypt",
-     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
-      android::util::
-          BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__FACTORY_RESET_BOOT_COMPLETE_POST_DECRYPT}},
     {"ota_boot_complete",
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE}},
     {"ota_boot_complete_no_encryption",
      {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
       android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_NO_ENCRYPTION}},
-    {"ota_boot_complete_post_decrypt",
-     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
-      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__OTA_BOOT_COMPLETE_POST_DECRYPT}},
-    {"post_decrypt_time_elapsed",
-     {android::util::BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
-      android::util::BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__POST_DECRYPT}},
     // DURATION
     {"absolute_boot_time",
      {android::util::BOOT_TIME_EVENT_DURATION_REPORTED,
@@ -1313,8 +1297,7 @@
   return android::base::boot_clock::now().time_since_epoch() - GetBootTimeOffset();
 }
 
-// Records several metrics related to the time it takes to boot the device,
-// including disambiguating boot time on encrypted or non-encrypted devices.
+// Records several metrics related to the time it takes to boot the device.
 void RecordBootComplete() {
   BootEventRecordStore boot_event_store;
   BootEventRecordStore::BootEventRecord record;
@@ -1341,25 +1324,15 @@
     return;
   }
 
-  // post_decrypt_time_elapsed is only logged on encrypted devices.
-  if (boot_event_store.GetBootEvent("post_decrypt_time_elapsed", &record)) {
-    // Log the amount of time elapsed until the device is decrypted, which
-    // includes the variable amount of time the user takes to enter the
-    // decryption password.
-    boot_event_store.AddBootEventWithValue("boot_decryption_complete", uptime_s.count());
+  // The *_no_encryption events are emitted unconditionally, since they are left
+  // over from a time when encryption meant "full-disk encryption".  But Android
+  // now always uses file-based encryption instead of full-disk encryption.  At
+  // some point, these misleading and redundant events should be removed.
+  boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
+                                         uptime_s.count());
 
-    // Subtract the decryption time to normalize the boot cycle timing.
-    std::chrono::seconds boot_complete = std::chrono::seconds(uptime_s.count() - record.second);
-    boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_post_decrypt",
-                                           boot_complete.count());
-  } else {
-    boot_event_store.AddBootEventWithValue(boot_complete_prefix + "_no_encryption",
-                                           uptime_s.count());
-  }
-
-  // Record the total time from device startup to boot complete, regardless of
-  // encryption state.
-  // Note: we are recording seconds here even though the field in statsd atom specifies
+  // Record the total time from device startup to boot complete.  Note: we are
+  // recording seconds here even though the field in statsd atom specifies
   // milliseconds.
   boot_event_store.AddBootEventWithValue(boot_complete_prefix, uptime_s.count());
 
diff --git a/bootstat/bootstat.rc b/bootstat/bootstat.rc
index a350fe7..23f01d1 100644
--- a/bootstat/bootstat.rc
+++ b/bootstat/bootstat.rc
@@ -33,7 +33,6 @@
     chown system log /data/misc/bootstat/last_boot_time_utc
     chown system log /data/misc/bootstat/ota_boot_complete
     chown system log /data/misc/bootstat/ota_boot_complete_no_encryption
-    chown system log /data/misc/bootstat/post_decrypt_time_elapsed
     chown system log /data/misc/bootstat/ro.boottime.init
     chown system log /data/misc/bootstat/ro.boottime.init.cold_boot_wait
     chown system log /data/misc/bootstat/ro.boottime.init.selinux
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index ed90ab4..aca476f 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -1403,7 +1403,7 @@
   // We can't actually generate a backtrace, just make sure that the process terminates.
 }
 
-__attribute__((noinline)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
+__attribute__((__noinline__)) extern "C" bool raise_debugger_signal(DebuggerdDumpType dump_type) {
   siginfo_t siginfo;
   siginfo.si_code = SI_QUEUE;
   siginfo.si_pid = getpid();
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 92e7675..c64de0e 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -24,6 +24,7 @@
 #include <sched.h>
 #include <signal.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,7 +52,6 @@
 
 #include "handler/fallback.h"
 
-using ::android::base::GetBoolProperty;
 using ::android::base::ParseBool;
 using ::android::base::ParseBoolResult;
 using ::android::base::Pipe;
@@ -87,10 +87,31 @@
   return syscall(__NR_gettid);
 }
 
+static bool property_parse_bool(const char* name) {
+  const prop_info* pi = __system_property_find(name);
+  if (!pi) return false;
+  bool cookie = false;
+  __system_property_read_callback(
+      pi,
+      [](void* cookie, const char*, const char* value, uint32_t) {
+        *reinterpret_cast<bool*>(cookie) = ParseBool(value) == ParseBoolResult::kTrue;
+      },
+      &cookie);
+  return cookie;
+}
+
 static bool is_permissive_mte() {
   // Environment variable for testing or local use from shell.
   char* permissive_env = getenv("MTE_PERMISSIVE");
-  return GetBoolProperty("persist.sys.mte.permissive", false) ||
+  char process_sysprop_name[512];
+  async_safe_format_buffer(process_sysprop_name, sizeof(process_sysprop_name),
+                           "persist.device_config.memory_safety_native.permissive.process.%s",
+                           getprogname());
+  // DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
+  // not async-safe (and this functiong gets used in a signal handler).
+  return property_parse_bool("persist.sys.mte.permissive") ||
+         property_parse_bool("persist.device_config.memory_safety_native.permissive.default") ||
+         property_parse_bool(process_sysprop_name) ||
          (permissive_env && ParseBool(permissive_env) == ParseBoolResult::kTrue);
 }
 
@@ -623,6 +644,18 @@
     async_safe_format_log(ANDROID_LOG_ERROR, "libc",
                           "MTE ERROR DETECTED BUT RUNNING IN PERMISSIVE MODE. CONTINUING.");
     pthread_mutex_unlock(&crash_mutex);
+  } else if (info->si_signo == SIGSEGV && info->si_code == SEGV_MTEAERR && getppid() == 1) {
+    // Back channel to init (see system/core/init/service.cpp) to signal that
+    // this process crashed due to an ASYNC MTE fault and should be considered
+    // for upgrade to SYNC mode. We are re-using the ART profiler signal, which
+    // is always handled (ignored in native processes, handled for generating a
+    // dump in ART processes), so a process will never crash from this signal
+    // except from here.
+    // The kernel is not particularly receptive to adding this information:
+    // https://lore.kernel.org/all/20220909180617.374238-1-fmayer@google.com/, so we work around
+    // like this.
+    info->si_signo = BIONIC_SIGNAL_ART_PROFILER;
+    resend_signal(info);
   }
 #endif
   else {
diff --git a/debuggerd/proto/tombstone.proto b/debuggerd/proto/tombstone.proto
index a0f2f82..f0d3d3f 100644
--- a/debuggerd/proto/tombstone.proto
+++ b/debuggerd/proto/tombstone.proto
@@ -1,3 +1,12 @@
+//
+// Protobuf definition for Android tombstones.
+//
+// An app can get hold of these for any `REASON_CRASH_NATIVE` instance of
+// `android.app.ApplicationExitInfo`.
+//
+// https://developer.android.com/reference/android/app/ApplicationExitInfo#getTraceInputStream()
+//
+
 syntax = "proto3";
 
 option java_package = "com.android.server.os";
diff --git a/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java b/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
index 5ff2b5b..0203adc 100644
--- a/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
+++ b/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
@@ -97,4 +97,33 @@
     }
     assertThat(numberTombstones).isEqualTo(1);
   }
+  @Test
+  public void testCrashProperty() throws Exception {
+    String prevValue = getDevice().getProperty("persist.sys.mte.permissive");
+    if (prevValue == null) {
+      prevValue = "";
+    }
+    assertThat(getDevice().setProperty("persist.sys.mte.permissive", "1")).isTrue();
+    CommandResult result =
+        getDevice().executeShellV2Command("/data/local/tmp/mte_crash testCrash " + mUUID);
+    assertThat(result.getExitCode()).isEqualTo(0);
+    int numberTombstones = 0;
+    String[] tombstones = getDevice().getChildren("/data/tombstones");
+    for (String tombstone : tombstones) {
+      if (!tombstone.endsWith(".pb")) {
+        continue;
+      }
+      String tombstonePath = "/data/tombstones/" + tombstone;
+      Tombstone tombstoneProto = parseTombstone(tombstonePath);
+      if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(mUUID))) {
+        continue;
+      }
+      if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains("testCrash"))) {
+        continue;
+      }
+      numberTombstones++;
+    }
+    assertThat(numberTombstones).isEqualTo(1);
+    assertThat(getDevice().setProperty("persist.sys.mte.permissive", prevValue)).isTrue();
+  }
 }
diff --git a/fastboot/constants.h b/fastboot/constants.h
index b732c76..f6fc74e 100644
--- a/fastboot/constants.h
+++ b/fastboot/constants.h
@@ -42,7 +42,7 @@
 #define RESPONSE_DATA "DATA"
 #define RESPONSE_INFO "INFO"
 
-#define FB_COMMAND_SZ 64
+#define FB_COMMAND_SZ 4096
 #define FB_RESPONSE_SZ 256
 
 #define FB_VAR_VERSION "version"
diff --git a/fastboot/device/commands.cpp b/fastboot/device/commands.cpp
index 823783e..3799d1f 100644
--- a/fastboot/device/commands.cpp
+++ b/fastboot/device/commands.cpp
@@ -40,6 +40,8 @@
 #include <storage_literals/storage_literals.h>
 #include <uuid/uuid.h>
 
+#include <bootloader_message/bootloader_message.h>
+
 #include "BootControlClient.h"
 #include "constants.h"
 #include "fastboot_device.h"
@@ -154,6 +156,14 @@
     return true;
 }
 
+static void PostWipeData() {
+    std::string err;
+    // Reset mte state of device.
+    if (!WriteMiscMemtagMessage({}, &err)) {
+        LOG(ERROR) << "Failed to reset MTE state: " << err;
+    }
+}
+
 const std::unordered_map<std::string, std::function<bool(FastbootDevice*)>> kSpecialVars = {
         {"all", GetVarAll},
         {"dmesg", GetDmesg},
@@ -232,6 +242,7 @@
         //Perform oem PostWipeData if Android userdata partition has been erased
         bool support_oem_postwipedata = false;
         if (partition_name == "userdata") {
+            PostWipeData();
             support_oem_postwipedata = OemPostWipeData(device);
         }
 
@@ -610,6 +621,10 @@
     if (ret < 0) {
         return device->WriteStatus(FastbootResult::FAIL, strerror(-ret));
     }
+    if (partition_name == "userdata") {
+        PostWipeData();
+    }
+
     return device->WriteStatus(FastbootResult::OKAY, "Flashing succeeded");
 }
 
diff --git a/fastboot/device/usb.cpp b/fastboot/device/usb.cpp
index b77d772..75a687f 100644
--- a/fastboot/device/usb.cpp
+++ b/fastboot/device/usb.cpp
@@ -161,6 +161,16 @@
         if (num_bufs == 1 && aiob->events[0].res == -EINTR) {
             continue;
         }
+        if (read && aiob->events[0].res == -EPIPE) {
+            // On initial connection, some clients will send a ClearFeature(HALT) to
+            // attempt to resynchronize host and device after the fastboot server is killed.
+            // On newer device kernels, the reads we've already dispatched will be cancelled.
+            // Instead of treating this as a failure, which will tear down the interface and
+            // lead to the client doing the same thing again, just resubmit if this happens
+            // before we've actually read anything.
+            PLOG(ERROR) << "aio: got -EPIPE on first read attempt. Re-submitting read... ";
+            continue;
+        }
         int ret = 0;
         for (int i = 0; i < num_bufs; i++) {
             if (aiob->events[i].res < 0) {
diff --git a/fastboot/fuzzy_fastboot/main.cpp b/fastboot/fuzzy_fastboot/main.cpp
index 074306b..e635937 100644
--- a/fastboot/fuzzy_fastboot/main.cpp
+++ b/fastboot/fuzzy_fastboot/main.cpp
@@ -901,19 +901,19 @@
             << "Device did not respond with failure after sending length " << s.size()
             << " string of random ASCII chars";
     if (ret == IO_ERROR) EXPECT_EQ(transport->Reset(), 0) << "USB reset failed";
-    std::string s1 = RandomString(1000, rand_legal);
+    std::string s1 = RandomString(10000, rand_legal);
     ret = fb->RawCommand(s1);
     EXPECT_TRUE(ret == DEVICE_FAIL || ret == IO_ERROR)
             << "Device did not respond with failure after sending length " << s1.size()
             << " string of random ASCII chars";
     if (ret == IO_ERROR) EXPECT_EQ(transport->Reset(), 0) << "USB reset failed";
-    std::string s2 = RandomString(1000, rand_illegal);
+    std::string s2 = RandomString(10000, rand_illegal);
     ret = fb->RawCommand(s2);
     EXPECT_TRUE(ret == DEVICE_FAIL || ret == IO_ERROR)
             << "Device did not respond with failure after sending length " << s2.size()
             << " string of random non-ASCII chars";
     if (ret == IO_ERROR) EXPECT_EQ(transport->Reset(), 0) << "USB reset failed";
-    std::string s3 = RandomString(1000, rand_char);
+    std::string s3 = RandomString(10000, rand_char);
     ret = fb->RawCommand(s3);
     EXPECT_TRUE(ret == DEVICE_FAIL || ret == IO_ERROR)
             << "Device did not respond with failure after sending length " << s3.size()
@@ -935,7 +935,7 @@
 
 TEST_F(Fuzz, CommandTooLarge) {
     for (const std::string& s : CMDS) {
-        std::string rs = RandomString(1000, rand_char);
+        std::string rs = RandomString(10000, rand_char);
         RetCode ret;
         ret = fb->RawCommand(s + rs);
         EXPECT_TRUE(ret == DEVICE_FAIL || ret == IO_ERROR)
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 1f54f5b..9fe8e18 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -903,9 +903,9 @@
         // Deal with alternate entries for the same point which are required to be all following
         // each other.
         if (mounted) {
-            LERROR << __FUNCTION__ << "(): skipping fstab dup mountpoint=" << fstab[i].mount_point
-                   << " rec[" << i << "].fs_type=" << fstab[i].fs_type << " already mounted as "
-                   << fstab[*attempted_idx].fs_type;
+            LINFO << __FUNCTION__ << "(): skipping fstab dup mountpoint=" << fstab[i].mount_point
+                  << " rec[" << i << "].fs_type=" << fstab[i].fs_type << " already mounted as "
+                  << fstab[*attempted_idx].fs_type;
             continue;
         }
 
@@ -933,9 +933,9 @@
                 *attempted_idx = i;
                 mounted = true;
                 if (i != start_idx) {
-                    LERROR << __FUNCTION__ << "(): Mounted " << fstab[i].blk_device << " on "
-                           << fstab[i].mount_point << " with fs_type=" << fstab[i].fs_type
-                           << " instead of " << fstab[start_idx].fs_type;
+                    LINFO << __FUNCTION__ << "(): Mounted " << fstab[i].blk_device << " on "
+                          << fstab[i].mount_point << " with fs_type=" << fstab[i].fs_type
+                          << " instead of " << fstab[start_idx].fs_type;
                 }
                 fs_stat &= ~FS_STAT_FULL_MOUNT_FAILED;
                 mount_errno = 0;
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 43961da..76ef9e4 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -309,6 +309,12 @@
             if (ReadFileToString("/sys/class/block/" + arg + "/queue/zoned", &zoned) &&
                 android::base::StartsWith(zoned, "host-managed")) {
                 entry->zoned_device = "/dev/block/" + arg;
+
+                // atgc in f2fs does not support a zoned device
+                auto options = Split(entry->fs_options, ",");
+                options.erase(std::remove(options.begin(), options.end(), "atgc"), options.end());
+                entry->fs_options = android::base::Join(options, ",");
+                LINFO << "Removed ATGC in fs_options as " << entry->fs_options;
             } else {
                 LWARNING << "Warning: cannot find the zoned device: " << arg;
             }
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index 2ef3068..1d8a452 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -102,8 +102,8 @@
     return false;
 }
 
-bool fs_mgr_overlayfs_teardown(const char*, bool*) {
-    return false;
+OverlayfsTeardownResult fs_mgr_overlayfs_teardown(const char*, bool*) {
+    return OverlayfsTeardownResult::Ok;
 }
 
 bool fs_mgr_overlayfs_is_setup() {
@@ -1331,22 +1331,22 @@
 }
 
 bool fs_mgr_overlayfs_mount_all(Fstab* fstab) {
-    auto ret = false;
-    if (fs_mgr_overlayfs_invalid()) return ret;
-
+    if (fs_mgr_overlayfs_invalid()) {
+        return false;
+    }
+    auto ret = true;
     auto scratch_can_be_mounted = true;
     for (const auto& entry : fs_mgr_overlayfs_candidate_list(*fstab)) {
         if (fs_mgr_is_verity_enabled(entry)) continue;
         auto mount_point = fs_mgr_mount_point(entry.mount_point);
         if (fs_mgr_overlayfs_already_mounted(mount_point)) {
-            ret = true;
             continue;
         }
         if (scratch_can_be_mounted) {
             scratch_can_be_mounted = false;
             TryMountScratch();
         }
-        if (fs_mgr_overlayfs_mount(mount_point)) ret = true;
+        ret &= fs_mgr_overlayfs_mount(mount_point);
     }
     return ret;
 }
diff --git a/fs_mgr/fs_mgr_remount.cpp b/fs_mgr/fs_mgr_remount.cpp
index 2202fda..a78f945 100644
--- a/fs_mgr/fs_mgr_remount.cpp
+++ b/fs_mgr/fs_mgr_remount.cpp
@@ -451,10 +451,9 @@
     }
 
     // Mount overlayfs.
-    errno = 0;
-    if (!fs_mgr_overlayfs_mount_all(&partitions) && errno) {
-        PLOG(ERROR) << "Can not mount overlayfs for partitions";
-        return BAD_OVERLAY;
+    if (!fs_mgr_overlayfs_mount_all(&partitions)) {
+        LOG(WARNING) << "Cannot mount overlayfs for some partitions";
+        // Continue regardless to handle raw remount case.
     }
 
     // Get actual mounts _after_ overlayfs has been added.
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index bc3efd9..59abd6f 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -1498,7 +1498,6 @@
     if (UpdateUsesUserSnapshots(lock) && !device()->IsTestDevice()) {
         if (snapuserd_client_) {
             snapuserd_client_->DetachSnapuserd();
-            snapuserd_client_->CloseConnection();
             snapuserd_client_ = nullptr;
         }
     }
@@ -2794,7 +2793,6 @@
     if (snapuserd_client_) {
         LOG(INFO) << "Shutdown snapuserd daemon";
         snapuserd_client_->DetachSnapuserd();
-        snapuserd_client_->CloseConnection();
         snapuserd_client_ = nullptr;
     }
 
@@ -3317,7 +3315,7 @@
         }
         if (snapuserd_client) {
             snapuserd_client->DetachSnapuserd();
-            snapuserd_client->CloseConnection();
+            snapuserd_client = nullptr;
         }
     }
 
diff --git a/fs_mgr/libsnapshot/snapshot_test.cpp b/fs_mgr/libsnapshot/snapshot_test.cpp
index 2233a38..2c01cf6 100644
--- a/fs_mgr/libsnapshot/snapshot_test.cpp
+++ b/fs_mgr/libsnapshot/snapshot_test.cpp
@@ -107,6 +107,12 @@
 
   protected:
     void SetUp() override {
+        const testing::TestInfo* const test_info =
+                testing::UnitTest::GetInstance()->current_test_info();
+        test_name_ = test_info->test_suite_name() + "/"s + test_info->name();
+
+        LOG(INFO) << "Starting test: " << test_name_;
+
         SKIP_IF_NON_VIRTUAL_AB();
 
         SetupProperties();
@@ -152,10 +158,14 @@
     void TearDown() override {
         RETURN_IF_NON_VIRTUAL_AB();
 
+        LOG(INFO) << "Tearing down SnapshotTest test: " << test_name_;
+
         lock_ = nullptr;
 
         CleanupTestArtifacts();
         SnapshotTestPropertyFetcher::TearDown();
+
+        LOG(INFO) << "Teardown complete for test: " << test_name_;
     }
 
     void InitializeState() {
@@ -487,6 +497,7 @@
     android::fiemap::IImageManager* image_manager_ = nullptr;
     std::string fake_super_;
     bool snapuserd_required_ = false;
+    std::string test_name_;
 };
 
 TEST_F(SnapshotTest, CreateSnapshot) {
@@ -1003,6 +1014,8 @@
     void TearDown() override {
         RETURN_IF_NON_VIRTUAL_AB();
 
+        LOG(INFO) << "Tearing down SnapshotUpdateTest test: " << test_name_;
+
         Cleanup();
         SnapshotTest::TearDown();
     }
@@ -2797,7 +2810,6 @@
         return;
     }
     snapuserd_client->DetachSnapuserd();
-    snapuserd_client->CloseConnection();
 }
 
 }  // namespace snapshot
diff --git a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
index 9a69d58..4b62b20 100644
--- a/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
+++ b/fs_mgr/libsnapshot/snapuserd/include/snapuserd/snapuserd_client.h
@@ -71,8 +71,6 @@
     // must ONLY be called if the control device has already been deleted.
     bool WaitForDeviceDelete(const std::string& control_device);
 
-    void CloseConnection() { sockfd_ = {}; }
-
     // Detach snapuserd. This shuts down the listener socket, and will cause
     // snapuserd to gracefully exit once all handler threads have terminated.
     // This should only be used on first-stage instances of snapuserd.
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd.rc b/fs_mgr/libsnapshot/snapuserd/snapuserd.rc
index 2750096..522fe08 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd.rc
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd.rc
@@ -4,6 +4,7 @@
     disabled
     user root
     group root system
+    task_profiles OtaProfiles
     seclabel u:r:snapuserd:s0
 
 service snapuserd_proxy /system/bin/snapuserd -socket-handoff
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
index 1e300d2..0d0f711 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_dm_user.cpp
@@ -253,6 +253,11 @@
 
 bool Worker::RunThread() {
     SNAP_LOG(INFO) << "Processing snapshot I/O requests....";
+
+    if (setpriority(PRIO_PROCESS, gettid(), kNiceValueForMergeThreads)) {
+        SNAP_PLOG(ERROR) << "Failed to set priority for TID: " << gettid();
+    }
+
     // Start serving IO
     while (true) {
         if (!ProcessIORequest()) {
diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
index 1bf33c8..d437d32 100644
--- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_server.cpp
@@ -462,15 +462,14 @@
 }
 
 bool UserSnapshotServer::HandleClient(android::base::borrowed_fd fd, int revents) {
-    if (revents & POLLHUP) {
-        LOG(DEBUG) << "Snapuserd client disconnected";
-        return false;
-    }
-
     std::string str;
     if (!Recv(fd, &str)) {
         return false;
     }
+    if (str.empty() && (revents & POLLHUP)) {
+        LOG(DEBUG) << "Snapuserd client disconnected";
+        return false;
+    }
     if (!Receivemsg(fd, str)) {
         LOG(ERROR) << "Encountered error handling client message, revents: " << revents;
         return false;
@@ -650,6 +649,12 @@
             while (active_merge_threads_ < kMaxMergeThreads && merge_handlers_.size() > 0) {
                 auto handler = merge_handlers_.front();
                 merge_handlers_.pop();
+
+                if (!handler->snapuserd()) {
+                    LOG(INFO) << "MonitorMerge: skipping deleted handler: " << handler->misc_name();
+                    continue;
+                }
+
                 LOG(INFO) << "Starting merge for partition: "
                           << handler->snapuserd()->GetMiscName();
                 handler->snapuserd()->InitiateMerge();
diff --git a/fs_mgr/libsnapshot/vts_ota_config_test.cpp b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
old mode 100644
new mode 100755
index 02bcc34..d387eb3
--- a/fs_mgr/libsnapshot/vts_ota_config_test.cpp
+++ b/fs_mgr/libsnapshot/vts_ota_config_test.cpp
@@ -22,6 +22,9 @@
 }
 
 TEST(VAB, Enabled) {
+    if (!android::base::GetBoolProperty("ro.build.ab_update", false) && (GetVsrLevel() < __ANDROID_API_T__)) {
+        GTEST_SKIP();
+    }
     ASSERT_TRUE(android::base::GetBoolProperty("ro.virtual_ab.enabled", false));
     if (GetVsrLevel() < __ANDROID_API_T__) {
         GTEST_SKIP();
diff --git a/fs_mgr/tests/Android.bp b/fs_mgr/tests/Android.bp
index fdc0d8e..b9bae25 100644
--- a/fs_mgr/tests/Android.bp
+++ b/fs_mgr/tests/Android.bp
@@ -53,8 +53,9 @@
 }
 
 sh_binary_host {
-    name: "adb-remount-test.sh",
+    name: "adb-remount-test",
     src: "adb-remount-test.sh",
+    filename_from_src: true,
     target: {
         darwin: {
             enabled: false,
@@ -68,7 +69,7 @@
 sh_test {
     name: "adb-remount-sh",
     src: "adb-remount-test.sh",
-    filename: "adb-remount-test.sh",
+    filename_from_src: true,
     test_suites: ["general-tests"],
     test_config: "adb-remount-sh.xml",
 }
diff --git a/gatekeeperd/Android.bp b/gatekeeperd/Android.bp
index 0aedc58..838f734 100644
--- a/gatekeeperd/Android.bp
+++ b/gatekeeperd/Android.bp
@@ -43,6 +43,8 @@
         "libutils",
         "libcrypto",
         "libhidlbase",
+        "lib_android_keymaster_keymint_utils",
+        "android.hardware.gatekeeper-V1-ndk",
         "android.hardware.gatekeeper@1.0",
         "libgatekeeper_aidl",
         "android.security.authorization-ndk",
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 8792c83..76fcd55 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -25,6 +25,7 @@
 #include <unistd.h>
 #include <memory>
 
+#include <KeyMintUtils.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android/binder_ibinder.h>
@@ -38,6 +39,7 @@
 #include <log/log.h>
 #include <utils/String16.h>
 
+#include <aidl/android/hardware/gatekeeper/IGatekeeper.h>
 #include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
 #include <aidl/android/security/authorization/IKeystoreAuthorization.h>
 #include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
@@ -49,27 +51,35 @@
 using android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
 using android::hardware::gatekeeper::V1_0::IGatekeeper;
 
+using AidlGatekeeperEnrollResp = aidl::android::hardware::gatekeeper::GatekeeperEnrollResponse;
+using AidlGatekeeperVerifyResp = aidl::android::hardware::gatekeeper::GatekeeperVerifyResponse;
+using AidlIGatekeeper = aidl::android::hardware::gatekeeper::IGatekeeper;
+
 using ::android::binder::Status;
 using ::android::service::gatekeeper::BnGateKeeperService;
 using GKResponse = ::android::service::gatekeeper::GateKeeperResponse;
 using GKResponseCode = ::android::service::gatekeeper::ResponseCode;
 using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
 using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
+using ::aidl::android::hardware::security::keymint::km_utils::authToken2AidlVec;
 using ::aidl::android::security::authorization::IKeystoreAuthorization;
 
 namespace android {
 
 static const String16 KEYGUARD_PERMISSION("android.permission.ACCESS_KEYGUARD_SECURE_STORAGE");
 static const String16 DUMP_PERMISSION("android.permission.DUMP");
+constexpr const char gatekeeperServiceName[] = "android.hardware.gatekeeper.IGatekeeper/default";
 
 class GateKeeperProxy : public BnGateKeeperService {
   public:
     GateKeeperProxy() {
         clear_state_if_needed_done = false;
         hw_device = IGatekeeper::getService();
+        ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(gatekeeperServiceName));
+        aidl_hw_device = AidlIGatekeeper::fromBinder(ks2Binder);
         is_running_gsi = android::base::GetBoolProperty(android::gsi::kGsiBootedProp, false);
 
-        if (!hw_device) {
+        if (!aidl_hw_device && !hw_device) {
             LOG(ERROR) << "Could not find Gatekeeper device, which makes me very sad.";
         }
     }
@@ -95,7 +105,9 @@
 
         if (mark_cold_boot() && !is_running_gsi) {
             ALOGI("cold boot: clearing state");
-            if (hw_device) {
+            if (aidl_hw_device) {
+                aidl_hw_device->deleteAllUsers();
+            } else if (hw_device) {
                 hw_device->deleteAllUsers([](const GatekeeperResponse&) {});
             }
         }
@@ -150,7 +162,7 @@
     uint32_t adjust_userId(uint32_t userId) {
         static constexpr uint32_t kGsiOffset = 1000000;
         CHECK(userId < kGsiOffset);
-        CHECK(hw_device != nullptr);
+        CHECK((aidl_hw_device != nullptr) || (hw_device != nullptr));
         if (is_running_gsi) {
             return userId + kGsiOffset;
         }
@@ -176,7 +188,7 @@
         // need a desired password to enroll
         if (desiredPassword.size() == 0) return GK_ERROR;
 
-        if (!hw_device) {
+        if (!aidl_hw_device && !hw_device) {
             LOG(ERROR) << "has no HAL to talk to";
             return GK_ERROR;
         }
@@ -185,9 +197,13 @@
         android::hardware::hidl_vec<uint8_t> curPwd;
 
         if (currentPasswordHandle && currentPassword) {
-            if (currentPasswordHandle->size() != sizeof(gatekeeper::password_handle_t)) {
-                LOG(INFO) << "Password handle has wrong length";
-                return GK_ERROR;
+            if (hw_device) {
+                // Hidl Implementations expects passwordHandle to be in
+                // gatekeeper::password_handle_t format.
+                if (currentPasswordHandle->size() != sizeof(gatekeeper::password_handle_t)) {
+                    LOG(INFO) << "Password handle has wrong length";
+                    return GK_ERROR;
+                }
             }
             curPwdHandle.setToExternal(const_cast<uint8_t*>(currentPasswordHandle->data()),
                                        currentPasswordHandle->size());
@@ -199,7 +215,27 @@
         newPwd.setToExternal(const_cast<uint8_t*>(desiredPassword.data()), desiredPassword.size());
 
         uint32_t hw_userId = adjust_userId(userId);
-        Return<void> hwRes = hw_device->enroll(
+        uint64_t secureUserId = 0;
+        if (aidl_hw_device) {
+            // AIDL gatekeeper service
+            AidlGatekeeperEnrollResp rsp;
+            auto result = aidl_hw_device->enroll(hw_userId, curPwdHandle, curPwd, newPwd, &rsp);
+            if (!result.isOk()) {
+                LOG(ERROR) << "enroll transaction failed";
+                return GK_ERROR;
+            }
+            if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
+                *gkResponse = GKResponse::ok({rsp.data.begin(), rsp.data.end()});
+                secureUserId = static_cast<uint64_t>(rsp.secureUserId);
+            } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT &&
+                       rsp.timeoutMs > 0) {
+                *gkResponse = GKResponse::retry(rsp.timeoutMs);
+            } else {
+                *gkResponse = GKResponse::error();
+            }
+        } else if (hw_device) {
+            // HIDL gatekeeper service
+            Return<void> hwRes = hw_device->enroll(
                 hw_userId, curPwdHandle, curPwd, newPwd,
                 [&gkResponse](const GatekeeperResponse& rsp) {
                     if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
@@ -211,22 +247,26 @@
                         *gkResponse = GKResponse::error();
                     }
                 });
-        if (!hwRes.isOk()) {
-            LOG(ERROR) << "enroll transaction failed";
-            return GK_ERROR;
+            if (!hwRes.isOk()) {
+                LOG(ERROR) << "enroll transaction failed";
+                return GK_ERROR;
+            }
+            if (gkResponse->response_code() == GKResponseCode::OK) {
+                if (gkResponse->payload().size() != sizeof(gatekeeper::password_handle_t)) {
+                    LOG(ERROR) << "HAL returned password handle of invalid length "
+                               << gkResponse->payload().size();
+                    return GK_ERROR;
+                }
+
+                const gatekeeper::password_handle_t* handle =
+                    reinterpret_cast<const gatekeeper::password_handle_t*>(
+                        gkResponse->payload().data());
+                secureUserId = handle->user_id;
+            }
         }
 
         if (gkResponse->response_code() == GKResponseCode::OK && !gkResponse->should_reenroll()) {
-            if (gkResponse->payload().size() != sizeof(gatekeeper::password_handle_t)) {
-                LOG(ERROR) << "HAL returned password handle of invalid length "
-                           << gkResponse->payload().size();
-                return GK_ERROR;
-            }
-
-            const gatekeeper::password_handle_t* handle =
-                    reinterpret_cast<const gatekeeper::password_handle_t*>(
-                            gkResponse->payload().data());
-            store_sid(userId, handle->user_id);
+            store_sid(userId, secureUserId);
 
             GKResponse verifyResponse;
             // immediately verify this password so we don't ask the user to enter it again
@@ -260,15 +300,18 @@
         // can't verify if we're missing either param
         if (enrolledPasswordHandle.size() == 0 || providedPassword.size() == 0) return GK_ERROR;
 
-        if (!hw_device) return GK_ERROR;
-
-        if (enrolledPasswordHandle.size() != sizeof(gatekeeper::password_handle_t)) {
-            LOG(INFO) << "Password handle has wrong length";
+        if (!aidl_hw_device && !hw_device) {
+            LOG(ERROR) << "has no HAL to talk to";
             return GK_ERROR;
         }
-        const gatekeeper::password_handle_t* handle =
-                reinterpret_cast<const gatekeeper::password_handle_t*>(
-                        enrolledPasswordHandle.data());
+
+        if (hw_device) {
+            // Hidl Implementations expects passwordHandle to be in gatekeeper::password_handle_t
+            if (enrolledPasswordHandle.size() != sizeof(gatekeeper::password_handle_t)) {
+                LOG(INFO) << "Password handle has wrong length";
+                return GK_ERROR;
+            }
+        }
 
         uint32_t hw_userId = adjust_userId(userId);
         android::hardware::hidl_vec<uint8_t> curPwdHandle;
@@ -278,13 +321,36 @@
         enteredPwd.setToExternal(const_cast<uint8_t*>(providedPassword.data()),
                                  providedPassword.size());
 
-        Return<void> hwRes = hw_device->verify(
+        uint64_t secureUserId = 0;
+        if (aidl_hw_device) {
+            // AIDL gatekeeper service
+            AidlGatekeeperVerifyResp rsp;
+            auto result =
+                aidl_hw_device->verify(hw_userId, challenge, curPwdHandle, enteredPwd, &rsp);
+            if (!result.isOk()) {
+                LOG(ERROR) << "verify transaction failed";
+                return GK_ERROR;
+            }
+            if (rsp.statusCode >= AidlIGatekeeper::STATUS_OK) {
+                secureUserId = rsp.hardwareAuthToken.userId;
+                // Serialize HardwareAuthToken to a vector as hw_auth_token_t.
+                *gkResponse = GKResponse::ok(authToken2AidlVec(rsp.hardwareAuthToken),
+                                             rsp.statusCode ==
+                                                 AidlIGatekeeper::STATUS_REENROLL /* reenroll */);
+            } else if (rsp.statusCode == AidlIGatekeeper::ERROR_RETRY_TIMEOUT) {
+                *gkResponse = GKResponse::retry(rsp.timeoutMs);
+            } else {
+                *gkResponse = GKResponse::error();
+            }
+        } else if (hw_device) {
+            // HIDL gatekeeper service
+            Return<void> hwRes = hw_device->verify(
                 hw_userId, challenge, curPwdHandle, enteredPwd,
                 [&gkResponse](const GatekeeperResponse& rsp) {
                     if (rsp.code >= GatekeeperStatusCode::STATUS_OK) {
                         *gkResponse = GKResponse::ok(
-                                {rsp.data.begin(), rsp.data.end()},
-                                rsp.code == GatekeeperStatusCode::STATUS_REENROLL /* reenroll */);
+                            {rsp.data.begin(), rsp.data.end()},
+                            rsp.code == GatekeeperStatusCode::STATUS_REENROLL /* reenroll */);
                     } else if (rsp.code == GatekeeperStatusCode::ERROR_RETRY_TIMEOUT) {
                         *gkResponse = GKResponse::retry(rsp.timeout);
                     } else {
@@ -292,9 +358,14 @@
                     }
                 });
 
-        if (!hwRes.isOk()) {
-            LOG(ERROR) << "verify transaction failed";
-            return GK_ERROR;
+            if (!hwRes.isOk()) {
+                LOG(ERROR) << "verify transaction failed";
+                return GK_ERROR;
+            }
+            const gatekeeper::password_handle_t* handle =
+                reinterpret_cast<const gatekeeper::password_handle_t*>(
+                    enrolledPasswordHandle.data());
+            secureUserId = handle->user_id;
         }
 
         if (gkResponse->response_code() == GKResponseCode::OK) {
@@ -333,7 +404,7 @@
                 }
             }
 
-            maybe_store_sid(userId, handle->user_id);
+            maybe_store_sid(userId, secureUserId);
         }
 
         return Status::ok();
@@ -354,8 +425,10 @@
         }
         clear_sid(userId);
 
-        if (hw_device) {
-            uint32_t hw_userId = adjust_userId(userId);
+        uint32_t hw_userId = adjust_userId(userId);
+        if (aidl_hw_device) {
+            aidl_hw_device->deleteUser(hw_userId);
+        } else if (hw_device) {
             hw_device->deleteUser(hw_userId, [](const GatekeeperResponse&) {});
         }
         return Status::ok();
@@ -382,7 +455,7 @@
             return PERMISSION_DENIED;
         }
 
-        if (hw_device == NULL) {
+        if (aidl_hw_device == nullptr && hw_device == nullptr) {
             const char* result = "Device not available";
             write(fd, result, strlen(result) + 1);
         } else {
@@ -394,6 +467,9 @@
     }
 
   private:
+    // AIDL gatekeeper service.
+    std::shared_ptr<AidlIGatekeeper> aidl_hw_device;
+    // HIDL gatekeeper service.
     sp<IGatekeeper> hw_device;
 
     bool clear_state_if_needed_done;
@@ -414,8 +490,8 @@
 
     android::sp<android::IServiceManager> sm = android::defaultServiceManager();
     android::sp<android::GateKeeperProxy> proxy = new android::GateKeeperProxy();
-    android::status_t ret = sm->addService(
-            android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
+    android::status_t ret =
+        sm->addService(android::String16("android.service.gatekeeper.IGateKeeperService"), proxy);
     if (ret != android::OK) {
         ALOGE("Couldn't register binder service!");
         return -1;
diff --git a/healthd/healthd_draw.cpp b/healthd/healthd_draw.cpp
index 3e73fcd..7c79319 100644
--- a/healthd/healthd_draw.cpp
+++ b/healthd/healthd_draw.cpp
@@ -99,7 +99,7 @@
     gr_fb_blank(blank, drm);
 }
 
-/* support screen rotation for foldable phone */
+// support screen rotation for foldable phone
 void HealthdDraw::rotate_screen(int drm) {
     if (!graphics_available) return;
     if (drm == 0)
@@ -108,6 +108,11 @@
         gr_rotate(GRRotation::NONE /* Portrait mode */);
 }
 
+// detect dual display
+bool HealthdDraw::has_multiple_connectors() {
+    return graphics_available && gr_has_multiple_connectors();
+}
+
 void HealthdDraw::clear_screen(void) {
     if (!graphics_available) return;
     gr_color(0, 0, 0, 255);
diff --git a/healthd/healthd_draw.h b/healthd/healthd_draw.h
index 3d4abbd..016db8e 100644
--- a/healthd/healthd_draw.h
+++ b/healthd/healthd_draw.h
@@ -38,6 +38,9 @@
   // Rotate screen.
   virtual void rotate_screen(int drm);
 
+  // Detect dual display
+  virtual bool has_multiple_connectors();
+
   static std::unique_ptr<HealthdDraw> Create(animation *anim);
 
  protected:
diff --git a/healthd/healthd_mode_charger.cpp b/healthd/healthd_mode_charger.cpp
index e305a86..1ce174b 100644
--- a/healthd/healthd_mode_charger.cpp
+++ b/healthd/healthd_mode_charger.cpp
@@ -289,6 +289,18 @@
     anim->run = false;
 }
 
+void Charger::BlankSecScreen() {
+    int drm = drm_ == DRM_INNER ? 1 : 0;
+
+    if (!init_screen_) {
+        /* blank the secondary screen */
+        healthd_draw_->blank_screen(false, drm);
+        healthd_draw_->redraw_screen(&batt_anim_, surf_unknown_);
+        healthd_draw_->blank_screen(true, drm);
+        init_screen_ = true;
+    }
+}
+
 void Charger::UpdateScreenState(int64_t now) {
     int disp_time;
 
@@ -315,6 +327,9 @@
         reset_animation(&batt_anim_);
         next_screen_transition_ = -1;
         healthd_draw_->blank_screen(true, static_cast<int>(drm_));
+        if (healthd_draw_->has_multiple_connectors()) {
+            BlankSecScreen();
+        }
         screen_blanked_ = true;
         LOGV("[%" PRId64 "] animation done\n", now);
         if (configuration_->ChargerIsOnline()) {
diff --git a/healthd/include_charger/charger/healthd_mode_charger.h b/healthd/include_charger/charger/healthd_mode_charger.h
index 82e4ddf..c463b92 100644
--- a/healthd/include_charger/charger/healthd_mode_charger.h
+++ b/healthd/include_charger/charger/healthd_mode_charger.h
@@ -108,9 +108,11 @@
     void InitAnimation();
     int RequestEnableSuspend();
     int RequestDisableSuspend();
+    void BlankSecScreen();
 
     bool have_battery_state_ = false;
     bool screen_blanked_ = false;
+    bool init_screen_ = false;
     int64_t next_screen_transition_ = 0;
     int64_t next_key_check_ = 0;
     int64_t next_pwr_check_ = 0;
diff --git a/init/Android.bp b/init/Android.bp
index 0416a7f..f0e362c 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -200,6 +200,7 @@
         "libutils",
         "libziparchive",
     ],
+    header_libs: ["bionic_libc_platform_headers"],
     bootstrap: true,
     visibility: [":__subpackages__"],
 }
@@ -275,7 +276,7 @@
                 "init.rc",
                 "ueventd.rc",
                 "e2fsdroid",
-                "extra_free_kbytes.sh",
+                "extra_free_kbytes",
                 "make_f2fs",
                 "mke2fs",
                 "sload_f2fs",
@@ -529,6 +530,7 @@
         "libcap",
     ],
     export_include_dirs: ["test_utils/include"], // for tests
+    header_libs: ["bionic_libc_platform_headers"],
 }
 
 // Host Verifier
@@ -607,6 +609,7 @@
 }
 
 sh_binary {
-    name: "extra_free_kbytes.sh",
+    name: "extra_free_kbytes",
     src: "extra_free_kbytes.sh",
+    filename_from_src: true,
 }
diff --git a/init/README.md b/init/README.md
index fed81db..7b3d32a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -352,9 +352,10 @@
 
 `socket <name> <type> <perm> [ <user> [ <group> [ <seclabel> ] ] ]`
 > Create a UNIX domain socket named /dev/socket/_name_ and pass its fd to the
-  launched process.  _type_ must be "dgram", "stream" or "seqpacket".  _type_
-  may end with "+passcred" to enable SO_PASSCRED on the socket. User and
-  group default to 0.  'seclabel' is the SELinux security context for the
+  launched process.  The socket is created synchronously when the service starts.
+  _type_ must be "dgram", "stream" or "seqpacket".  _type_ may end with "+passcred"
+  to enable SO_PASSCRED on the socket or "+listen" to synchronously make it a listening socket.
+  User and group default to 0.  'seclabel' is the SELinux security context for the
   socket.  It defaults to the service security context, as specified by
   seclabel or computed based on the service executable file security context.
   For native executables see libcutils android\_get\_control\_socket().
diff --git a/init/extra_free_kbytes.sh b/init/extra_free_kbytes.sh
index aeaa912..a0141be 100755
--- a/init/extra_free_kbytes.sh
+++ b/init/extra_free_kbytes.sh
@@ -77,7 +77,19 @@
     exit
 fi
 
-watermark_scale=`cat /proc/sys/vm/watermark_scale_factor`
+# record the original watermark_scale_factor value
+watermark_scale=$(getprop "ro.kernel.watermark_scale_factor")
+if [ -z "$watermark_scale" ]
+then
+    watermark_scale=$(cat /proc/sys/vm/watermark_scale_factor)
+    setprop "ro.kernel.watermark_scale_factor" "$watermark_scale"
+    # On older distributions with no policies configured setprop may fail.
+    # If that happens, use the kernel default of 10.
+    if [ -z $(getprop "ro.kernel.watermark_scale_factor") ]
+    then
+        watermark_scale=10
+    fi
+fi
 
 # convert extra_free_kbytes to pages
 page_size=$(getconf PAGESIZE)
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 202a86a..107e99a 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -295,9 +295,6 @@
     // stage init
     CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
                     "mode=0755,uid=0,gid=0"))
-
-    // First stage init stores Mainline sepolicy here.
-    CHECKCALL(mkdir("/dev/selinux", 0744));
 #undef CHECKCALL
 
     SetStdioToDevNull(argv);
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 05cf3fd..5c1e9ef 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -246,6 +246,27 @@
             &ServiceList::GetInstance());
 }
 
+void CleanupApexServices() {
+    std::vector<std::string> names;
+    for (const auto& s : ServiceList::GetInstance()) {
+        names.push_back(s->name());
+    }
+
+    for (const auto& name : names) {
+        auto s = ServiceList::GetInstance().FindService(name);
+        auto pid = s->pid();
+        ServiceList::GetInstance().RemoveService(*s);
+        if (pid > 0) {
+            kill(pid, SIGTERM);
+            kill(pid, SIGKILL);
+        }
+    }
+
+    ActionManager::GetInstance().RemoveActionIf([&](const std::unique_ptr<Action>& s) -> bool {
+        return true;
+    });
+}
+
 void TestApexServicesInit(const std::vector<std::string>& apex_services,
             const std::vector<std::string>& other_apex_services,
             const std::vector<std::string> non_apex_services) {
@@ -270,16 +291,14 @@
     TestRemoveApexService(other_apex_services, /*exist*/ true);
     TestRemoveApexService(non_apex_services, /*exist*/ true);
 
-    ServiceList::GetInstance().RemoveServiceIf([&](const std::unique_ptr<Service>& s) -> bool {
-        return true;
-    });
-
-    ActionManager::GetInstance().RemoveActionIf([&](const std::unique_ptr<Action>& s) -> bool {
-        return true;
-    });
+    CleanupApexServices();
 }
 
 TEST(init, StopServiceByApexName) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string_view script_template = R"init(
 service apex_test_service /system/bin/yes
     user shell
@@ -291,6 +310,10 @@
 }
 
 TEST(init, StopMultipleServicesByApexName) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string_view script_template = R"init(
 service apex_test_service_multiple_a /system/bin/yes
     user shell
@@ -307,6 +330,10 @@
 }
 
 TEST(init, StopServicesFromMultipleApexes) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string_view apex_script_template = R"init(
 service apex_test_service_multi_apex_a /system/bin/yes
     user shell
@@ -332,6 +359,10 @@
 }
 
 TEST(init, StopServicesFromApexAndNonApex) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string_view apex_script_template = R"init(
 service apex_test_service_apex_a /system/bin/yes
     user shell
@@ -357,6 +388,10 @@
 }
 
 TEST(init, StopServicesFromApexMixed) {
+    if (getuid() != 0) {
+        GTEST_SKIP() << "Must be run as root.";
+        return;
+    }
     std::string_view script_template = R"init(
 service apex_test_service_mixed_a /system/bin/yes
     user shell
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 7e92538..c2ba8d5 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -1404,7 +1404,8 @@
     StartSendingMessages();
 
     if (auto result = CreateSocket(PROP_SERVICE_NAME, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
-                                   false, 0666, 0, 0, {});
+                                   /*passcred=*/false, /*should_listen=*/false, 0666, /*uid=*/0,
+                                   /*gid=*/0, /*socketcon=*/{});
         result.ok()) {
         property_set_fd = *result;
     } else {
diff --git a/init/selinux.cpp b/init/selinux.cpp
index be8c554..ab5b0a0 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -237,9 +237,9 @@
     // If there is an odm partition, precompiled_sepolicy will be in
     // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
     static constexpr const char vendor_precompiled_sepolicy[] =
-        "/vendor/etc/selinux/precompiled_sepolicy";
+            "/vendor/etc/selinux/precompiled_sepolicy";
     static constexpr const char odm_precompiled_sepolicy[] =
-        "/odm/etc/selinux/precompiled_sepolicy";
+            "/odm/etc/selinux/precompiled_sepolicy";
     if (access(odm_precompiled_sepolicy, R_OK) == 0) {
         precompiled_sepolicy = odm_precompiled_sepolicy;
     } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
@@ -525,6 +525,32 @@
                                              "apex_service_contexts", "apex_seapp_contexts",
                                              "apex_test"};
 
+Result<void> CreateTmpfsDir() {
+    mode_t mode = 0744;
+    struct stat stat_data;
+    if (stat(kTmpfsDir.c_str(), &stat_data) != 0) {
+        if (errno != ENOENT) {
+            return ErrnoError() << "Could not stat " << kTmpfsDir;
+        }
+        if (mkdir(kTmpfsDir.c_str(), mode) != 0) {
+            return ErrnoError() << "Could not mkdir " << kTmpfsDir;
+        }
+    } else {
+        if (!S_ISDIR(stat_data.st_mode)) {
+            return Error() << kTmpfsDir << " exists and is not a directory.";
+        }
+        LOG(WARNING) << "Directory " << kTmpfsDir << " already exists";
+    }
+
+    // Need to manually call chmod because mkdir will create a folder with
+    // permissions mode & ~umask.
+    if (chmod(kTmpfsDir.c_str(), mode) != 0) {
+        return ErrnoError() << "Could not chmod " << kTmpfsDir;
+    }
+
+    return {};
+}
+
 Result<void> PutFileInTmpfs(ZipArchiveHandle archive, const std::string& fileName) {
     ZipEntry entry;
     std::string dstPath = kTmpfsDir + fileName;
@@ -538,7 +564,7 @@
     unique_fd fd(TEMP_FAILURE_RETRY(
             open(dstPath.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, S_IRUSR | S_IWUSR)));
     if (fd == -1) {
-        return Error() << "Failed to open " << dstPath;
+        return ErrnoError() << "Failed to open " << dstPath;
     }
 
     ret = ExtractEntryToFile(archive, &entry, fd);
@@ -568,6 +594,11 @@
 
     auto handle_guard = android::base::make_scope_guard([&handle] { CloseArchive(handle); });
 
+    auto create = CreateTmpfsDir();
+    if (!create.ok()) {
+        return create.error();
+    }
+
     for (const auto& file : kApexSepolicy) {
         auto extract = PutFileInTmpfs(handle, file);
         if (!extract.ok()) {
diff --git a/init/service.cpp b/init/service.cpp
index 99a0367..a633048 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -36,10 +36,16 @@
 #include <processgroup/processgroup.h>
 #include <selinux/selinux.h>
 
+#include <string>
+
 #include "lmkd_service.h"
 #include "service_list.h"
 #include "util.h"
 
+#if defined(__BIONIC__)
+#include <bionic/reserved_signals.h>
+#endif
+
 #ifdef INIT_FULL_SOURCES
 #include <ApexProperties.sysprop.h>
 #include <android/api-level.h>
@@ -53,6 +59,7 @@
 
 using android::base::boot_clock;
 using android::base::GetBoolProperty;
+using android::base::GetIntProperty;
 using android::base::GetProperty;
 using android::base::Join;
 using android::base::make_scope_guard;
@@ -320,6 +327,34 @@
             mount_namespace_.has_value() && *mount_namespace_ == NS_DEFAULT;
     const bool is_process_updatable = use_default_mount_ns && is_apex_updatable;
 
+#if defined(__BIONIC__) && defined(SEGV_MTEAERR)
+    // As a precaution, we only upgrade a service once per reboot, to limit
+    // the potential impact.
+    //
+    // BIONIC_SIGNAL_ART_PROFILER is a magic value used by deuggerd to signal
+    // that the process crashed with SIGSEGV and SEGV_MTEAERR. This signal will
+    // never be seen otherwise in a crash, because it always gets handled by the
+    // profiling signal handlers in bionic. See also
+    // debuggerd/handler/debuggerd_handler.cpp.
+    bool should_upgrade_mte = siginfo.si_code != CLD_EXITED &&
+                              siginfo.si_status == BIONIC_SIGNAL_ART_PROFILER && !upgraded_mte_;
+
+    if (should_upgrade_mte) {
+        constexpr int kDefaultUpgradeSecs = 60;
+        int secs = GetIntProperty("persist.device_config.memory_safety_native.upgrade_secs.default",
+                                  kDefaultUpgradeSecs);
+        secs = GetIntProperty(
+                "persist.device_config.memory_safety_native.upgrade_secs.service." + name_, secs);
+        if (secs > 0) {
+            LOG(INFO) << "Upgrading service " << name_ << " to sync MTE for " << secs << " seconds";
+            once_environment_vars_.emplace_back("BIONIC_MEMTAG_UPGRADE_SECS", std::to_string(secs));
+            upgraded_mte_ = true;
+        } else {
+            LOG(INFO) << "Not upgrading service " << name_ << " to sync MTE due to device config";
+        }
+    }
+#endif
+
     // If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
@@ -484,6 +519,9 @@
         LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
     }
 
+    for (const auto& [key, value] : once_environment_vars_) {
+        setenv(key.c_str(), value.c_str(), 1);
+    }
     for (const auto& [key, value] : environment_vars_) {
         setenv(key.c_str(), value.c_str(), 1);
     }
@@ -628,6 +666,8 @@
         return ErrnoError() << "Failed to fork";
     }
 
+    once_environment_vars_.clear();
+
     if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
         std::string oom_str = std::to_string(oom_score_adjust_);
         std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);
diff --git a/init/service.h b/init/service.h
index 6d9a0ca..ab19865 100644
--- a/init/service.h
+++ b/init/service.h
@@ -171,6 +171,7 @@
     android::base::boot_clock::time_point time_started_;  // time of last start
     android::base::boot_clock::time_point time_crashed_;  // first crash within inspection window
     int crash_count_;                     // number of times crashed within window
+    bool upgraded_mte_ = false;           // whether we upgraded async MTE -> sync MTE before
     std::chrono::minutes fatal_crash_window_ = 4min;  // fatal() when more than 4 crashes in it
     std::optional<std::string> fatal_reboot_target_;  // reboot target of fatal handler
 
@@ -183,6 +184,8 @@
     std::vector<SocketDescriptor> sockets_;
     std::vector<FileDescriptor> files_;
     std::vector<std::pair<std::string, std::string>> environment_vars_;
+    // Environment variables that only get applied to the next run.
+    std::vector<std::pair<std::string, std::string>> once_environment_vars_;
 
     Subcontext* subcontext_;
     Action onrestart_;  // Commands to execute on restart.
diff --git a/init/service_parser.cpp b/init/service_parser.cpp
index 32c57c4..24a2024 100644
--- a/init/service_parser.cpp
+++ b/init/service_parser.cpp
@@ -434,11 +434,14 @@
                        << "' instead.";
     }
 
-    if (types.size() > 1) {
-        if (types.size() == 2 && types[1] == "passcred") {
+    for (size_t i = 1; i < types.size(); i++) {
+        if (types[i] == "passcred") {
             socket.passcred = true;
+        } else if (types[i] == "listen") {
+            socket.listen = true;
         } else {
-            return Error() << "Only 'passcred' may be used to modify the socket type";
+            return Error() << "Unknown socket type decoration '" << types[i]
+                           << "'. Known values are ['passcred', 'listen']";
         }
     }
 
diff --git a/init/service_utils.cpp b/init/service_utils.cpp
index eed5c65..d19f5ee 100644
--- a/init/service_utils.cpp
+++ b/init/service_utils.cpp
@@ -168,7 +168,8 @@
 
 Result<Descriptor> SocketDescriptor::Create(const std::string& global_context) const {
     const auto& socket_context = context.empty() ? global_context : context;
-    auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, perm, uid, gid, socket_context);
+    auto result = CreateSocket(name, type | SOCK_CLOEXEC, passcred, listen, perm, uid, gid,
+                               socket_context);
     if (!result.ok()) {
         return result.error();
     }
diff --git a/init/service_utils.h b/init/service_utils.h
index 9b65dca..65a2012 100644
--- a/init/service_utils.h
+++ b/init/service_utils.h
@@ -54,6 +54,7 @@
     int perm = 0;
     std::string context;
     bool passcred = false;
+    bool listen = false;
     bool persist = false;
 
     // Create() creates the named unix domain socket in /dev/socket and returns a Descriptor object.
diff --git a/init/test_upgrade_mte/Android.bp b/init/test_upgrade_mte/Android.bp
new file mode 100644
index 0000000..1bfc76c
--- /dev/null
+++ b/init/test_upgrade_mte/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2022 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.
+
+package {
+    default_applicable_licenses: ["system_core_init_license"],
+}
+
+cc_binary {
+  name: "mte_upgrade_test_helper",
+  srcs: ["mte_upgrade_test_helper.cpp"],
+  sanitize: {
+    memtag_heap: true,
+    diag: {
+      memtag_heap: false,
+    },
+  },
+  init_rc: [
+    "mte_upgrade_test.rc",
+  ],
+}
+
+java_test_host {
+    name: "mte_upgrade_test",
+    libs: ["tradefed"],
+    static_libs: ["frameworks-base-hostutils", "cts-install-lib-host"],
+    srcs:  ["src/**/MteUpgradeTest.java", ":libtombstone_proto-src"],
+    data: [":mte_upgrade_test_helper", "mte_upgrade_test.rc" ],
+    test_config: "AndroidTest.xml",
+    test_suites: ["general-tests"],
+}
diff --git a/init/test_upgrade_mte/AndroidTest.xml b/init/test_upgrade_mte/AndroidTest.xml
new file mode 100644
index 0000000..b89cde8
--- /dev/null
+++ b/init/test_upgrade_mte/AndroidTest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Runs the MTE upgrade tests">
+    <option name="test-suite-tag" value="init_test_upgrade_mte" />
+    <option name="test-suite-tag" value="apct" />
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+      <option name="cleanup" value="true" />
+      <option name="remount-system" value="true" />
+      <option name="push" value="mte_upgrade_test.rc->/system/etc/init/mte_upgrade_test.rc" />
+      <option name="push" value="mte_upgrade_test_helper->/system/bin/mte_upgrade_test_helper" />
+      <option name="push" value="mte_upgrade_test_helper->/data/local/tmp/app_process64" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.HostTest" >
+        <option name="jar" value="mte_upgrade_test.jar" />
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/init/test_upgrade_mte/mte_upgrade_test.rc b/init/test_upgrade_mte/mte_upgrade_test.rc
new file mode 100644
index 0000000..a3e596c
--- /dev/null
+++ b/init/test_upgrade_mte/mte_upgrade_test.rc
@@ -0,0 +1,24 @@
+# Copyright (C) 2022 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.
+
+service mte_upgrade_test_helper /system/bin/mte_upgrade_test_helper ${sys.mte_crash_test_uuid}
+  class late_start
+  disabled
+  seclabel u:r:su:s0
+
+service mte_upgrade_test_helper_overridden /system/bin/mte_upgrade_test_helper ${sys.mte_crash_test_uuid}
+  class late_start
+  disabled
+  seclabel u:r:su:s0
+  setenv BIONIC_MEMTAG_UPGRADE_SECS 0
diff --git a/init/test_upgrade_mte/mte_upgrade_test_helper.cpp b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
new file mode 100644
index 0000000..10af06b
--- /dev/null
+++ b/init/test_upgrade_mte/mte_upgrade_test_helper.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 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 <linux/prctl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/prctl.h>
+#include <time.h>
+#include <unistd.h>
+
+int MaybeDowngrade() {
+    int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+    if (res == -1) return 1;
+    if (static_cast<unsigned long>(res) & PR_MTE_TCF_ASYNC) return 2;
+    time_t t = time(nullptr);
+    while (time(nullptr) - t < 100) {
+        res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+        if (static_cast<unsigned long>(res) & PR_MTE_TCF_ASYNC) {
+            return 0;
+        }
+        sleep(1);
+    }
+    return 3;
+}
+
+int main(int argc, char** argv) {
+    if (argc == 2 && strcmp(argv[1], "--check-downgrade") == 0) {
+        return MaybeDowngrade();
+    }
+    int res = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);
+    if (res == -1) abort();
+    if (argc == 2 && strcmp(argv[1], "--get-mode") == 0) {
+        if (res & PR_MTE_TCF_ASYNC) {
+            return 1;
+        }
+        if (res & PR_MTE_TCF_SYNC) {
+            return 2;
+        }
+        abort();
+    }
+
+    if (res & PR_MTE_TCF_ASYNC && res & PR_MTE_TCF_SYNC) {
+        // Disallow automatic upgrade from ASYNC mode.
+        if (prctl(PR_SET_TAGGED_ADDR_CTRL, res & ~PR_MTE_TCF_SYNC, 0, 0, 0) == -1) abort();
+    }
+    volatile char* f = (char*)malloc(1);
+    f[17] = 'x';
+    char buf[1];
+    read(1, buf, 1);
+    return 0;
+}
diff --git a/init/test_upgrade_mte/src/com/android/tests/init/MteUpgradeTest.java b/init/test_upgrade_mte/src/com/android/tests/init/MteUpgradeTest.java
new file mode 100644
index 0000000..f4e4a9c
--- /dev/null
+++ b/init/test_upgrade_mte/src/com/android/tests/init/MteUpgradeTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+package com.android.tests.init;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeTrue;
+
+import com.android.server.os.TombstoneProtos.Tombstone;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class MteUpgradeTest extends BaseHostJUnit4Test {
+    @Before
+    public void setUp() throws Exception {
+        CommandResult result =
+                getDevice().executeShellV2Command("/system/bin/mte_upgrade_test_helper --checking");
+        assumeTrue("mte_upgrade_test_binary needs to segfault", result.getExitCode() == 139);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        // Easier here than in a finally in testCrash, and doesn't really hurt.
+        getDevice().executeShellV2Command("stop mte_upgrade_test_helper");
+        getDevice().executeShellV2Command("stop mte_upgrade_test_helper_overridden");
+        getDevice().setProperty("sys.mte_crash_test_uuid", "");
+    }
+
+    Tombstone parseTombstone(String tombstonePath) throws Exception {
+        File tombstoneFile = getDevice().pullFile(tombstonePath);
+        InputStream istr = new FileInputStream(tombstoneFile);
+        Tombstone tombstoneProto;
+        try {
+            tombstoneProto = Tombstone.parseFrom(istr);
+        } finally {
+            istr.close();
+        }
+        return tombstoneProto;
+    }
+
+    @Test
+    public void testCrash() throws Exception {
+        String uuid = java.util.UUID.randomUUID().toString();
+        getDevice().reboot();
+        assertThat(getDevice().setProperty("sys.mte_crash_test_uuid", uuid)).isTrue();
+
+        CommandResult result = getDevice().executeShellV2Command("start mte_upgrade_test_helper");
+        assertThat(result.getExitCode()).isEqualTo(0);
+        java.lang.Thread.sleep(20000);
+        String[] tombstonesAfter = getDevice().getChildren("/data/tombstones");
+        ArrayList<String> segvCodeNames = new ArrayList<String>();
+        for (String tombstone : tombstonesAfter) {
+            if (!tombstone.endsWith(".pb")) {
+                continue;
+            }
+            String tombstoneFilename = "/data/tombstones/" + tombstone;
+            Tombstone tombstoneProto = parseTombstone(tombstoneFilename);
+            if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(uuid))) {
+                continue;
+            }
+            assertThat(tombstoneProto.getSignalInfo().getName()).isEqualTo("SIGSEGV");
+            segvCodeNames.add(tombstoneProto.getSignalInfo().getCodeName());
+            getDevice().deleteFile(tombstoneFilename);
+            // remove the non .pb file as well.
+            getDevice().deleteFile(tombstoneFilename.substring(0, tombstoneFilename.length() - 3));
+        }
+        assertThat(segvCodeNames.size()).isAtLeast(3);
+        assertThat(segvCodeNames.get(0)).isEqualTo("SEGV_MTEAERR");
+        assertThat(segvCodeNames.get(1)).isEqualTo("SEGV_MTESERR");
+        assertThat(segvCodeNames.get(2)).isEqualTo("SEGV_MTEAERR");
+    }
+
+    @Test
+    public void testCrashOverridden() throws Exception {
+        String uuid = java.util.UUID.randomUUID().toString();
+        getDevice().reboot();
+        assertThat(getDevice().setProperty("sys.mte_crash_test_uuid", uuid)).isTrue();
+
+        CommandResult result =
+                getDevice().executeShellV2Command("start mte_upgrade_test_helper_overridden");
+        assertThat(result.getExitCode()).isEqualTo(0);
+        java.lang.Thread.sleep(20000);
+        String[] tombstonesAfter = getDevice().getChildren("/data/tombstones");
+        ArrayList<String> segvCodeNames = new ArrayList<String>();
+        for (String tombstone : tombstonesAfter) {
+            if (!tombstone.endsWith(".pb")) {
+                continue;
+            }
+            String tombstoneFilename = "/data/tombstones/" + tombstone;
+            Tombstone tombstoneProto = parseTombstone(tombstoneFilename);
+            if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(uuid))) {
+                continue;
+            }
+            assertThat(tombstoneProto.getSignalInfo().getName()).isEqualTo("SIGSEGV");
+            segvCodeNames.add(tombstoneProto.getSignalInfo().getCodeName());
+            getDevice().deleteFile(tombstoneFilename);
+            // remove the non .pb file as well.
+            getDevice().deleteFile(tombstoneFilename.substring(0, tombstoneFilename.length() - 3));
+        }
+        assertThat(segvCodeNames.size()).isAtLeast(3);
+        assertThat(segvCodeNames.get(0)).isEqualTo("SEGV_MTEAERR");
+        assertThat(segvCodeNames.get(1)).isEqualTo("SEGV_MTEAERR");
+        assertThat(segvCodeNames.get(2)).isEqualTo("SEGV_MTEAERR");
+    }
+
+    @Test
+    public void testDowngrade() throws Exception {
+        CommandResult result =
+                getDevice()
+                        .executeShellV2Command(
+                                "MEMTAG_OPTIONS=async BIONIC_MEMTAG_UPGRADE_SECS=5"
+                                        + " /system/bin/mte_upgrade_test_helper --check-downgrade");
+        assertThat(result.getExitCode()).isEqualTo(0);
+    }
+
+    @Test
+    public void testAppProcess() throws Exception {
+        CommandResult result =
+                getDevice()
+                        .executeShellV2Command(
+                                "MEMTAG_OPTIONS=async BIONIC_MEMTAG_UPGRADE_SECS=5"
+                                        + " /data/local/tmp/app_process64 --get-mode");
+        assertThat(result.getExitCode()).isEqualTo(1);  // ASYNC
+    }
+}
diff --git a/init/util.cpp b/init/util.cpp
index 2d40142..3d42855 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -89,8 +89,8 @@
  * daemon. We communicate the file descriptor's value via the environment
  * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
  */
-Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
-                         gid_t gid, const std::string& socketcon) {
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, bool should_listen,
+                         mode_t perm, uid_t uid, gid_t gid, const std::string& socketcon) {
     if (!socketcon.empty()) {
         if (setsockcreatecon(socketcon.c_str()) == -1) {
             return ErrnoError() << "setsockcreatecon(\"" << socketcon << "\") failed";
@@ -145,6 +145,9 @@
     if (fchmodat(AT_FDCWD, addr.sun_path, perm, AT_SYMLINK_NOFOLLOW)) {
         return ErrnoError() << "Failed to fchmodat socket '" << addr.sun_path << "'";
     }
+    if (should_listen && listen(fd, /* use OS maximum */ 1 << 30)) {
+        return ErrnoError() << "Failed to listen on socket '" << addr.sun_path << "'";
+    }
 
     LOG(INFO) << "Created socket '" << addr.sun_path << "'"
               << ", mode " << std::oct << perm << std::dec
diff --git a/init/util.h b/init/util.h
index 0181bf0..e58e70e 100644
--- a/init/util.h
+++ b/init/util.h
@@ -44,8 +44,8 @@
 
 extern void (*trigger_shutdown)(const std::string& command);
 
-Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
-                         gid_t gid, const std::string& socketcon);
+Result<int> CreateSocket(const std::string& name, int type, bool passcred, bool should_listen,
+                         mode_t perm, uid_t uid, gid_t gid, const std::string& socketcon);
 
 Result<std::string> ReadFile(const std::string& path);
 Result<void> WriteFile(const std::string& path, const std::string& content);
diff --git a/janitors/OWNERS b/janitors/OWNERS
index 3e32c26..e132f0b 100644
--- a/janitors/OWNERS
+++ b/janitors/OWNERS
@@ -2,5 +2,5 @@
 ccross@google.com
 dwillemsen@google.com
 enh@google.com
-hhb@google.com
 narayan@google.com
+sadafebrahimi@google.com
\ No newline at end of file
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index c8bfb01..fde30ad 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -168,6 +168,9 @@
     target: {
         linux_bionic: {
             enabled: true,
+            static_libs: [
+                "libasync_safe",
+            ],
         },
         not_windows: {
             srcs: libcutils_nonwindows_sources + [
@@ -190,6 +193,9 @@
             ],
         },
         android: {
+            static_libs: [
+                "libasync_safe",
+            ],
             srcs: libcutils_nonwindows_sources + [
                 "android_reboot.cpp",
                 "ashmem-dev.cpp",
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index 4f07456..e46e7cd 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -49,18 +49,28 @@
 typedef const native_handle_t* buffer_handle_t;
 
 /*
- * native_handle_close
- * 
- * closes the file descriptors contained in this native_handle_t
- * 
+ * Closes the file descriptors contained in this native_handle_t, which may
+ * either be untagged or tagged for ownership by this native_handle_t via
+ * native_handle_set_tag(). Mixing untagged and tagged fds in the same
+ * native_handle_t is not permitted and triggers an fdsan exception, but
+ * native_handle_set_fdsan_tag() can be used to bring consistency if this is
+ * intentional.
+ *
+ * If it's known that fds are tagged, prefer native_handle_close_with_tag() for
+ * better safety.
+ *
  * return 0 on success, or a negative error code on failure
- * 
  */
 int native_handle_close(const native_handle_t* h);
 
 /*
- * native_handle_init
- *
+ * Equivalent to native_handle_close(), but throws an fdsan exception if the fds
+ * are untagged. Use if it's known that the fds in this native_handle_t were
+ * previously tagged via native_handle_set_tag().
+ */
+int native_handle_close_with_tag(const native_handle_t* h);
+
+/*
  * Initializes a native_handle_t from storage.  storage must be declared with
  * NATIVE_HANDLE_DECLARE_STORAGE.  numFds and numInts must not respectively
  * exceed maxFds and maxInts used to declare the storage.
@@ -68,33 +78,42 @@
 native_handle_t* native_handle_init(char* storage, int numFds, int numInts);
 
 /*
- * native_handle_create
- *
- * creates a native_handle_t and initializes it. must be destroyed with
+ * Creates a native_handle_t and initializes it. Must be destroyed with
  * 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);
 
 /*
- * native_handle_clone
- *
- * creates a native_handle_t and initializes it from another native_handle_t.
+ * Updates the fdsan tag for any file descriptors contained in the supplied
+ * handle to indicate that they are owned by this handle and should only be
+ * closed via native_handle_close()/native_handle_close_with_tag(). Each fd in
+ * the handle must have a tag of either 0 (unset) or the tag associated with
+ * this handle, otherwise an fdsan exception will be triggered.
+ */
+void native_handle_set_fdsan_tag(const native_handle_t* handle);
+
+/*
+ * Clears the fdsan tag for any file descriptors contained in the supplied
+ * native_handle_t. Use if this native_handle_t is giving up ownership of its
+ * fds, but the fdsan tags were previously set. Each fd in the handle must have
+ * a tag of either 0 (unset) or the tag associated with this handle, otherwise
+ * an fdsan exception will be triggered.
+ */
+void native_handle_unset_fdsan_tag(const native_handle_t* handle);
+
+/*
+ * Creates a native_handle_t and initializes it from another native_handle_t.
  * Must be destroyed with native_handle_delete().
- *
  */
 native_handle_t* native_handle_clone(const native_handle_t* handle);
 
 /*
- * native_handle_delete
- * 
- * frees a native_handle_t allocated with native_handle_create().
+ * Frees a native_handle_t allocated with native_handle_create().
  * This ONLY frees the memory allocated for the native_handle_t, but doesn't
  * close the file descriptors; which can be achieved with native_handle_close().
- * 
+ *
  * return 0 on success, or a negative error code on failure
- * 
  */
 int native_handle_delete(native_handle_t* h);
 
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index da5005c..1e035bb 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -140,6 +140,7 @@
 #define AID_JC_IDENTITYCRED 1089  /* Javacard Identity Cred HAL - to manage omapi ARA rules */
 #define AID_SDK_SANDBOX 1090      /* SDK sandbox virtual UID */
 #define AID_SECURITY_LOG_WRITER 1091 /* write to security log */
+#define AID_PRNG_SEEDER 1092         /* PRNG seeder daemon */
 /* Changes to this file must be made in AOSP, *not* in internal branches. */
 
 #define AID_SHELL 2000 /* adb and debug shell user */
diff --git a/libcutils/native_handle.cpp b/libcutils/native_handle.cpp
index 5804ab1..b85c93b 100644
--- a/libcutils/native_handle.cpp
+++ b/libcutils/native_handle.cpp
@@ -22,13 +22,74 @@
 #include <string.h>
 #include <unistd.h>
 
+// Needs to come after stdlib includes to capture the __BIONIC__ definition
+#ifdef __BIONIC__
+#include <android/fdsan.h>
+#endif
+
+namespace {
+
+#if !defined(__BIONIC__)
+// fdsan stubs when not linked against bionic
+#define ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE 0
+
+uint64_t android_fdsan_create_owner_tag(int /*type*/, uint64_t /*tag*/) {
+    return 0;
+}
+uint64_t android_fdsan_get_owner_tag(int /*fd*/) {
+    return 0;
+}
+int android_fdsan_close_with_tag(int fd, uint64_t /*tag*/) {
+    return close(fd);
+}
+void android_fdsan_exchange_owner_tag(int /*fd*/, uint64_t /*expected_tag*/, uint64_t /*tag*/) {}
+#endif  // !__BIONIC__
+
+uint64_t get_fdsan_tag(const native_handle_t* handle) {
+    return android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_NATIVE_HANDLE,
+                                          reinterpret_cast<uint64_t>(handle));
+}
+
+int close_internal(const native_handle_t* h, bool allowUntagged) {
+    if (!h) return 0;
+
+    if (h->version != sizeof(native_handle_t)) return -EINVAL;
+
+    const int numFds = h->numFds;
+    uint64_t tag;
+    if (allowUntagged && numFds > 0 && android_fdsan_get_owner_tag(h->data[0]) == 0) {
+        tag = 0;
+    } else {
+        tag = get_fdsan_tag(h);
+    }
+    int saved_errno = errno;
+    for (int i = 0; i < numFds; ++i) {
+        android_fdsan_close_with_tag(h->data[i], tag);
+    }
+    errno = saved_errno;
+    return 0;
+}
+
+void swap_fdsan_tags(const native_handle_t* handle, uint64_t expected_tag, uint64_t new_tag) {
+    if (!handle || handle->version != sizeof(native_handle_t)) return;
+
+    for (int i = 0; i < handle->numFds; i++) {
+        // allow for idempotence to make the APIs easier to use
+        if (android_fdsan_get_owner_tag(handle->data[i]) != new_tag) {
+            android_fdsan_exchange_owner_tag(handle->data[i], expected_tag, new_tag);
+        }
+    }
+}
+
+}  // anonymous namespace
+
 native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
-    if ((uintptr_t) storage % alignof(native_handle_t)) {
+    if ((uintptr_t)storage % alignof(native_handle_t)) {
         errno = EINVAL;
         return NULL;
     }
 
-    native_handle_t* handle = (native_handle_t*) storage;
+    native_handle_t* handle = (native_handle_t*)storage;
     handle->version = sizeof(native_handle_t);
     handle->numFds = numFds;
     handle->numInts = numInts;
@@ -52,6 +113,14 @@
     return h;
 }
 
+void native_handle_set_fdsan_tag(const native_handle_t* handle) {
+    swap_fdsan_tags(handle, 0, get_fdsan_tag(handle));
+}
+
+void native_handle_unset_fdsan_tag(const native_handle_t* handle) {
+    swap_fdsan_tags(handle, get_fdsan_tag(handle), 0);
+}
+
 native_handle_t* native_handle_clone(const native_handle_t* handle) {
     native_handle_t* clone = native_handle_create(handle->numFds, handle->numInts);
     if (clone == NULL) return NULL;
@@ -81,15 +150,9 @@
 }
 
 int native_handle_close(const native_handle_t* h) {
-    if (!h) return 0;
+    return close_internal(h, /*allowUntagged=*/true);
+}
 
-    if (h->version != sizeof(native_handle_t)) return -EINVAL;
-
-    int saved_errno = errno;
-    const int numFds = h->numFds;
-    for (int i = 0; i < numFds; ++i) {
-        close(h->data[i]);
-    }
-    errno = saved_errno;
-    return 0;
+int native_handle_close_with_tag(const native_handle_t* h) {
+    return close_internal(h, /*allowUntagged=*/false);
 }
diff --git a/libprocessgroup/cgrouprc/libcgrouprc.map.txt b/libprocessgroup/cgrouprc/libcgrouprc.map.txt
index ce5c419..b62b10f 100644
--- a/libprocessgroup/cgrouprc/libcgrouprc.map.txt
+++ b/libprocessgroup/cgrouprc/libcgrouprc.map.txt
@@ -1,18 +1,18 @@
 LIBCGROUPRC { # introduced=29
   global:
-    ACgroupFile_getVersion;
-    ACgroupFile_getControllerCount;
-    ACgroupFile_getController;
-    ACgroupController_getVersion;
-    ACgroupController_getName;
-    ACgroupController_getPath;
+    ACgroupFile_getVersion; # llndk systemapi
+    ACgroupFile_getControllerCount; # llndk systemapi
+    ACgroupFile_getController; # llndk systemapi
+    ACgroupController_getVersion; # llndk systemapi
+    ACgroupController_getName; # llndk systemapi
+    ACgroupController_getPath; # llndk systemapi
   local:
     *;
 };
 
 LIBCGROUPRC_30 { # introduced=30
   global:
-    ACgroupController_getFlags;
+    ACgroupController_getFlags; # llndk systemapi
   local:
     *;
 };
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 02bfee6..8e83e16 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -80,16 +80,12 @@
 }
 
 python_binary_host {
-    name: "simg_dump.py",
+    name: "simg_dump",
     main: "simg_dump.py",
     srcs: ["simg_dump.py"],
     version: {
-        py2: {
-            enabled: false,
-        },
         py3: {
             embedded_launcher: true,
-            enabled: true,
         },
     },
 }
diff --git a/libsparse/simg_dump.py b/libsparse/simg_dump.py
index 8811a52..47537ca 100755
--- a/libsparse/simg_dump.py
+++ b/libsparse/simg_dump.py
@@ -158,7 +158,7 @@
           curtype = format("Fill with 0x%08X" % (fill))
           if showhash:
             h = hashlib.sha1()
-            data = fill_bin * (blk_sz / 4);
+            data = fill_bin * (blk_sz // 4);
             for block in range(chunk_sz):
               h.update(data)
             curhash = h.hexdigest()
diff --git a/libsync/Android.bp b/libsync/Android.bp
index 99c88cf..b6b4a6e 100644
--- a/libsync/Android.bp
+++ b/libsync/Android.bp
@@ -27,6 +27,9 @@
     name: "libsync",
     symbol_file: "libsync.map.txt",
     first_version: "26",
+    export_header_libs: [
+        "libsync_headers",
+    ],
 }
 
 cc_defaults {
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 7939e82..c744b53 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -299,6 +299,7 @@
 
     srcs: [
         "BitSet_test.cpp",
+        "CallStack_test.cpp",
         "Errors_test.cpp",
         "FileMap_test.cpp",
         "LruCache_test.cpp",
@@ -319,11 +320,14 @@
                 "SystemClock_test.cpp",
             ],
             shared_libs: [
-                "libz",
-                "liblog",
-                "libcutils",
-                "libutils",
                 "libbase",
+                "libcutils",
+                "liblog",
+                "liblzma",
+                "libunwindstack",
+                "libutils",
+                "libutilscallstack",
+                "libz",
             ],
         },
         linux: {
@@ -334,9 +338,12 @@
         },
         host: {
             static_libs: [
-                "libutils",
-                "liblog",
                 "libbase",
+                "liblog",
+                "liblzma",
+                "libunwindstack_no_dex",
+                "libutils",
+                "libutilscallstack",
             ],
         },
     },
diff --git a/libutils/CallStack.cpp b/libutils/CallStack.cpp
index f19ba6a..4dcb35b 100644
--- a/libutils/CallStack.cpp
+++ b/libutils/CallStack.cpp
@@ -49,7 +49,7 @@
     unwindstack::AndroidUnwinderData data;
     std::optional<pid_t> tid_val;
     if (tid != -1) {
-        *tid_val = tid;
+        tid_val = tid;
     }
     if (!unwinder.Unwind(tid_val, data)) {
         ALOGW("%s: Failed to unwind callstack: %s", __FUNCTION__, data.GetErrorString().c_str());
diff --git a/libutils/CallStack_test.cpp b/libutils/CallStack_test.cpp
new file mode 100644
index 0000000..2cfaf61
--- /dev/null
+++ b/libutils/CallStack_test.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2022 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 <unistd.h>
+
+#include <thread>
+
+#include <android-base/threads.h>
+#include <gtest/gtest.h>
+#include <utils/CallStack.h>
+
+__attribute__((__noinline__)) extern "C" void CurrentCaller(android::String8& backtrace) {
+    android::CallStack cs;
+    cs.update();
+    backtrace = cs.toString();
+}
+
+TEST(CallStackTest, current_backtrace) {
+    android::String8 backtrace;
+    CurrentCaller(backtrace);
+
+    ASSERT_NE(-1, backtrace.find("(CurrentCaller")) << "Full backtrace:\n" << backtrace;
+}
+
+__attribute__((__noinline__)) extern "C" void ThreadBusyWait(std::atomic<pid_t>* tid,
+                                                             volatile bool* done) {
+    *tid = android::base::GetThreadId();
+    while (!*done) {
+    }
+}
+
+TEST(CallStackTest, thread_backtrace) {
+    // Use a volatile to avoid any problems unwinding since sometimes
+    // accessing a std::atomic does not include unwind data at every
+    // instruction and leads to failed unwinds.
+    volatile bool done = false;
+    std::atomic<pid_t> tid = -1;
+    std::thread thread([&tid, &done]() { ThreadBusyWait(&tid, &done); });
+
+    while (tid == -1) {
+    }
+
+    android::CallStack cs;
+    cs.update(0, tid);
+
+    done = true;
+    thread.join();
+
+    ASSERT_NE(-1, cs.toString().find("(ThreadBusyWait")) << "Full backtrace:\n" << cs.toString();
+}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 60bf57b..ec760d3 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -796,6 +796,7 @@
     mkdir /data/misc/vpn 0770 system vpn
     mkdir /data/misc/shared_relro 0771 shared_relro shared_relro
     mkdir /data/misc/systemkeys 0700 system system
+    mkdir /data/misc/threadnetwork 0770 thread_network thread_network
     mkdir /data/misc/wifi 0770 wifi wifi
     mkdir /data/misc/wifi/sockets 0770 wifi wifi
     mkdir /data/misc/wifi/wpa_supplicant 0770 wifi wifi
diff --git a/rootdir/init.zygote64.rc b/rootdir/init.zygote64.rc
index 5bde5f4..b6ca5c0 100644
--- a/rootdir/init.zygote64.rc
+++ b/rootdir/init.zygote64.rc
@@ -1,4 +1,4 @@
-service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
+service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
     class main
     priority -20
     user root
@@ -13,5 +13,5 @@
     onrestart restart media.tuner
     onrestart restart netd
     onrestart restart wificond
-    task_profiles ProcessCapacityHigh
+    task_profiles ProcessCapacityHigh MaxPerformance
     critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
diff --git a/rootdir/init.zygote64_32.rc b/rootdir/init.zygote64_32.rc
index efb30d6..109bf6c 100644
--- a/rootdir/init.zygote64_32.rc
+++ b/rootdir/init.zygote64_32.rc
@@ -1,20 +1,4 @@
-service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
-    class main
-    priority -20
-    user root
-    group root readproc reserved_disk
-    socket zygote stream 660 root system
-    socket usap_pool_primary stream 660 root system
-    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
-    onrestart write /sys/power/state on
-    onrestart restart audioserver
-    onrestart restart cameraserver
-    onrestart restart media
-    onrestart restart media.tuner
-    onrestart restart netd
-    onrestart restart wificond
-    task_profiles ProcessCapacityHigh MaxPerformance
-    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal
+import /system/etc/init/hw/init.zygote64.rc
 
 service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
     class main
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index a140c8c..4ec59af 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -37,6 +37,8 @@
 /dev/tty                  0666   root       root
 /dev/random               0666   root       root
 /dev/urandom              0666   root       root
+# Aside from kernel threads, only prng_seeder needs access to HW RNG
+/dev/hw_random            0400   prng_seeder prng_seeder
 /dev/ashmem*              0666   root       root
 /dev/binder               0666   root       root
 /dev/hwbinder             0666   root       root
diff --git a/storaged/storaged.cpp b/storaged/storaged.cpp
index cefef6e..ba79ff7 100644
--- a/storaged/storaged.cpp
+++ b/storaged/storaged.cpp
@@ -27,6 +27,7 @@
 #include <fstream>
 #include <sstream>
 #include <string>
+#include <utility>
 
 #include <aidl/android/hardware/health/BnHealthInfoCallback.h>
 #include <android-base/file.h>
@@ -62,7 +63,7 @@
 
 constexpr ssize_t benchmark_unit_size = 16 * 1024;  // 16KB
 
-constexpr ssize_t min_benchmark_size = 128 * 1024;  // 128KB
+constexpr size_t min_benchmark_size = 128 * 1024;  // 128KB
 
 }  // namespace
 
@@ -244,9 +245,10 @@
     proto.ParseFromString(ss.str());
 
     const UidIOUsage& uid_io_usage = proto.uid_io_usage();
-    uint32_t computed_crc = crc32(current_version,
-        reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()),
-        uid_io_usage.ByteSize());
+    uint32_t computed_crc =
+            crc32(current_version,
+                  reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()),
+                  uid_io_usage.ByteSizeLong());
     if (proto.crc() != computed_crc) {
         LOG(WARNING) << "CRC mismatch in " << proto_file;
         return;
@@ -264,31 +266,29 @@
 
     const UidIOUsage& uid_io_usage = proto->uid_io_usage();
     proto->set_crc(crc32(current_version,
-        reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()),
-        uid_io_usage.ByteSize()));
+                         reinterpret_cast<const Bytef*>(uid_io_usage.SerializeAsString().c_str()),
+                         uid_io_usage.ByteSizeLong()));
 
     uint32_t pagesize = sysconf(_SC_PAGESIZE);
     if (user_id == USER_SYSTEM) {
         proto->set_padding("", 1);
         vector<char> padding;
-        ssize_t size = ROUND_UP(MAX(min_benchmark_size, proto->ByteSize()),
-                                pagesize);
-        padding = vector<char>(size - proto->ByteSize(), 0xFD);
+        ssize_t size = ROUND_UP(std::max(min_benchmark_size, proto->ByteSizeLong()), pagesize);
+        padding = vector<char>(size - proto->ByteSizeLong(), 0xFD);
         proto->set_padding(padding.data(), padding.size());
-        while (!IS_ALIGNED(proto->ByteSize(), pagesize)) {
+        while (!IS_ALIGNED(proto->ByteSizeLong(), pagesize)) {
             padding.push_back(0xFD);
             proto->set_padding(padding.data(), padding.size());
         }
     }
 
     char* data = nullptr;
-    if (posix_memalign(reinterpret_cast<void**>(&data),
-                       pagesize, proto->ByteSize())) {
-        PLOG(ERROR) << "Faied to alloc aligned buffer (size: " << proto->ByteSize() << ")";
+    if (posix_memalign(reinterpret_cast<void**>(&data), pagesize, proto->ByteSizeLong())) {
+        PLOG(ERROR) << "Faied to alloc aligned buffer (size: " << proto->ByteSizeLong() << ")";
         return data;
     }
 
-    proto->SerializeToArray(data, proto->ByteSize());
+    proto->SerializeToArray(data, proto->ByteSizeLong());
     return data;
 }
 
@@ -314,7 +314,7 @@
 
         while (size > 0) {
             start = steady_clock::now();
-            ret = write(fd, data, MIN(benchmark_unit_size, size));
+            ret = write(fd, data, std::min(benchmark_unit_size, size));
             if (ret <= 0) {
                 PLOG(ERROR) << "Faied to write tmp file: " << tmp_file;
                 return;
@@ -352,7 +352,7 @@
     unique_ptr<char> proto_data(prepare_proto(user_id, proto));
     if (proto_data == nullptr) return;
 
-    flush_proto_data(user_id, proto_data.get(), proto->ByteSize());
+    flush_proto_data(user_id, proto_data.get(), proto->ByteSizeLong());
 }
 
 void storaged_t::flush_protos(unordered_map<int, StoragedProto>* protos) {
diff --git a/trusty/keymaster/Android.bp b/trusty/keymaster/Android.bp
index 0e916ef..adc9fdf 100644
--- a/trusty/keymaster/Android.bp
+++ b/trusty/keymaster/Android.bp
@@ -123,7 +123,6 @@
     ],
     required: [
         "android.hardware.hardware_keystore.xml",
-        "RemoteProvisioner",
     ],
 }
 
diff --git a/trusty/trusty-base.mk b/trusty/trusty-base.mk
index d40a59e..0609709 100644
--- a/trusty/trusty-base.mk
+++ b/trusty/trusty-base.mk
@@ -25,7 +25,8 @@
 PRODUCT_PACKAGES += \
 	android.hardware.security.keymint-service.trusty \
 	android.hardware.gatekeeper@1.0-service.trusty \
-	trusty_apploader
+	trusty_apploader \
+	RemoteProvisioner
 
 PRODUCT_PROPERTY_OVERRIDES += \
 	ro.hardware.keystore_desede=true \