Merge "SF: Clean up forced refresh and repaint"
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index f8fdaa0..3d2bdf1 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -21,7 +21,9 @@
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <binder/BpBinder.h>
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/Stability.h>
@@ -58,27 +60,30 @@
 }
 
 static void usage() {
-    fprintf(stderr,
-            "usage: dumpsys\n"
-            "         To dump all services.\n"
-            "or:\n"
-            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--dump] [--pid] [--thread] [--help | "
-            "-l | --skip SERVICES "
-            "| SERVICE [ARGS]]\n"
-            "         --help: shows this help\n"
-            "         -l: only list services, do not dump them\n"
-            "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
-            "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
-            "         --dump: ask the service to dump itself (this is the default)\n"
-            "         --pid: dump PID instead of usual dump\n"
-            "         --proto: filter services that support dumping data in proto format. Dumps\n"
-            "               will be in proto format.\n"
-            "         --priority LEVEL: filter services based on specified priority\n"
-            "               LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
-            "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
-            "         --stability: dump binder stability information instead of usual dump\n"
-            "         --thread: dump thread usage instead of usual dump\n"
-            "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
+    fprintf(
+        stderr,
+        "usage: dumpsys\n"
+        "         To dump all services.\n"
+        "or:\n"
+        "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--clients] [--dump] [--pid] [--thread] "
+        "[--help | "
+        "-l | --skip SERVICES "
+        "| SERVICE [ARGS]]\n"
+        "         --help: shows this help\n"
+        "         -l: only list services, do not dump them\n"
+        "         -t TIMEOUT_SEC: TIMEOUT to use in seconds instead of default 10 seconds\n"
+        "         -T TIMEOUT_MS: TIMEOUT to use in milliseconds instead of default 10 seconds\n"
+        "         --clients: dump client PIDs instead of usual dump\n"
+        "         --dump: ask the service to dump itself (this is the default)\n"
+        "         --pid: dump PID instead of usual dump\n"
+        "         --proto: filter services that support dumping data in proto format. Dumps\n"
+        "               will be in proto format.\n"
+        "         --priority LEVEL: filter services based on specified priority\n"
+        "               LEVEL must be one of CRITICAL | HIGH | NORMAL\n"
+        "         --skip SERVICES: dumps all services but SERVICES (comma-separated list)\n"
+        "         --stability: dump binder stability information instead of usual dump\n"
+        "         --thread: dump thread usage instead of usual dump\n"
+        "         SERVICE [ARGS]: dumps only service SERVICE, optionally passing ARGS to it\n");
 }
 
 static bool IsSkipped(const Vector<String16>& skipped, const String16& service) {
@@ -131,15 +136,12 @@
     int dumpTypeFlags = 0;
     int timeoutArgMs = 10000;
     int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
-    static struct option longOptions[] = {{"help", no_argument, 0, 0},
-                                          {"dump", no_argument, 0, 0},
-                                          {"pid", no_argument, 0, 0},
-                                          {"priority", required_argument, 0, 0},
-                                          {"proto", no_argument, 0, 0},
-                                          {"skip", no_argument, 0, 0},
-                                          {"stability", no_argument, 0, 0},
-                                          {"thread", no_argument, 0, 0},
-                                          {0, 0, 0, 0}};
+    static struct option longOptions[] = {
+        {"help", no_argument, 0, 0},           {"clients", no_argument, 0, 0},
+        {"dump", no_argument, 0, 0},           {"pid", no_argument, 0, 0},
+        {"priority", required_argument, 0, 0}, {"proto", no_argument, 0, 0},
+        {"skip", no_argument, 0, 0},           {"stability", no_argument, 0, 0},
+        {"thread", no_argument, 0, 0},         {0, 0, 0, 0}};
 
     // Must reset optind, otherwise subsequent calls will fail (wouldn't happen on main.cpp, but
     // happens on test cases).
@@ -178,6 +180,8 @@
                 dumpTypeFlags |= TYPE_STABILITY;
             } else if (!strcmp(longOptions[optionIndex].name, "thread")) {
                 dumpTypeFlags |= TYPE_THREAD;
+            } else if (!strcmp(longOptions[optionIndex].name, "clients")) {
+                dumpTypeFlags |= TYPE_CLIENTS;
             }
             break;
 
@@ -373,6 +377,35 @@
     return OK;
 }
 
+static status_t dumpClientsToFd(const sp<IBinder>& service, const unique_fd& fd) {
+    std::string clientPids;
+    const auto remoteBinder = service->remoteBinder();
+    if (remoteBinder == nullptr) {
+        WriteStringToFd("Client PIDs are not available for local binders.\n", fd.get());
+        return OK;
+    }
+    const auto handle = remoteBinder->getDebugBinderHandle();
+    if (handle == std::nullopt) {
+        return OK;
+    }
+    std::vector<pid_t> pids;
+    pid_t myPid = getpid();
+    pid_t servicePid;
+    status_t status = service->getDebugPid(&servicePid);
+    if (status != OK) {
+        return status;
+    }
+    status =
+        getBinderClientPids(BinderDebugContext::BINDER, myPid, servicePid, handle.value(), &pids);
+    if (status != OK) {
+        return status;
+    }
+    pids.erase(std::remove_if(pids.begin(), pids.end(), [&](pid_t pid) { return pid == myPid; }),
+               pids.end());
+    WriteStringToFd("Client PIDs: " + ::android::base::Join(pids, ", ") + "\n", fd.get());
+    return OK;
+}
+
 static void reportDumpError(const String16& serviceName, status_t error, const char* context) {
     if (error == OK) return;
 
@@ -413,6 +446,10 @@
             status_t err = dumpThreadsToFd(service, remote_end);
             reportDumpError(serviceName, err, "dumping thread info");
         }
