Merge "libbinder: RPC delay bp refcounts"
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 92df874..06542f0 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -48,10 +48,6 @@
 // Another arbitrary value a binder count needs to drop below before another callback will be called
 uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
 
-// Once the limit has been exceeded, keep calling the limit callback for every this many new proxies
-// created over the limit.
-constexpr uint32_t REPEAT_LIMIT_CALLBACK_INTERVAL = 1000;
-
 enum {
     LIMIT_REACHED_MASK = 0x80000000,        // A flag denoting that the limit has been reached
     COUNTING_VALUE_MASK = 0x7FFFFFFF,       // A mask of the remaining bits for the count value
@@ -129,7 +125,7 @@
             uint32_t lastLimitCallbackAt = sLastLimitCallbackMap[trackedUid];
 
             if (trackedValue > lastLimitCallbackAt &&
-                (trackedValue - lastLimitCallbackAt > REPEAT_LIMIT_CALLBACK_INTERVAL)) {
+                (trackedValue - lastLimitCallbackAt > sBinderProxyCountHighWatermark)) {
                 ALOGE("Still too many binder proxy objects sent to uid %d from uid %d (%d proxies "
                       "held)",
                       getuid(), trackedUid, trackedValue);
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index 49f83ff..5e22593 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -17,11 +17,13 @@
 #define LOG_TAG "FdTrigger"
 #include <log/log.h>
 
+#include "FdTrigger.h"
+
 #include <poll.h>
 
 #include <android-base/macros.h>
 
-#include "FdTrigger.h"
+#include "RpcState.h"
 namespace android {
 
 std::unique_ptr<FdTrigger> FdTrigger::make() {
@@ -42,21 +44,53 @@
 }
 
 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 DEAD_OBJECT;
-        }
-        return pfd[0].revents & event ? OK : DEAD_OBJECT;
+    LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get());
+    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;
     }
+    LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get());
+
+    // At least one FD has events. Check them.
+
+    // Detect explicit trigger(): DEAD_OBJECT
+    if (pfd[1].revents & POLLHUP) {
+        return DEAD_OBJECT;
+    }
+    // See unknown flags in trigger FD's revents (POLLERR / POLLNVAL).
+    // Treat this error condition as UNKNOWN_ERROR.
+    if (pfd[1].revents != 0) {
+        ALOGE("Unknown revents on trigger FD %d: revents = %d", pfd[1].fd, pfd[1].revents);
+        return UNKNOWN_ERROR;
+    }
+
+    // pfd[1].revents is 0, hence pfd[0].revents must be set, and only possible values are
+    // a subset of event | POLLHUP | POLLERR | POLLNVAL.
+
+    // POLLNVAL: invalid FD number, e.g. not opened.
+    if (pfd[0].revents & POLLNVAL) {
+        return BAD_VALUE;
+    }
+
+    // Error condition. It wouldn't be possible to do I/O on |fd| afterwards.
+    // Note: If this is the write end of a pipe then POLLHUP may also be set simultaneously. We
+    //   still want DEAD_OBJECT in this case.
+    if (pfd[0].revents & POLLERR) {
+        LOG_RPC_DETAIL("poll() incoming FD %d results in revents = %d", pfd[0].fd, pfd[0].revents);
+        return DEAD_OBJECT;
+    }
+
+    // Success condition; event flag(s) set. Even though POLLHUP may also be set,
+    // treat it as a success condition to ensure data is drained.
+    if (pfd[0].revents & event) {
+        return OK;
+    }
+
+    // POLLHUP: Peer closed connection. Treat as DEAD_OBJECT.
+    // This is a very common case, so don't log.
+    return DEAD_OBJECT;
 }
 
 } // namespace android
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index cf95fda..ba2920e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -205,8 +205,11 @@
     }
 
     mShutdownTrigger->trigger();
