Merge "rust: Fix Debug implementation for declare_binder_enum!"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 260ee8d..f54f132 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -56,6 +56,9 @@
         },
         {
           "include-filter": "*RefreshRateOverlayTest.*"
+        },
+        {
+          "exclude-filter": "*ChildLayerTest#ChildrenSurviveParentDestruction"
         }
       ]
     },
diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp
index 6fb9a4d..48d48ac 100644
--- a/cmds/atrace/atrace.cpp
+++ b/cmds/atrace/atrace.cpp
@@ -193,8 +193,9 @@
         { OPT,      "events/ext4/ext4_da_write_end/enable" },
         { OPT,      "events/ext4/ext4_sync_file_enter/enable" },
         { OPT,      "events/ext4/ext4_sync_file_exit/enable" },
-        { REQ,      "events/block/block_rq_issue/enable" },
-        { REQ,      "events/block/block_rq_complete/enable" },
+        { OPT,      "events/block/block_bio_queue/enable" },
+        { OPT,      "events/block/block_bio_complete/enable" },
+        { OPT,      "events/ufs/ufshcd_command/enable" },
     } },
     { "mmc",        "eMMC commands",    0, {
         { REQ,      "events/mmc/enable" },
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 6dea91b..6e9747f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -183,6 +183,7 @@
 #define PACKAGE_DEX_USE_LIST "/data/system/package-dex-usage.list"
 #define SYSTEM_TRACE_SNAPSHOT "/data/misc/perfetto-traces/bugreport/systrace.pftrace"
 #define CGROUPFS_DIR "/sys/fs/cgroup"
+#define SDK_EXT_INFO "/apex/com.android.sdkext/bin/derive_sdk"
 
 // TODO(narayan): Since this information has to be kept in sync
 // with tombstoned, we should just put it in a common header.
@@ -765,7 +766,7 @@
 }
 
 void Dumpstate::PrintHeader() const {
-    std::string build, fingerprint, radio, bootloader, network;
+    std::string build, fingerprint, radio, bootloader, network, sdkversion;
     char date[80];
 
     build = android::base::GetProperty("ro.build.display.id", "(unknown)");
@@ -773,6 +774,7 @@
     radio = android::base::GetProperty("gsm.version.baseband", "(unknown)");
     bootloader = android::base::GetProperty("ro.bootloader", "(unknown)");
     network = android::base::GetProperty("gsm.operator.alpha", "(unknown)");
+    sdkversion = android::base::GetProperty("ro.build.version.sdk", "(unknown)");
     strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&now_));
 
     printf("========================================================\n");
@@ -790,9 +792,10 @@
     if (module_metadata_version != 0) {
         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
     }
-    printf("SDK extension versions [r=%s s=%s]\n",
-           android::base::GetProperty("build.version.extensions.r", "-").c_str(),
-           android::base::GetProperty("build.version.extensions.s", "-").c_str());
+    printf("Android SDK version: %s\n", sdkversion.c_str());
+    printf("SDK extensions: ");
+    RunCommandToFd(STDOUT_FILENO, "", {SDK_EXT_INFO, "--header"},
+                   CommandOptions::WithTimeout(1).Always().DropRoot().Build());
 
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -1025,7 +1028,7 @@
         MYLOGE("Could not open %s to dump incident report.\n", path.c_str());
         return;
     }