+        if (dumpTypeFlags & TYPE_CLIENTS) {
+            status_t err = dumpClientsToFd(service, remote_end);
+            reportDumpError(serviceName, err, "dumping clients info");
+        }
 
         // other types always act as a header, this is usually longer
         if (dumpTypeFlags & TYPE_DUMP) {
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 05c5d5e..6ab1a7d 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,10 +52,11 @@
     static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
     enum Type {
-        TYPE_DUMP = 0x1,      // dump using `dump` function
-        TYPE_PID = 0x2,       // dump pid of server only
-        TYPE_STABILITY = 0x4, // dump stability information of server
-        TYPE_THREAD = 0x8,    // dump thread usage of server only
+        TYPE_DUMP = 0x1,       // dump using `dump` function
+        TYPE_PID = 0x2,        // dump pid of server only
+        TYPE_STABILITY = 0x4,  // dump stability information of server
+        TYPE_THREAD = 0x8,     // dump thread usage of server only
+        TYPE_CLIENTS = 0x10,   // dump pid of clients
     };
 
     /**
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 312f4d7..fa63db5 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -627,6 +627,29 @@
     AssertOutputFormat(format);
 }
 
+// Tests 'dumpsys --clients'
+TEST_F(DumpsysTest, ListAllServicesWithClients) {
+    ExpectListServices({"Locksmith", "Valet"});
+    ExpectCheckService("Locksmith");
+    ExpectCheckService("Valet");
+
+    CallMain({"--clients"});
+
+    AssertRunningServices({"Locksmith", "Valet"});
+
+    const std::string format("(.|\n)*((Client PIDs are not available for local binders.)(.|\n)*){2}");
+    AssertOutputFormat(format);
+}
+
+// Tests 'dumpsys --clients service_name'
+TEST_F(DumpsysTest, ListServiceWithClients) {
+    ExpectCheckService("Locksmith");
+
+    CallMain({"--clients", "Locksmith"});
+
+    const std::string format("Client PIDs are not available for local binders.\n");
+    AssertOutputFormat(format);
+}
 // Tests 'dumpsys --thread --stability'
 TEST_F(DumpsysTest, ListAllServicesWithMultipleOptions) {
     ExpectListServices({"Locksmith", "Valet"});
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index c18b1ce..20bf301 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -101,6 +101,7 @@
         "BpBinder.cpp",
         "BufferedTextOutput.cpp",
         "Debug.cpp",
+        "FdTrigger.cpp",
         "IInterface.cpp",
         "IMemory.cpp",
         "IPCThreadState.cpp",
@@ -231,6 +232,42 @@
     },
 }
 
+cc_defaults {
+    name: "libbinder_tls_shared_deps",
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+        "liblog",
+        "libssl",
+        "libutils",
+    ],
+}
+
+cc_defaults {
+    name: "libbinder_tls_defaults",
+    defaults: ["libbinder_tls_shared_deps"],
+    host_supported: true,
+
+    header_libs: [
+        "libbinder_headers",
+    ],
+    export_header_lib_headers: [
+        "libbinder_headers",
+    ],
+    export_include_dirs: ["include_tls"],
+    static_libs: [
+        "libbase",
+    ],
+    srcs: [
+        "RpcTransportTls.cpp",
+    ],
+}
+
+cc_library_shared {
+    name: "libbinder_tls",
+    defaults: ["libbinder_tls_defaults"],
+}
+
 // AIDL interface between libbinder and framework.jar
 filegroup {
     name: "libbinder_aidl",
@@ -249,6 +286,9 @@
         "aidl/android/content/pm/IPackageChangeObserver.aidl",
         "aidl/android/content/pm/IPackageManagerNative.aidl",
         "aidl/android/content/pm/PackageChangeEvent.aidl",
+        "aidl/android/content/pm/IStagedApexObserver.aidl",
+        "aidl/android/content/pm/ApexStagedEvent.aidl",
+        "aidl/android/content/pm/StagedApexInfo.aidl",
     ],
     path: "aidl",
 }
@@ -356,5 +396,6 @@
         "libbinder",
         "liblog",
         "libutils",
+        "android.debug_aidl-cpp",
     ],
 }
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 765e21c..55566e2 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -188,6 +188,14 @@
     return std::get<BinderHandle>(mHandle).handle;
 }
 
+std::optional<int32_t> BpBinder::getDebugBinderHandle() const {
+    if (!isRpcBinder()) {
+        return binderHandle();
+    } else {
+        return std::nullopt;
+    }
+}
+
 bool BpBinder::isDescriptorCached() const {
     Mutex::Autolock _l(mLock);
     return mDescriptorCache.size() ? true : false;
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
new file mode 100644
index 0000000..b197a6a
--- /dev/null
+++ b/libs/binder/FdTrigger.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "FdTrigger"
+#include <log/log.h>
+
+#include <poll.h>
+
+#include <android-base/macros.h>
+
+#include "FdTrigger.h"
+namespace android {
+
+std::unique_ptr<FdTrigger> FdTrigger::make() {
+    auto ret = std::make_unique<FdTrigger>();
+    if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) {
+        ALOGE("Could not create pipe %s", strerror(errno));
+        return nullptr;
+    }
+    return ret;
+}
+
+void FdTrigger::trigger() {
+    mWrite.reset();
+}
+
+bool FdTrigger::isTriggered() {
+    return mWrite == -1;
+}
+
+status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
+    while (true) {
+        pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
+                     {.fd = mRead.get(), .events = 0, .revents = 0}};
+        int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
+        if (ret < 0) {
+            return -errno;
+        }
+        if (ret == 0) {
+            continue;
+        }
+        if (pfd[1].revents & POLLHUP) {
+            return -ECANCELED;
+        }
+        return pfd[0].revents & event ? OK : DEAD_OBJECT;
+    }
+}
+
+android::base::Result<bool> FdTrigger::isTriggeredPolled() {
+    pollfd pfd{.fd = mRead.get(), .events = 0, .revents = 0};
+    int ret = TEMP_FAILURE_RETRY(poll(&pfd, 1, 0));
+    if (ret < 0) {
+        return android::base::ErrnoError() << "FdTrigger::isTriggeredPolled: Error in poll()";
+    }
+    if (ret == 0) {
+        return false;
+    }
+    if (pfd.revents & POLLHUP) {
+        return true;
+    }
+    return android::base::Error() << "FdTrigger::isTriggeredPolled: poll() returns " << pfd.revents;
+}
+
+} // namespace android
diff --git a/libs/binder/FdTrigger.h b/libs/binder/FdTrigger.h
new file mode 100644
index 0000000..a428417
--- /dev/null
+++ b/libs/binder/FdTrigger.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+#include <memory>
+
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+/** This is not a pipe. */
+class FdTrigger {
+public:
+    /** Returns nullptr for error case */
+    static std::unique_ptr<FdTrigger> make();
+
+    /**
+     * Close the write end of the pipe so that the read end receives POLLHUP.
+     * Not threadsafe.
+     */
+    void trigger();
+
+    /**
+     * Check whether this has been triggered by checking the write end.
+     */
+    bool isTriggered();
+
+    /**
+     * Poll for a read event.
+     *
+     * event - for pollfd
+     *
+     * Return:
+     *   true - time to read!
+     *   false - trigger happened
+     */
+    status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
+
+    /**
+     * Check whether this has been triggered by poll()ing the read end.
+     *
+     * Return:
+     *   true - triggered
+     *   false - not triggered
+     *   error - error when polling
+     */
+    android::base::Result<bool> isTriggeredPolled();
+
+private:
+    base::unique_fd mWrite;
+    base::unique_fd mRead;
+};
+} // namespace android
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index 650a108..52a6cf1 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -409,7 +409,7 @@
         uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
         result = ioctl(fd, BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
         if (result == -1) {
-            ALOGD("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
+            ALOGV("Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
         }
     } else {
         ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 4fa99c0..a20445b 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -29,6 +29,7 @@
 #include <binder/RpcTransportRaw.h>
 #include <log/log.h>
 
+#include "FdTrigger.h"
 #include "RpcSocketAddress.h"
 #include "RpcState.h"
 #include "RpcWireFormat.h"
@@ -156,7 +157,7 @@
         LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
         LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
         mJoinThreadRunning = true;
-        mShutdownTrigger = RpcSession::FdTrigger::make();
+        mShutdownTrigger = FdTrigger::make();
         LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler");
 
         mCtx = mRpcTransportCtxFactory->newServerCtx();
@@ -167,7 +168,7 @@
     status_t status;
     while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
         unique_fd clientFd(TEMP_FAILURE_RETRY(
-                accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
+                accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK)));
 
         if (clientFd < 0) {
             ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -259,7 +260,7 @@
     status_t status = OK;
 
     int clientFdForLog = clientFd.get();
-    auto client = server->mCtx->newTransport(std::move(clientFd));
+    auto client = server->mCtx->newTransport(std::move(clientFd), server->mShutdownTrigger.get());
     if (client == nullptr) {
         ALOGE("Dropping accept4()-ed socket because sslAccept fails");
         status = DEAD_OBJECT;
@@ -270,8 +271,8 @@
 
     RpcConnectionHeader header;
     if (status == OK) {
-        status = server->mShutdownTrigger->interruptableReadFully(client.get(), &header,
-                                                                  sizeof(header));
+        status = client->interruptableReadFully(server->mShutdownTrigger.get(), &header,
+                                                sizeof(header));
         if (status != OK) {
             ALOGE("Failed to read ID for client connecting to RPC server: %s",
                   statusToString(status).c_str());
@@ -296,8 +297,8 @@
                     .version = protocolVersion,
             };
 
-            status = server->mShutdownTrigger->interruptableWriteFully(client.get(), &response,
-                                                                       sizeof(response));
+            status = client->interruptableWriteFully(server->mShutdownTrigger.get(), &response,
+                                                     sizeof(response));
             if (status != OK) {
                 ALOGE("Failed to send new session response: %s", statusToString(status).c_str());
                 // still need to cleanup before we can return
@@ -387,8 +388,8 @@
     LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
     LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
 
-    unique_fd serverFd(
-            TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+    unique_fd serverFd(TEMP_FAILURE_RETRY(
+            socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
     if (serverFd == -1) {
         int savedErrno = errno;
         ALOGE("Could not create socket: %s", strerror(savedErrno));
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 107210b..4c47005 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -35,9 +35,11 @@
 #include <jni.h>
 #include <utils/String8.h>
 
+#include "FdTrigger.h"
 #include "RpcSocketAddress.h"
 #include "RpcState.h"
 #include "RpcWireFormat.h"
+#include "Utils.h"
 
 #ifdef __GLIBC__
 extern "C" pid_t gettid();
@@ -133,12 +135,18 @@
             fd = request();
             if (!fd.ok()) return BAD_VALUE;
         }
+        if (auto res = setNonBlocking(fd); !res.ok()) {
+            ALOGE("setupPreconnectedClient: %s", res.error().message().c_str());
+            return res.error().code() == 0 ? UNKNOWN_ERROR : -res.error().code();
+        }
         return initAndAddConnection(std::move(fd), sessionId, incoming);
     });
 }
 
 status_t RpcSession::addNullDebuggingClient() {
     // Note: only works on raw sockets.
+    if (auto status = initShutdownTrigger(); status != OK) return status;
+
     unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
 
     if (serverFd == -1) {
@@ -152,7 +160,7 @@
         ALOGE("Unable to create RpcTransportCtx for null debugging client");
         return NO_MEMORY;
     }
-    auto server = ctx->newTransport(std::move(serverFd));
+    auto server = ctx->newTransport(std::move(serverFd), mShutdownTrigger.get());
     if (server == nullptr) {
         ALOGE("Unable to set up RpcTransport");
         return UNKNOWN_ERROR;
@@ -216,91 +224,6 @@
     return state()->sendDecStrong(connection.get(), sp<RpcSession>::fromExisting(this), address);
 }
 
-std::unique_ptr<RpcSession::FdTrigger> RpcSession::FdTrigger::make() {
-    auto ret = std::make_unique<RpcSession::FdTrigger>();
-    if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) {
-        ALOGE("Could not create pipe %s", strerror(errno));
-        return nullptr;
-    }
-    return ret;
-}
-
-void RpcSession::FdTrigger::trigger() {
-    mWrite.reset();
-}
-
-bool RpcSession::FdTrigger::isTriggered() {
-    return mWrite == -1;
-}
-
-status_t RpcSession::FdTrigger::triggerablePoll(RpcTransport* rpcTransport, int16_t event) {
-    return triggerablePoll(rpcTransport->pollSocket(), event);
-}
-
-status_t RpcSession::FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
-    while (true) {
-        pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
-                     {.fd = mRead.get(), .events = POLLHUP, .revents = 0}};
-        int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
-        if (ret < 0) {
-            return -errno;
-        }
-        if (ret == 0) {
-            continue;
-        }
-        if (pfd[1].revents & POLLHUP) {
-            return -ECANCELED;
-        }
-        return pfd[0].revents & event ? OK : DEAD_OBJECT;
-    }
-}
-
-status_t RpcSession::FdTrigger::interruptableWriteFully(RpcTransport* rpcTransport,
-                                                        const void* data, size_t size) {
-    const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data);
-    const uint8_t* end = buffer + size;
-
-    MAYBE_WAIT_IN_FLAKE_MODE;
-
-    status_t status;
-    while ((status = triggerablePoll(rpcTransport, POLLOUT)) == OK) {
-        auto writeSize = rpcTransport->send(buffer, end - buffer);
-        if (!writeSize.ok()) {
-            LOG_RPC_DETAIL("RpcTransport::send(): %s", writeSize.error().message().c_str());
-            return writeSize.error().code() == 0 ? UNKNOWN_ERROR : -writeSize.error().code();
-        }
-
-        if (*writeSize == 0) return DEAD_OBJECT;
-
-        buffer += *writeSize;
-        if (buffer == end) return OK;
-    }
-    return status;
-}
-
-status_t RpcSession::FdTrigger::interruptableReadFully(RpcTransport* rpcTransport, void* data,
-                                                       size_t size) {
-    uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
-    uint8_t* end = buffer + size;
-
-    MAYBE_WAIT_IN_FLAKE_MODE;
-
-    status_t status;
-    while ((status = triggerablePoll(rpcTransport, POLLIN)) == OK) {
-        auto readSize = rpcTransport->recv(buffer, end - buffer);
-        if (!readSize.ok()) {
-            LOG_RPC_DETAIL("RpcTransport::recv(): %s", readSize.error().message().c_str());
-            return readSize.error().code() == 0 ? UNKNOWN_ERROR : -readSize.error().code();
-        }
-
-        if (*readSize == 0) return DEAD_OBJECT; // EOF
-
-        buffer += *readSize;
-        if (buffer == end) return OK;
-    }
-    return status;
-}
-
 status_t RpcSession::readId() {
     {
         std::lock_guard<std::mutex> _l(mMutex);
@@ -484,6 +407,7 @@
                             "Must only setup session once, but already has %zu clients",
                             mOutgoingConnections.size());
     }
+    if (auto status = initShutdownTrigger(); status != OK) return status;
 
     if (status_t status = connectAndInit(RpcAddress::zero(), false /*incoming*/); status != OK)
         return status;
@@ -550,8 +474,8 @@
     for (size_t tries = 0; tries < 5; tries++) {
         if (tries > 0) usleep(10000);
 
-        unique_fd serverFd(
-                TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
+        unique_fd serverFd(TEMP_FAILURE_RETRY(
+                socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)));
         if (serverFd == -1) {
             int savedErrno = errno;
             ALOGE("Could not create socket at %s: %s", addr.toString().c_str(),
@@ -564,10 +488,34 @@
                 ALOGW("Connection reset on %s", addr.toString().c_str());
                 continue;
             }
-            int savedErrno = errno;
-            ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
-                  strerror(savedErrno));
-            return -savedErrno;
+            if (errno != EAGAIN && errno != EINPROGRESS) {
+                int savedErrno = errno;
+                ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(),
+                      strerror(savedErrno));
+                return -savedErrno;
+            }
+            // For non-blocking sockets, connect() may return EAGAIN (for unix domain socket) or
+            // EINPROGRESS (for others). Call poll() and getsockopt() to get the error.
+            status_t pollStatus = mShutdownTrigger->triggerablePoll(serverFd, POLLOUT);
+            if (pollStatus != OK) {
+                ALOGE("Could not POLLOUT after connect() on non-blocking socket: %s",
+                      statusToString(pollStatus).c_str());
+                return pollStatus;
+            }
+            int soError;
+            socklen_t soErrorLen = sizeof(soError);
+            int ret = getsockopt(serverFd.get(), SOL_SOCKET, SO_ERROR, &soError, &soErrorLen);
+            if (ret == -1) {
+                int savedErrno = errno;
+                ALOGE("Could not getsockopt() after connect() on non-blocking socket: %s",
+                      strerror(savedErrno));
+                return -savedErrno;
+            }
+            if (soError != 0) {
+                ALOGE("After connect(), getsockopt() returns error for socket at %s: %s",
+                      addr.toString().c_str(), strerror(soError));
+                return -soError;
+            }
         }
         LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
 
@@ -580,13 +528,14 @@
 
 status_t RpcSession::initAndAddConnection(unique_fd fd, const RpcAddress& sessionId,
                                           bool incoming) {
+    LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr);
     auto ctx = mRpcTransportCtxFactory->newClientCtx();
     if (ctx == nullptr) {
         ALOGE("Unable to create client RpcTransportCtx with %s sockets",
               mRpcTransportCtxFactory->toCString());
         return NO_MEMORY;
     }
-    auto server = ctx->newTransport(std::move(fd));
+    auto server = ctx->newTransport(std::move(fd), mShutdownTrigger.get());
     if (server == nullptr) {
         ALOGE("Unable to set up RpcTransport in %s context", mRpcTransportCtxFactory->toCString());
         return UNKNOWN_ERROR;
@@ -602,16 +551,12 @@
 
     if (incoming) header.options |= RPC_CONNECTION_OPTION_INCOMING;
 
-    auto sentHeader = server->send(&header, sizeof(header));
-    if (!sentHeader.ok()) {
+    auto sendHeaderStatus =
+            server->interruptableWriteFully(mShutdownTrigger.get(), &header, sizeof(header));
+    if (sendHeaderStatus != OK) {
         ALOGE("Could not write connection header to socket: %s",
-              sentHeader.error().message().c_str());
-        return -sentHeader.error().code();
-    }
-    if (*sentHeader != sizeof(header)) {
-        ALOGE("Could not write connection header to socket: sent %zd bytes, expected %zd",
-              *sentHeader, sizeof(header));
-        return UNKNOWN_ERROR;
+              statusToString(sendHeaderStatus).c_str());
+        return sendHeaderStatus;
     }
 
     LOG_RPC_DETAIL("Socket at client: header sent");
@@ -652,19 +597,21 @@
     return OK;
 }
 
+status_t RpcSession::initShutdownTrigger() {
+    // first client connection added, but setForServer not called, so
+    // initializaing for a client.
+    if (mShutdownTrigger == nullptr) {
+        mShutdownTrigger = FdTrigger::make();
+        mEventListener = mShutdownListener = sp<WaitForShutdownListener>::make();
+        if (mShutdownTrigger == nullptr) return INVALID_OPERATION;
+    }
+    return OK;
+}
+
 status_t RpcSession::addOutgoingConnection(std::unique_ptr<RpcTransport> rpcTransport, bool init) {
     sp<RpcConnection> connection = sp<RpcConnection>::make();
     {
         std::lock_guard<std::mutex> _l(mMutex);
-
-        // first client connection added, but setForServer not called, so
-        // initializaing for a client.
-        if (mShutdownTrigger == nullptr) {
-            mShutdownTrigger = FdTrigger::make();
-            mEventListener = mShutdownListener = sp<WaitForShutdownListener>::make();
-            if (mShutdownTrigger == nullptr) return INVALID_OPERATION;
-        }
-
         connection->rpcTransport = std::move(rpcTransport);
         connection->exclusiveTid = gettid();
         mOutgoingConnections.push_back(connection);
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 23382c3..b58f1b3 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -283,8 +283,8 @@
     }
 
     if (status_t status =
-                session->mShutdownTrigger->interruptableWriteFully(connection->rpcTransport.get(),
-                                                                   data, size);
+                connection->rpcTransport->interruptableWriteFully(session->mShutdownTrigger.get(),
+                                                                  data, size);
         status != OK) {
         LOG_RPC_DETAIL("Failed to write %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
                        connection->rpcTransport.get(), statusToString(status).c_str());
@@ -305,8 +305,8 @@
     }
 
     if (status_t status =
-                session->mShutdownTrigger->interruptableReadFully(connection->rpcTransport.get(),
-                                                                  data, size);
+                connection->rpcTransport->interruptableReadFully(session->mShutdownTrigger.get(),
+                                                                 data, size);
         status != OK) {
         LOG_RPC_DETAIL("Failed to read %s (%zu bytes) on RpcTransport %p, error: %s", what, size,
                        connection->rpcTransport.get(), statusToString(status).c_str());
diff --git a/libs/binder/RpcTransportRaw.cpp b/libs/binder/RpcTransportRaw.cpp
index 2fc1945..d77fc52 100644
--- a/libs/binder/RpcTransportRaw.cpp
+++ b/libs/binder/RpcTransportRaw.cpp
@@ -17,8 +17,11 @@
 #define LOG_TAG "RpcRawTransport"
 #include <log/log.h>
 
+#include <poll.h>
+
 #include <binder/RpcTransportRaw.h>
 
+#include "FdTrigger.h"
 #include "RpcState.h"
 
 using android::base::ErrnoError;
@@ -32,14 +35,14 @@
 class RpcTransportRaw : public RpcTransport {
 public:
     explicit RpcTransportRaw(android::base::unique_fd socket) : mSocket(std::move(socket)) {}
-    Result<size_t> send(const void *buf, size_t size) override {
+    Result<size_t> send(const void* buf, size_t size) {
         ssize_t ret = TEMP_FAILURE_RETRY(::send(mSocket.get(), buf, size, MSG_NOSIGNAL));
         if (ret < 0) {
             return ErrnoError() << "send()";
         }
         return ret;
     }
-    Result<size_t> recv(void *buf, size_t size) override {
+    Result<size_t> recv(void* buf, size_t size) {
         ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_NOSIGNAL));
         if (ret < 0) {
             return ErrnoError() << "recv()";
@@ -47,14 +50,56 @@
         return ret;
     }
     Result<size_t> peek(void *buf, size_t size) override {
-        ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK | MSG_DONTWAIT));
+        ssize_t ret = TEMP_FAILURE_RETRY(::recv(mSocket.get(), buf, size, MSG_PEEK));
         if (ret < 0) {
             return ErrnoError() << "recv(MSG_PEEK)";
         }
         return ret;
     }
-    bool pending() override { return false; }
-    android::base::borrowed_fd pollSocket() const override { return mSocket; }
+
+    status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override {
+        const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data);
+        const uint8_t* end = buffer + size;
+
+        MAYBE_WAIT_IN_FLAKE_MODE;
+
+        status_t status;
+        while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLOUT)) == OK) {
+            auto writeSize = this->send(buffer, end - buffer);
+            if (!writeSize.ok()) {
+                LOG_RPC_DETAIL("RpcTransport::send(): %s", writeSize.error().message().c_str());
+                return writeSize.error().code() == 0 ? UNKNOWN_ERROR : -writeSize.error().code();
+            }
+
+            if (*writeSize == 0) return DEAD_OBJECT;
+
+            buffer += *writeSize;
+            if (buffer == end) return OK;
+        }
+        return status;
+    }
+
+    status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override {
+        uint8_t* buffer = reinterpret_cast<uint8_t*>(data);
+        uint8_t* end = buffer + size;
+
+        MAYBE_WAIT_IN_FLAKE_MODE;
+
+        status_t status;
+        while ((status = fdTrigger->triggerablePoll(mSocket.get(), POLLIN)) == OK) {
+            auto readSize = this->recv(buffer, end - buffer);
+            if (!readSize.ok()) {
+                LOG_RPC_DETAIL("RpcTransport::recv(): %s", readSize.error().message().c_str());
+                return readSize.error().code() == 0 ? UNKNOWN_ERROR : -readSize.error().code();
+            }
+
+            if (*readSize == 0) return DEAD_OBJECT; // EOF
+
+            buffer += *readSize;
+            if (buffer == end) return OK;
+        }
+        return status;
+    }
 
 private:
     android::base::unique_fd mSocket;