+
     for (auto& [id, session] : mSessions) {
         (void)id;
+        // server lock is a more general lock
+        std::lock_guard<std::mutex> _lSession(session->mMutex);
         session->mShutdownTrigger->trigger();
     }
 
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 82efe6d..b5c6cb0 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -454,12 +454,16 @@
                             const sp<IBinder>& binder, uint32_t code, const Parcel& data,
                             const sp<RpcSession>& session, Parcel* reply, uint32_t flags) {
     if (!data.isForRpc()) {
-        ALOGE("Refusing to send RPC with parcel not crafted for RPC");
+        ALOGE("Refusing to send RPC with parcel not crafted for RPC call on binder %p code "
+              "%" PRIu32,
+              binder.get(), code);
         return BAD_TYPE;
     }
 
     if (data.objectsCount() != 0) {
-        ALOGE("Parcel at %p has attached objects but is being used in an RPC call", &data);
+        ALOGE("Parcel at %p has attached objects but is being used in an RPC call on binder %p "
+              "code %" PRIu32,
+              &data, binder.get(), code);
         return BAD_TYPE;
     }
 
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index e7c3396..a91092e 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -441,6 +441,8 @@
 ///
 /// Registers the given binder object with the given identifier. If successful,
 /// this service can then be retrieved using that identifier.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
 pub fn add_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
     let instance = CString::new(identifier).unwrap();
     let status = unsafe {
@@ -462,6 +464,8 @@
 ///
 /// If any service in the process is registered as lazy, all should be, otherwise
 /// the process may be shut down while a service is in use.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
 pub fn register_lazy_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
     let instance = CString::new(identifier).unwrap();
     let status = unsafe {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 71c0e86..680f0ed 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -134,6 +134,37 @@
     },
 }
 
+cc_library_static {
+    name: "libbinder_tls_test_utils",
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    defaults: [
+        "binder_test_defaults",
+        "libbinder_tls_shared_deps",
+    ],
+    shared_libs: [
+        "libbinder",
+        "libbase",
+        "liblog",
+    ],
+    static_libs: [
+        "libbinder_tls_static",
+    ],
+    srcs: [
+        "RpcTlsTestUtils.cpp",
+    ],
+    export_include_dirs: [
+        "include_tls_test_utils",
+    ],
+    visibility: [
+        ":__subpackages__",
+    ],
+}
+
 cc_test {
     name: "binderRpcTest",
     host_supported: true,
@@ -153,8 +184,6 @@
 
     srcs: [
         "binderRpcTest.cpp",
-        "RpcAuthTesting.cpp",
-        "RpcCertificateVerifierSimple.cpp",
     ],
     shared_libs: [
         "libbinder",
@@ -166,6 +195,7 @@
     ],
     static_libs: [
         "libbinder_tls_static",
+        "libbinder_tls_test_utils",
         "binderRpcTestIface-cpp",
         "binderRpcTestIface-ndk",
     ],
@@ -189,7 +219,6 @@
         "libbinder_tls_shared_deps",
     ],
     srcs: [
-        "RpcAuthTesting.cpp",
         "RpcTlsUtilsTest.cpp",
     ],
     shared_libs: [
@@ -199,6 +228,7 @@
         "liblog",
     ],
     static_libs: [
+        "libbinder_tls_test_utils",
         "libbinder_tls_static",
     ],
     test_suites: ["general-tests", "device-tests"],
@@ -219,7 +249,6 @@
     srcs: [
         "binderRpcBenchmark.cpp",
         "IBinderRpcBenchmark.aidl",
-        "RpcAuthTesting.cpp",
     ],
     shared_libs: [
         "libbase",
@@ -228,6 +257,7 @@
         "libutils",
     ],
     static_libs: [
+        "libbinder_tls_test_utils",
         "libbinder_tls_static",
     ],
 }