-    RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(120).Build());
+    RunCommandToFd(fd, "", {"incident", "-u"}, CommandOptions::WithTimeout(20).Build());
     bool empty = 0 == lseek(fd, 0, SEEK_END);
     if (!empty) {
         // Use a different name from "incident.proto"
@@ -1063,7 +1066,7 @@
         return;
     }
     RunCommandToFd(fd, "", {"cmd", "window", "dump-visible-window-views"},
-                   CommandOptions::WithTimeout(120).Build());
+                   CommandOptions::WithTimeout(10).Build());
     bool empty = 0 == lseek(fd, 0, SEEK_END);
     if (!empty) {
         ds.AddZipEntry("visible_windows.zip", path);
@@ -1402,7 +1405,9 @@
 // Dump all of the files that make up the vendor interface.
 // See the files listed in dumpFileList() for the latest list of files.
 static void DumpVintf() {
-    const auto vintfFiles = android::vintf::details::dumpFileList();
+
+    const std::string sku = android::base::GetProperty("ro.boot.product.hardware.sku", "");
+    const auto vintfFiles = android::vintf::details::dumpFileList(sku);
     for (const auto vintfFile : vintfFiles) {
         struct stat st;
         if (stat(vintfFile.c_str(), &st) == 0) {
@@ -1859,6 +1864,9 @@
     DumpFile("PSI memory", "/proc/pressure/memory");
     DumpFile("PSI io", "/proc/pressure/io");
 
+    RunCommand("SDK EXTENSIONS", {SDK_EXT_INFO, "--dump"},
+               CommandOptions::WithTimeout(10).Always().DropRoot().Build());
+
     if (dump_pool_) {
         RETURN_IF_USER_DENIED_CONSENT();
         WaitForTask(std::move(dump_traces));
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index e978e79..6a3120c 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -27,6 +27,7 @@
 #include <sys/prctl.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <sys/wait.h>
 
 #include <android-base/logging.h>
 #include <android-base/macros.h>
@@ -504,6 +505,11 @@
             return 0;
         }
 
+        if (WIFSIGNALED(dexopt_result)) {
+            LOG(WARNING) << "Interrupted by signal " << WTERMSIG(dexopt_result) ;
+            return dexopt_result;
+        }
+
         // If this was a profile-guided run, we may have profile version issues. Try to downgrade,
         // if possible.
         if ((parameters_.dexopt_flags & DEXOPT_PROFILE_GUIDED) == 0) {
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 0727383..3681d5b 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -49,14 +49,14 @@
 #ifdef __ANDROID_RECOVERY__
     auto vintfObject = vintf::VintfObjectRecovery::GetInstance();
     if (vintfObject == nullptr) {
-        LOG(ERROR) << "NULL VintfObjectRecovery!";
+        ALOGE("NULL VintfObjectRecovery!");
         return {};
     }
     return {ManifestWithDescription{vintfObject->getRecoveryHalManifest(), "recovery"}};
 #else
     auto vintfObject = vintf::VintfObject::GetInstance();
     if (vintfObject == nullptr) {
-        LOG(ERROR) << "NULL VintfObject!";
+        ALOGE("NULL VintfObject!");
         return {};
     }
     return {ManifestWithDescription{vintfObject->getDeviceHalManifest(), "device"},
@@ -68,10 +68,10 @@
 static bool forEachManifest(const std::function<bool(const ManifestWithDescription&)>& func) {
     for (const ManifestWithDescription& mwd : GetManifestsWithDescription()) {
         if (mwd.manifest == nullptr) {
-          LOG(ERROR) << "NULL VINTF MANIFEST!: " << mwd.description;
-          // note, we explicitly do not retry here, so that we can detect VINTF
-          // or other bugs (b/151696835)
-          continue;
+            ALOGE("NULL VINTF MANIFEST!: %s", mwd.description);
+            // note, we explicitly do not retry here, so that we can detect VINTF
+            // or other bugs (b/151696835)
+            continue;
         }
         if (func(mwd)) return true;
     }
@@ -87,8 +87,9 @@
         size_t firstSlash = name.find('/');
         size_t lastDot = name.rfind('.', firstSlash);
         if (firstSlash == std::string::npos || lastDot == std::string::npos) {
-            LOG(ERROR) << "VINTF HALs require names in the format type/instance (e.g. "
-                       << "some.package.foo.IFoo/default) but got: " << name;
+            ALOGE("VINTF HALs require names in the format type/instance (e.g. "
+                  "some.package.foo.IFoo/default) but got: %s",
+                  name.c_str());
             return false;
         }
         aname->package = name.substr(0, lastDot);
@@ -104,7 +105,7 @@
 
     bool found = forEachManifest([&](const ManifestWithDescription& mwd) {
         if (mwd.manifest->hasAidlInstance(aname.package, aname.iface, aname.instance)) {
-            LOG(INFO) << "Found " << name << " in " << mwd.description << " VINTF manifest.";
+            ALOGI("Found %s in %s VINTF manifest.", name.c_str(), mwd.description);
             return true; // break
         }
         return false;  // continue
@@ -113,8 +114,8 @@
     if (!found) {
         // Although it is tested, explicitly rebuilding qualified name, in case it
         // becomes something unexpected.
-        LOG(INFO) << "Could not find " << aname.package << "." << aname.iface << "/"
-                  << aname.instance << " in the VINTF manifest.";
+        ALOGI("Could not find %s.%s/%s in the VINTF manifest.", aname.package.c_str(),
+              aname.iface.c_str(), aname.instance.c_str());
     }
 
     return found;
@@ -173,7 +174,9 @@
 static std::vector<std::string> getVintfInstances(const std::string& interface) {
     size_t lastDot = interface.rfind('.');
     if (lastDot == std::string::npos) {
-        LOG(ERROR) << "VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) but got: " << interface;
+        ALOGE("VINTF interfaces require names in Java package format (e.g. some.package.foo.IFoo) "
+              "but got: %s",
+              interface.c_str());
         return {};
     }
     const std::string package = interface.substr(0, lastDot);
@@ -308,7 +311,7 @@
     }
 
     if (!isValidServiceName(name)) {
-        LOG(ERROR) << "Invalid service name: " << name;
+        ALOGE("Invalid service name: %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT, "Invalid service name");
     }
 
@@ -322,20 +325,44 @@
     // implicitly unlinked when the binder is removed
     if (binder->remoteBinder() != nullptr &&
         binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
-        LOG(ERROR) << "Could not linkToDeath when adding " << name;
+        ALOGE("Could not linkToDeath when adding %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
     }
 
+    auto it = mNameToService.find(name);
+    if (it != mNameToService.end()) {
+        const Service& existing = it->second;
+
+        // We could do better than this because if the other service dies, it
+        // may not have an entry here. However, this case is unlikely. We are
+        // only trying to detect when two different services are accidentally installed.
+
+        if (existing.ctx.uid != ctx.uid) {
+            ALOGW("Service '%s' originally registered from UID %u but it is now being registered "
+                  "from UID %u. Multiple instances installed?",
+                  name.c_str(), existing.ctx.uid, ctx.uid);
+        }
+
+        if (existing.ctx.sid != ctx.sid) {
+            ALOGW("Service '%s' originally registered from SID %s but it is now being registered "
+                  "from SID %s. Multiple instances installed?",
+                  name.c_str(), existing.ctx.sid.c_str(), ctx.sid.c_str());
+        }
+
+        ALOGI("Service '%s' originally registered from PID %d but it is being registered again "
+              "from PID %d. Bad state? Late death notification? Multiple instances installed?",
+              name.c_str(), existing.ctx.debugPid, ctx.debugPid);
+    }
+
     // Overwrite the old service if it exists
-    mNameToService[name] = Service {
-        .binder = binder,
-        .allowIsolated = allowIsolated,
-        .dumpPriority = dumpPriority,
-        .debugPid = ctx.debugPid,
+    mNameToService[name] = Service{
+            .binder = binder,
+            .allowIsolated = allowIsolated,
+            .dumpPriority = dumpPriority,
+            .ctx = ctx,
     };
 
-    auto it = mNameToRegistrationCallback.find(name);
-    if (it != mNameToRegistrationCallback.end()) {
+    if (auto it = mNameToRegistrationCallback.find(name); it != mNameToRegistrationCallback.end()) {
         for (const sp<IServiceCallback>& cb : it->second) {
             mNameToService[name].guaranteeClient = true;
             // permission checked in registerForNotifications
@@ -381,7 +408,7 @@
     }
 
     if (!isValidServiceName(name)) {
-        LOG(ERROR) << "Invalid service name: " << name;
+        ALOGE("Invalid service name: %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
     }
 
@@ -392,7 +419,7 @@
     if (OK !=
         IInterface::asBinder(callback)->linkToDeath(
                 sp<ServiceManager>::fromExisting(this))) {
-        LOG(ERROR) << "Could not linkToDeath when adding " << name;
+        ALOGE("Could not linkToDeath when adding %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
@@ -424,7 +451,7 @@
     }
 
     if (!found) {
-        LOG(ERROR) << "Trying to unregister callback, but none exists " << name;
+        ALOGE("Trying to unregister callback, but none exists %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
@@ -546,10 +573,11 @@
 
     std::thread([=] {
         if (!base::SetProperty("ctl.interface_start", "aidl/" + name)) {
-            LOG(INFO) << "Tried to start aidl service " << name
-                      << " as a lazy service, but was unable to. Usually this happens when a "
-                         "service is not installed, but if the service is intended to be used as a "
-                         "lazy service, then it may be configured incorrectly.";
+            ALOGI("Tried to start aidl service %s as a lazy service, but was unable to. Usually "
+                  "this happens when a "
+                  "service is not installed, but if the service is intended to be used as a "
+                  "lazy service, then it may be configured incorrectly.",
+                  name.c_str());
         }
     }).detach();
 }
@@ -567,24 +595,25 @@
 
     auto serviceIt = mNameToService.find(name);
     if (serviceIt == mNameToService.end()) {
-        LOG(ERROR) << "Could not add callback for nonexistent service: " << name;
+        ALOGE("Could not add callback for nonexistent service: %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
     }
 
-    if (serviceIt->second.debugPid != IPCThreadState::self()->getCallingPid()) {
-        LOG(WARNING) << "Only a server can register for client callbacks (for " << name << ")";
+    if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
+        ALOGW("Only a server can register for client callbacks (for %s)", name.c_str());
         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
     }
 
     if (serviceIt->second.binder != service) {
-        LOG(WARNING) << "Tried to register client callback for " << name
-            << " but a different service is registered under this name.";
+        ALOGW("Tried to register client callback for %s but a different service is registered "
+              "under this name.",
+              name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
     }
 
     if (OK !=
         IInterface::asBinder(cb)->linkToDeath(sp<ServiceManager>::fromExisting(this))) {
-        LOG(ERROR) << "Could not linkToDeath when adding client callback for " << name;
+        ALOGE("Could not linkToDeath when adding client callback for %s", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
@@ -669,7 +698,7 @@
 void ServiceManager::sendClientCallbackNotifications(const std::string& serviceName, bool hasClients) {
     auto serviceIt = mNameToService.find(serviceName);
     if (serviceIt == mNameToService.end()) {
-        LOG(WARNING) << "sendClientCallbackNotifications could not find service " << serviceName;
+        ALOGW("sendClientCallbackNotifications could not find service %s", serviceName.c_str());
         return;
     }
     Service& service = serviceIt->second;
@@ -677,7 +706,7 @@
     CHECK(hasClients != service.hasClients) << "Record shows: " << service.hasClients
         << " so we can't tell clients again that we have client: " << hasClients;
 
-    LOG(INFO) << "Notifying " << serviceName << " they have clients: " << hasClients;
+    ALOGI("Notifying %s they have clients: %d", serviceName.c_str(), hasClients);
 
     auto ccIt = mNameToClientCallback.find(serviceName);
     CHECK(ccIt != mNameToClientCallback.end())
@@ -702,26 +731,26 @@
 
     auto serviceIt = mNameToService.find(name);
     if (serviceIt == mNameToService.end()) {
-        LOG(WARNING) << "Tried to unregister " << name
-            << ", but that service wasn't registered to begin with.";
+        ALOGW("Tried to unregister %s, but that service wasn't registered to begin with.",
+              name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
-    if (serviceIt->second.debugPid != IPCThreadState::self()->getCallingPid()) {
-        LOG(WARNING) << "Only a server can unregister itself (for " << name << ")";
+    if (serviceIt->second.ctx.debugPid != IPCThreadState::self()->getCallingPid()) {
+        ALOGW("Only a server can unregister itself (for %s)", name.c_str());
         return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
     }
 
     sp<IBinder> storedBinder = serviceIt->second.binder;
 
     if (binder != storedBinder) {
-        LOG(WARNING) << "Tried to unregister " << name
-            << ", but a different service is registered under this name.";
+        ALOGW("Tried to unregister %s, but a different service is registered under this name.",
+              name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
     if (serviceIt->second.guaranteeClient) {
-        LOG(INFO) << "Tried to unregister " << name << ", but there is about to be a client.";
+        ALOGI("Tried to unregister %s, but there is about to be a client.", name.c_str());
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
@@ -734,7 +763,7 @@
     // So, if clients > 2, then at least one other service on the system must hold a refcount.
     if (clients < 0 || clients > 2) {
         // client callbacks are either disabled or there are other clients
-        LOG(INFO) << "Tried to unregister " << name << ", but there are clients: " << clients;
+        ALOGI("Tried to unregister %s, but there are clients: %d", name.c_str(), clients);
         // Set this flag to ensure the clients are acknowledged in the next callback
         serviceIt->second.guaranteeClient = true;
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
@@ -754,7 +783,7 @@
     for (auto const& [name, service] : mNameToService) {
         ServiceDebugInfo info;
         info.name = name;
-        info.debugPid = service.debugPid;
+        info.debugPid = service.ctx.debugPid;
 
         outReturn->push_back(std::move(info));
     }
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index c6db697..07b79f8 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -74,7 +74,7 @@
         int32_t dumpPriority;
         bool hasClients = false; // notifications sent on true -> false.
         bool guaranteeClient = false; // forces the client check to true
-        pid_t debugPid = 0; // the process in which this service runs
+        Access::CallingContext ctx;   // process that originally registers this
 
         // the number of clients of the service, including servicemanager itself
         ssize_t getNodeStrongRefCount();
diff --git a/libs/adbd_auth/adbd_auth.cpp b/libs/adbd_auth/adbd_auth.cpp
index 15bd5c3..ebc74fb 100644
--- a/libs/adbd_auth/adbd_auth.cpp
+++ b/libs/adbd_auth/adbd_auth.cpp
@@ -23,8 +23,10 @@
 #include <sys/eventfd.h>
 #include <sys/uio.h>
 
+#include <atomic>
 #include <chrono>
 #include <deque>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <tuple>
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index 481d704..5e725a9 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -232,7 +232,10 @@
           : mRpcServer(rpcServer), mKeepAliveBinder(keepAliveBinder), mBinder(binder) {}
     virtual ~RpcServerLink();
     void binderDied(const wp<IBinder>&) override {
-        LOG_RPC_DETAIL("RpcServerLink: binder died, shutting down RpcServer");
+        auto promoted = mBinder.promote();
+        ALOGI("RpcBinder: binder died, shutting down RpcServer for %s",
+              promoted ? String8(promoted->getInterfaceDescriptor()).c_str() : "<NULL>");
+
         if (mRpcServer == nullptr) {
             ALOGW("RpcServerLink: Unable to shut down RpcServer because it does not exist.");
         } else {
@@ -241,11 +244,7 @@
         }
         mRpcServer.clear();
 
-        auto promoted = mBinder.promote();
-        if (promoted == nullptr) {
-            ALOGW("RpcServerLink: Unable to remove link from parent binder object because parent "
-                  "binder object is gone.");
-        } else {
+        if (promoted) {
             promoted->removeRpcServerLink(sp<RpcServerLink>::fromExisting(this));
         }
         mBinder.clear();
@@ -706,6 +705,7 @@
         return status;
     }
     rpcServer->setMaxThreads(binderThreadPoolMaxCount);
+    LOG(INFO) << "RpcBinder: Started Binder debug on " << getInterfaceDescriptor();
     rpcServer->start();
     e->mRpcServerLinks.emplace(link);
     LOG_RPC_DETAIL("%s(fd=%d) successful", __PRETTY_FUNCTION__, socketFdForPrint);
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index bfcf39a..11c8e5d 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -39,7 +39,6 @@
 #include <sys/resource.h>
 #include <unistd.h>
 
-#include "Static.h"
 #include "binder_module.h"
 
 #if LOG_NDEBUG
@@ -124,46 +123,43 @@
         return "unknown";
 }
 
-static const void* printBinderTransactionData(TextOutput& out, const void* data)
-{
+static const void* printBinderTransactionData(std::ostream& out, const void* data) {
     const binder_transaction_data* btd =
         (const binder_transaction_data*)data;
     if (btd->target.handle < 1024) {
         /* want to print descriptors in decimal; guess based on value */
-        out << "target.desc=" << btd->target.handle;
+        out << "\ttarget.desc=" << btd->target.handle;
     } else {
-        out << "target.ptr=" << btd->target.ptr;
+        out << "\ttarget.ptr=" << btd->target.ptr;
     }
-    out << " (cookie " << btd->cookie << ")" << endl
-        << "code=" << TypeCode(btd->code) << ", flags=" << (void*)(uint64_t)btd->flags << endl
-        << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size
-        << " bytes)" << endl
-        << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size
-        << " bytes)";
+    out << "\t (cookie " << btd->cookie << ")"
+        << "\n"
+        << "\tcode=" << TypeCode(btd->code) << ", flags=" << (void*)(uint64_t)btd->flags << "\n"
+        << "\tdata=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size << " bytes)"
+        << "\n"
+        << "\toffsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size << " bytes)";
     return btd+1;
 }
 
-static const void* printReturnCommand(TextOutput& out, const void* _cmd)
-{
+static const void* printReturnCommand(std::ostream& out, const void* _cmd) {
     static const size_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]);
     const int32_t* cmd = (const int32_t*)_cmd;
     uint32_t code = (uint32_t)*cmd++;
     size_t cmdIndex = code & 0xff;
     if (code == BR_ERROR) {
-        out << "BR_ERROR: " << (void*)(uint64_t)(*cmd++) << endl;
+        out << "\tBR_ERROR: " << (void*)(uint64_t)(*cmd++) << "\n";
         return cmd;
     } else if (cmdIndex >= N) {
-        out << "Unknown reply: " << code << endl;
+        out << "\tUnknown reply: " << code << "\n";
         return cmd;
     }
-    out << kReturnStrings[cmdIndex];
+    out << "\t" << kReturnStrings[cmdIndex];
 
     switch (code) {
         case BR_TRANSACTION:
         case BR_REPLY: {
-            out << ": " << indent;
-            cmd = (const int32_t *)printBinderTransactionData(out, cmd);
-            out << dedent;
+            out << ": ";
+            cmd = (const int32_t*)printBinderTransactionData(out, cmd);
         } break;
 
         case BR_ACQUIRE_RESULT: {
@@ -200,19 +196,18 @@
             break;
     }
 
-    out << endl;
+    out << "\n";
     return cmd;
 }
 
-static const void* printCommand(TextOutput& out, const void* _cmd)
-{
+static const void* printCommand(std::ostream& out, const void* _cmd) {
     static const size_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]);
     const int32_t* cmd = (const int32_t*)_cmd;
     uint32_t code = (uint32_t)*cmd++;
     size_t cmdIndex = code & 0xff;
 
     if (cmdIndex >= N) {
-        out << "Unknown command: " << code << endl;
+        out << "Unknown command: " << code << "\n";
         return cmd;
     }
     out << kCommandStrings[cmdIndex];
@@ -220,9 +215,8 @@
     switch (code) {
         case BC_TRANSACTION:
         case BC_REPLY: {
-            out << ": " << indent;
-            cmd = (const int32_t *)printBinderTransactionData(out, cmd);
-            out << dedent;
+            out << ": ";
+            cmd = (const int32_t*)printBinderTransactionData(out, cmd);
         } break;
 
         case BC_ACQUIRE_RESULT: {
@@ -274,7 +268,7 @@
             break;
     }
 
-    out << endl;
+    out << "\n";
     return cmd;
 }
 
@@ -548,8 +542,10 @@
         if (IN < sizeof(int32_t)) return result;
         cmd = mIn.readInt32();
         IF_LOG_COMMANDS() {
-            alog << "Processing top-level Command: "
-                 << getReturnString(cmd) << endl;
+            std::ostringstream logStream;
+            logStream << "Processing top-level Command: " << getReturnString(cmd) << "\n";
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
 
         pthread_mutex_lock(&mProcess->mThreadCountLock);
@@ -726,10 +722,11 @@
     flags |= TF_ACCEPT_FDS;
 
     IF_LOG_TRANSACTIONS() {
-        TextOutput::Bundle _b(alog);
-        alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand "
-            << handle << " / code " << TypeCode(code) << ": "
-            << indent << data << dedent << endl;
+        std::ostringstream logStream;
+        logStream << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " << handle
+                  << " / code " << TypeCode(code) << ": \t" << data << "\n";
+        std::string message = logStream.str();
+        ALOGI("%s", message.c_str());
     }
 
     LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
@@ -774,11 +771,15 @@
         #endif
 
         IF_LOG_TRANSACTIONS() {
-            TextOutput::Bundle _b(alog);
-            alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand "
-                << handle << ": ";
-            if (reply) alog << indent << *reply << dedent << endl;
-            else alog << "(none requested)" << endl;
+            std::ostringstream logStream;
+            logStream << "BR_REPLY thr " << (void*)pthread_self() << " / hand " << handle << ": ";
+            if (reply)
+                logStream << "\t" << *reply << "\n";
+            else
+                logStream << "(none requested)"
+                          << "\n";
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
     } else {
         err = waitForResponse(nullptr, nullptr);
@@ -920,8 +921,10 @@
         cmd = (uint32_t)mIn.readInt32();
 
         IF_LOG_COMMANDS() {
-            alog << "Processing waitForResponse Command: "
-                << getReturnString(cmd) << endl;
+            std::ostringstream logStream;
+            logStream << "Processing waitForResponse Command: " << getReturnString(cmd) << "\n";
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
 
         switch (cmd) {
@@ -1033,17 +1036,19 @@
     }
 
     IF_LOG_COMMANDS() {
-        TextOutput::Bundle _b(alog);
+        std::ostringstream logStream;
         if (outAvail != 0) {
-            alog << "Sending commands to driver: " << indent;
+            logStream << "Sending commands to driver: ";
             const void* cmds = (const void*)bwr.write_buffer;
-            const void* end = ((const uint8_t*)cmds)+bwr.write_size;
-            alog << HexDump(cmds, bwr.write_size) << endl;
-            while (cmds < end) cmds = printCommand(alog, cmds);
-            alog << dedent;
+            const void* end = ((const uint8_t*)cmds) + bwr.write_size;
+            logStream << "\t" << HexDump(cmds, bwr.write_size) << "\n";
+            while (cmds < end) cmds = printCommand(logStream, cmds);
         }
-        alog << "Size of receive buffer: " << bwr.read_size
-            << ", needRead: " << needRead << ", doReceive: " << doReceive << endl;
+        logStream << "Size of receive buffer: " << bwr.read_size << ", needRead: " << needRead
+                  << ", doReceive: " << doReceive << "\n";
+
+        std::string message = logStream.str();
+        ALOGI("%s", message.c_str());
     }
 
     // Return immediately if there is nothing to do.
@@ -1054,7 +1059,10 @@
     status_t err;
     do {
         IF_LOG_COMMANDS() {
-            alog << "About to read/write, write size = " << mOut.dataSize() << endl;
+            std::ostringstream logStream;
+            logStream << "About to read/write, write size = " << mOut.dataSize() << "\n";
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
 #if defined(__ANDROID__)
         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
@@ -1068,14 +1076,20 @@
             err = -EBADF;
         }
         IF_LOG_COMMANDS() {
-            alog << "Finished read/write, write size = " << mOut.dataSize() << endl;
+            std::ostringstream logStream;
+            logStream << "Finished read/write, write size = " << mOut.dataSize() << "\n";
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
     } while (err == -EINTR);
 
     IF_LOG_COMMANDS() {
-        alog << "Our err: " << (void*)(intptr_t)err << ", write consumed: "
-            << bwr.write_consumed << " (of " << mOut.dataSize()
-                        << "), read consumed: " << bwr.read_consumed << endl;
+        std::ostringstream logStream;
+        logStream << "Our err: " << (void*)(intptr_t)err
+                  << ", write consumed: " << bwr.write_consumed << " (of " << mOut.dataSize()
+                  << "), read consumed: " << bwr.read_consumed << "\n";
+        std::string message = logStream.str();
+        ALOGI("%s", message.c_str());
     }
 
     if (err >= NO_ERROR) {
@@ -1096,14 +1110,15 @@
             mIn.setDataPosition(0);
         }
         IF_LOG_COMMANDS() {
-            TextOutput::Bundle _b(alog);
-            alog << "Remaining data size: " << mOut.dataSize() << endl;
-            alog << "Received commands from driver: " << indent;
+            std::ostringstream logStream;
+            logStream << "Remaining data size: " << mOut.dataSize() << "\n";
+            logStream << "Received commands from driver: ";
             const void* cmds = mIn.data();
             const void* end = mIn.data() + mIn.dataSize();
-            alog << HexDump(cmds, mIn.dataSize()) << endl;
-            while (cmds < end) cmds = printReturnCommand(alog, cmds);
-            alog << dedent;
+            logStream << "\t" << HexDump(cmds, mIn.dataSize()) << "\n";
+            while (cmds < end) cmds = printReturnCommand(logStream, cmds);
+            std::string message = logStream.str();
+            ALOGI("%s", message.c_str());
         }
         return NO_ERROR;
     }
@@ -1285,15 +1300,15 @@
             Parcel reply;
             status_t error;
             IF_LOG_TRANSACTIONS() {
-                TextOutput::Bundle _b(alog);
-                alog << "BR_TRANSACTION thr " << (void*)pthread_self()
-                    << " / obj " << tr.target.ptr << " / code "
-                    << TypeCode(tr.code) << ": " << indent << buffer
-                    << dedent << endl
-                    << "Data addr = "
-                    << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
-                    << ", offsets addr="
-                    << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl;
+                std::ostringstream logStream;
+                logStream << "BR_TRANSACTION thr " << (void*)pthread_self() << " / obj "
+                          << tr.target.ptr << " / code " << TypeCode(tr.code) << ": \t" << buffer
+                          << "\n"
+                          << "Data addr = " << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer)
+                          << ", offsets addr="
+                          << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << "\n";
+                std::string message = logStream.str();
+                ALOGI("%s", message.c_str());
             }
             if (tr.target.ptr) {
                 // We only have a weak reference on the target object, so we must first try to
@@ -1329,21 +1344,21 @@
                 sendReply(reply, (tr.flags & kForwardReplyFlags));
             } else {
                 if (error != OK) {
-                    alog << "oneway function results for code " << tr.code
-                         << " on binder at "
-                         << reinterpret_cast<void*>(tr.target.ptr)
-                         << " will be dropped but finished with status "
-                         << statusToString(error);
+                    std::ostringstream logStream;
+                    logStream << "oneway function results for code " << tr.code << " on binder at "
+                              << reinterpret_cast<void*>(tr.target.ptr)
+                              << " will be dropped but finished with status "
+                              << statusToString(error);
 
                     // ideally we could log this even when error == OK, but it
                     // causes too much logspam because some manually-written
                     // interfaces have clients that call methods which always
                     // write results, sometimes as oneway methods.
                     if (reply.dataSize() != 0) {
-                         alog << " and reply parcel size " << reply.dataSize();
+                        logStream << " and reply parcel size " << reply.dataSize();
                     }
-
-                    alog << endl;
+                    std::string message = logStream.str();
+                    ALOGI("%s", message.c_str());
                 }
                 LOG_ONEWAY("NOT sending reply to %d!", mCallingPid);
             }
@@ -1358,9 +1373,11 @@
             mPropagateWorkSource = origPropagateWorkSet;
 
             IF_LOG_TRANSACTIONS() {
-                TextOutput::Bundle _b(alog);
-                alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj "
-                    << tr.target.ptr << ": " << indent << reply << dedent << endl;
+                std::ostringstream logStream;
+                logStream << "BC_REPLY thr " << (void*)pthread_self() << " / obj " << tr.target.ptr
+                          << ": \t" << reply << "\n";
+                std::string message = logStream.str();
+                ALOGI("%s", message.c_str());
             }
 
         }
@@ -1481,7 +1498,10 @@
                                 const binder_size_t* /*objects*/, size_t /*objectsSize*/) {
     //ALOGI("Freeing parcel %p", &parcel);
     IF_LOG_COMMANDS() {
-        alog << "Writing BC_FREE_BUFFER for " << data << endl;
+        std::ostringstream logStream;
+        logStream << "Writing BC_FREE_BUFFER for " << data << "\n";
+        std::string message = logStream.str();
+        ALOGI("%s", message.c_str());
     }
     ALOG_ASSERT(data != NULL, "Called with NULL data");
     IPCThreadState* state = self();
diff --git a/libs/binder/OS.cpp b/libs/binder/OS.cpp
index 24ce2bb..77e401f 100644
--- a/libs/binder/OS.cpp
+++ b/libs/binder/OS.cpp
@@ -18,6 +18,7 @@
 
 #include <android-base/file.h>
 #include <binder/RpcTransportRaw.h>
+#include <log/log.h>
 #include <string.h>
 
 using android::base::ErrnoError;
@@ -25,6 +26,9 @@
 
 namespace android {
 
+// Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
+constexpr size_t kMaxFdsPerMsg = 253;
+
 Result<void> setNonBlocking(android::base::borrowed_fd fd) {
     int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL));
     if (flags == -1) {
@@ -63,4 +67,99 @@
     return RpcTransportCtxFactoryRaw::make();
 }
 
+int sendMessageOnSocket(
+        const RpcTransportFd& socket, iovec* iovs, int niovs,
+        const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) {
+    if (ancillaryFds != nullptr && !ancillaryFds->empty()) {
+        if (ancillaryFds->size() > kMaxFdsPerMsg) {
+            errno = EINVAL;
+            return -1;
+        }
+
+        // CMSG_DATA is not necessarily aligned, so we copy the FDs into a buffer and then
+        // use memcpy.
+        int fds[kMaxFdsPerMsg];
+        for (size_t i = 0; i < ancillaryFds->size(); i++) {
+            fds[i] = std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i));
+        }
+        const size_t fdsByteSize = sizeof(int) * ancillaryFds->size();
+
+        alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(int) * kMaxFdsPerMsg)];
+
+        msghdr msg{
+                .msg_iov = iovs,
+                .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
+                .msg_control = msgControlBuf,
+                .msg_controllen = sizeof(msgControlBuf),
+        };
+
+        cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
+        cmsg->cmsg_level = SOL_SOCKET;
+        cmsg->cmsg_type = SCM_RIGHTS;
+        cmsg->cmsg_len = CMSG_LEN(fdsByteSize);
+        memcpy(CMSG_DATA(cmsg), fds, fdsByteSize);
+
+        msg.msg_controllen = CMSG_SPACE(fdsByteSize);
+        return TEMP_FAILURE_RETRY(sendmsg(socket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
+    }
+
+    msghdr msg{
+            .msg_iov = iovs,
+            // posix uses int, glibc uses size_t.  niovs is a
+            // non-negative int and can be cast to either.
+            .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
+    };
+    return TEMP_FAILURE_RETRY(sendmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
+}
+
+int receiveMessageFromSocket(
+        const RpcTransportFd& socket, iovec* iovs, int niovs,
+        std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) {
+    if (ancillaryFds != nullptr) {
+        int fdBuffer[kMaxFdsPerMsg];
+        alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))];
+
+        msghdr msg{
+                .msg_iov = iovs,
+                .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
+                .msg_control = msgControlBuf,
+                .msg_controllen = sizeof(msgControlBuf),
+        };
+        ssize_t processSize = TEMP_FAILURE_RETRY(recvmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
+        if (processSize < 0) {
+            return -1;
+        }
+
+        for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+            if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
+                // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks
+                // application devs to memcpy the data to ensure memory alignment.
+                size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0);
+                LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // validity check
+                memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen);
+                size_t fdCount = dataLen / sizeof(int);
+                ancillaryFds->reserve(ancillaryFds->size() + fdCount);
+                for (size_t i = 0; i < fdCount; i++) {
+                    ancillaryFds->emplace_back(base::unique_fd(fdBuffer[i]));
+                }
+                break;
+            }
+        }
+
+        if (msg.msg_flags & MSG_CTRUNC) {
+            errno = EPIPE;
+            return -1;
+        }
+        return processSize;
+    }
+    msghdr msg{
+            .msg_iov = iovs,
+            // posix uses int, glibc uses size_t.  niovs is a
+            // non-negative int and can be cast to either.
+            .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
+    };
+
+    return TEMP_FAILURE_RETRY(recvmsg(socket.fd.get(), &msg, MSG_NOSIGNAL));
+}
+
 } // namespace android
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index 5ab8bab..0d38968 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -33,4 +33,12 @@
 
 std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory();
 
+int sendMessageOnSocket(
+        const RpcTransportFd& socket, iovec* iovs, int niovs,
+        const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds);
+
+int receiveMessageFromSocket(
+        const RpcTransportFd& socket, iovec* iovs, int niovs,
+        std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds);
+
 } // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8887572..07d0a65 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -1439,7 +1439,8 @@
             case RpcSession::FileDescriptorTransportMode::NONE: {
                 return FDS_NOT_ALLOWED;
             }
-            case RpcSession::FileDescriptorTransportMode::UNIX: {
+            case RpcSession::FileDescriptorTransportMode::UNIX:
+            case RpcSession::FileDescriptorTransportMode::TRUSTY: {
                 if (rpcFields->mFds == nullptr) {
                     rpcFields->mFds = std::make_unique<decltype(rpcFields->mFds)::element_type>();
                 }
@@ -2639,8 +2640,7 @@
     return OK;
 }
 
-void Parcel::print(TextOutput& to, uint32_t /*flags*/) const
-{
+void Parcel::print(std::ostream& to, uint32_t /*flags*/) const {
     to << "Parcel(";
 
     if (errorCheck() != NO_ERROR) {
@@ -2648,7 +2648,7 @@
         to << "Error: " << (void*)(intptr_t)err << " \"" << strerror(-err) << "\"";
     } else if (dataSize() > 0) {
         const uint8_t* DATA = data();
-        to << indent << HexDump(DATA, dataSize()) << dedent;
+        to << "\t" << HexDump(DATA, dataSize());
 #ifdef BINDER_WITH_KERNEL_IPC
         if (const auto* kernelFields = maybeKernelFields()) {
             const binder_size_t* OBJS = kernelFields->mObjects;
@@ -2656,8 +2656,7 @@
             for (size_t i = 0; i < N; i++) {
                 const flat_binder_object* flat =
                         reinterpret_cast<const flat_binder_object*>(DATA + OBJS[i]);
-                to << endl
-                   << "Object #" << i << " @ " << (void*)OBJS[i] << ": "
+                to << "Object #" << i << " @ " << (void*)OBJS[i] << ": "
                    << TypeCode(flat->hdr.type & 0x7f7f7f00) << " = " << flat->binder;
             }
         }
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index e581d0b..83d0de7 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -37,6 +37,7 @@
 #include "OS.h"
 #include "RpcSocketAddress.h"
 #include "RpcState.h"
+#include "RpcTransportUtils.h"
 #include "RpcWireFormat.h"
 #include "Utils.h"
 
@@ -61,6 +62,10 @@
     return sp<RpcServer>::make(std::move(ctx));
 }
 
+status_t RpcServer::setupUnixDomainSocketBootstrapServer(unique_fd bootstrapFd) {
+    return setupExternalServer(std::move(bootstrapFd), &RpcServer::recvmsgSocketConnection);
+}
+
 status_t RpcServer::setupUnixDomainServer(const char* path) {
     return setupSocketServer(UnixSocketAddress(path));
 }
@@ -177,11 +182,50 @@
     rpcJoinIfSingleThreaded(*mJoinThread);
 }
 
+status_t RpcServer::acceptSocketConnection(const RpcServer& server, RpcTransportFd* out) {
+    RpcTransportFd clientSocket(unique_fd(TEMP_FAILURE_RETRY(
+            accept4(server.mServer.fd.get(), nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK))));
+    if (clientSocket.fd < 0) {
+        int savedErrno = errno;
+        ALOGE("Could not accept4 socket: %s", strerror(savedErrno));
+        return -savedErrno;
+    }
+
+    *out = std::move(clientSocket);
+    return OK;
+}
+
+status_t RpcServer::recvmsgSocketConnection(const RpcServer& server, RpcTransportFd* out) {
+    int zero = 0;
+    iovec iov{&zero, sizeof(zero)};
+    std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
+
+    if (receiveMessageFromSocket(server.mServer, &iov, 1, &fds) < 0) {
+        int savedErrno = errno;
+        ALOGE("Failed recvmsg: %s", strerror(savedErrno));
+        return -savedErrno;
+    }
+    if (fds.size() != 1) {
+        ALOGE("Expected exactly one fd from recvmsg, got %zu", fds.size());
+        return -EINVAL;
+    }
+
+    unique_fd fd(std::move(std::get<unique_fd>(fds.back())));
+    if (auto res = setNonBlocking(fd); !res.ok()) {
+        ALOGE("Failed setNonBlocking: %s", res.error().message().c_str());
+        return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
+    }
+
+    *out = RpcTransportFd(std::move(fd));
+    return OK;
+}
+
 void RpcServer::join() {
 
     {
         RpcMutexLockGuard _l(mLock);
         LOG_ALWAYS_FATAL_IF(!mServer.fd.ok(), "RpcServer must be setup to join.");
+        LOG_ALWAYS_FATAL_IF(mAcceptFn == nullptr, "RpcServer must have an accept() function");
         LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
         mJoinThreadRunning = true;
         mShutdownTrigger = FdTrigger::make();
@@ -192,20 +236,19 @@
     while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
         std::array<uint8_t, kRpcAddressSize> addr;
         static_assert(addr.size() >= sizeof(sockaddr_storage), "kRpcAddressSize is too small");
-
         socklen_t addrLen = addr.size();
-        RpcTransportFd clientSocket(unique_fd(TEMP_FAILURE_RETRY(
-                accept4(mServer.fd.get(), reinterpret_cast<sockaddr*>(addr.data()), &addrLen,
-                        SOCK_CLOEXEC | SOCK_NONBLOCK))));
 
-        LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(sockaddr_storage)),
-                            "Truncated address");
-
-        if (clientSocket.fd < 0) {
-            ALOGE("Could not accept4 socket: %s", strerror(errno));
+        RpcTransportFd clientSocket;
+        if (mAcceptFn(*this, &clientSocket) != OK) {
             continue;
         }
-        LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());
+        if (getpeername(clientSocket.fd.get(), reinterpret_cast<sockaddr*>(addr.data()),
+                        &addrLen)) {
+            ALOGE("Could not getpeername socket: %s", strerror(errno));
+            continue;
+        }
+
+        LOG_RPC_DETAIL("accept on fd %d yields fd %d", mServer.fd.get(), clientSocket.fd.get());
 
         {
             RpcMutexLockGuard _l(mLock);
@@ -550,16 +593,23 @@
     return std::move(mServer.fd);
 }
 
-status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
+status_t RpcServer::setupExternalServer(
+        base::unique_fd serverFd,
+        std::function<status_t(const RpcServer&, RpcTransportFd*)>&& acceptFn) {
     RpcMutexLockGuard _l(mLock);
     if (mServer.fd.ok()) {
         ALOGE("Each RpcServer can only have one server.");
         return INVALID_OPERATION;
     }
     mServer = std::move(serverFd);
+    mAcceptFn = std::move(acceptFn);
     return OK;
 }
 
+status_t RpcServer::setupExternalServer(base::unique_fd serverFd) {
+    return setupExternalServer(std::move(serverFd), &RpcServer::acceptSocketConnection);
+}
+
 bool RpcServer::hasActiveRequests() {
     RpcMutexLockGuard _l(mLock);
     for (const auto& [_, session] : mSessions) {
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 49843e5..7d6bcfc 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -41,6 +41,7 @@
 #include "OS.h"
 #include "RpcSocketAddress.h"
 #include "RpcState.h"
+#include "RpcTransportUtils.h"
 #include "RpcWireFormat.h"
 #include "Utils.h"
 
@@ -147,6 +148,34 @@
     return setupSocketClient(UnixSocketAddress(path));
 }
 
+status_t RpcSession::setupUnixDomainSocketBootstrapClient(unique_fd bootstrapFd) {
+    mBootstrapTransport =
+            mCtx->newTransport(RpcTransportFd(std::move(bootstrapFd)), mShutdownTrigger.get());
+    return setupClient([&](const std::vector<uint8_t>& sessionId, bool incoming) {
+        int socks[2];
+        if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, socks) < 0) {
+            int savedErrno = errno;
+            ALOGE("Failed socketpair: %s", strerror(savedErrno));
+            return -savedErrno;
+        }
+        unique_fd clientFd(socks[0]), serverFd(socks[1]);
+
+        int zero = 0;
+        iovec iov{&zero, sizeof(zero)};
+        std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
+        fds.push_back(std::move(serverFd));
+
+        status_t status = mBootstrapTransport->interruptableWriteFully(mShutdownTrigger.get(), &iov,
+                                                                       1, std::nullopt, &fds);
+        if (status != OK) {
+            ALOGE("Failed to send fd over bootstrap transport: %s", strerror(-status));
+            return status;
+        }
+
+        return initAndAddConnection(RpcTransportFd(std::move(clientFd)), sessionId, incoming);
+    });
+}
+
 status_t RpcSession::setupVsockClient(unsigned int cid, unsigned int port) {
     return setupSocketClient(VsockSocketAddress(cid, port));
 }
@@ -295,16 +324,18 @@
 }
 
 void RpcSession::WaitForShutdownListener::onSessionIncomingThreadEnded() {
+    mShutdownCount += 1;
     mCv.notify_all();
 }
 
 void RpcSession::WaitForShutdownListener::waitForShutdown(RpcMutexUniqueLock& lock,
                                                           const sp<RpcSession>& session) {
-    while (session->mConnections.mIncoming.size() > 0) {
+    while (mShutdownCount < session->mConnections.mMaxIncoming) {
         if (std::cv_status::timeout == mCv.wait_for(lock, std::chrono::seconds(1))) {
             ALOGE("Waiting for RpcSession to shut down (1s w/o progress): %zu incoming connections "
-                  "still.",
-                  session->mConnections.mIncoming.size());
+                  "still %zu/%zu fully shutdown.",
+                  session->mConnections.mIncoming.size(), mShutdownCount.load(),
+                  session->mConnections.mMaxIncoming);
         }
     }
 }
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index c0e36c4..b27f102 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -41,7 +41,7 @@
 #if RPC_FLAKE_PRONE
 void rpcMaybeWaitToFlake() {
     [[clang::no_destroy]] static std::random_device r;
-    [[clang::no_destroy]] static std::mutex m;
+    [[clang::no_destroy]] static RpcMutex m;
     unsigned num;
     {
         RpcMutexLockGuard lock(m);
@@ -56,6 +56,7 @@
         case RpcSession::FileDescriptorTransportMode::NONE:
             return false;
         case RpcSession::FileDescriptorTransportMode::UNIX:
+        case RpcSession::FileDescriptorTransportMode::TRUSTY:
             return true;
     }
 }
@@ -886,6 +887,7 @@
                 it->second.asyncTodo.push(BinderNode::AsyncTodo{
                         .ref = target,
                         .data = std::move(transactionData),
+                        .ancillaryFds = std::move(ancillaryFds),
                         .asyncNumber = transaction->asyncNumber,
                 });
 
@@ -1046,6 +1048,7 @@
 
                 // reset up arguments
                 transactionData = std::move(todo.data);
+                ancillaryFds = std::move(todo.ancillaryFds);
                 LOG_ALWAYS_FATAL_IF(target != todo.ref,
                                     "async list should be associated with a binder");
 
@@ -1205,6 +1208,20 @@
                                              rpcFields->mFds->size(), kMaxFdsPerMsg);
                     return BAD_VALUE;
                 }
+                break;
+            }
+            case RpcSession::FileDescriptorTransportMode::TRUSTY: {
+                // Keep this in sync with trusty_ipc.h!!!
+                // We could import that file here on Trusty, but it's not
+                // available on Android
+                constexpr size_t kMaxFdsPerMsg = 8;
+                if (rpcFields->mFds->size() > kMaxFdsPerMsg) {
+                    *errorMsg = StringPrintf("Too many file descriptors in Parcel for Trusty "
+                                             "IPC connection: %zu (max is %zu)",
+                                             rpcFields->mFds->size(), kMaxFdsPerMsg);
+                    return BAD_VALUE;
+                }
+                break;
             }
         }
     }
diff --git a/libs/binder/RpcState.h b/libs/binder/RpcState.h
index 7aab5ee..ac86585 100644
--- a/libs/binder/RpcState.h
+++ b/libs/binder/RpcState.h
@@ -250,6 +250,7 @@
         struct AsyncTodo {
             sp<IBinder> ref;
             CommandData data;
+            std::vector<std::variant<base::unique_fd, base::borrowed_fd>> ancillaryFds;
             uint64_t asyncNumber = 0;
 
             bool operator<(const AsyncTodo& o) const {
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 65e8fac..1912d14 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -23,6 +23,7 @@
 #include <binder/RpcTransportRaw.h>
 
 #include "FdTrigger.h"
+#include "OS.h"
 #include "RpcState.h"
 #include "RpcTransportUtils.h"
 
@@ -30,9 +31,6 @@
 
 namespace {
 
-// Linux kernel supports up to 253 (from SCM_MAX_FD) for unix sockets.
-constexpr size_t kMaxFdsPerMsg = 253;
-
 // RpcTransport with TLS disabled.
 class RpcTransportRaw : public RpcTransport {
 public:
@@ -63,57 +61,9 @@
             override {
         bool sentFds = false;
         auto send = [&](iovec* iovs, int niovs) -> ssize_t {
-            if (ancillaryFds != nullptr && !ancillaryFds->empty() && !sentFds) {
-                if (ancillaryFds->size() > kMaxFdsPerMsg) {
-                    // This shouldn't happen because we check the FD count in RpcState.
-                    ALOGE("Saw too many file descriptors in RpcTransportCtxRaw: %zu (max is %zu). "
-                          "Aborting session.",
-                          ancillaryFds->size(), kMaxFdsPerMsg);
-                    errno = EINVAL;
-                    return -1;
-                }
-
-                // CMSG_DATA is not necessarily aligned, so we copy the FDs into a buffer and then
-                // use memcpy.
-                int fds[kMaxFdsPerMsg];
-                for (size_t i = 0; i < ancillaryFds->size(); i++) {
-                    fds[i] = std::visit([](const auto& fd) { return fd.get(); },
-                                        ancillaryFds->at(i));
-                }
-                const size_t fdsByteSize = sizeof(int) * ancillaryFds->size();
-
-                alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(int) * kMaxFdsPerMsg)];
-
-                msghdr msg{
-                        .msg_iov = iovs,
-                        .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
-                        .msg_control = msgControlBuf,
-                        .msg_controllen = sizeof(msgControlBuf),
-                };
-
-                cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
-                cmsg->cmsg_level = SOL_SOCKET;
-                cmsg->cmsg_type = SCM_RIGHTS;
-                cmsg->cmsg_len = CMSG_LEN(fdsByteSize);
-                memcpy(CMSG_DATA(cmsg), fds, fdsByteSize);
-
-                msg.msg_controllen = CMSG_SPACE(fdsByteSize);
-
-                ssize_t processedSize = TEMP_FAILURE_RETRY(
-                        sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL | MSG_CMSG_CLOEXEC));
-                if (processedSize > 0) {
-                    sentFds = true;
-                }
-                return processedSize;
-            }
-
-            msghdr msg{
-                    .msg_iov = iovs,
-                    // posix uses int, glibc uses size_t.  niovs is a
-                    // non-negative int and can be cast to either.
-                    .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
-            };
-            return TEMP_FAILURE_RETRY(sendmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
+            int ret = sendMessageOnSocket(mSocket, iovs, niovs, sentFds ? nullptr : ancillaryFds);
+            sentFds |= ret > 0;
+            return ret;
         };
         return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, send, "sendmsg", POLLOUT,
                                         altPoll);
@@ -124,54 +74,7 @@
             const std::optional<android::base::function_ref<status_t()>>& altPoll,
             std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
         auto recv = [&](iovec* iovs, int niovs) -> ssize_t {
-            if (ancillaryFds != nullptr) {
-                int fdBuffer[kMaxFdsPerMsg];
-                alignas(struct cmsghdr) char msgControlBuf[CMSG_SPACE(sizeof(fdBuffer))];
-
-                msghdr msg{
-                        .msg_iov = iovs,
-                        .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
-                        .msg_control = msgControlBuf,
-                        .msg_controllen = sizeof(msgControlBuf),
-                };
-                ssize_t processSize =
-                        TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
-                if (processSize < 0) {
-                    return -1;
-                }
-
-                for (cmsghdr* cmsg = CMSG_FIRSTHDR(&msg); cmsg != nullptr;
-                     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
-                    if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
-                        // NOTE: It is tempting to reinterpret_cast, but cmsg(3) explicitly asks
-                        // application devs to memcpy the data to ensure memory alignment.
-                        size_t dataLen = cmsg->cmsg_len - CMSG_LEN(0);
-                        LOG_ALWAYS_FATAL_IF(dataLen > sizeof(fdBuffer)); // sanity check
-                        memcpy(fdBuffer, CMSG_DATA(cmsg), dataLen);
-                        size_t fdCount = dataLen / sizeof(int);
-                        ancillaryFds->reserve(ancillaryFds->size() + fdCount);
-                        for (size_t i = 0; i < fdCount; i++) {
-                            ancillaryFds->emplace_back(base::unique_fd(fdBuffer[i]));
-                        }
-                        break;
-                    }
-                }
-
-                if (msg.msg_flags & MSG_CTRUNC) {
-                    ALOGE("msg was truncated. Aborting session.");
-                    errno = EPIPE;
-                    return -1;
-                }
-
-                return processSize;
-            }
-            msghdr msg{
-                    .msg_iov = iovs,
-                    // posix uses int, glibc uses size_t.  niovs is a
-                    // non-negative int and can be cast to either.
-                    .msg_iovlen = static_cast<decltype(msg.msg_iovlen)>(niovs),
-            };
-            return TEMP_FAILURE_RETRY(recvmsg(mSocket.fd.get(), &msg, MSG_NOSIGNAL));
+            return receiveMessageFromSocket(mSocket, iovs, niovs, ancillaryFds);
         };
         return interruptableReadOrWrite(mSocket, fdTrigger, iovs, niovs, recv, "recvmsg", POLLIN,
                                         altPoll);
diff --git a/libs/binder/RpcTrusty.cpp b/libs/binder/RpcTrusty.cpp
index ea49eef..3b53b05 100644
--- a/libs/binder/RpcTrusty.cpp
+++ b/libs/binder/RpcTrusty.cpp
@@ -26,8 +26,12 @@
 
 using android::base::unique_fd;
 
-sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+        const char* device, const char* port,
+        std::function<void(sp<RpcSession>&)> sessionInitializer) {
     auto session = RpcSession::make(RpcTransportCtxFactoryTipcAndroid::make());
+    // using the callback to initialize the session
+    sessionInitializer(session);
     auto request = [=] {
         int tipcFd = tipc_connect(device, port);
         if (tipcFd < 0) {
@@ -40,6 +44,11 @@
         LOG(ERROR) << "Failed to set up Trusty client. Error: " << statusToString(status).c_str();
         return nullptr;
     }
+    return session;
+}
+
+sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+    auto session = RpcTrustyConnectWithSessionInitializer(device, port, [](auto) {});
     return session->getRootObject();
 }
 
diff --git a/libs/binder/TEST_MAPPING b/libs/binder/TEST_MAPPING
index c91d56c..342e4a3 100644
--- a/libs/binder/TEST_MAPPING
+++ b/libs/binder/TEST_MAPPING
@@ -58,13 +58,10 @@
       "name": "CtsOsTestCases",
       "options": [
         {
-          "exclude-annotation": "android.platform.test.annotations.LargeTest"
+          "include-filter": "android.os.cts.BinderTest"
         },
         {
-          "exclude-filter": "android.os.cts.BuildTest#testSdkInt"
-        },
-        {
-          "exclude-filter": "android.os.cts.StrictModeTest#testNonSdkApiUsage"
+          "include-filter": "android.os.cts.ParcelTest"
         }
       ]
     },
diff --git a/libs/binder/TextOutput.cpp b/libs/binder/TextOutput.cpp
index a0ade50..5dd1f90 100644
--- a/libs/binder/TextOutput.cpp
+++ b/libs/binder/TextOutput.cpp
@@ -39,11 +39,10 @@
 
 static void textOutputPrinter(void* cookie, const char* txt)
 {
-    ((TextOutput*)cookie)->print(txt, strlen(txt));
+    ((std::ostream*)cookie)->write(txt, strlen(txt));
 }
 
-TextOutput& operator<<(TextOutput& to, const TypeCode& val)
-{
+std::ostream& operator<<(std::ostream& to, const TypeCode& val) {
     printTypeCode(val.typeCode(), textOutputPrinter, (void*)&to);
     return to;
 }
@@ -61,8 +60,7 @@
     else mAlignment = 1;
 }
 
-TextOutput& operator<<(TextOutput& to, const HexDump& val)
-{
+std::ostream& operator<<(std::ostream& to, const HexDump& val) {
     printHexData(0, val.buffer(), val.size(), val.bytesPerLine(),
         val.singleLineCutoff(), val.alignment(), val.carrayStyle(),
         textOutputPrinter, (void*)&to);
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 5469239..6de6ce8 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -595,7 +595,7 @@
     // uid.
     uid_t               readCallingWorkSourceUid() const;
 
-    void                print(TextOutput& to, uint32_t flags = 0) const;
+    void print(std::ostream& to, uint32_t flags = 0) const;
 
 private:
     // `objects` and `objectsSize` always 0 for RPC Parcels.
@@ -1594,8 +1594,7 @@
 
 // ---------------------------------------------------------------------------
 
-inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
-{
+inline std::ostream& operator<<(std::ostream& to, const Parcel& parcel) {
     parcel.print(to);
     return to;
 }
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index 2c99334..81ae26a3 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -50,6 +50,17 @@
             std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
 
     /**
+     * Creates an RPC server that bootstraps sessions using an existing
+     * Unix domain socket pair.
+     *
+     * Callers should create a pair of SOCK_STREAM Unix domain sockets, pass
+     * one to RpcServer::setupUnixDomainSocketBootstrapServer and the other
+     * to RpcSession::setupUnixDomainSocketBootstrapClient. Multiple client
+     * session can be created from the client end of the pair.
+     */
+    [[nodiscard]] status_t setupUnixDomainSocketBootstrapServer(base::unique_fd serverFd);
+
+    /**
      * This represents a session for responses, e.g.:
      *
      *     process A serves binder a
@@ -202,11 +213,18 @@
     void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
     void onSessionIncomingThreadEnded() override;
 
+    status_t setupExternalServer(
+            base::unique_fd serverFd,
+            std::function<status_t(const RpcServer&, RpcTransportFd*)>&& acceptFn);
+
     static constexpr size_t kRpcAddressSize = 128;
     static void establishConnection(
             sp<RpcServer>&& server, RpcTransportFd clientFd,
             std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen,
             std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn);
+    static status_t acceptSocketConnection(const RpcServer& server, RpcTransportFd* out);
+    static status_t recvmsgSocketConnection(const RpcServer& server, RpcTransportFd* out);
+
     [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
 
     const std::unique_ptr<RpcTransportCtx> mCtx;
@@ -228,6 +246,7 @@
     std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
     std::unique_ptr<FdTrigger> mShutdownTrigger;
     RpcConditionVariable mShutdownCv;
+    std::function<status_t(const RpcServer& server, RpcTransportFd* out)> mAcceptFn;
 };
 
 } // namespace android
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index a25ba98..40faf2c 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -100,6 +100,8 @@
         NONE = 0,
         // Send file descriptors via unix domain socket ancillary data.
         UNIX = 1,
+        // Send file descriptors as Trusty IPC handles.
+        TRUSTY = 2,
     };
 
     /**
@@ -115,6 +117,11 @@
     [[nodiscard]] status_t setupUnixDomainClient(const char* path);
 
     /**
+     * Connects to an RPC server over a nameless Unix domain socket pair.
+     */
+    [[nodiscard]] status_t setupUnixDomainSocketBootstrapClient(base::unique_fd bootstrap);
+
+    /**
      * Connects to an RPC server at the CVD & port.
      */
     [[nodiscard]] status_t setupVsockClient(unsigned int cvd, unsigned int port);
@@ -233,6 +240,7 @@
 
     private:
         RpcConditionVariable mCv;
+        std::atomic<size_t> mShutdownCount = 0;
     };
     friend WaitForShutdownListener;
 
@@ -366,11 +374,14 @@
 
     RpcConditionVariable mAvailableConnectionCv; // for mWaitingThreads
 
+    std::unique_ptr<RpcTransport> mBootstrapTransport;
+
     struct ThreadState {
         size_t mWaitingThreads = 0;
         // hint index into clients, ++ when sending an async transaction
         size_t mOutgoingOffset = 0;
         std::vector<sp<RpcConnection>> mOutgoing;
+        // max size of mIncoming. Once any thread starts down, no more can be started.
         size_t mMaxIncoming = 0;
         std::vector<sp<RpcConnection>> mIncoming;
         std::map<RpcMaybeThread::id, RpcMaybeThread> mThreads;
diff --git a/libs/binder/include/binder/TextOutput.h b/libs/binder/include/binder/TextOutput.h
index bf9c92b..eb98042 100644
--- a/libs/binder/include/binder/TextOutput.h
+++ b/libs/binder/include/binder/TextOutput.h
@@ -94,7 +94,7 @@
     uint32_t mCode;
 };
 
-TextOutput& operator<<(TextOutput& to, const TypeCode& val);
+std::ostream& operator<<(std::ostream& to, const TypeCode& val);
 
 class HexDump
 {
@@ -123,7 +123,7 @@
     bool mCArrayStyle;
 };
 
-TextOutput& operator<<(TextOutput& to, const HexDump& val);
+std::ostream& operator<<(std::ostream& to, const HexDump& val);
 inline TextOutput& operator<<(TextOutput& to,
                               decltype(std::endl<char,
                                        std::char_traits<char>>)
diff --git a/libs/binder/include_trusty/binder/RpcTrusty.h b/libs/binder/include_trusty/binder/RpcTrusty.h
index f124e0c..b034b9b 100644
--- a/libs/binder/include_trusty/binder/RpcTrusty.h
+++ b/libs/binder/include_trusty/binder/RpcTrusty.h
@@ -22,4 +22,8 @@
 
 sp<IBinder> RpcTrustyConnect(const char* device, const char* port);
 
+sp<RpcSession> RpcTrustyConnectWithSessionInitializer(
+        const char* device, const char* port,
+        std::function<void(sp<RpcSession>&)> sessionInitializer);
+
 } // namespace android
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 33d28e6..8ae7537 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -182,4 +182,8 @@
     name: "libbinder_ndk",
     symbol_file: "libbinder_ndk.map.txt",
     first_version: "29",
+    export_header_libs: [
+        "libbinder_ndk_headers",
+        "libbinder_ndk_helper_headers",
+    ],
 }
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index 7ea9be7..fccc0af 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -349,7 +349,7 @@
     /**
      * See AIBinder_Weak_promote.
      */
-    SpAIBinder promote() { return SpAIBinder(AIBinder_Weak_promote(get())); }
+    SpAIBinder promote() const { return SpAIBinder(AIBinder_Weak_promote(get())); }
 };
 
 namespace internal {
diff --git a/libs/binder/ndk/include_platform/android/binder_libbinder.h b/libs/binder/ndk/include_platform/android/binder_libbinder.h
index dfe12a1..74a7157 100644
--- a/libs/binder/ndk/include_platform/android/binder_libbinder.h
+++ b/libs/binder/ndk/include_platform/android/binder_libbinder.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#if !defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)
+#if (!defined(__ANDROID_APEX__) && !defined(__ANDROID_VNDK__)) || defined(__TRUSTY__)
 
 #include <android/binder_ibinder.h>
 #include <android/binder_parcel.h>
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 6d29238..01b9472 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -670,6 +670,26 @@
     EXPECT_EQ(42, pparcel->readInt32());
 }
 
+TEST(NdkBinder, GetAndVerifyScopedAIBinder_Weak) {
+    for (const ndk::SpAIBinder& binder :
+         {// remote
+          ndk::SpAIBinder(AServiceManager_getService(kBinderNdkUnitTestService)),
+          // local
+          ndk::SharedRefBase::make<MyBinderNdkUnitTest>()->asBinder()}) {
+        // get a const ScopedAIBinder_Weak and verify promote
+        EXPECT_NE(binder.get(), nullptr);
+        const ndk::ScopedAIBinder_Weak wkAIBinder =
+                ndk::ScopedAIBinder_Weak(AIBinder_Weak_new(binder.get()));
+        EXPECT_EQ(wkAIBinder.promote().get(), binder.get());
+        // get another ScopedAIBinder_Weak and verify
+        ndk::ScopedAIBinder_Weak wkAIBinder2 =
+                ndk::ScopedAIBinder_Weak(AIBinder_Weak_new(binder.get()));
+        EXPECT_FALSE(AIBinder_Weak_lt(wkAIBinder.get(), wkAIBinder2.get()));
+        EXPECT_FALSE(AIBinder_Weak_lt(wkAIBinder2.get(), wkAIBinder.get()));
+        EXPECT_EQ(wkAIBinder2.promote(), wkAIBinder.promote());
+    }
+}
+
 class MyResultReceiver : public BnResultReceiver {
    public:
     Mutex mMutex;
diff --git a/libs/binder/tests/BinderRpcTestServerConfig.aidl b/libs/binder/tests/BinderRpcTestServerConfig.aidl
index 34d74be..4cdeac4 100644
--- a/libs/binder/tests/BinderRpcTestServerConfig.aidl
+++ b/libs/binder/tests/BinderRpcTestServerConfig.aidl
@@ -21,5 +21,6 @@
     int rpcSecurity;
     int serverVersion;
     int vsockPort;
+    int unixBootstrapFd; // Inherited from parent
     @utf8InCpp String addr;
 }
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index b15a225..a3ed571 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -71,4 +71,13 @@
     ParcelFileDescriptor echoAsFile(@utf8InCpp String content);
 
     ParcelFileDescriptor concatFiles(in List<ParcelFileDescriptor> files);
+
+    // FDs sent via `blockingSendFdOneway` can be received via
+    // `blockingRecvFd`. The handler for `blockingSendFdOneway` will block
+    // until the next `blockingRecvFd` call.
+    //
+    // This is useful for carefully controlling how/when oneway transactions
+    // get queued.
+    oneway void blockingSendFdOneway(in ParcelFileDescriptor fd);
+    ParcelFileDescriptor blockingRecvFd();
 }
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 6e1c8ac..25b524f 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -115,6 +115,7 @@
     BINDER_LIB_TEST_NOP_TRANSACTION_WAIT,
     BINDER_LIB_TEST_GETPID,
     BINDER_LIB_TEST_ECHO_VECTOR,
+    BINDER_LIB_TEST_GET_NON_BLOCKING_FD,
     BINDER_LIB_TEST_REJECT_OBJECTS,
     BINDER_LIB_TEST_CAN_GET_SID,
     BINDER_LIB_TEST_GET_MAX_THREAD_COUNT,
@@ -1158,6 +1159,21 @@
     EXPECT_EQ(readValue, testValue);
 }
 
+TEST_F(BinderLibTest, FileDescriptorRemainsNonBlocking) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    Parcel reply;
+    EXPECT_THAT(server->transact(BINDER_LIB_TEST_GET_NON_BLOCKING_FD, {} /*data*/, &reply),
+                StatusEq(NO_ERROR));
+    base::unique_fd fd;
+    EXPECT_THAT(reply.readUniqueFileDescriptor(&fd), StatusEq(OK));
+
+    const int result = fcntl(fd.get(), F_GETFL);
+    ASSERT_NE(result, -1);
+    EXPECT_EQ(result & O_NONBLOCK, O_NONBLOCK);
+}
+
 // see ProcessState.cpp BINDER_VM_SIZE = 1MB.
 // This value is not exposed, but some code in the framework relies on being able to use
 // buffers near the cap size.
@@ -1801,6 +1817,28 @@
                 reply->writeUint64Vector(vector);
                 return NO_ERROR;
             }
+            case BINDER_LIB_TEST_GET_NON_BLOCKING_FD: {
+                std::array<int, 2> sockets;
+                const bool created = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets.data()) == 0;
+                if (!created) {
+                    ALOGE("Could not create socket pair");
+                    return UNKNOWN_ERROR;
+                }
+
+                const int result = fcntl(sockets[0], F_SETFL, O_NONBLOCK);
+                if (result != 0) {
+                    ALOGE("Could not make socket non-blocking: %s", strerror(errno));
+                    return UNKNOWN_ERROR;
+                }
+                base::unique_fd out(sockets[0]);
+                status_t writeResult = reply->writeUniqueFileDescriptor(out);
+                if (writeResult != NO_ERROR) {
+                    ALOGE("Could not write unique_fd");
+                    return writeResult;
+                }
+                close(sockets[1]); // we don't need the other side of the fd
+                return NO_ERROR;
+            }
             case BINDER_LIB_TEST_REJECT_OBJECTS: {
                 return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
             }
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 21b0354..7294305 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -85,6 +85,11 @@
     return base::StringPrintf("unexpected state %d", wstatus);
 }
 
+static void debugBacktrace(pid_t pid) {
+    std::cerr << "TAKING BACKTRACE FOR PID " << pid << std::endl;
+    system((std::string("debuggerd -b ") + std::to_string(pid)).c_str());
+}
+
 class Process {
 public:
     Process(Process&&) = default;
@@ -125,6 +130,8 @@
     // Kill the process. Avoid if possible. Shutdown gracefully via an RPC instead.
     void terminate() { kill(mPid, SIGTERM); }
 
+    pid_t getPid() { return mPid; }
+
 private:
     std::function<void(int wstatus)> mCustomExitStatusCheck;
     pid_t mPid = 0;
@@ -173,7 +180,21 @@
 
             wp<RpcSession> weakSession = session;
             session = nullptr;
-            EXPECT_EQ(nullptr, weakSession.promote()) << "Leaked session";
+
+            // b/244325464 - 'getStrongCount' is printing '1' on failure here, which indicates the
+            // the object should not actually be promotable. By looping, we distinguish a race here
+            // from a bug causing the object to not be promotable.
+            for (size_t i = 0; i < 3; i++) {
+                sp<RpcSession> strongSession = weakSession.promote();
+                EXPECT_EQ(nullptr, strongSession)
+                        << (debugBacktrace(host.getPid()), debugBacktrace(getpid()),
+                            "Leaked sess: ")
+                        << strongSession->getStrongCount() << " checked time " << i;
+
+                if (strongSession != nullptr) {
+                    sleep(1);
+                }
+            }
         }
     }
 };
@@ -233,6 +254,25 @@
     return serverFd;
 }
 
+static base::unique_fd connectToUnixBootstrap(const RpcTransportFd& transportFd) {
+    base::unique_fd sockClient, sockServer;
+    if (!base::Socketpair(SOCK_STREAM, &sockClient, &sockServer)) {
+        int savedErrno = errno;
+        LOG(FATAL) << "Failed socketpair(): " << strerror(savedErrno);
+    }
+
+    int zero = 0;
+    iovec iov{&zero, sizeof(zero)};
+    std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
+    fds.emplace_back(std::move(sockServer));
+
+    if (sendMessageOnSocket(transportFd, &iov, 1, &fds) < 0) {
+        int savedErrno = errno;
+        LOG(FATAL) << "Failed sendMessageOnSocket: " << strerror(savedErrno);
+    }
+    return std::move(sockClient);
+}
+
 using RunServiceFn = void (*)(android::base::borrowed_fd writeEnd,
                               android::base::borrowed_fd readEnd);
 
@@ -253,7 +293,14 @@
     // Whether the test params support sending FDs in parcels.
     bool supportsFdTransport() const {
         return clientVersion() >= 1 && serverVersion() >= 1 && rpcSecurity() != RpcSecurity::TLS &&
-                (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX);
+                (socketType() == SocketType::PRECONNECTED || socketType() == SocketType::UNIX ||
+                 socketType() == SocketType::UNIX_BOOTSTRAP);
+    }
+
+    void SetUp() override {
+        if (socketType() == SocketType::UNIX_BOOTSTRAP && rpcSecurity() == RpcSecurity::TLS) {
+            GTEST_SKIP() << "Unix bootstrap not supported over a TLS transport";
+        }
     }
 
     static inline std::string PrintParamInfo(const testing::TestParamInfo<ParamType>& info) {
@@ -287,6 +334,14 @@
                                             singleThreaded ? "_single_threaded" : "",
                                             noKernel ? "_no_kernel" : "");
 
+        base::unique_fd bootstrapClientFd, bootstrapServerFd;
+        // Do not set O_CLOEXEC, bootstrapServerFd needs to survive fork/exec.
+        // This is because we cannot pass ParcelFileDescriptor over a pipe.
+        if (!base::Socketpair(SOCK_STREAM, &bootstrapClientFd, &bootstrapServerFd)) {
+            int savedErrno = errno;
+            LOG(FATAL) << "Failed socketpair(): " << strerror(savedErrno);
+        }
+
         auto ret = ProcessSession{
                 .host = Process([=](android::base::borrowed_fd writeEnd,
                                     android::base::borrowed_fd readEnd) {
@@ -304,6 +359,7 @@
         serverConfig.serverVersion = serverVersion;
         serverConfig.vsockPort = allocateVsockPort();
         serverConfig.addr = allocateSocketAddress();
+        serverConfig.unixBootstrapFd = bootstrapServerFd.get();
         for (auto mode : options.serverSupportedFileDescriptorTransportModes) {
             serverConfig.serverSupportedFileDescriptorTransportModes.push_back(
                     static_cast<int32_t>(mode));
@@ -353,6 +409,10 @@
                 case SocketType::UNIX:
                     status = session->setupUnixDomainClient(serverConfig.addr.c_str());
                     break;
+                case SocketType::UNIX_BOOTSTRAP:
+                    status = session->setupUnixDomainSocketBootstrapClient(
+                            base::unique_fd(dup(bootstrapClientFd.get())));
+                    break;
                 case SocketType::VSOCK:
                     status = session->setupVsockClient(VMADDR_CID_LOCAL, serverConfig.vsockPort);
                     break;
@@ -419,7 +479,8 @@
     }
 
     SocketType type = std::get<0>(GetParam());
-    if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
+    if (type == SocketType::PRECONNECTED || type == SocketType::UNIX ||
+        type == SocketType::UNIX_BOOTSTRAP) {
         // we can't get port numbers for unix sockets
         return;
     }
@@ -777,12 +838,12 @@
         ts.push_back(std::thread([&] { proc.rootIface->lockUnlock(); }));
     }
 
-    usleep(100000); // give chance for calls on other threads
+    usleep(10000); // give chance for calls on other threads
 
     // other calls still work
     EXPECT_EQ(OK, proc.rootBinder->pingBinder());
 
-    constexpr size_t blockTimeMs = 500;
+    constexpr size_t blockTimeMs = 50;
     size_t epochMsBefore = epochMillis();
     // after this, we should never see a response within this time
     EXPECT_OK(proc.rootIface->unlockInMsAsync(blockTimeMs));
@@ -911,6 +972,45 @@
     EXPECT_LT(epochMsAfter, epochMsBefore + kReallyLongTimeMs);
 }
 
+TEST_P(BinderRpc, OnewayCallQueueingWithFds) {
+    if (!supportsFdTransport()) {
+        GTEST_SKIP() << "Would fail trivially (which is tested elsewhere)";
+    }
+    if (clientOrServerSingleThreaded()) {
+        GTEST_SKIP() << "This test requires multiple threads";
+    }
+
+    // This test forces a oneway transaction to be queued by issuing two
+    // `blockingSendFdOneway` calls, then drains the queue by issuing two
+    // `blockingRecvFd` calls.
+    //
+    // For more details about the queuing semantics see
+    // https://developer.android.com/reference/android/os/IBinder#FLAG_ONEWAY
+
+    auto proc = createRpcTestSocketServerProcess({
+            .numThreads = 3,
+            .clientFileDescriptorTransportMode = RpcSession::FileDescriptorTransportMode::UNIX,
+            .serverSupportedFileDescriptorTransportModes =
+                    {RpcSession::FileDescriptorTransportMode::UNIX},
+    });
+
+    EXPECT_OK(proc.rootIface->blockingSendFdOneway(
+            android::os::ParcelFileDescriptor(mockFileDescriptor("a"))));
+    EXPECT_OK(proc.rootIface->blockingSendFdOneway(
+            android::os::ParcelFileDescriptor(mockFileDescriptor("b"))));
+
+    android::os::ParcelFileDescriptor fdA;
+    EXPECT_OK(proc.rootIface->blockingRecvFd(&fdA));
+    std::string result;
+    CHECK(android::base::ReadFdToString(fdA.get(), &result));
+    EXPECT_EQ(result, "a");
+
+    android::os::ParcelFileDescriptor fdB;
+    EXPECT_OK(proc.rootIface->blockingRecvFd(&fdB));
+    CHECK(android::base::ReadFdToString(fdB.get(), &result));
+    EXPECT_EQ(result, "b");
+}
+
 TEST_P(BinderRpc, OnewayCallQueueing) {
     if (clientOrServerSingleThreaded()) {
         GTEST_SKIP() << "This test requires multiple threads";
@@ -1074,7 +1174,7 @@
     }
 
     std::unique_lock<std::mutex> lock(dr->mMtx);
-    ASSERT_TRUE(dr->mCv.wait_for(lock, 1000ms, [&]() { return dr->dead; }));
+    ASSERT_TRUE(dr->mCv.wait_for(lock, 100ms, [&]() { return dr->dead; }));
 
     // need to wait for the session to shutdown so we don't "Leak session"
     EXPECT_TRUE(proc.proc.sessions.at(0).session->shutdownAndWait(true));
@@ -1109,7 +1209,7 @@
 
     std::unique_lock<std::mutex> lock(dr->mMtx);
     if (!dr->dead) {
-        EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 1000ms));
+        EXPECT_EQ(std::cv_status::no_timeout, dr->mCv.wait_for(lock, 100ms));
     }
     EXPECT_TRUE(dr->dead) << "Failed to receive the death notification.";
 
@@ -1516,7 +1616,7 @@
 }
 
 static std::vector<SocketType> testSocketTypes(bool hasPreconnected = true) {
-    std::vector<SocketType> ret = {SocketType::UNIX, SocketType::INET};
+    std::vector<SocketType> ret = {SocketType::UNIX, SocketType::UNIX_BOOTSTRAP, SocketType::INET};
 
     if (hasPreconnected) ret.push_back(SocketType::PRECONNECTED);
 
@@ -1692,7 +1792,7 @@
 
     bool shutdown = false;
     for (int i = 0; i < 10 && !shutdown; i++) {
-        usleep(300 * 1000); // 300ms; total 3s
+        usleep(30 * 1000); // 30ms; total 300ms
         if (server->shutdown()) shutdown = true;
     }
     ASSERT_TRUE(shutdown) << "server->shutdown() never returns true";
@@ -1717,6 +1817,8 @@
     // A server that handles client socket connections.
     class Server {
     public:
+        using AcceptConnection = std::function<base::unique_fd(Server*)>;
+
         explicit Server() {}
         Server(Server&&) = default;
         ~Server() { shutdownAndWait(); }
@@ -1741,6 +1843,21 @@
                         return connectTo(UnixSocketAddress(addr.c_str()));
                     };
                 } break;
+                case SocketType::UNIX_BOOTSTRAP: {
+                    base::unique_fd bootstrapFdClient, bootstrapFdServer;
+                    if (!base::Socketpair(SOCK_STREAM, &bootstrapFdClient, &bootstrapFdServer)) {
+                        return AssertionFailure() << "Socketpair() failed";
+                    }
+                    auto status = rpcServer->setupUnixDomainSocketBootstrapServer(
+                            std::move(bootstrapFdServer));
+                    if (status != OK) {
+                        return AssertionFailure() << "setupUnixDomainSocketBootstrapServer: "
+                                                  << statusToString(status);
+                    }
+                    mBootstrapSocket = RpcTransportFd(std::move(bootstrapFdClient));
+                    mAcceptConnection = &Server::recvmsgServerConnection;
+                    mConnectToServer = [this] { return connectToUnixBootstrap(mBootstrapSocket); };
+                } break;
                 case SocketType::VSOCK: {
                     auto port = allocateVsockPort();
                     auto status = rpcServer->setupVsockServer(port);
@@ -1788,14 +1905,33 @@
             LOG_ALWAYS_FATAL_IF(!mSetup, "Call Server::setup first!");
             mThread = std::make_unique<std::thread>(&Server::run, this);
         }
+
+        base::unique_fd acceptServerConnection() {
+            return base::unique_fd(TEMP_FAILURE_RETRY(
+                    accept4(mFd.fd.get(), nullptr, nullptr, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+        }
+
+        base::unique_fd recvmsgServerConnection() {
+            std::vector<std::variant<base::unique_fd, base::borrowed_fd>> fds;
+            int buf;
+            iovec iov{&buf, sizeof(buf)};
+
+            if (receiveMessageFromSocket(mFd, &iov, 1, &fds) < 0) {
+                int savedErrno = errno;
+                LOG(FATAL) << "Failed receiveMessage: " << strerror(savedErrno);
+            }
+            if (fds.size() != 1) {
+                LOG(FATAL) << "Expected one FD from receiveMessage(), got " << fds.size();
+            }
+            return std::move(std::get<base::unique_fd>(fds[0]));
+        }
+
         void run() {
             LOG_ALWAYS_FATAL_IF(!mSetup, "Call Server::setup first!");
 
             std::vector<std::thread> threads;
             while (OK == mFdTrigger->triggerablePoll(mFd, POLLIN)) {
-                base::unique_fd acceptedFd(
-                        TEMP_FAILURE_RETRY(accept4(mFd.fd.get(), nullptr, nullptr /*length*/,
-                                                   SOCK_CLOEXEC | SOCK_NONBLOCK)));
+                base::unique_fd acceptedFd = mAcceptConnection(this);
                 threads.emplace_back(&Server::handleOne, this, std::move(acceptedFd));
             }
 
@@ -1822,8 +1958,9 @@
     private:
         std::unique_ptr<std::thread> mThread;
         ConnectToServer mConnectToServer;
+        AcceptConnection mAcceptConnection = &Server::acceptServerConnection;
         std::unique_ptr<FdTrigger> mFdTrigger = FdTrigger::make();
-        RpcTransportFd mFd;
+        RpcTransportFd mFd, mBootstrapSocket;
         std::unique_ptr<RpcTransportCtx> mCtx;
         std::shared_ptr<RpcCertificateVerifierSimple> mCertVerifier =
                 std::make_shared<RpcCertificateVerifierSimple>();
diff --git a/libs/binder/tests/binderRpcTestCommon.h b/libs/binder/tests/binderRpcTestCommon.h
index 4513d36..823bbf6 100644
--- a/libs/binder/tests/binderRpcTestCommon.h
+++ b/libs/binder/tests/binderRpcTestCommon.h
@@ -49,6 +49,7 @@
 
 #include "../BuildFlags.h"
 #include "../FdTrigger.h"
+#include "../OS.h"               // for testing UnixBootstrap clients
 #include "../RpcSocketAddress.h" // for testing preconnected clients
 #include "../RpcState.h"         // for debugging
 #include "../vm_sockets.h"       // for VMADDR_*
@@ -67,15 +68,19 @@
 enum class SocketType {
     PRECONNECTED,
     UNIX,
+    UNIX_BOOTSTRAP,
     VSOCK,
     INET,
 };
+
 static inline std::string PrintToString(SocketType socketType) {
     switch (socketType) {
         case SocketType::PRECONNECTED:
             return "preconnected_uds";
         case SocketType::UNIX:
             return "unix_domain_socket";
+        case SocketType::UNIX_BOOTSTRAP:
+            return "unix_domain_socket_bootstrap";
         case SocketType::VSOCK:
             return "vm_socket";
         case SocketType::INET:
@@ -167,6 +172,42 @@
     return readFd;
 }
 
+// A threadsafe channel where writes block until the value is read.
+template <typename T>
+class HandoffChannel {
+public:
+    void write(T v) {
+        {
+            RpcMutexUniqueLock lock(mMutex);
+            // Wait for space to send.
+            mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
+            mValue.emplace(std::move(v));
+        }
+        mCvFull.notify_all();
+        RpcMutexUniqueLock lock(mMutex);
+        // Wait for it to be taken.
+        mCvEmpty.wait(lock, [&]() { return !mValue.has_value(); });
+    }
+
+    T read() {
+        RpcMutexUniqueLock lock(mMutex);
+        if (!mValue.has_value()) {
+            mCvFull.wait(lock, [&]() { return mValue.has_value(); });
+        }
+        T v = std::move(mValue.value());
+        mValue.reset();
+        lock.unlock();
+        mCvEmpty.notify_all();
+        return std::move(v);
+    }
+
+private:
+    RpcMutex mMutex;
+    RpcConditionVariable mCvEmpty;
+    RpcConditionVariable mCvFull;
+    std::optional<T> mValue;
+};
+
 using android::binder::Status;
 
 class MyBinderRpcSession : public BnBinderRpcSession {
@@ -374,6 +415,18 @@
         out->reset(mockFileDescriptor(acc));
         return Status::ok();
     }
+
+    HandoffChannel<android::base::unique_fd> mFdChannel;
+
+    Status blockingSendFdOneway(const android::os::ParcelFileDescriptor& fd) override {
+        mFdChannel.write(android::base::unique_fd(fcntl(fd.get(), F_DUPFD_CLOEXEC, 0)));
+        return Status::ok();
+    }
+
+    Status blockingRecvFd(android::os::ParcelFileDescriptor* fd) override {
+        fd->reset(mFdChannel.read());
+        return Status::ok();
+    }
 };
 
 } // namespace android
diff --git a/libs/binder/tests/binderRpcTestService.cpp b/libs/binder/tests/binderRpcTestService.cpp
index 31eb5da..a922b21 100644
--- a/libs/binder/tests/binderRpcTestService.cpp
+++ b/libs/binder/tests/binderRpcTestService.cpp
@@ -42,6 +42,7 @@
     server->setSupportedFileDescriptorTransportModes(serverSupportedFileDescriptorTransportModes);
 
     unsigned int outPort = 0;
+    base::unique_fd unixBootstrapFd(serverConfig.unixBootstrapFd);
 
     switch (socketType) {
         case SocketType::PRECONNECTED:
@@ -50,6 +51,9 @@
             CHECK_EQ(OK, server->setupUnixDomainServer(serverConfig.addr.c_str()))
                     << serverConfig.addr;
             break;
+        case SocketType::UNIX_BOOTSTRAP:
+            CHECK_EQ(OK, server->setupUnixDomainSocketBootstrapServer(std::move(unixBootstrapFd)));
+            break;
         case SocketType::VSOCK:
             CHECK_EQ(OK, server->setupVsockServer(serverConfig.vsockPort));
             break;
diff --git a/libs/binder/tests/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
index 0210237..3904e1d 100644
--- a/libs/binder/tests/parcel_fuzzer/Android.bp
+++ b/libs/binder/tests/parcel_fuzzer/Android.bp
@@ -84,6 +84,7 @@
         },
     },
     srcs: [
+        "random_binder.cpp",
         "random_fd.cpp",
         "random_parcel.cpp",
         "libbinder_driver.cpp",
diff --git a/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h
new file mode 100644
index 0000000..8fc9263
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_binder.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <binder/IBinder.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+namespace android {
+
+// Get a random binder object for use in fuzzing.
+//
+// May return nullptr.
+sp<IBinder> getRandomBinder(FuzzedDataProvider* provider);
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/random_binder.cpp b/libs/binder/tests/parcel_fuzzer/random_binder.cpp
new file mode 100644
index 0000000..8a1fecb
--- /dev/null
+++ b/libs/binder/tests/parcel_fuzzer/random_binder.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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 <fuzzbinder/random_binder.h>
+
+#include <fuzzbinder/random_parcel.h>
+
+#include <android-base/logging.h>
+#include <binder/IInterface.h>
+#include <binder/IServiceManager.h>
+
+namespace android {
+
+class RandomBinder : public BBinder {
+public:
+    RandomBinder(const String16& descriptor, std::vector<uint8_t>&& bytes)
+          : mDescriptor(descriptor),
+            mBytes(std::move(bytes)),
+            mProvider(mBytes.data(), mBytes.size()) {}
+    const String16& getInterfaceDescriptor() const override { return mDescriptor; }
+
+    status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) override {
+        (void)code;
+        (void)data;
+        (void)reply;
+        (void)flags; // note - for maximum coverage even ignore if oneway
+
+        if (mProvider.ConsumeBool()) {
+            return mProvider.ConsumeIntegral<status_t>();
+        }
+
+        if (reply == nullptr) return OK;
+
+        // TODO: things we could do to increase state space
+        // - also pull FDs and binders from 'data'
+        //     (optionally combine these into random parcel 'options')
+        // - also pull FDs and binders from random parcel 'options'
+        RandomParcelOptions options;
+
+        // random output
+        std::vector<uint8_t> subData = mProvider.ConsumeBytes<uint8_t>(
+                mProvider.ConsumeIntegralInRange<size_t>(0, mProvider.remaining_bytes()));
+        fillRandomParcel(reply, FuzzedDataProvider(subData.data(), subData.size()), &options);
+
+        return OK;
+    }
+
+private:
+    String16 mDescriptor;
+
+    // note may not all be used
+    std::vector<uint8_t> mBytes;
+    FuzzedDataProvider mProvider;
+};
+
+sp<IBinder> getRandomBinder(FuzzedDataProvider* provider) {
+    auto makeFunc = provider->PickValueInArray<const std::function<sp<IBinder>()>>({
+            [&]() {
+                // descriptor is the length of a class name, e.g.
+                // "some.package.Foo"
+                std::string str = provider->ConsumeRandomLengthString(100 /*max length*/);
+
+                // arbitrarily consume remaining data to create a binder that can return
+                // random results - coverage guided fuzzer should ensure all of the remaining
+                // data isn't always used
+                std::vector<uint8_t> bytes = provider->ConsumeBytes<uint8_t>(
+                        provider->ConsumeIntegralInRange<size_t>(0, provider->remaining_bytes()));
+
+                return new RandomBinder(String16(str.c_str()), std::move(bytes));
+            },
+            []() {
+                // this is the easiest remote binder to get ahold of, and it
+                // should be able to handle anything thrown at it, and
+                // essentially every process can talk to it, so it's a good
+                // candidate for checking usage of an actual BpBinder
+                return IInterface::asBinder(defaultServiceManager());
+            },
+            [&]() -> sp<IBinder> { return nullptr; },
+    });
+    return makeFunc();
+}
+
+} // namespace android
diff --git a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 51cb768..edc695f 100644
--- a/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -17,23 +17,14 @@
 #include <fuzzbinder/random_parcel.h>
 
 #include <android-base/logging.h>
-#include <binder/IServiceManager.h>
 #include <binder/RpcSession.h>
 #include <binder/RpcTransportRaw.h>
+#include <fuzzbinder/random_binder.h>
 #include <fuzzbinder/random_fd.h>
 #include <utils/String16.h>
 
 namespace android {
 
-class NamedBinder : public BBinder {
-public:
-    NamedBinder(const String16& descriptor) : mDescriptor(descriptor) {}
-    const String16& getInterfaceDescriptor() const override { return mDescriptor; }
-
-private:
-    String16 mDescriptor;
-};
-
 static void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
     std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
     CHECK(OK == p->write(data.data(), data.size()));
@@ -45,6 +36,11 @@
     if (provider.ConsumeBool()) {
         auto session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
         CHECK_EQ(OK, session->addNullDebuggingClient());
+        // Set the protocol version so that we don't crash if the session
+        // actually gets used. This isn't cheating because the version should
+        // always be set if the session init succeeded and we aren't testing the
+        // session init here (it is bypassed by addNullDebuggingClient).
+        session->setProtocolVersion(RPC_WIRE_PROTOCOL_VERSION);
         p->markForRpc(session);
 
         if (options->writeHeader) {
@@ -89,32 +85,16 @@
                 },
                 // write binder
                 [&]() {
-                    auto makeFunc = provider.PickValueInArray<const std::function<sp<IBinder>()>>({
-                            [&]() {
-                                // descriptor is the length of a class name, e.g.
-                                // "some.package.Foo"
-                                std::string str =
-                                        provider.ConsumeRandomLengthString(100 /*max length*/);
-                                return new NamedBinder(String16(str.c_str()));
-                            },
-                            []() {
-                                // this is the easiest remote binder to get ahold of, and it
-                                // should be able to handle anything thrown at it, and
-                                // essentially every process can talk to it, so it's a good
-                                // candidate for checking usage of an actual BpBinder
-                                return IInterface::asBinder(defaultServiceManager());
-                            },
-                            [&]() -> sp<IBinder> {
-                                if (options->extraBinders.size() > 0 && provider.ConsumeBool()) {
-                                    return options->extraBinders.at(
-                                            provider.ConsumeIntegralInRange<
-                                                    size_t>(0, options->extraBinders.size() - 1));
-                                } else {
-                                    return nullptr;
-                                }
-                            },
-                    });
-                    sp<IBinder> binder = makeFunc();
+                    sp<IBinder> binder;
+                    if (options->extraBinders.size() > 0 && provider.ConsumeBool()) {
+                        binder = options->extraBinders.at(
+                                provider.ConsumeIntegralInRange<size_t>(0,
+                                                                        options->extraBinders
+                                                                                        .size() -
+                                                                                1));
+                    } else {
+                        binder = getRandomBinder(&provider);
+                    }
                     CHECK(OK == p->writeStrongBinder(binder));
                 },
         });
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 46346bb..397ff41 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -16,6 +16,7 @@
 
 #if defined(TRUSTY_USERSPACE)
 #include <openssl/rand.h>
+#include <trusty_ipc.h>
 #else
 #include <lib/rand/rand.h>
 #endif
@@ -23,6 +24,7 @@
 #include <binder/RpcTransportTipcTrusty.h>
 
 #include "../OS.h"
+#include "TrustyStatus.h"
 
 using android::base::Result;
 
@@ -43,13 +45,32 @@
 #endif // TRUSTY_USERSPACE
 }
 
-status_t dupFileDescriptor(int /*oldFd*/, int* /*newFd*/) {
-    // TODO: implement separately
-    return INVALID_OPERATION;
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+    int res = dup(oldFd);
+    if (res < 0) {
+        return statusFromTrusty(res);
+    }
+
+    *newFd = res;
+    return OK;
 }
 
 std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() {
     return RpcTransportCtxFactoryTipcTrusty::make();
 }
 
+int sendMessageOnSocket(
+        const RpcTransportFd& /* socket */, iovec* /* iovs */, int /* niovs */,
+        const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /* ancillaryFds */) {
+    errno = ENOTSUP;
+    return -1;
+}
+
+int receiveMessageFromSocket(
+        const RpcTransportFd& /* socket */, iovec* /* iovs */, int /* niovs */,
+        std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /* ancillaryFds */) {
+    errno = ENOTSUP;
+    return -1;
+}
+
 } // namespace android
diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
index 0b67b9f..58bfe71 100644
--- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp
+++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "RpcTransportTipcTrusty"
 
+#include <inttypes.h>
 #include <trusty_ipc.h>
 
 #include <binder/RpcSession.h>
@@ -47,7 +48,7 @@
     status_t interruptableWriteFully(
             FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
             const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/,
-            const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/)
+            const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds)
             override {
         if (niovs < 0) {
             return BAD_VALUE;
@@ -58,12 +59,32 @@
             size += iovs[i].iov_len;
         }
 
+        handle_t msgHandles[IPC_MAX_MSG_HANDLES];
         ipc_msg_t msg{
                 .num_iov = static_cast<uint32_t>(niovs),
                 .iov = iovs,
-                .num_handles = 0, // TODO: add ancillaryFds
+                .num_handles = 0,
                 .handles = nullptr,
         };
+
+        if (ancillaryFds != nullptr && !ancillaryFds->empty()) {
+            if (ancillaryFds->size() > IPC_MAX_MSG_HANDLES) {
+                // This shouldn't happen because we check the FD count in RpcState.
+                ALOGE("Saw too many file descriptors in RpcTransportCtxTipcTrusty: "
+                      "%zu (max is %u). Aborting session.",
+                      ancillaryFds->size(), IPC_MAX_MSG_HANDLES);
+                return BAD_VALUE;
+            }
+
+            for (size_t i = 0; i < ancillaryFds->size(); i++) {
+                msgHandles[i] =
+                        std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i));
+            }
+
+            msg.num_handles = ancillaryFds->size();
+            msg.handles = msgHandles;
+        }
+
         ssize_t rc = send_msg(mSocket.fd.get(), &msg);
         if (rc == ERR_NOT_ENOUGH_BUFFER) {
             // Peer is blocked, wait until it unblocks.
@@ -97,8 +118,7 @@
     status_t interruptableReadFully(
             FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs,
             const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/,
-            std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/)
-            override {
+            std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override {
         if (niovs < 0) {
             return BAD_VALUE;
         }
@@ -124,11 +144,16 @@
                 return status;
             }
 
+            LOG_ALWAYS_FATAL_IF(mMessageInfo.num_handles > IPC_MAX_MSG_HANDLES,
+                                "Received too many handles %" PRIu32, mMessageInfo.num_handles);
+            bool haveHandles = mMessageInfo.num_handles != 0;
+            handle_t msgHandles[IPC_MAX_MSG_HANDLES];
+
             ipc_msg_t msg{
                     .num_iov = static_cast<uint32_t>(niovs),
                     .iov = iovs,
-                    .num_handles = 0, // TODO: support ancillaryFds
-                    .handles = nullptr,
+                    .num_handles = mMessageInfo.num_handles,
+                    .handles = haveHandles ? msgHandles : 0,
             };
             ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg);
             if (rc < 0) {
@@ -141,6 +166,28 @@
                                 "Message offset exceeds length %zu/%zu", mMessageOffset,
                                 mMessageInfo.len);
 
+            if (haveHandles) {
+                if (ancillaryFds != nullptr) {
+                    ancillaryFds->reserve(ancillaryFds->size() + mMessageInfo.num_handles);
+                    for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
+                        ancillaryFds->emplace_back(base::unique_fd(msgHandles[i]));
+                    }
+
+                    // Clear the saved number of handles so we don't accidentally
+                    // read them multiple times
+                    mMessageInfo.num_handles = 0;
+                    haveHandles = false;
+                } else {
+                    ALOGE("Received unexpected handles %" PRIu32, mMessageInfo.num_handles);
+                    // It should be safe to continue here. We could abort, but then
+                    // peers could DoS us by sending messages with handles in them.
+                    // Close the handles since we are ignoring them.
+                    for (size_t i = 0; i < mMessageInfo.num_handles; i++) {
+                        ::close(msgHandles[i]);
+                    }
+                }
+            }
+
             // Release the message if all of it has been read
             if (mMessageOffset == mMessageInfo.len) {
                 releaseMessage();
diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h
index cc31c95..7d9dd8c 100644
--- a/libs/binder/trusty/include/binder/RpcServerTrusty.h
+++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h
@@ -60,6 +60,10 @@
             std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
 
     void setProtocolVersion(uint32_t version) { mRpcServer->setProtocolVersion(version); }
+    void setSupportedFileDescriptorTransportModes(
+            const std::vector<RpcSession::FileDescriptorTransportMode>& modes) {
+        mRpcServer->setSupportedFileDescriptorTransportModes(modes);
+    }
     void setRootObject(const sp<IBinder>& binder) { mRpcServer->setRootObject(binder); }
     void setRootObjectWeak(const wp<IBinder>& binder) { mRpcServer->setRootObjectWeak(binder); }
     void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object) {
diff --git a/libs/binder/trusty/ndk/include/sys/cdefs.h b/libs/binder/trusty/ndk/include/sys/cdefs.h
new file mode 100644
index 0000000..6a48d2b
--- /dev/null
+++ b/libs/binder/trusty/ndk/include/sys/cdefs.h
@@ -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.
+ */
+#pragma once
+
+#include <lk/compiler.h>
+
+/* Alias the bionic macros to the ones from lk/compiler.h */
+#define __BEGIN_DECLS __BEGIN_CDECLS
+#define __END_DECLS __END_CDECLS
+
+#define __INTRODUCED_IN(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/ndk/rules.mk b/libs/binder/trusty/ndk/rules.mk
new file mode 100644
index 0000000..03fd006
--- /dev/null
+++ b/libs/binder/trusty/ndk/rules.mk
@@ -0,0 +1,38 @@
+# Copyright (C) 2021 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+
+MODULE := $(LOCAL_DIR)
+
+LIBBINDER_NDK_DIR := frameworks/native/libs/binder/ndk
+
+MODULE_SRCS := \
+	$(LIBBINDER_NDK_DIR)/ibinder.cpp \
+	$(LIBBINDER_NDK_DIR)/libbinder.cpp \
+	$(LIBBINDER_NDK_DIR)/parcel.cpp \
+	$(LIBBINDER_NDK_DIR)/status.cpp \
+
+MODULE_EXPORT_INCLUDES += \
+	$(LOCAL_DIR)/include \
+	$(LIBBINDER_NDK_DIR)/include_cpp \
+	$(LIBBINDER_NDK_DIR)/include_ndk \
+	$(LIBBINDER_NDK_DIR)/include_platform \
+
+MODULE_LIBRARY_DEPS += \
+	trusty/user/base/lib/libstdc++-trusty \
+	frameworks/native/libs/binder/trusty \
+
+include make/library.mk
diff --git a/libs/binderthreadstate/test.cpp b/libs/binderthreadstate/test.cpp
index 2f73137..df1f35d 100644
--- a/libs/binderthreadstate/test.cpp
+++ b/libs/binderthreadstate/test.cpp
@@ -73,6 +73,15 @@
     CHECK(ret.isOk()) << ret;
 }
 
+static std::string getStackPointerDebugInfo() {
+    const void* hwbinderSp = android::hardware::IPCThreadState::self()->getServingStackPointer();
+    const void* binderSp = android::IPCThreadState::self()->getServingStackPointer();
+
+    std::stringstream ss;
+    ss << "(hwbinder sp: " << hwbinderSp << " binder sp: " << binderSp << ")";
+    return ss.str();
+}
+
 static inline std::ostream& operator<<(std::ostream& o, const BinderCallType& s) {
     return o << static_cast<std::underlying_type_t<BinderCallType>>(s);
 }
@@ -88,17 +97,21 @@
         return android::hardware::Status::ok();
     }
     Return<void> call(int32_t idx) {
+        bool doCallHidl = thisId == kP1Id && idx % 4 < 2;
+
         LOG(INFO) << "HidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
-                  << " with tid: " << gettid();
-        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+                << " before call " << getStackPointerDebugInfo();
         if (idx > 0) {
-            if (thisId == kP1Id && idx % 4 < 2) {
+            if (doCallHidl) {
                 callHidl(otherId, idx - 1);
             } else {
                 callAidl(otherId, idx - 1);
             }
         }
-        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall());
+        CHECK_EQ(BinderCallType::HWBINDER, getCurrentServingCall())
+                << " after call " << getStackPointerDebugInfo();
         return android::hardware::Status::ok();
     }
 };
@@ -113,17 +126,20 @@
         return Status::ok();
     }
     Status call(int32_t idx) {
+        bool doCallHidl = thisId == kP2Id && idx % 4 < 2;
         LOG(INFO) << "AidlServer CALL " << thisId << " to " << otherId << " at idx: " << idx
-                  << " with tid: " << gettid();
-        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+                  << " with tid: " << gettid() << " calling " << (doCallHidl ? "HIDL" : "AIDL");
+        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+                << " before call " << getStackPointerDebugInfo();
         if (idx > 0) {
-            if (thisId == kP2Id && idx % 4 < 2) {
+            if (doCallHidl) {
                 callHidl(otherId, idx - 1);
             } else {
                 callAidl(otherId, idx - 1);
             }
         }
-        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall());
+        CHECK_EQ(BinderCallType::BINDER, getCurrentServingCall())
+                << " after call " << getStackPointerDebugInfo();
         return Status::ok();
     }
 };
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index dd07319..d7db6bd 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -61,6 +61,9 @@
 
     // Android O
     first_version: "26",