@@ -63,7 +108,7 @@
 // RpcTransportCtx with TLS disabled.
 class RpcTransportCtxRaw : public RpcTransportCtx {
 public:
-    std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd) const {
+    std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd, FdTrigger*) const {
         return std::make_unique<RpcTransportRaw>(std::move(fd));
     }
 };
diff --git a/libs/binder/RpcTransportTls.cpp b/libs/binder/RpcTransportTls.cpp
new file mode 100644
index 0000000..a102913
--- /dev/null
+++ b/libs/binder/RpcTransportTls.cpp
@@ -0,0 +1,535 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RpcTransportTls"
+#include <log/log.h>
+
+#include <poll.h>
+
+#include <openssl/bn.h>
+#include <openssl/ssl.h>
+
+#include <binder/RpcTransportTls.h>
+
+#include "FdTrigger.h"
+#include "RpcState.h"
+
+#define SHOULD_LOG_TLS_DETAIL false
+
+#if SHOULD_LOG_TLS_DETAIL
+#define LOG_TLS_DETAIL(...) ALOGI(__VA_ARGS__)
+#else
+#define LOG_TLS_DETAIL(...) ALOGV(__VA_ARGS__) // for type checking
+#endif
+
+#define TEST_AND_RETURN(value, expr)            \
+    do {                                        \
+        if (!(expr)) {                          \
+            ALOGE("Failed to call: %s", #expr); \
+            return value;                       \
+        }                                       \
+    } while (0)
+
+using android::base::ErrnoError;
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+namespace {
+
+constexpr const int kCertValidDays = 30;
+
+// Implement BIO for socket that ignores SIGPIPE.
+int socketNew(BIO* bio) {
+    BIO_set_data(bio, reinterpret_cast<void*>(-1));
+    BIO_set_init(bio, 0);
+    return 1;
+}
+int socketFree(BIO* bio) {
+    LOG_ALWAYS_FATAL_IF(bio == nullptr);
+    return 1;
+}
+int socketRead(BIO* bio, char* buf, int size) {
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    int ret = TEMP_FAILURE_RETRY(::recv(fd.get(), buf, size, MSG_NOSIGNAL));
+    BIO_clear_retry_flags(bio);
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        BIO_set_retry_read(bio);
+    }
+    return ret;
+}
+
+int socketWrite(BIO* bio, const char* buf, int size) {
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    int ret = TEMP_FAILURE_RETRY(::send(fd.get(), buf, size, MSG_NOSIGNAL));
+    BIO_clear_retry_flags(bio);
+    if (errno == EAGAIN || errno == EWOULDBLOCK) {
+        BIO_set_retry_write(bio);
+    }
+    return ret;
+}
+
+long socketCtrl(BIO* bio, int cmd, long num, void*) { // NOLINT
+    android::base::borrowed_fd fd(static_cast<int>(reinterpret_cast<intptr_t>(BIO_get_data(bio))));
+    if (cmd == BIO_CTRL_FLUSH) return 1;
+    LOG_ALWAYS_FATAL("sockCtrl(fd=%d, %d, %ld)", fd.get(), cmd, num);
+    return 0;
+}
+
+bssl::UniquePtr<BIO> newSocketBio(android::base::borrowed_fd fd) {
+    static const BIO_METHOD* gMethods = ([] {
+        auto methods = BIO_meth_new(BIO_get_new_index(), "socket_no_signal");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_write(methods, socketWrite), "BIO_meth_set_write");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_read(methods, socketRead), "BIO_meth_set_read");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_ctrl(methods, socketCtrl), "BIO_meth_set_ctrl");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_create(methods, socketNew), "BIO_meth_set_create");
+        LOG_ALWAYS_FATAL_IF(0 == BIO_meth_set_destroy(methods, socketFree), "BIO_meth_set_destroy");
+        return methods;
+    })();
+    bssl::UniquePtr<BIO> ret(BIO_new(gMethods));
+    if (ret == nullptr) return nullptr;
+    BIO_set_data(ret.get(), reinterpret_cast<void*>(fd.get()));
+    BIO_set_init(ret.get(), 1);
+    return ret;
+}
+
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert() {
+    bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (ec_key == nullptr || !EC_KEY_generate_key(ec_key.get())) {
+        ALOGE("Failed to generate key pair.");
+        return nullptr;
+    }
+    bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
+    // Use set1 instead of assign to avoid leaking ec_key when assign fails. set1 increments
+    // the refcount of the ec_key, so it is okay to release it at the end of this function.
+    if (evp_pkey == nullptr || !EVP_PKEY_set1_EC_KEY(evp_pkey.get(), ec_key.get())) {
+        ALOGE("Failed to assign key pair.");
+        return nullptr;
+    }
+    return evp_pkey;
+}
+
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* evp_pkey, const int valid_days) {
+    bssl::UniquePtr<X509> x509(X509_new());
+    bssl::UniquePtr<BIGNUM> serial(BN_new());
+    bssl::UniquePtr<BIGNUM> serialLimit(BN_new());
+    TEST_AND_RETURN(nullptr, BN_lshift(serialLimit.get(), BN_value_one(), 128));
+    TEST_AND_RETURN(nullptr, BN_rand_range(serial.get(), serialLimit.get()));
+    TEST_AND_RETURN(nullptr, BN_to_ASN1_INTEGER(serial.get(), X509_get_serialNumber(x509.get())));
+    TEST_AND_RETURN(nullptr, X509_gmtime_adj(X509_getm_notBefore(x509.get()), 0));
+    TEST_AND_RETURN(nullptr,
+                    X509_gmtime_adj(X509_getm_notAfter(x509.get()), 60 * 60 * 24 * valid_days));
+
+    X509_NAME* subject = X509_get_subject_name(x509.get());
+    TEST_AND_RETURN(nullptr,
+                    X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
+                                               reinterpret_cast<const uint8_t*>("Android"), -1, -1,
+                                               0));
+    TEST_AND_RETURN(nullptr,
+                    X509_NAME_add_entry_by_txt(subject, "CN", MBSTRING_ASC,
+                                               reinterpret_cast<const uint8_t*>("BinderRPC"), -1,
+                                               -1, 0));
+    TEST_AND_RETURN(nullptr, X509_set_issuer_name(x509.get(), subject));
+
+    TEST_AND_RETURN(nullptr, X509_set_pubkey(x509.get(), evp_pkey));
+    TEST_AND_RETURN(nullptr, X509_sign(x509.get(), evp_pkey, EVP_sha256()));
+    return x509;
+}
+
+[[maybe_unused]] void sslDebugLog(const SSL* ssl, int type, int value) {
+    switch (type) {
+        case SSL_CB_HANDSHAKE_START:
+            LOG_TLS_DETAIL("Handshake started.");
+            break;
+        case SSL_CB_HANDSHAKE_DONE:
+            LOG_TLS_DETAIL("Handshake done.");
+            break;
+        case SSL_CB_ACCEPT_LOOP:
+            LOG_TLS_DETAIL("Handshake progress: %s", SSL_state_string_long(ssl));
+            break;
+        default:
+            LOG_TLS_DETAIL("SSL Debug Log: type = %d, value = %d", type, value);
+            break;
+    }
+}
+
+// Handles libssl's error queue.
+//
+// Call into any of its member functions to ensure the error queue is properly handled or cleared.
+// If the error queue is not handled or cleared, the destructor will abort.
+class ErrorQueue {
+public:
+    ~ErrorQueue() { LOG_ALWAYS_FATAL_IF(!mHandled); }
+
+    // Clear the error queue.
+    void clear() {
+        ERR_clear_error();
+        mHandled = true;
+    }
+
+    // Stores the error queue in |ssl| into a string, then clears the error queue.
+    std::string toString() {
+        std::stringstream ss;
+        ERR_print_errors_cb(
+                [](const char* str, size_t len, void* ctx) {
+                    auto ss = (std::stringstream*)ctx;
+                    (*ss) << std::string_view(str, len) << "\n";
+                    return 1; // continue
+                },
+                &ss);
+        // Though ERR_print_errors_cb should have cleared it, it is okay to clear again.
+        clear();
+        return ss.str();
+    }
+
+    // |sslError| should be from Ssl::getError().
+    // If |sslError| is WANT_READ / WANT_WRITE, poll for POLLIN / POLLOUT respectively. Otherwise
+    // return error. Also return error if |fdTrigger| is triggered before or during poll().
+    status_t pollForSslError(android::base::borrowed_fd fd, int sslError, FdTrigger* fdTrigger,
+                             const char* fnString, int additionalEvent = 0) {
+        switch (sslError) {
+            case SSL_ERROR_WANT_READ:
+                return handlePoll(POLLIN | additionalEvent, fd, fdTrigger, fnString);
+            case SSL_ERROR_WANT_WRITE:
+                return handlePoll(POLLOUT | additionalEvent, fd, fdTrigger, fnString);
+            case SSL_ERROR_SYSCALL: {
+                auto queue = toString();
+                LOG_TLS_DETAIL("%s(): %s. Treating as DEAD_OBJECT. Error queue: %s", fnString,
+                               SSL_error_description(sslError), queue.c_str());
+                return DEAD_OBJECT;
+            }
+            default: {
+                auto queue = toString();
+                ALOGE("%s(): %s. Error queue: %s", fnString, SSL_error_description(sslError),
+                      queue.c_str());
+                return UNKNOWN_ERROR;
+            }
+        }
+    }
+
+private:
+    bool mHandled = false;
+
+    status_t handlePoll(int event, android::base::borrowed_fd fd, FdTrigger* fdTrigger,
+                        const char* fnString) {
+        status_t ret = fdTrigger->triggerablePoll(fd, event);
+        if (ret != OK && ret != DEAD_OBJECT && ret != -ECANCELED) {
+            ALOGE("triggerablePoll error while poll()-ing after %s(): %s", fnString,
+                  statusToString(ret).c_str());
+        }
+        clear();
+        return ret;
+    }
+};
+
+// Helper to call a function, with its return value instantiable.
+template <typename Fn, typename... Args>
+struct FuncCaller {
+    struct Monostate {};
+    static constexpr bool sIsVoid = std::is_void_v<std::invoke_result_t<Fn, Args...>>;
+    using Result = std::conditional_t<sIsVoid, Monostate, std::invoke_result_t<Fn, Args...>>;
+    static inline Result call(Fn fn, Args&&... args) {
+        if constexpr (std::is_void_v<std::invoke_result_t<Fn, Args...>>) {
+            std::invoke(fn, std::forward<Args>(args)...);
+            return {};
+        } else {
+            return std::invoke(fn, std::forward<Args>(args)...);
+        }
+    }
+};
+
+// Helper to Ssl::call(). Returns the result to the SSL_* function as well as an ErrorQueue object.
+template <typename Fn, typename... Args>
+struct SslCaller {
+    using RawCaller = FuncCaller<Fn, SSL*, Args...>;
+    struct ResultAndErrorQueue {
+        typename RawCaller::Result result;
+        ErrorQueue errorQueue;
+    };
+    static inline ResultAndErrorQueue call(Fn fn, SSL* ssl, Args&&... args) {
+        LOG_ALWAYS_FATAL_IF(ssl == nullptr);
+        auto result = RawCaller::call(fn, std::forward<SSL*>(ssl), std::forward<Args>(args)...);
+        return ResultAndErrorQueue{std::move(result), ErrorQueue()};
+    }
+};
+
+// A wrapper over bssl::UniquePtr<SSL>. This class ensures that all SSL_* functions are called
+// through call(), which returns an ErrorQueue object that requires the caller to either handle
+// or clear it.
+// Example:
+//   auto [ret, errorQueue] = ssl.call(SSL_read, buf, size);
+//   if (ret >= 0) errorQueue.clear();
+//   else ALOGE("%s", errorQueue.toString().c_str());
+class Ssl {
+public:
+    explicit Ssl(bssl::UniquePtr<SSL> ssl) : mSsl(std::move(ssl)) {
+        LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+    }
+
+    template <typename Fn, typename... Args>
+    inline typename SslCaller<Fn, Args...>::ResultAndErrorQueue call(Fn fn, Args&&... args) {
+        return SslCaller<Fn, Args...>::call(fn, mSsl.get(), std::forward<Args>(args)...);
+    }
+
+    int getError(int ret) {
+        LOG_ALWAYS_FATAL_IF(mSsl == nullptr);
+        return SSL_get_error(mSsl.get(), ret);
+    }
+
+private:
+    bssl::UniquePtr<SSL> mSsl;
+};
+
+class RpcTransportTls : public RpcTransport {
+public:
+    RpcTransportTls(android::base::unique_fd socket, Ssl ssl)
+          : mSocket(std::move(socket)), mSsl(std::move(ssl)) {}
+    Result<size_t> peek(void* buf, size_t size) override;
+    status_t interruptableWriteFully(FdTrigger* fdTrigger, const void* data, size_t size) override;
+    status_t interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) override;
+
+private:
+    android::base::unique_fd mSocket;
+    Ssl mSsl;
+
+    static status_t isTriggered(FdTrigger* fdTrigger);
+};
+
+// Error code is errno.
+Result<size_t> RpcTransportTls::peek(void* buf, size_t size) {
+    size_t todo = std::min<size_t>(size, std::numeric_limits<int>::max());
+    auto [ret, errorQueue] = mSsl.call(SSL_peek, buf, static_cast<int>(todo));
+    if (ret < 0) {
+        int err = mSsl.getError(ret);
+        if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+            // Seen EAGAIN / EWOULDBLOCK on recv(2) / send(2).
+            // Like RpcTransportRaw::peek(), don't handle it here.
+            return Error(EWOULDBLOCK) << "SSL_peek(): " << errorQueue.toString();
+        }
+        return Error() << "SSL_peek(): " << errorQueue.toString();
+    }
+    errorQueue.clear();
+    LOG_TLS_DETAIL("TLS: Peeked %d bytes!", ret);
+    return ret;
+}
+
+status_t RpcTransportTls::isTriggered(FdTrigger* fdTrigger) {
+    auto ret = fdTrigger->isTriggeredPolled();
+    if (!ret.ok()) {
+        ALOGE("%s: %s", __PRETTY_FUNCTION__, ret.error().message().c_str());
+        return ret.error().code() == 0 ? UNKNOWN_ERROR : -ret.error().code();
+    }
+    return OK;
+}
+
+status_t RpcTransportTls::interruptableWriteFully(FdTrigger* fdTrigger, const void* data,
+                                                  size_t size) {
+    auto buffer = reinterpret_cast<const uint8_t*>(data);
+    const uint8_t* end = buffer + size;
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
+    // once. The trigger is also checked via triggerablePoll() after every SSL_write().
+    if (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+    while (buffer < end) {
+        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+        auto [writeSize, errorQueue] = mSsl.call(SSL_write, buffer, todo);
+        if (writeSize > 0) {
+            buffer += writeSize;
+            errorQueue.clear();
+            continue;
+        }
+        // SSL_write() should never return 0 unless BIO_write were to return 0.
+        int sslError = mSsl.getError(writeSize);
+        // TODO(b/195788248): BIO should contain the FdTrigger, and send(2) / recv(2) should be
+        //   triggerablePoll()-ed. Then additionalEvent is no longer necessary.
+        status_t pollStatus =
+                errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_write", POLLIN);
+        if (pollStatus != OK) return pollStatus;
+        // Do not advance buffer. Try SSL_write() again.
+    }
+    LOG_TLS_DETAIL("TLS: Sent %zu bytes!", size);
+    return OK;
+}
+
+status_t RpcTransportTls::interruptableReadFully(FdTrigger* fdTrigger, void* data, size_t size) {
+    auto buffer = reinterpret_cast<uint8_t*>(data);
+    uint8_t* end = buffer + size;
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    // Before doing any I/O, check trigger once. This ensures the trigger is checked at least
+    // once. The trigger is also checked via triggerablePoll() after every SSL_write().
+    if (status_t status = isTriggered(fdTrigger); status != OK) return status;
+
+    while (buffer < end) {
+        size_t todo = std::min<size_t>(end - buffer, std::numeric_limits<int>::max());
+        auto [readSize, errorQueue] = mSsl.call(SSL_read, buffer, todo);
+        if (readSize > 0) {
+            buffer += readSize;
+            errorQueue.clear();
+            continue;
+        }
+        if (readSize == 0) {
+            // SSL_read() only returns 0 on EOF.
+            errorQueue.clear();
+            return DEAD_OBJECT;
+        }
+        int sslError = mSsl.getError(readSize);
+        status_t pollStatus =
+                errorQueue.pollForSslError(mSocket.get(), sslError, fdTrigger, "SSL_read");
+        if (pollStatus != OK) return pollStatus;
+        // Do not advance buffer. Try SSL_read() again.
+    }
+    LOG_TLS_DETAIL("TLS: Received %zu bytes!", size);
+    return OK;
+}
+
+// For |ssl|, set internal FD to |fd|, and do handshake. Handshake is triggerable by |fdTrigger|.
+bool setFdAndDoHandshake(Ssl* ssl, android::base::borrowed_fd fd, FdTrigger* fdTrigger) {
+    bssl::UniquePtr<BIO> bio = newSocketBio(fd);
+    TEST_AND_RETURN(false, bio != nullptr);
+    auto [_, errorQueue] = ssl->call(SSL_set_bio, bio.get(), bio.get());
+    (void)bio.release(); // SSL_set_bio takes ownership.
+    errorQueue.clear();
+
+    MAYBE_WAIT_IN_FLAKE_MODE;
+
+    while (true) {
+        auto [ret, errorQueue] = ssl->call(SSL_do_handshake);
+        if (ret > 0) {
+            errorQueue.clear();
+            return true;
+        }
+        if (ret == 0) {
+            // SSL_do_handshake() only returns 0 on EOF.
+            ALOGE("SSL_do_handshake(): EOF: %s", errorQueue.toString().c_str());
+            return false;
+        }
+        int sslError = ssl->getError(ret);
+        status_t pollStatus =
+                errorQueue.pollForSslError(fd, sslError, fdTrigger, "SSL_do_handshake");
+        if (pollStatus != OK) return false;
+    }
+}
+
+class RpcTransportCtxTlsServer : public RpcTransportCtx {
+public:
+    static std::unique_ptr<RpcTransportCtxTlsServer> create();
+    std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd acceptedFd,
+                                               FdTrigger* fdTrigger) const override;
+
+private:
+    bssl::UniquePtr<SSL_CTX> mCtx;
+};
+
+std::unique_ptr<RpcTransportCtxTlsServer> RpcTransportCtxTlsServer::create() {
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+    TEST_AND_RETURN(nullptr, ctx != nullptr);
+
+    // Server use self-signing cert
+    auto evp_pkey = makeKeyPairForSelfSignedCert();
+    TEST_AND_RETURN(nullptr, evp_pkey != nullptr);
+    auto cert = makeSelfSignedCert(evp_pkey.get(), kCertValidDays);
+    TEST_AND_RETURN(nullptr, cert != nullptr);
+    TEST_AND_RETURN(nullptr, SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get()));
+    TEST_AND_RETURN(nullptr, SSL_CTX_use_certificate(ctx.get(), cert.get()));
+    // Require at least TLS 1.3
+    TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
+
+    if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
+        SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
+    }
+
+    auto rpcTransportTlsServerCtx = std::make_unique<RpcTransportCtxTlsServer>();
+    rpcTransportTlsServerCtx->mCtx = std::move(ctx);
+    return rpcTransportTlsServerCtx;
+}
+
+std::unique_ptr<RpcTransport> RpcTransportCtxTlsServer::newTransport(
+        android::base::unique_fd acceptedFd, FdTrigger* fdTrigger) const {
+    bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
+    TEST_AND_RETURN(nullptr, ssl != nullptr);
+    Ssl wrapped(std::move(ssl));
+
+    wrapped.call(SSL_set_accept_state).errorQueue.clear();
+    TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, acceptedFd, fdTrigger));
+    return std::make_unique<RpcTransportTls>(std::move(acceptedFd), std::move(wrapped));
+}
+
+class RpcTransportCtxTlsClient : public RpcTransportCtx {
+public:
+    static std::unique_ptr<RpcTransportCtxTlsClient> create();
+    std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd connectedFd,
+                                               FdTrigger* fdTrigger) const override;
+
+private:
+    bssl::UniquePtr<SSL_CTX> mCtx;
+};
+
+std::unique_ptr<RpcTransportCtxTlsClient> RpcTransportCtxTlsClient::create() {
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+    TEST_AND_RETURN(nullptr, ctx != nullptr);
+
+    // TODO(b/195166979): server should send certificate in a different channel, and client
+    //  should verify it here.
+    SSL_CTX_set_custom_verify(ctx.get(), SSL_VERIFY_PEER,
+                              [](SSL*, uint8_t*) -> ssl_verify_result_t { return ssl_verify_ok; });
+
+    // Require at least TLS 1.3
+    TEST_AND_RETURN(nullptr, SSL_CTX_set_min_proto_version(ctx.get(), TLS1_3_VERSION));
+
+    if constexpr (SHOULD_LOG_TLS_DETAIL) { // NOLINT
+        SSL_CTX_set_info_callback(ctx.get(), sslDebugLog);
+    }
+
+    auto rpcTransportTlsClientCtx = std::make_unique<RpcTransportCtxTlsClient>();
+    rpcTransportTlsClientCtx->mCtx = std::move(ctx);
+    return rpcTransportTlsClientCtx;
+}
+
+std::unique_ptr<RpcTransport> RpcTransportCtxTlsClient::newTransport(
+        android::base::unique_fd connectedFd, FdTrigger* fdTrigger) const {
+    bssl::UniquePtr<SSL> ssl(SSL_new(mCtx.get()));
+    TEST_AND_RETURN(nullptr, ssl != nullptr);
+    Ssl wrapped(std::move(ssl));
+
+    wrapped.call(SSL_set_connect_state).errorQueue.clear();
+    TEST_AND_RETURN(nullptr, setFdAndDoHandshake(&wrapped, connectedFd, fdTrigger));
+    return std::make_unique<RpcTransportTls>(std::move(connectedFd), std::move(wrapped));
+}
+
+} // namespace
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newServerCtx() const {
+    return android::RpcTransportCtxTlsServer::create();
+}
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTls::newClientCtx() const {
+    return android::RpcTransportCtxTlsClient::create();
+}
+
+const char* RpcTransportCtxFactoryTls::toCString() const {
+    return "tls";
+}
+
+std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTls::make() {
+    return std::unique_ptr<RpcTransportCtxFactoryTls>(new RpcTransportCtxFactoryTls());
+}
+
+} // namespace android
diff --git a/libs/binder/Utils.cpp b/libs/binder/Utils.cpp
index 90a4502..d2a5be1 100644
--- a/libs/binder/Utils.cpp
+++ b/libs/binder/Utils.cpp
@@ -18,10 +18,24 @@
 
 #include <string.h>
 