diff --git a/libs/binder/tests/RpcAuthTesting.h b/libs/binder/tests/RpcAuthTesting.h
deleted file mode 100644
index c3c2df4..0000000
--- a/libs/binder/tests/RpcAuthTesting.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <binder/RpcAuth.h>
-
-namespace android {
-
-constexpr const uint32_t kCertValidSeconds = 30 * (60 * 60 * 24); // 30 days
-bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert();
-bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pKey, uint32_t validSeconds);
-
-// An implementation of RpcAuth that generates a key pair and a self-signed
-// certificate every time configure() is called.
-class RpcAuthSelfSigned : public RpcAuth {
-public:
-    RpcAuthSelfSigned(uint32_t validSeconds = kCertValidSeconds) : mValidSeconds(validSeconds) {}
-    status_t configure(SSL_CTX* ctx) override;
-
-private:
-    const uint32_t mValidSeconds;
-};
-
-class RpcAuthPreSigned : public RpcAuth {
-public:
-    RpcAuthPreSigned(bssl::UniquePtr<EVP_PKEY> pkey, bssl::UniquePtr<X509> cert)
-          : mPkey(std::move(pkey)), mCert(std::move(cert)) {}
-    status_t configure(SSL_CTX* ctx) override;
-
-private:
-    bssl::UniquePtr<EVP_PKEY> mPkey;
-    bssl::UniquePtr<X509> mCert;
-};
-
-} // namespace android
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.cpp b/libs/binder/tests/RpcCertificateVerifierSimple.cpp
deleted file mode 100644
index 1f74adc..0000000
--- a/libs/binder/tests/RpcCertificateVerifierSimple.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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 "RpcCertificateVerifierSimple"
-#include <log/log.h>
-
-#include <binder/RpcTlsUtils.h>
-
-#include "RpcCertificateVerifierSimple.h"
-
-namespace android {
-
-status_t RpcCertificateVerifierSimple::verify(const SSL* ssl, uint8_t* outAlert) {
-    const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
-    bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
-    LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
-                        "%s: libssl should not ask to verify non-existing cert", logPrefix);
-
-    std::lock_guard<std::mutex> lock(mMutex);
-    for (const auto& trustedCert : mTrustedPeerCertificates) {
-        if (0 == X509_cmp(trustedCert.get(), peerCert.get())) {
-            return OK;
-        }
-    }
-    *outAlert = SSL_AD_CERTIFICATE_UNKNOWN;
-    return PERMISSION_DENIED;
-}
-
-status_t RpcCertificateVerifierSimple::addTrustedPeerCertificate(RpcCertificateFormat format,
-                                                                 const std::vector<uint8_t>& cert) {
-    bssl::UniquePtr<X509> x509 = deserializeCertificate(cert, format);
-    if (x509 == nullptr) {
-        ALOGE("Certificate is not in the proper format %s", PrintToString(format).c_str());
-        return BAD_VALUE;
-    }
-    std::lock_guard<std::mutex> lock(mMutex);
-    mTrustedPeerCertificates.push_back(std::move(x509));
-    return OK;
-}
-
-} // namespace android
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.h b/libs/binder/tests/RpcCertificateVerifierSimple.h
deleted file mode 100644
index bdb2426..0000000
--- a/libs/binder/tests/RpcCertificateVerifierSimple.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <mutex>
-#include <string_view>
-#include <vector>
-
-#include <openssl/ssl.h>
-
-#include <binder/RpcCertificateFormat.h>
-#include <binder/RpcCertificateVerifier.h>
-
-namespace android {
-
-// A simple certificate verifier for testing.
-// Keep a list of leaf certificates as trusted. No certificate chain support.
-//
-// All APIs are thread-safe. However, if verify() and addTrustedPeerCertificate() are called
-// simultaneously in different threads, it is not deterministic whether verify() will use the
-// certificate being added.
-class RpcCertificateVerifierSimple : public RpcCertificateVerifier {
-public:
-    status_t verify(const SSL*, uint8_t*) override;
-
-    // Add a trusted peer certificate. Peers presenting this certificate are accepted.
-    //
-    // Caller must ensure that RpcTransportCtx::newTransport() are called after all trusted peer
-    // certificates are added. Otherwise, RpcTransport-s created before may not trust peer
-    // certificates added later.
-    [[nodiscard]] status_t addTrustedPeerCertificate(RpcCertificateFormat format,
-                                                     const std::vector<uint8_t>& cert);
-
-private:
-    std::mutex mMutex; // for below
-    std::vector<bssl::UniquePtr<X509>> mTrustedPeerCertificates;
-};
-
-} // namespace android
diff --git a/libs/binder/tests/RpcAuthTesting.cpp b/libs/binder/tests/RpcTlsTestUtils.cpp
similarity index 72%
rename from libs/binder/tests/RpcAuthTesting.cpp
rename to libs/binder/tests/RpcTlsTestUtils.cpp
index c0587a2..6119313 100644
--- a/libs/binder/tests/RpcAuthTesting.cpp
+++ b/libs/binder/tests/RpcTlsTestUtils.cpp
@@ -13,7 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include "RpcAuthTesting.h"
+
+#define LOG_TAG "RpcTlsTestUtils"
+#include <log/log.h>
+
+#include <binder/RpcTlsTestUtils.h>
+
+#include <binder/RpcTlsUtils.h>
+
 #include "../Utils.h" // for TEST_AND_RETURN
 
 namespace android {
@@ -80,4 +87,32 @@
     return OK;
 }
 