+    export_header_libs: [
+        "libnativewindow_ndk_headers",
+    ],
 }
 
 cc_library {
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 2237d2d..62cf255 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -12,7 +12,10 @@
     name: "libETC1",
     srcs: ["ETC1/etc1.cpp"],
     host_supported: true,
-    cflags: ["-Wall", "-Werror"],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
 
     target: {
         android: {
@@ -37,6 +40,9 @@
     symbol_file: "libEGL.map.txt",
     first_version: "9",
     unversioned_until: "current",
+    export_header_libs: [
+        "libEGL_headers",
+    ],
 }
 
 ndk_library {
@@ -44,6 +50,9 @@
     symbol_file: "libGLESv1_CM.map.txt",
     first_version: "9",
     unversioned_until: "current",
+    export_header_libs: [
+        "libGLESv1_CM_headers",
+    ],
 }
 
 ndk_library {
@@ -51,6 +60,9 @@
     symbol_file: "libGLESv2.map.txt",
     first_version: "9",
     unversioned_until: "current",
+    export_header_libs: [
+        "libGLESv2_headers",
+    ],
 }
 
 ndk_library {
@@ -58,6 +70,9 @@
     symbol_file: "libGLESv3.map.txt",
     first_version: "18",
     unversioned_until: "current",
+    export_header_libs: [
+        "libGLESv3_headers",
+    ],
 }
 
 cc_defaults {
diff --git a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
index 79dcd15..3651231 100644
--- a/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/AidlComposerHal.cpp
@@ -264,17 +264,21 @@
     }
 
     std::string str;
+    // Use other thread to read pipe to prevent
+    // pipe is full, making HWC be blocked in writing.
+    std::thread t([&]() {
+        base::ReadFdToString(pipefds[0], &str);
+    });
     const auto status = mAidlComposer->dump(pipefds[1], /*args*/ nullptr, /*numArgs*/ 0);
     // Close the write-end of the pipe to make sure that when reading from the
     // read-end we will get eof instead of blocking forever
     close(pipefds[1]);
 
-    if (status == STATUS_OK) {
-        base::ReadFdToString(pipefds[0], &str);
-    } else {
+    if (status != STATUS_OK) {
         ALOGE("dumpDebugInfo: dump failed: %d", status);
     }
 
+    t.join();
     close(pipefds[0]);
     return str;
 }
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 5719b5c..a87f82f 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -27,6 +27,9 @@
     symbol_file: "libvulkan.map.txt",
     first_version: "24",
     unversioned_until: "current",
+    export_header_libs: [
+        "ndk_vulkan_headers",
+    ],
 }
 
 cc_library_shared {
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 1fe8800..6af2cc1 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -668,10 +668,11 @@
         // VkSurfaceProtectedCapabilitiesKHR::supportsProtected.  The following
         // four values cannot be known without a surface.  Default values will
         // be supplied anyway, but cannot be relied upon.
-        width = 1000;
-        height = 1000;
-        transform_hint = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
-        max_buffer_count = 10;
+        width = 0xFFFFFFFF;
+        height = 0xFFFFFFFF;
+        transform_hint = VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR;
+        capabilities->minImageCount = 0xFFFFFFFF;
+        capabilities->maxImageCount = 0xFFFFFFFF;
     } else {
         ANativeWindow* window = SurfaceFromHandle(surface)->window.get();
 
@@ -703,9 +704,9 @@
                   strerror(-err), err);
             return VK_ERROR_SURFACE_LOST_KHR;
         }
+        capabilities->minImageCount = std::min(max_buffer_count, 3);
+        capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
     }
-    capabilities->minImageCount = std::min(max_buffer_count, 3);
-    capabilities->maxImageCount = static_cast<uint32_t>(max_buffer_count);
 
     capabilities->currentExtent =
         VkExtent2D{static_cast<uint32_t>(width), static_cast<uint32_t>(height)};