+using android::base::ErrnoError;
+using android::base::Result;
+
 namespace android {
 
 void zeroMemory(uint8_t* data, size_t size) {
     memset(data, 0, size);
 }
 
-}   // namespace android
+Result<void> setNonBlocking(android::base::borrowed_fd fd) {
+    int flags = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_GETFL));
+    if (flags == -1) {
+        return ErrnoError() << "Could not get flags for fd";
+    }
+    if (int ret = TEMP_FAILURE_RETRY(fcntl(fd.get(), F_SETFL, flags | O_NONBLOCK)); ret == -1) {
+        return ErrnoError() << "Could not set non-blocking flag for fd";
+    }
+    return {};
+}
+
+} // namespace android
diff --git a/libs/binder/Utils.h b/libs/binder/Utils.h
index f94b158..1e383da 100644
--- a/libs/binder/Utils.h
+++ b/libs/binder/Utils.h
@@ -17,9 +17,14 @@
 #include <cstdint>
 #include <stddef.h>
 
+#include <android-base/result.h>
+#include <android-base/unique_fd.h>
+
 namespace android {
 
 // avoid optimizations
 void zeroMemory(uint8_t* data, size_t size);
 
+android::base::Result<void> setNonBlocking(android::base::borrowed_fd fd);
+
 }   // namespace android