+status_t RpcCertificateVerifierSimple::verify(const SSL* ssl, uint8_t* outAlert) {
+    const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
+    bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
+    LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
+                        "%s: libssl should not ask to verify non-existing cert", logPrefix);
+
+    std::lock_guard<std::mutex> lock(mMutex);
+    for (const auto& trustedCert : mTrustedPeerCertificates) {
+        if (0 == X509_cmp(trustedCert.get(), peerCert.get())) {
+            return OK;
+        }
+    }
+    *outAlert = SSL_AD_CERTIFICATE_UNKNOWN;
+    return PERMISSION_DENIED;
+}
+
+status_t RpcCertificateVerifierSimple::addTrustedPeerCertificate(RpcCertificateFormat format,
+                                                                 const std::vector<uint8_t>& cert) {
+    bssl::UniquePtr<X509> x509 = deserializeCertificate(cert, format);
+    if (x509 == nullptr) {
+        ALOGE("Certificate is not in the proper format %s", PrintToString(format).c_str());
+        return BAD_VALUE;
+    }
+    std::lock_guard<std::mutex> lock(mMutex);
+    mTrustedPeerCertificates.push_back(std::move(x509));
+    return OK;
+}
+
 } // namespace android
diff --git a/libs/binder/tests/RpcTlsUtilsTest.cpp b/libs/binder/tests/RpcTlsUtilsTest.cpp
index 9b3078d..530606c 100644
--- a/libs/binder/tests/RpcTlsUtilsTest.cpp
+++ b/libs/binder/tests/RpcTlsUtilsTest.cpp
@@ -14,11 +14,10 @@
  * limitations under the License.
  */
 
+#include <binder/RpcTlsTestUtils.h>
 #include <binder/RpcTlsUtils.h>
 #include <gtest/gtest.h>
 
-#include "RpcAuthTesting.h"
-
 namespace android {
 
 std::string toDebugString(EVP_PKEY* pkey) {
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 0477d50..f8718aa 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -25,6 +25,7 @@
 #include <binder/RpcCertificateVerifier.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
 #include <binder/RpcTlsUtils.h>
 #include <binder/RpcTransportRaw.h>
 #include <binder/RpcTransportTls.h>
@@ -37,8 +38,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "RpcAuthTesting.h"
-
 using android::BBinder;
 using android::defaultServiceManager;
 using android::IBinder;
@@ -50,6 +49,7 @@
 using android::RpcAuthPreSigned;
 using android::RpcCertificateFormat;
 using android::RpcCertificateVerifier;
+using android::RpcCertificateVerifierNoOp;
 using android::RpcServer;
 using android::RpcSession;
 using android::RpcTransportCtxFactory;
@@ -90,25 +90,20 @@
         Transport::RPC_TLS,
 };
 
-// Certificate validation happens during handshake and does not affect the result of benchmarks.
-// Skip certificate validation to simplify the setup process.
-class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
-public:
-    status_t verify(const SSL*, uint8_t*) override { return OK; }
-};
-
 std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
     auto pkey = android::makeKeyPairForSelfSignedCert();
     CHECK_NE(pkey.get(), nullptr);
     auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
     CHECK_NE(cert.get(), nullptr);
 