diff --git a/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
new file mode 100644
index 0000000..75f8753
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/ApexStagedEvent.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package android.content.pm;
+
+/**
+ * This event is designed for notification to native code listener about
+ * any changes to set of apex packages staged for installation on next boot.
+ *
+ * @hide
+ */
+parcelable ApexStagedEvent {
+  @utf8InCpp String[] stagedApexModuleNames;
+}
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index c20d9f6..d71f496 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -18,6 +18,8 @@
 package android.content.pm;
 
 import android.content.pm.IPackageChangeObserver;
+import android.content.pm.IStagedApexObserver;
+import android.content.pm.StagedApexInfo;
 
 /**
  * Parallel implementation of certain {@link PackageManager} APIs that need to
@@ -123,4 +125,24 @@
      * requested version.
      */
     boolean hasSystemFeature(in String featureName, in int version);
+
+    /** Register a observer for change in set of staged APEX ready for installation */
+    void registerStagedApexObserver(in IStagedApexObserver observer);
+
+    /**
+     * Unregister an existing staged apex observer.
+     * This does nothing if this observer was not already registered.
+     */
+    void unregisterStagedApexObserver(in IStagedApexObserver observer);
+
+    /**
+     * Get APEX module names of all APEX that are staged ready for installation
+     */
+    @utf8InCpp String[] getStagedApexModuleNames();
+
+    /**
+     * Get information of APEX which is staged ready for installation.
+     * Returns null if no such APEX is found.
+     */
+    StagedApexInfo getStagedApexInfo(in @utf8InCpp String moduleName);
 }
diff --git a/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
new file mode 100644
index 0000000..9906436
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/IStagedApexObserver.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.content.pm;
+
+import android.content.pm.ApexStagedEvent;
+
+/**
+ * This is a non-blocking notification when set of staged apex has changed
+ *
+ * @hide
+ */
+oneway interface IStagedApexObserver {
+  void onApexStaged(in ApexStagedEvent event);
+}
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
new file mode 100644
index 0000000..ece7989
--- /dev/null
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+package android.content.pm;
+
+/**
+ * This object is designed for returning information regarding
+ * staged APEX that are ready to be installed on next reboot.
+ *
+ * @hide
+ */
+parcelable StagedApexInfo {
+  @utf8InCpp String moduleName;
+  @utf8InCpp String diskImagePath;
+  long versionCode;
+  @utf8InCpp String versionName;
+}
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index c69bb9e..a6d35c7 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -90,6 +90,8 @@
     static void         setLimitCallback(binder_proxy_limit_callback cb);
     static void         setBinderProxyCountWatermarks(int high, int low);
 
+    std::optional<int32_t> getDebugBinderHandle() const;
+
     class ObjectManager {
     public:
         ObjectManager();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 02052ad..fd8ac62 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -245,9 +245,10 @@
     template<typename T>
     status_t            writeNullableParcelable(const std::optional<T>& parcelable)
             { return writeData(parcelable); }
-    template<typename T>
-    status_t            writeNullableParcelable(const std::unique_ptr<T>& parcelable) __attribute__((deprecated("use std::optional version instead")))
-            { return writeData(parcelable); }
+    template <typename T>
+    status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
+        return writeData(parcelable);
+    }
 
     status_t            writeParcelable(const Parcelable& parcelable);
 
@@ -401,9 +402,10 @@
     template<typename T>
     status_t            readParcelable(std::optional<T>* parcelable) const
             { return readData(parcelable); }
-    template<typename T>
-    status_t            readParcelable(std::unique_ptr<T>* parcelable) const __attribute__((deprecated("use std::optional version instead")))
-            { return readData(parcelable); }
+    template <typename T>
+    status_t readParcelable(std::unique_ptr<T>* parcelable) const {
+        return readData(parcelable);
+    }
 
     // If strong binder would be nullptr, readStrongBinder() returns an error.
     // TODO: T must be derived from IInterface, fix for clarity.
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index f79d85f..bf3e7e0 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -32,6 +32,7 @@
 
 namespace android {
 
+class FdTrigger;
 class RpcSocketAddress;
 
 /**
@@ -190,7 +191,7 @@
     sp<IBinder> mRootObject;
     wp<IBinder> mRootObjectWeak;
     std::map<RpcAddress, sp<RpcSession>> mSessions;
-    std::unique_ptr<RpcSession::FdTrigger> mShutdownTrigger;
+    std::unique_ptr<FdTrigger> mShutdownTrigger;
     std::condition_variable mShutdownCv;
     std::unique_ptr<RpcTransportCtx> mCtx;
 };
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 7ed6e43..6e6eb74 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -18,7 +18,6 @@
 #include <android-base/unique_fd.h>
 #include <binder/IBinder.h>
 #include <binder/RpcAddress.h>
-#include <binder/RpcSession.h>
 #include <binder/RpcTransport.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -39,6 +38,7 @@
 class RpcSocketAddress;
 class RpcState;
 class RpcTransport;
+class FdTrigger;
 
 constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_NEXT = 0;
 constexpr uint32_t RPC_WIRE_PROTOCOL_VERSION_EXPERIMENTAL = 0xF0000000;
@@ -161,50 +161,6 @@
     friend RpcState;
     explicit RpcSession(std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory);
 
-    /** This is not a pipe. */
-    struct FdTrigger {
-        /** Returns nullptr for error case */
-        static std::unique_ptr<FdTrigger> make();
-
-        /**
-         * Close the write end of the pipe so that the read end receives POLLHUP.
-         * Not threadsafe.
-         */
-        void trigger();
-
-        /**
-         * Whether this has been triggered.
-         */
-        bool isTriggered();
-
-        /**
-         * Poll for a read event.
-         *
-         * event - for pollfd
-         *
-         * Return:
-         *   true - time to read!
-         *   false - trigger happened
-         */
-        status_t triggerablePoll(base::borrowed_fd fd, int16_t event);
-
-        /**
-         * Read (or write), but allow to be interrupted by this trigger.
-         *
-         * Return:
-         *   true - succeeded in completely processing 'size'
-         *   false - interrupted (failure or trigger)
-         */
-        status_t interruptableReadFully(RpcTransport* rpcTransport, void* data, size_t size);
-        status_t interruptableWriteFully(RpcTransport* rpcTransport, const void* data, size_t size);
-
-    private:
-        status_t triggerablePoll(RpcTransport* rpcTransport, int16_t event);
-
-        base::unique_fd mWrite;
-        base::unique_fd mRead;
-    };
-
     class EventListener : public virtual RefBase {
     public:
         virtual void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) = 0;
@@ -271,6 +227,8 @@
             std::unique_ptr<RpcTransport> rpcTransport);
     [[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
 
+    status_t initShutdownTrigger();
+
     enum class ConnectionUse {
         CLIENT,
         CLIENT_ASYNC,
diff --git a/libs/binder/include/binder/RpcTransport.h b/libs/binder/include/binder/RpcTransport.h
index 1164600..1b69519 100644
--- a/libs/binder/include/binder/RpcTransport.h
+++ b/libs/binder/include/binder/RpcTransport.h
@@ -23,42 +23,30 @@
 
 #include <android-base/result.h>
 #include <android-base/unique_fd.h>
+#include <utils/Errors.h>
 
 namespace android {
 
+class FdTrigger;
+
 // Represents a socket connection.
 class RpcTransport {
 public:
     virtual ~RpcTransport() = default;
 
-    // replacement of ::send(). errno may not be set if TLS is enabled.
-    virtual android::base::Result<size_t> send(const void *buf, size_t size) = 0;
-
-    // replacement of ::recv(). errno may not be set if TLS is enabled.
-    virtual android::base::Result<size_t> recv(void *buf, size_t size) = 0;
-
-    // replacement of ::recv(MSG_PEEK). errno may not be set if TLS is enabled.
-    //
-    // Implementation details:
-    // - For TLS, this may invoke syscalls and read data from the transport
-    // into an internal buffer in userspace. After that, pending() == true.
-    // - For raw sockets, this calls ::recv(MSG_PEEK), which leaves the data in the kernel buffer;
-    // pending() is always false.
+    // replacement of ::recv(MSG_PEEK). Error code may not be set if TLS is enabled.
     virtual android::base::Result<size_t> peek(void *buf, size_t size) = 0;
 
-    // Returns true if there are data pending in a userspace buffer that RpcTransport holds.
-    //
-    // Implementation details:
-    // - For TLS, this does not invoke any syscalls or read any data from the
-    // transport. This only returns whether there are data pending in the internal buffer in
-    // userspace.
-    // - For raw sockets, this always returns false.
-    virtual bool pending() = 0;
-
-    // Returns fd for polling.
-    //
-    // Do not directly read / write on this raw fd!
-    [[nodiscard]] virtual android::base::borrowed_fd pollSocket() const = 0;
+    /**
+     * Read (or write), but allow to be interrupted by a trigger.
+     *
+     * Return:
+     *   OK - succeeded in completely processing 'size'
+     *   error - interrupted (failure or trigger)
+     */
+    virtual status_t interruptableWriteFully(FdTrigger *fdTrigger, const void *buf,
+                                             size_t size) = 0;
+    virtual status_t interruptableReadFully(FdTrigger *fdTrigger, void *buf, size_t size) = 0;
 
 protected:
     RpcTransport() = default;
@@ -68,8 +56,13 @@
 class RpcTransportCtx {
 public:
     virtual ~RpcTransportCtx() = default;
+
+    // Create a new RpcTransport object.
+    //
+    // Implemenion details: for TLS, this function may incur I/O. |fdTrigger| may be used
+    // to interrupt I/O. This function blocks until handshake is finished.
     [[nodiscard]] virtual std::unique_ptr<RpcTransport> newTransport(
-            android::base::unique_fd fd) const = 0;
+            android::base::unique_fd fd, FdTrigger *fdTrigger) const = 0;
 
 protected:
     RpcTransportCtx() = default;
diff --git a/libs/binder/include_tls/binder/RpcTransportTls.h b/libs/binder/include_tls/binder/RpcTransportTls.h
new file mode 100644
index 0000000..531aaa9
--- /dev/null
+++ b/libs/binder/include_tls/binder/RpcTransportTls.h
@@ -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.
+ */
+
+// Wraps the transport layer of RPC. Implementation uses TLS.
+
+#pragma once
+
+#include <binder/RpcTransport.h>
+
+namespace android {
+
+// RpcTransportCtxFactory with TLS enabled with self-signed certificate.
+class RpcTransportCtxFactoryTls : public RpcTransportCtxFactory {
+public:
+    static std::unique_ptr<RpcTransportCtxFactory> make();
+
+    std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
+    std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
+    const char* toCString() const override;
+
+private:
+    RpcTransportCtxFactoryTls() = default;
+};
+
+} // namespace android
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 785e032..717beec 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -82,8 +82,8 @@
         const String16& currentDescriptor = mClazz->getInterfaceDescriptor();
         if (newDescriptor == currentDescriptor) {
             LOG(ERROR) << __func__ << ": Class descriptors '" << currentDescriptor
-                       << "' match during associateClass, but they are different class objects. "
-                          "Class descriptor collision?";
+                       << "' match during associateClass, but they are different class objects ("
+                       << clazz << " vs " << mClazz << "). Class descriptor collision?";
         } else {
             LOG(ERROR) << __func__
                        << ": Class cannot be associated on object which already has a class. "
diff --git a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
index 6c44726..5de64f8 100644
--- a/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_interface_utils.h
@@ -55,6 +55,12 @@
         std::call_once(mFlagThis, [&]() {
             __assert(__FILE__, __LINE__, "SharedRefBase: no ref created during lifetime");
         });
+
+        if (ref() != nullptr) {
+            __assert(__FILE__, __LINE__,
+                     "SharedRefBase: destructed but still able to lock weak_ptr. Is this object "
+                     "double-owned?");
+        }
     }
 
     /**
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
index 5092d87..563d011 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcel_utils.h
@@ -469,6 +469,22 @@
 }
 
 /**
+ * Convenience API for writing a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_writeNullableParcelable(AParcel* parcel,
+                                                              const std::unique_ptr<P>& p) {
+    if (!p) {
+        return AParcel_writeInt32(parcel, 0);  // null
+    }
+    binder_status_t status = AParcel_writeInt32(parcel, 1);  // non-null
+    if (status != STATUS_OK) {
+        return status;
+    }
+    return p->writeToParcel(parcel);
+}
+
+/**
  * Convenience API for reading a nullable parcelable.
  */
 template <typename P>
@@ -488,6 +504,25 @@
 }
 
 /**
+ * Convenience API for reading a nullable parcelable.
+ */
+template <typename P>
+static inline binder_status_t AParcel_readNullableParcelable(const AParcel* parcel,
+                                                             std::unique_ptr<P>* p) {
+    int32_t null;
+    binder_status_t status = AParcel_readInt32(parcel, &null);
+    if (status != STATUS_OK) {
+        return status;
+    }
+    if (null == 0) {
+        p->reset();
+        return STATUS_OK;
+    }
+    *p = std::make_unique<P>();
+    return (*p)->readFromParcel(parcel);
+}
+
+/**
  * Writes a parcelable object of type P inside a std::vector<P> at index 'index' to 'parcel'.
  */
 template <typename P>
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index ce12ccf..4b36530 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -224,6 +224,17 @@
     return true;
 }
 
+TEST(NdkBinder, DetectDoubleOwn) {
+    auto badService = ndk::SharedRefBase::make<MyBinderNdkUnitTest>();
+    EXPECT_DEATH(std::shared_ptr<MyBinderNdkUnitTest>(badService.get()),
+                 "Is this object double-owned?");
+}
+
+TEST(NdkBinder, DetectNoSharedRefBaseCreated) {
+    EXPECT_DEATH(std::make_shared<MyBinderNdkUnitTest>(),
+                 "SharedRefBase: no ref created during lifetime");
+}
+
 TEST(NdkBinder, GetServiceThatDoesntExist) {
     sp<IFoo> foo = IFoo::getService("asdfghkl;");
     EXPECT_EQ(nullptr, foo.get());
diff --git a/libs/binder/run_rpc_tests.sh b/libs/binder/run_rpc_tests.sh
new file mode 100755
index 0000000..7ba682d
--- /dev/null
+++ b/libs/binder/run_rpc_tests.sh
@@ -0,0 +1,44 @@
+#!/usr/bin/env bash
+
+set -ex
+
+if [ $# -eq 0 ]; then
+  :
+elif [ $# -eq 1 ] && [[ "$1" =~ ^host|device$ ]]; then
+  :
+else
+  echo "usage: $0 [device|host]"
+  false
+fi
+
+# Script maintained for RPC development, while it is active, to quickly run
+# tests. Generally, to match VTS/presubmit behavior, 'atest' should be used.
+
+function dtest () { adb shell /data/nativetest64/$1/$@; }
+function hbench () { $AT/out/host/linux-x86/benchmarktest/$1/$@; }
+function hfuzz () { time $ANDROID_HOST_OUT/fuzz/x86_64/$1/$@; }
+function htest () { time $ANDROID_BUILD_TOP/out/host/linux-x86/nativetest/$1/$@; }
+function pdtest () { adb wait-for-device && adb shell mkdir -p /data/nativetest64/$1 && adb push $OUT/data/nativetest64/$1/$1 /data/nativetest64/$1/$1 && dtest $@; }
+function dbench () { adb shell /data/benchmarktest64/$1/$@; }
+function pdbench () { adb wait-for-device && adb shell mkdir -p /data/benchmarktest64/$1 && adb push $OUT/data/benchmarktest64/$1/$1 /data/benchmarktest64/$1/$1 && dbench $@; }
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode \
+  binderRpcTest \
+  binder_rpc_fuzzer \
+  binder_parcel_fuzzer \
+  binderLibTest \
+  binderRpcBenchmark
+
+if ! [ "$1" = "device" ]; then
+  htest binderRpcTest
+  hbench binderRpcBenchmark
+  hfuzz binder_rpc_fuzzer -max_total_time=30
+  hfuzz binder_parcel_fuzzer -max_total_time=30
+fi
+
+if ! [ "$1" = "host" ]; then
+  pdtest binderRpcTest
+  pdtest binderLibTest
+  pdbench binderRpcBenchmark
+fi
+
diff --git a/libs/binder/rust/src/parcel/parcelable.rs b/libs/binder/rust/src/parcel/parcelable.rs
index 956ecfe..56c6165 100644
--- a/libs/binder/rust/src/parcel/parcelable.rs
+++ b/libs/binder/rust/src/parcel/parcelable.rs
@@ -764,6 +764,30 @@
     }
 }
 
+impl<T: Serialize> Serialize for Box<T> {
+    fn serialize(&self, parcel: &mut Parcel) -> Result<()> {
+        Serialize::serialize(&**self, parcel)
+    }
+}
+
+impl<T: Deserialize> Deserialize for Box<T> {
+    fn deserialize(parcel: &Parcel) -> Result<Self> {
+        Deserialize::deserialize(parcel).map(Box::new)
+    }
+}
+
+impl<T: SerializeOption> SerializeOption for Box<T> {
+    fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> {
+        SerializeOption::serialize_option(this.map(|inner| &**inner), parcel)
+    }
+}
+
+impl<T: DeserializeOption> DeserializeOption for Box<T> {
+    fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> {
+        DeserializeOption::deserialize_option(parcel).map(|t| t.map(Box::new))
+    }
+}
+
 #[test]
 fn test_custom_parcelable() {
     use crate::binder::Interface;
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 48fc60a..9811cdf 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -23,9 +23,12 @@
 #include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
+#include <android/debug/BnAdbCallback.h>
+#include <android/debug/IAdbManager.h>
 #include <android/os/BnServiceManager.h>
 #include <android/os/IServiceManager.h>
 #include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
 #include <binder/RpcServer.h>
 
 using android::BBinder;
@@ -50,6 +53,7 @@
 
 const char* kLocalInetAddress = "127.0.0.1";
 using ServiceRetriever = decltype(&android::IServiceManager::checkService);
+using android::debug::IAdbManager;
 
 int Usage(const char* program) {
     auto basename = Basename(program);
@@ -213,6 +217,25 @@
     __builtin_unreachable();
 }
 
+class AdbCallback : public android::debug::BnAdbCallback {
+public:
+    android::binder::Status onDebuggingChanged(bool enabled,
+                                               android::debug::AdbTransportType) override {
+        if (!enabled) {
+            LOG(ERROR) << "ADB debugging disabled, exiting.";
+            exit(EX_SOFTWARE);
+        }
+        return android::binder::Status::ok();
+    }
+};
+
+void exitOnAdbDebuggingDisabled() {
+    auto adb = android::waitForService<IAdbManager>(String16("adb"));
+    CHECK(adb != nullptr) << "Unable to retrieve service adb";
+    auto status = adb->registerCallback(sp<AdbCallback>::make());
+    CHECK(status.isOk()) << "Unable to call IAdbManager::registerCallback: " << status;
+}
+
 // Log to logd. For warning and more severe messages, also log to stderr.
 class ServiceDispatcherLogger {
 public:
@@ -253,6 +276,10 @@
         }
     }
 
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    android::ProcessState::self()->startThreadPool();
+    exitOnAdbDebuggingDisabled();
+
     if (optind + 1 != argc) return Usage(argv[0]);
     auto name = argv[optind];
 
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 0c452ff..e430c28 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -153,7 +153,7 @@
                        {64, 1024, 2048, 4096, 8182, 16364, 32728, 65535, 65536, 65537}});
 
 void BM_repeatBinder(benchmark::State& state) {
-    sp<IBinder> binder = gSession->getRootObject();
+    sp<IBinder> binder = getBinderForOptions(state);
     CHECK(binder != nullptr);
     sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
     CHECK(iface != nullptr);
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index 6dd4019..15ccae9 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -1196,7 +1196,12 @@
     unsigned int vsockPort = allocateVsockPort();
     sp<RpcServer> server = RpcServer::make(RpcTransportCtxFactoryRaw::make());
     server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
-    CHECK_EQ(OK, server->setupVsockServer(vsockPort));
+    if (status_t status = server->setupVsockServer(vsockPort); status != OK) {
+        if (status == -EAFNOSUPPORT) {
+            return false;
+        }
+        LOG_ALWAYS_FATAL("Could not setup vsock server: %s", statusToString(status).c_str());
+    }
     server->start();
 
     sp<RpcSession> session = RpcSession::make(RpcTransportCtxFactoryRaw::make());
diff --git a/libs/binderdebug/BinderDebug.cpp b/libs/binderdebug/BinderDebug.cpp
index b435dba..d086b49 100644
--- a/libs/binderdebug/BinderDebug.cpp
+++ b/libs/binderdebug/BinderDebug.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <android-base/parseint.h>
 #include <android-base/strings.h>
 #include <binder/Binder.h>
@@ -116,4 +117,60 @@
     return ret;
 }
 
+status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
+                             int32_t handle, std::vector<pid_t>* pids) {
+    std::smatch match;
+    static const std::regex kNodeNumber("^\\s+ref \\d+:\\s+desc\\s+(\\d+)\\s+node\\s+(\\d+).*");
+    std::string contextStr = contextToString(context);
+    int32_t node;
+    status_t ret = scanBinderContext(pid, contextStr, [&](const std::string& line) {
+        if (std::regex_search(line, match, kNodeNumber)) {
+            const std::string& descString = match.str(1);
+            int32_t desc;
+            if (!::android::base::ParseInt(descString.c_str(), &desc)) {
+                LOG(ERROR) << "Failed to parse desc int: " << descString;
+                return;
+            }
+            if (handle != desc) {
+                return;
+            }
+            const std::string& nodeString = match.str(2);
+            if (!::android::base::ParseInt(nodeString.c_str(), &node)) {
+                LOG(ERROR) << "Failed to parse node int: " << nodeString;
+                return;
+            }
+            return;
+        }
+        return;
+    });
+    if (ret != OK) {
+        return ret;
+    }
+    static const std::regex kClients("^\\s+node\\s+(\\d+).*proc\\s+([\\d+\\s*]*)");
+    ret = scanBinderContext(servicePid, contextStr, [&](const std::string& line) {
+        if (std::regex_search(line, match, kClients)) {
+            const std::string nodeString = match.str(1);
+            int32_t matchedNode;
+            if (!::android::base::ParseInt(nodeString.c_str(), &matchedNode)) {
+                LOG(ERROR) << "Failed to parse node int: " << nodeString;
+                return;
+            }
+            if (node != matchedNode) {
+                return;
+            }
+            const std::string clients = match.str(2);
+            for (const std::string& pidStr : base::Split(clients, " ")) {
+                int32_t pid;
+                if (!::android::base::ParseInt(pidStr, &pid)) {
+                    return;
+                }
+                pids->push_back(pid);
+            }
+            return;
+        }
+        return;
+    });
+    return ret;
+}
+
 } // namespace  android
diff --git a/libs/binderdebug/include/binderdebug/BinderDebug.h b/libs/binderdebug/include/binderdebug/BinderDebug.h
index 14a0ef3..dfd5a7c 100644
--- a/libs/binderdebug/include/binderdebug/BinderDebug.h
+++ b/libs/binderdebug/include/binderdebug/BinderDebug.h
@@ -32,6 +32,14 @@
     VNDBINDER,
 };
 
+/**
+ * pid is the pid of the service
+ */
 status_t getBinderPidInfo(BinderDebugContext context, pid_t pid, BinderPidInfo* pidInfo);
+/**
+ * pid is typically the pid of this process that is making the query
+ */
+status_t getBinderClientPids(BinderDebugContext context, pid_t pid, pid_t servicePid,
+                             int32_t handle, std::vector<pid_t>* pids);
 
 } // namespace  android
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 95a2f60..1fd9d13 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -173,6 +173,7 @@
     SAFE_PARCEL(output.write, destinationFrame);
     SAFE_PARCEL(output.writeBool, isTrustedOverlay);
 
+    SAFE_PARCEL(output.writeStrongBinder, releaseBufferEndpoint);
     return NO_ERROR;
 }
 
@@ -302,6 +303,7 @@
     SAFE_PARCEL(input.read, destinationFrame);
     SAFE_PARCEL(input.readBool, &isTrustedOverlay);
 
+    SAFE_PARCEL(input.readNullableStrongBinder, &releaseBufferEndpoint);
     return NO_ERROR;
 }
 
@@ -453,6 +455,7 @@
     if (other.what & eBufferChanged) {
         what |= eBufferChanged;
         buffer = other.buffer;
+        releaseBufferEndpoint = other.releaseBufferEndpoint;
     }
     if (other.what & eAcquireFenceChanged) {
         what |= eAcquireFenceChanged;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index c3d632f..05554ca 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -147,8 +147,16 @@
     return mCallbackIdCounter++;
 }
 
+sp<TransactionCompletedListener> TransactionCompletedListener::sInstance = nullptr;
+
+void TransactionCompletedListener::setInstance(const sp<TransactionCompletedListener>& listener) {
+    sInstance = listener;
+}
+
 sp<TransactionCompletedListener> TransactionCompletedListener::getInstance() {
-    static sp<TransactionCompletedListener> sInstance = new TransactionCompletedListener;
+    if (sInstance == nullptr) {
+        sInstance = new TransactionCompletedListener;
+    }
     return sInstance;
 }
 
@@ -1274,6 +1282,7 @@
     removeReleaseBufferCallback(s);
     s->what |= layer_state_t::eBufferChanged;
     s->buffer = buffer;
+    s->releaseBufferEndpoint = IInterface::asBinder(TransactionCompletedListener::getIInstance());
     if (mIsAutoTimestamp) {
         mDesiredPresentTime = systemTime();
     }
diff --git a/libs/gui/WindowInfo.cpp b/libs/gui/WindowInfo.cpp
index ff0bb8a..6b68e1a 100644
--- a/libs/gui/WindowInfo.cpp
+++ b/libs/gui/WindowInfo.cpp
@@ -114,7 +114,8 @@
         applicationInfo.writeToParcel(parcel) ?:
         parcel->write(touchableRegion) ?:
         parcel->writeBool(replaceTouchableRegionWithCrop) ?:
-        parcel->writeStrongBinder(touchableRegionCropHandle.promote());
+        parcel->writeStrongBinder(touchableRegionCropHandle.promote()) ?:
+        parcel->writeStrongBinder(windowToken);
     // clang-format on
     return status;
 }
@@ -188,7 +189,8 @@
     touchableRegionCropHandle = parcel->readStrongBinder();
     transform.set({dsdx, dtdx, tx, dtdy, dsdy, ty, 0, 0, 1});
 
-    return OK;
+    status = parcel->readNullableStrongBinder(&windowToken);
+    return status;
 }
 
 // --- WindowInfoHandle ---
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 427f2a5..f14127c 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -243,6 +243,11 @@
     // is used to remove the old callback from the client process map if it is
     // overwritten by another setBuffer call.
     ReleaseCallbackId releaseCallbackId;