-    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
+    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(OK);
     auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
     return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
 }
 
 static sp<RpcSession> gSession = RpcSession::make();
+// Certificate validation happens during handshake and does not affect the result of benchmarks.
+// Skip certificate validation to simplify the setup process.
 static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
 #ifdef __BIONIC__
 static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index ed477d6..a1058bc 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -31,6 +31,7 @@
 #include <binder/ProcessState.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
 #include <binder/RpcTlsUtils.h>
 #include <binder/RpcTransport.h>
 #include <binder/RpcTransportRaw.h>
@@ -51,8 +52,6 @@
 #include "../RpcSocketAddress.h" // for testing preconnected clients
 #include "../RpcState.h"         // for debugging
 #include "../vm_sockets.h"       // for VMADDR_*
-#include "RpcAuthTesting.h"
-#include "RpcCertificateVerifierSimple.h"
 
 using namespace std::chrono_literals;
 using namespace std::placeholders;
diff --git a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
new file mode 100644
index 0000000..094addd
--- /dev/null
+++ b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
@@ -0,0 +1,90 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <mutex>
+
+#include <binder/RpcAuth.h>
+#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcCertificateVerifier.h>
+#include <binder/RpcTransport.h>
+#include <openssl/ssl.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+constexpr const uint32_t kCertValidSeconds = 30 * (60 * 60 * 24); // 30 days
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert();
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pKey, uint32_t validSeconds);
+
+// An implementation of RpcAuth that generates a key pair and a self-signed
+// certificate every time configure() is called.
+class RpcAuthSelfSigned : public RpcAuth {
+public:
+    RpcAuthSelfSigned(uint32_t validSeconds = kCertValidSeconds) : mValidSeconds(validSeconds) {}
+    status_t configure(SSL_CTX* ctx) override;
+
+private:
+    const uint32_t mValidSeconds;
+};
+
+class RpcAuthPreSigned : public RpcAuth {
+public:
+    RpcAuthPreSigned(bssl::UniquePtr<EVP_PKEY> pkey, bssl::UniquePtr<X509> cert)
+          : mPkey(std::move(pkey)), mCert(std::move(cert)) {}
+    status_t configure(SSL_CTX* ctx) override;
+
+private:
+    bssl::UniquePtr<EVP_PKEY> mPkey;
+    bssl::UniquePtr<X509> mCert;
+};
+
+// A simple certificate verifier for testing.
+// Keep a list of leaf certificates as trusted. No certificate chain support.
+//
+// All APIs are thread-safe. However, if verify() and addTrustedPeerCertificate() are called
+// simultaneously in different threads, it is not deterministic whether verify() will use the
+// certificate being added.
+class RpcCertificateVerifierSimple : public RpcCertificateVerifier {
+public:
+    status_t verify(const SSL*, uint8_t*) override;
+
+    // Add a trusted peer certificate. Peers presenting this certificate are accepted.
+    //
+    // Caller must ensure that RpcTransportCtx::newTransport() are called after all trusted peer
+    // certificates are added. Otherwise, RpcTransport-s created before may not trust peer
+    // certificates added later.
+    [[nodiscard]] status_t addTrustedPeerCertificate(RpcCertificateFormat format,
+                                                     const std::vector<uint8_t>& cert);
+
+private:
+    std::mutex mMutex; // for below
+    std::vector<bssl::UniquePtr<X509>> mTrustedPeerCertificates;
+};
+
+// A RpcCertificateVerifier that does not verify anything.
+class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
+public:
+    RpcCertificateVerifierNoOp(status_t status) : mStatus(status) {}
+    status_t verify(const SSL*, uint8_t*) override { return mStatus; }
+
+private:
+    status_t mStatus;
+};
+
+} // namespace android
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index be55eba..c0f0a12 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -19,12 +19,19 @@
     srcs: [
         "main.cpp",
     ],
+    // Not using libbinder_tls_shared_deps to use deterministic boringssl libraries.
     static_libs: [
         "libbase",
         "libcutils",
         "liblog",
+        "libbinder_tls_static",
+        "libbinder_tls_test_utils",
+        "libssl_fuzz_unsafe",
+        "libcrypto_fuzz_unsafe",
     ],
-
+    cflags: [
+        "-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE" // for RAND_reset_for_fuzzing
+    ],
     target: {
         android: {
             shared_libs: [
@@ -39,4 +46,8 @@
             ],
         },
     },
+    data: [
+        "server.crt",
+        "server.key",
+    ],
 }
diff --git a/libs/binder/tests/rpc_fuzzer/create_certs.sh b/libs/binder/tests/rpc_fuzzer/create_certs.sh
new file mode 100755
index 0000000..4ae4cb1
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/create_certs.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# As explained in
+#  https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca
+
+openssl genrsa -des3 -passout pass:xxxx -out server.pass.key 2048
+openssl rsa -passin pass:xxxx -in server.pass.key -out server.key
+rm -f server.pass.key
+
+openssl req \
+    -subj "/" \
+    -new -key server.key -out server.csr
+
+openssl x509 -req -sha256 -days 99999 -in server.csr -signkey server.key -out server.crt
+rm -f server.csr
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index c848798..518849a 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -13,13 +13,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <binder/Binder.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
-#include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
+#include <binder/RpcTransport.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
 #include <fuzzer/FuzzedDataProvider.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
 
 #include <sys/resource.h>
 #include <sys/un.h>
@@ -51,13 +58,66 @@
     }
 };
 