+
+    // Stores which endpoint the release information should be sent to. We don't want to send the
+    // releaseCallbackId and release fence to all listeners so we store which listener the setBuffer
+    // was called with.
+    sp<IBinder> releaseBufferEndpoint;
 };
 
 struct ComposerState {
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index ec68ca9..a980ce2 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -652,8 +652,10 @@
 };
 
 class TransactionCompletedListener : public BnTransactionCompletedListener {
+public:
     TransactionCompletedListener();
 
+protected:
     int64_t getNextIdLocked() REQUIRES(mMutex);
 
     std::mutex mMutex;
@@ -731,8 +733,12 @@
     void onReleaseBuffer(ReleaseCallbackId, sp<Fence> releaseFence, uint32_t transformHint,
                          uint32_t currentMaxAcquiredBufferCount) override;
 
+    // For Testing Only
+    static void setInstance(const sp<TransactionCompletedListener>&);
+
 private:
     ReleaseBufferCallback popReleaseBufferCallbackLocked(const ReleaseCallbackId&);
+    static sp<TransactionCompletedListener> sInstance;
 };
 
 } // namespace android
diff --git a/libs/gui/include/gui/WindowInfo.h b/libs/gui/include/gui/WindowInfo.h
index 7af1f0e..9c28b11 100644
--- a/libs/gui/include/gui/WindowInfo.h
+++ b/libs/gui/include/gui/WindowInfo.h
@@ -132,6 +132,10 @@
     // This value should NOT be used to uniquely identify the window. There may be different
     // input windows that have the same token.
     sp<IBinder> token;
+
+    // The token that identifies which client window this WindowInfo was created for.
+    sp<IBinder> windowToken;
+
     // This uniquely identifies the input window.
     int32_t id = -1;
     std::string name;
diff --git a/libs/gui/tests/WindowInfo_test.cpp b/libs/gui/tests/WindowInfo_test.cpp
index 58f3981..a4f436c 100644
--- a/libs/gui/tests/WindowInfo_test.cpp
+++ b/libs/gui/tests/WindowInfo_test.cpp
@@ -46,6 +46,7 @@
     sp<IBinder> touchableRegionCropHandle = new BBinder();
     WindowInfo i;
     i.token = new BBinder();
+    i.windowToken = new BBinder();
     i.id = 1;
     i.name = "Foobar";
     i.flags = WindowInfo::Flag::SLIPPERY;
@@ -85,6 +86,7 @@
     WindowInfo i2;
     i2.readFromParcel(&p);
     ASSERT_EQ(i.token, i2.token);
+    ASSERT_EQ(i.windowToken, i2.windowToken);
     ASSERT_EQ(i.id, i2.id);
     ASSERT_EQ(i.name, i2.name);
     ASSERT_EQ(i.flags, i2.flags);
diff --git a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
index 6eaa84e..bac44c9 100644
--- a/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
+++ b/libs/nativedisplay/include/surfacetexture/SurfaceTexture.h
@@ -272,10 +272,11 @@
     status_t attachToContext(uint32_t tex);
 
     sp<GraphicBuffer> dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
-                                    float* outTransformMatrix, bool* outQueueEmpty,
+                                    float* outTransformMatrix, uint32_t* outTransform,
+                                    bool* outQueueEmpty,
                                     SurfaceTexture_createReleaseFence createFence,
                                     SurfaceTexture_fenceWait fenceWait,
-                                    void* fencePassThroughHandle);
+                                    void* fencePassThroughHandle, ARect* currentCrop);
 
     /**
      * takeConsumerOwnership attaches a SurfaceTexture that is currently in the
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index 85fe42f..e85009c 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -84,10 +84,11 @@
  */
 AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
                                                android_dataspace* outDataspace,
-                                               float* outTransformMatrix, bool* outNewContent,
+                                               float* outTransformMatrix, uint32_t* outTransform,
+                                               bool* outNewContent,
                                                ASurfaceTexture_createReleaseFence createFence,
                                                ASurfaceTexture_fenceWait fenceWait,
-                                               void* fencePassThroughHandle);
+                                               void* fencePassThroughHandle, ARect* currentCrop);
 
 } // namespace android
 
diff --git a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
index 62db6d0..3535e67 100644
--- a/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
+++ b/libs/nativedisplay/surfacetexture/SurfaceTexture.cpp
@@ -464,10 +464,11 @@
 }
 
 sp<GraphicBuffer> SurfaceTexture::dequeueBuffer(int* outSlotid, android_dataspace* outDataspace,
-                                                float* outTransformMatrix, bool* outQueueEmpty,
+                                                float* outTransformMatrix, uint32_t* outTransform,
+                                                bool* outQueueEmpty,
                                                 SurfaceTexture_createReleaseFence createFence,
                                                 SurfaceTexture_fenceWait fenceWait,
-                                                void* fencePassThroughHandle) {
+                                                void* fencePassThroughHandle, ARect* currentCrop) {
     Mutex::Autolock _l(mMutex);
     sp<GraphicBuffer> buffer;
 
@@ -484,6 +485,8 @@
     buffer = mImageConsumer.dequeueBuffer(outSlotid, outDataspace, outQueueEmpty, *this,
                                           createFence, fenceWait, fencePassThroughHandle);
     memcpy(outTransformMatrix, mCurrentTransformMatrix, sizeof(mCurrentTransformMatrix));
+    *outTransform = mCurrentTransform;
+    *currentCrop = mCurrentCrop;
     return buffer;
 }
 
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index c214ab7..cc0a12d 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -194,15 +194,18 @@
 
 AHardwareBuffer* ASurfaceTexture_dequeueBuffer(ASurfaceTexture* st, int* outSlotid,
                                                android_dataspace* outDataspace,
-                                               float* outTransformMatrix, bool* outNewContent,
+                                               float* outTransformMatrix, uint32_t* outTransform,
+                                               bool* outNewContent,
                                                ASurfaceTexture_createReleaseFence createFence,
-                                               ASurfaceTexture_fenceWait fenceWait, void* handle) {
+                                               ASurfaceTexture_fenceWait fenceWait, void* handle,
+                                               ARect* currentCrop) {
     sp<GraphicBuffer> buffer;
     *outNewContent = false;
     bool queueEmpty;
     do {
         buffer = st->consumer->dequeueBuffer(outSlotid, outDataspace, outTransformMatrix,
-                                             &queueEmpty, createFence, fenceWait, handle);
+                                             outTransform, &queueEmpty, createFence, fenceWait,
+                                             handle, currentCrop);
         if (!queueEmpty) {
             *outNewContent = true;
         }
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 50e1854..0fc4708 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -16,6 +16,7 @@
 
 #include "../dispatcher/InputDispatcher.h"
 
+#include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <android-base/thread_annotations.h>
 #include <binder/Binder.h>
@@ -678,7 +679,11 @@
 
 // --- InputDispatcherTest SetInputWindowTest ---
 static constexpr std::chrono::duration INJECT_EVENT_TIMEOUT = 500ms;
-static constexpr std::chrono::nanoseconds DISPATCHING_TIMEOUT = 5s;
+// Default input dispatching timeout if there is no focused application or paused window
+// from which to determine an appropriate dispatching timeout.
+static const std::chrono::duration DISPATCHING_TIMEOUT = std::chrono::milliseconds(
+        android::os::IInputConstants::UNMULTIPLIED_DEFAULT_DISPATCHING_TIMEOUT_MILLIS *
+        android::base::HwTimeoutMultiplier());
 
 class FakeApplicationHandle : public InputApplicationHandle {
 public:
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 8bc51df..4d86598 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
 //#define LOG_NDEBUG 0
 #undef LOG_TAG
 #define LOG_TAG "BufferStateLayer"
@@ -158,7 +153,8 @@
     // transaction doesn't need a previous release fence.
     sp<CallbackHandle> ch;
     for (auto& handle : mDrawingState.callbackHandles) {
-        if (handle->releasePreviousBuffer) {
+        if (handle->releasePreviousBuffer &&
+            mDrawingState.releaseBufferEndpoint == handle->listener) {
             ch = handle;
             break;
         }
@@ -199,14 +195,9 @@
                 mFlinger->getMaxAcquiredBufferCountForCurrentRefreshRate(mOwnerUid);
     }
 
-    // If there are multiple transactions in this frame, set the previous id on the earliest
-    // transacton. We don't need to pass in the released buffer id to multiple transactions.
-    // The buffer id does not have to correspond to any particular transaction as long as the
-    // listening end point is the same but the client expects the first transaction callback that
-    // replaces the presented buffer to contain the release fence. This follows the same logic.
-    // see BufferStateLayer::onLayerDisplayed.
     for (auto& handle : mDrawingState.callbackHandles) {
-        if (handle->releasePreviousBuffer) {
+        if (handle->releasePreviousBuffer &&
+            mDrawingState.releaseBufferEndpoint == handle->listener) {
             handle->previousReleaseCallbackId = mPreviousReleaseCallbackId;
             break;
         }
@@ -420,7 +411,8 @@
                                  nsecs_t desiredPresentTime, bool isAutoTimestamp,
                                  const client_cache_t& clientCacheId, uint64_t frameNumber,
                                  std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
-                                 const sp<ITransactionCompletedListener>& releaseBufferListener) {
+                                 const sp<ITransactionCompletedListener>& releaseBufferListener,
+                                 const sp<IBinder>& releaseBufferEndpoint) {
     ATRACE_CALL();
 
     if (mDrawingState.buffer) {
@@ -485,6 +477,7 @@
 
     mDrawingState.width = mDrawingState.buffer->getBuffer()->getWidth();
     mDrawingState.height = mDrawingState.buffer->getBuffer()->getHeight();
+    mDrawingState.releaseBufferEndpoint = releaseBufferEndpoint;
 
     return true;
 }
@@ -598,7 +591,7 @@
     return true;
 }
 
-Rect BufferStateLayer::getBufferSize(const State& s) const {
+Rect BufferStateLayer::getBufferSize(const State& /*s*/) const {
     // for buffer state layers we use the display frame size as the buffer size.
 
     if (mBufferInfo.mBuffer == nullptr) {
@@ -620,7 +613,7 @@
         }
     }
 
-    return Rect(0, 0, bufWidth, bufHeight);
+    return Rect(0, 0, static_cast<int32_t>(bufWidth), static_cast<int32_t>(bufHeight));
 }
 
 FloatRect BufferStateLayer::computeSourceBounds(const FloatRect& parentBounds) const {
@@ -819,7 +812,7 @@
     eraseBufferLocked(clientCacheId);
 }
 
-uint32_t BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
+int BufferStateLayer::HwcSlotGenerator::getHwcCacheSlot(const client_cache_t& clientCacheId) {
     std::lock_guard<std::mutex> lock(mMutex);
     auto itr = mCachedBuffers.find(clientCacheId);
     if (itr == mCachedBuffers.end()) {
@@ -830,7 +823,7 @@
     return hwcCacheSlot;
 }
 
-uint32_t BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
+int BufferStateLayer::HwcSlotGenerator::addCachedBuffer(const client_cache_t& clientCacheId)
         REQUIRES(mMutex) {
     if (!clientCacheId.isValid()) {
         ALOGE("invalid process, returning invalid slot");
@@ -839,17 +832,17 @@
 
     ClientCache::getInstance().registerErasedRecipient(clientCacheId, wp<ErasedRecipient>(this));
 
-    uint32_t hwcCacheSlot = getFreeHwcCacheSlot();
+    int hwcCacheSlot = getFreeHwcCacheSlot();
     mCachedBuffers[clientCacheId] = {hwcCacheSlot, mCounter++};
     return hwcCacheSlot;
 }
 
-uint32_t BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
+int BufferStateLayer::HwcSlotGenerator::getFreeHwcCacheSlot() REQUIRES(mMutex) {
     if (mFreeHwcCacheSlots.empty()) {
         evictLeastRecentlyUsed();
     }
 
-    uint32_t hwcCacheSlot = mFreeHwcCacheSlots.top();
+    int hwcCacheSlot = mFreeHwcCacheSlots.top();
     mFreeHwcCacheSlots.pop();
     return hwcCacheSlot;
 }
@@ -936,8 +929,8 @@
         return false;
     }
 
-    uint32_t bufferWidth = s.buffer->getBuffer()->width;
-    uint32_t bufferHeight = s.buffer->getBuffer()->height;
+    int32_t bufferWidth = s.buffer->getBuffer()->width;
+    int32_t bufferHeight = s.buffer->getBuffer()->height;
 
     // Undo any transformations on the buffer and return the result.
     if (s.bufferTransform & ui::Transform::ROT_90) {
@@ -996,6 +989,3 @@
 }
 
 } // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index cab4899..124e91a 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -59,7 +59,8 @@
                    const sp<Fence>& acquireFence, nsecs_t postTime, nsecs_t desiredPresentTime,
                    bool isAutoTimestamp, const client_cache_t& clientCacheId, uint64_t frameNumber,
                    std::optional<nsecs_t> dequeueTime, const FrameTimelineInfo& info,
-                   const sp<ITransactionCompletedListener>& transactionListener) override;
+                   const sp<ITransactionCompletedListener>& transactionListener,
+                   const sp<IBinder>& releaseBufferEndpoint) override;
     bool setAcquireFence(const sp<Fence>& fence) override;
     bool setDataspace(ui::Dataspace dataspace) override;
     bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
@@ -177,19 +178,19 @@
     class HwcSlotGenerator : public ClientCache::ErasedRecipient {
     public:
         HwcSlotGenerator() {
-            for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+            for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
                 mFreeHwcCacheSlots.push(i);
             }
         }
 
         void bufferErased(const client_cache_t& clientCacheId);
 
-        uint32_t getHwcCacheSlot(const client_cache_t& clientCacheId);
+        int getHwcCacheSlot(const client_cache_t& clientCacheId);
 
     private:
         friend class SlotGenerationTest;
-        uint32_t addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
-        uint32_t getFreeHwcCacheSlot() REQUIRES(mMutex);
+        int addCachedBuffer(const client_cache_t& clientCacheId) REQUIRES(mMutex);
+        int getFreeHwcCacheSlot() REQUIRES(mMutex);
         void evictLeastRecentlyUsed() REQUIRES(mMutex);
         void eraseBufferLocked(const client_cache_t& clientCacheId) REQUIRES(mMutex);
 
@@ -201,11 +202,10 @@
 
         std::mutex mMutex;
 
-        std::unordered_map<client_cache_t,
-                           std::pair<uint32_t /*HwcCacheSlot*/, uint32_t /*counter*/>,
+        std::unordered_map<client_cache_t, std::pair<int /*HwcCacheSlot*/, uint64_t /*counter*/>,
                            CachedBufferHash>
                 mCachedBuffers GUARDED_BY(mMutex);
-        std::stack<uint32_t /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
+        std::stack<int /*HwcCacheSlot*/> mFreeHwcCacheSlots GUARDED_BY(mMutex);
 
         // The cache increments this counter value when a slot is updated or used.
         // Used to track the least recently-used buffer
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 5156854..d27b51b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2027,6 +2027,7 @@
         layerInfo->set_curr_frame(mCurrentFrameNumber);
         layerInfo->set_effective_scaling_mode(getEffectiveScalingMode());
 
+        layerInfo->set_requested_corner_radius(getDrawingState().cornerRadius);
         layerInfo->set_corner_radius(getRoundedCornerState().radius);
         layerInfo->set_background_blur_radius(getBackgroundBlurRadius());
         layerInfo->set_is_trusted_overlay(isTrustedOverlay());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 982f246..60a66f4 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -275,6 +275,8 @@
 
         Rect bufferCrop;
         Rect destinationFrame;
+
+        sp<IBinder> releaseBufferEndpoint;
     };
 
     /*
@@ -417,7 +419,8 @@
                            const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */,
                            std::optional<nsecs_t> /* dequeueTime */,
                            const FrameTimelineInfo& /*info*/,
-                           const sp<ITransactionCompletedListener>& /* releaseBufferListener */) {
+                           const sp<ITransactionCompletedListener>& /* releaseBufferListener */,
+                           const sp<IBinder>& /* releaseBufferEndpoint */) {
         return false;
     };
     virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 40d4c61..0789e8d 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -292,7 +292,7 @@
     mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
                       mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
                       std::nullopt /* dequeueTime */, FrameTimelineInfo{},