+int passwordCallback(char* buf, int size, int /*rwflag*/, void* /*u*/) {
+    constexpr const char pass[] = "xxxx"; // See create_certs.sh
+    if (size <= 0) return 0;
+    int numCopy = std::min<int>(size, sizeof(pass));
+    (void)memcpy(buf, pass, numCopy);
+    return numCopy;
+}
+
+struct ServerAuth {
+    bssl::UniquePtr<EVP_PKEY> pkey;
+    bssl::UniquePtr<X509> cert;
+};
+
+// Use pre-configured keys because runtime generated keys / certificates are not
+// deterministic, and the algorithm is time consuming.
+ServerAuth readServerKeyAndCert() {
+    ServerAuth ret;
+
+    auto keyPath = android::base::GetExecutableDirectory() + "/data/server.key";
+    bssl::UniquePtr<BIO> keyBio(BIO_new_file(keyPath.c_str(), "r"));
+    ret.pkey.reset(PEM_read_bio_PrivateKey(keyBio.get(), nullptr, passwordCallback, nullptr));
+    CHECK_NE(ret.pkey.get(), nullptr);
+
+    auto certPath = android::base::GetExecutableDirectory() + "/data/server.crt";
+    bssl::UniquePtr<BIO> certBio(BIO_new_file(certPath.c_str(), "r"));
+    ret.cert.reset(PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
+    CHECK_NE(ret.cert.get(), nullptr);
+
+    return ret;
+}
+
+std::unique_ptr<RpcAuth> createServerRpcAuth() {
+    static auto sAuth = readServerKeyAndCert();
+
+    CHECK(EVP_PKEY_up_ref(sAuth.pkey.get()));
+    bssl::UniquePtr<EVP_PKEY> pkey(sAuth.pkey.get());
+    CHECK(X509_up_ref(sAuth.cert.get()));
+    bssl::UniquePtr<X509> cert(sAuth.cert.get());
+
+    return std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
+}
+
+std::unique_ptr<RpcTransportCtxFactory> makeTransportCtxFactory(FuzzedDataProvider* provider) {
+    bool isTls = provider->ConsumeBool();
+    if (!isTls) {
+        return RpcTransportCtxFactoryRaw::make();
+    }
+    status_t verifyStatus = provider->ConsumeIntegral<status_t>();
+    auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(verifyStatus);
+    return RpcTransportCtxFactoryTls::make(verifier, createServerRpcAuth());
+}
+
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
     if (size > 50000) return 0;
     FuzzedDataProvider provider(data, size);
+    RAND_reset_for_fuzzing();
 
     unlink(kSock.c_str());
 
-    sp<RpcServer> server = RpcServer::make();
+    sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
     server->setRootObject(sp<SomeBinder>::make());
     server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
     CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
diff --git a/libs/binder/tests/rpc_fuzzer/server.crt b/libs/binder/tests/rpc_fuzzer/server.crt
new file mode 100644
index 0000000..9142474
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICiTCCAXECFG1ggXE36l2WXeG6YTnaRVB7EmgQMA0GCSqGSIb3DQEBCwUAMAAw
+IBcNMjEwOTI5MDEzOTEzWhgPMjI5NTA3MTQwMTM5MTNaMAAwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDE3KnhPMwINpP5aIHIo/3GTlROZOK5AmkEsWmP
+w8smSWo2hJ7M0sOhruvOz82WORj48K8C0W72yFN+e9g32qoNMJFP/s6j1RWmaAKZ
+eSQUq6ixyaGhFLBOoukVykfTnY4qn4RbX5HzgpAPR1gv5ELvMXXPrxvtpIcVIrhm
+/dBQIa3iHZS6kypNbmRx/nhDVU8FK9s9WU5VLpbuNxv+m4X4Y1M/VZNatUMx5I0o
+ystV4JTqzjRZRPR4sxtMhu8/A11JsBVLeu8ZM/0IGCjmLOF4hy5a5YDv8MOJtdG2
+LI7ibZNtyrZiKwwhJc3tElzeIFit4T5Xjx69y/EMS4Hwhf3zAgMBAAEwDQYJKoZI
+hvcNAQELBQADggEBAD3gRbUybW7P2CihMyskTgS9HoIT9c02JWjtueWQIiQkyqTB
+6QdUQTHM5weil6TiW8NfpQQUIvrh66Pkph65shvFqxUsjdW25b4RbfUldFihfs1n
+kTa+e+hZONnVuzLvezIs2b8dygH9GA5y2OiLxwrMUcyaoCHGwKF7iOE0SJhfx0kY
+JDs4O+gAVjEsBSc24pm9aHBxgRCiEm1I4+RZf6PRBIz1ZadGBFsCZ+Gj6wyLP2Wq
+kjjMiV6o8pEjJjM+Oi4GfxvNewMCd2hMZYuJYpYC3cc7fPIpx8luidqKJdve8c6m
+KQ+dJ6ZQxEi0Zc9Jzre7NNoVcpIdc8SbkEM/DDo=
+-----END CERTIFICATE-----
diff --git a/libs/binder/tests/rpc_fuzzer/server.key b/libs/binder/tests/rpc_fuzzer/server.key
new file mode 100644
index 0000000..743470e
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAxNyp4TzMCDaT+WiByKP9xk5UTmTiuQJpBLFpj8PLJklqNoSe
+zNLDoa7rzs/NljkY+PCvAtFu9shTfnvYN9qqDTCRT/7Oo9UVpmgCmXkkFKuoscmh
+oRSwTqLpFcpH052OKp+EW1+R84KQD0dYL+RC7zF1z68b7aSHFSK4Zv3QUCGt4h2U
+upMqTW5kcf54Q1VPBSvbPVlOVS6W7jcb/puF+GNTP1WTWrVDMeSNKMrLVeCU6s40
+WUT0eLMbTIbvPwNdSbAVS3rvGTP9CBgo5izheIcuWuWA7/DDibXRtiyO4m2Tbcq2
+YisMISXN7RJc3iBYreE+V48evcvxDEuB8IX98wIDAQABAoIBACcI5jp+NqrOP6st
+uMZTFifzMi5VPMuYmcBPeXIDTc3qsr/ari5JAHeX2rQoakiGS9hYySsS4iDW+g9T
+eT0iA6QX5Ehrawf7YY6cgx9xcOEUZJ/ULlNlacw961/huzpPvHfhJ3qCycryMaSF
+7guZBFivgv/KZgxKGmrrdosdeufYXL3eHWZIrvcN4cDVgxslZg0o3Y5kCW3/KmDO
+QwvBlqgja93yImmkFA5BA/hQUsWuMBiR0xAd4b1NSBVCGTAYuCm6Up+6tIxeBSu5
+MVnNXbAIyVkbAS+gaR4uut6ObzFwUyGKDMaMpJ0LHLbusZy0svevu6Hjx+eH0ePC
+rj1xmDECgYEA4WR+1m3Tej0botG68+pZ8yLBgomSBAqpINCFkMEGQ2sQ1CqMMkHq
+8LAQNotU56W/0/H3eQemE3qBSKt1BUffpCvCHWkL9DRyDNhiq9U2PvV2Lx0Bv77e
+ET5MSDECUjlIsDqnv2qbq/m23BiP7AM8c9s6HjD0PqptyHjLlWHK86kCgYEA35hW
+AZEqMzsTNVQ8lXQtbqCyv8lls1SJbvIf3b5KItw9CwqpLr+UXssXh713j+yMW+WN
+3nv5+VaggkNBa9fHdqQEYT0L52OnLNjsfTlVhP5g2lOIa5VQYb/wqF1TaiZ27SGU
+lmLqiyArZgTnc3yo1wuIRPAbYbbm6CVnz7bm5jsCgYEAqfov7WZF5hnPjaq9YtWJ
+oGLFrLwy8flYMvcOw2vOXWmQ93Be6kfr9jfRAlFxZoEJeb0w9IVgKbBpb3Ree+0I
+K7cUXTmrWi9zE1zcjNnuXuyehElL2F8I+dgRjx/msDujJcQWXbT4UWmxDas4XrTS
+Ek1yNvKUP+4nfNgcMDvf4oECgYEAjgfYajpqEgzukKunqFAaI/HUWdt2zMlgW6dV
+8qdTtH0uEXt+KIHtn6FmmwURk8zxA9b3nWInUeljIBvUzMpOm+BoH9SFYUB+CxDo
+eEsZNdfYchcpyx0X6F/iYTCXMhCo7syr9DN1RVbz+mQXGdcP8ToUH6Zd3l4uozxP
+izRly80CgYEAqz7fCgQH74BwHoroSNdD3Cn6KNVx+oPuwRmzO4xMSOGyd/dNB2NA
+uzzuCTbrzC0jCXpqR0Bh9gYMjxyRZbifPX/YuFHyCIKK4+SQfeC4ZEwmSJVGWeh7
+3NksFJPCH4K3KbLNputByWJWOgKUdy70e/xOi83acBAVyRs+7H9LocE=
+-----END RSA PRIVATE KEY-----
diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
index 6f054d2..8ea948c 100644
--- a/libs/binder/tests/unit_fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -30,16 +30,28 @@
         "-Wall",
         "-Werror",
     ],
-    shared_libs: [
-        "libbinder",
-        "libutils",
-        "libbase",
-    ],
     target: {
+        android: {
+            shared_libs: [
+                "libcutils",
+                "libutils",
+                "libbase",
+                "libbinder",
+            ],
+        },
+        host: {
+            static_libs: [
+                "libcutils",
+                "liblog",
+                "libutils",
+                "libbase",
+                "libbinder",
+            ],
+        },
         darwin: {
             enabled: false,
-        }
-    }
+        },
+    },
 }
 
 cc_fuzz {