-                      nullptr /* releaseBufferListener */);
+                      nullptr /* releaseBufferListener */, nullptr /* releaseBufferEndpoint */);
 
     mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
 }
@@ -306,7 +306,7 @@
     mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
                       mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */),
                       std::nullopt /* dequeueTime */, FrameTimelineInfo{},
-                      nullptr /* releaseBufferListener */);
+                      nullptr /* releaseBufferListener */, nullptr /* releaseBufferEndpoint */);
 
     mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
 }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 33c0b0c..bf53c5e 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4190,7 +4190,7 @@
 
         if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
                              s.cachedBuffer, frameNumber, dequeueBufferTimestamp, frameTimelineInfo,
-                             s.releaseBufferListener)) {
+                             s.releaseBufferListener, s.releaseBufferEndpoint)) {
             flags |= eTraversalNeeded;
         }
     } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
@@ -6762,7 +6762,7 @@
     return NO_ERROR;
 }
 
-int SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const {
+uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const {
     Fps refreshRate(60.f);
 
     if (const auto frameRateOverride = mScheduler->getFrameRateOverride(uid)) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index cb4925f..00d42af 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -942,7 +942,7 @@
         return width > mMaxRenderTargetSize || height > mMaxRenderTargetSize;
     }
 
-    int getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
+    uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
 
     /*
      * Display and layer stack management
diff --git a/services/surfaceflinger/layerproto/layers.proto b/services/surfaceflinger/layerproto/layers.proto
index dddc677..9f4e7d2 100644
--- a/services/surfaceflinger/layerproto/layers.proto
+++ b/services/surfaceflinger/layerproto/layers.proto
@@ -130,6 +130,9 @@
   repeated BlurRegion blur_regions = 54;
 
   bool is_trusted_overlay = 55;
+
+  // Corner radius explicitly set on layer rather than inherited
+  float requested_corner_radius = 56;
 }
 
 message PositionProto {
@@ -228,4 +231,4 @@
     int32 top = 8;
     int32 right = 9;
     int32 bottom = 10;
-}
\ No newline at end of file
+}
diff --git a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
index 579a26e..c4d42fa 100644
--- a/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
+++ b/services/surfaceflinger/tests/ReleaseBufferCallback_test.cpp
@@ -99,10 +99,10 @@
     }
 
     static void waitForReleaseBufferCallback(ReleaseBufferCallbackHelper& releaseCallback,
-                                             const ReleaseCallbackId& expectedCallbackId) {
+                                             const ReleaseCallbackId& expectedReleaseBufferId) {
         ReleaseCallbackId actualReleaseBufferId;
         releaseCallback.getCallbackData(&actualReleaseBufferId);
-        EXPECT_EQ(expectedCallbackId, actualReleaseBufferId);
+        EXPECT_EQ(expectedReleaseBufferId, actualReleaseBufferId);
         releaseCallback.verifyNoCallbacks();
     }
     static ReleaseBufferCallbackHelper* getReleaseBufferCallbackHelper() {
@@ -333,4 +333,60 @@
     ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
 }
 
+TEST_F(ReleaseBufferCallbackTest, DISABLED_Merge_Different_Processes) {
+    sp<TransactionCompletedListener> firstCompletedListener = new TransactionCompletedListener();
+    sp<TransactionCompletedListener> secondCompletedListener = new TransactionCompletedListener();
+
+    CallbackHelper callback1, callback2;
+
+    TransactionCompletedListener::setInstance(firstCompletedListener);
+
+    sp<SurfaceControl> layer = createBufferStateLayer();
+    ReleaseBufferCallbackHelper* releaseCallback = getReleaseBufferCallbackHelper();
+
+    sp<GraphicBuffer> firstBuffer = getBuffer();
+    ReleaseCallbackId firstBufferCallbackId(firstBuffer->getId(), generateFrameNumber());
+
+    // Send initial buffer for the layer
+    submitBuffer(layer, firstBuffer, Fence::NO_FENCE, callback1, firstBufferCallbackId,
+                 *releaseCallback);
+
+    ExpectedResult expected;
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+                        ExpectedResult::Buffer::NOT_ACQUIRED);
+    ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+
+    // Sent a second buffer to allow the first buffer to get released.
+    sp<GraphicBuffer> secondBuffer = getBuffer();
+    ReleaseCallbackId secondBufferCallbackId(secondBuffer->getId(), generateFrameNumber());
+
+    Transaction transaction1;
+    transaction1.setFrameNumber(layer, secondBufferCallbackId.framenumber);
+    transaction1.setBuffer(layer, secondBuffer, secondBufferCallbackId,
+                           releaseCallback->getCallback());
+    transaction1.setAcquireFence(layer, Fence::NO_FENCE);
+    transaction1.addTransactionCompletedCallback(callback1.function, callback1.getContext());
+
+    // Set a different TransactionCompletedListener to mimic a second process
+    TransactionCompletedListener::setInstance(secondCompletedListener);
+
+    // Make sure the second "process" has a callback set up.
+    Transaction transaction2;
+    transaction2.addTransactionCompletedCallback(callback2.function, callback2.getContext());
+
+    // This merging order, merge transaction1 first then transaction2, seems to ensure the listener
+    // for transaction2 is ordered first. This makes sure the wrong process is added first to the
+    // layer's vector of listeners. With the bug, only the secondCompletedListener will get the
+    // release callback id, since it's ordered first. Then firstCompletedListener would fail to get
+    // the release callback id and not invoke the release callback.
+    Transaction().merge(std::move(transaction1)).merge(std::move(transaction2)).apply();
+
+    expected = ExpectedResult();
+    expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer,
+                        ExpectedResult::Buffer::NOT_ACQUIRED,
+                        ExpectedResult::PreviousBuffer::RELEASED);
+    ASSERT_NO_FATAL_FAILURE(waitForCallback(callback1, expected));
+    ASSERT_NO_FATAL_FAILURE(waitForReleaseBufferCallback(*releaseCallback, firstBufferCallbackId));
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp
index 6a7ec9b..6f85498 100644
--- a/services/surfaceflinger/tests/unittests/CachingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp
@@ -14,11 +14,6 @@
  * limitations under the License.
  */
 
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-#pragma clang diagnostic ignored "-Wextra"
-
 #undef LOG_TAG
 #define LOG_TAG "CachingTest"
 
@@ -42,7 +37,7 @@
     sp<IBinder> binder = new BBinder();
     // test getting invalid client_cache_id
     client_cache_t id;
-    uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+    int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
     EXPECT_EQ(BufferQueue::INVALID_BUFFER_SLOT, slot);
 }
 
@@ -51,7 +46,7 @@
     client_cache_t id;
     id.token = binder;
     id.id = 0;
-    uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+    int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
     EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - 1, slot);
 
     client_cache_t idB;
@@ -72,31 +67,28 @@
     std::vector<client_cache_t> ids;
     uint32_t cacheId = 0;
     // fill up cache
-    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
         client_cache_t id;
         id.token = binder;
         id.id = cacheId;
         ids.push_back(id);
 
-        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+        int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
         EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
         cacheId++;
     }
-    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
-        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(ids[i]);
+    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+        int slot = mHwcSlotGenerator->getHwcCacheSlot(ids[static_cast<uint32_t>(i)]);
         EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
     }
 
-    for (uint32_t i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
+    for (int i = 0; i < BufferQueue::NUM_BUFFER_SLOTS; i++) {
         client_cache_t id;
         id.token = binder;
         id.id = cacheId;
-        uint32_t slot = mHwcSlotGenerator->getHwcCacheSlot(id);
+        int slot = mHwcSlotGenerator->getHwcCacheSlot(id);
         EXPECT_EQ(BufferQueue::NUM_BUFFER_SLOTS - (i + 1), slot);
         cacheId++;
     }
 }
 } // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
diff --git a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
index 2845d0a..a749ece 100644
--- a/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionFrameTracerTest.cpp
@@ -119,7 +119,7 @@
                                    FrameTracer::FrameEvent::QUEUE, /*duration*/ 0));
         layer->setBuffer(buffer, fence, postTime, /*desiredPresentTime*/ 30, false, mClientCache,
                          frameNumber, dequeueTime, FrameTimelineInfo{},
-                         nullptr /* releaseBufferCallback */);
+                         nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint*/);
 
         commitTransaction(layer.get());
         bool computeVisisbleRegions;
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index 7bf224d..2a7921f 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -119,7 +119,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         acquireFence->signalForTest(12);
 
         commitTransaction(layer.get());
@@ -147,7 +148,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -160,7 +162,8 @@
                                                mRenderEngine, false);
         nsecs_t start = systemTime();
         layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         nsecs_t end = systemTime();
         acquireFence2->signalForTest(12);
 
@@ -200,7 +203,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         acquireFence->signalForTest(12);
 
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
@@ -228,7 +232,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
 
@@ -260,7 +265,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer, fence, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 3, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         EXPECT_EQ(2u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto bufferSurfaceFrameTX = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -298,7 +304,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame = layer->mDrawingState.bufferSurfaceFrameTX;
 
@@ -309,7 +316,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         acquireFence2->signalForTest(12);
 
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -339,7 +347,8 @@
                                                                  1, 0),
                                                mRenderEngine, false);
         layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
         const auto droppedSurfaceFrame1 = layer->mDrawingState.bufferSurfaceFrameTX;
@@ -353,7 +362,7 @@
         auto dropStartTime1 = systemTime();
         layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
                          {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0},
-                         nullptr /* releaseBufferCallback */);
+                         nullptr /* releaseBufferCallback */, nullptr /* releaseBufferEndpoint */);
         auto dropEndTime1 = systemTime();
         EXPECT_EQ(0u, layer->mDrawingState.bufferlessSurfaceFramesTX.size());
         ASSERT_NE(nullptr, layer->mDrawingState.bufferSurfaceFrameTX);
@@ -367,7 +376,8 @@
                                                mRenderEngine, false);
         auto dropStartTime2 = systemTime();
         layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt,
-                         {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */);
+                         {/*vsyncId*/ 2, /*inputEventId*/ 0}, nullptr /* releaseBufferCallback */,
+                         nullptr /* releaseBufferEndpoint */);
         auto dropEndTime2 = systemTime();
         acquireFence3->signalForTest(12);
 
@@ -411,7 +421,8 @@
                                                    mRenderEngine, false);
             layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
                              {/*vsyncId*/ 1, /*inputEventId*/ 0},
-                             nullptr /* releaseBufferCallback */);
+                             nullptr /* releaseBufferCallback */,
+                             nullptr /* releaseBufferEndpoint */);
             layer->setFrameTimelineVsyncForBufferlessTransaction({/*vsyncId*/ 2,
                                                                   /*inputEventId*/ 0},
                                                                  10);