Merge "libbinder: support BR_ONEWAY_SPAM_SUSPECT"
diff --git a/.clang-format b/.clang-format
index 03af56d..6725a1f 100644
--- a/.clang-format
+++ b/.clang-format
@@ -11,3 +11,4 @@
 IndentWidth: 4
 PenaltyBreakBeforeFirstCallParameter: 100000
 SpacesBeforeTrailingComments: 1
+IncludeBlocks: Preserve
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index f48f1fb..aff32c3 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -99,6 +99,7 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libbinderdebug",
     ],
     srcs: [
         "DumpstateService.cpp",
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 039dbc5..b8df99f 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -793,6 +793,9 @@
     if (module_metadata_version != 0) {
         printf("Module Metadata version: %" PRId64 "\n", module_metadata_version);
     }
+    printf("SDK extension versions [r=%s s=%s]\n",
+           android::base::GetProperty("build.version.extensions.r", "-").c_str(),
+           android::base::GetProperty("build.version.extensions.s", "-").c_str());
 
     printf("Kernel: ");
     DumpFileToFd(STDOUT_FILENO, "", "/proc/version");
@@ -2174,13 +2177,13 @@
     }
 
     /*
-     * mount debugfs for non-user builds with ro.product.enforce_debugfs_restrictions
+     * mount debugfs for non-user builds with ro.product.debugfs_restrictions.enabled
      * set to true and unmount it after invoking dumpstateBoard_* methods.
      * This is to enable debug builds to not have debugfs mounted during runtime.
      * It will also ensure that debugfs is only accessed by the dumpstate HAL.
      */
     auto mount_debugfs =
-        android::base::GetBoolProperty("ro.product.enforce_debugfs_restrictions", false);
+        android::base::GetBoolProperty("ro.product.debugfs_restrictions.enabled", false);
     if (mount_debugfs) {
         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
                    AS_ROOT_20);
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index 91aa018..6ab6b7f 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -32,6 +32,7 @@
         "libutils",
         "liblog",
         "libbinder",
+        "libbinderdebug",
     ],
 
     static_libs: [
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index a017246..ba1c449 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -25,6 +25,7 @@
 #include <binder/Parcel.h>
 #include <binder/ProcessState.h>
 #include <binder/TextOutput.h>
+#include <binderdebug/BinderDebug.h>
 #include <serviceutils/PriorityDumper.h>
 #include <utils/Log.h>
 #include <utils/Vector.h>
@@ -60,13 +61,15 @@
             "usage: dumpsys\n"
             "         To dump all services.\n"
             "or:\n"
-            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--pid] [--help | -l | --skip SERVICES "
+            "       dumpsys [-t TIMEOUT] [--priority LEVEL] [--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"
             "         --pid: dump PID instead of usual dump\n"
+            "         --thread: dump thread usage 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"
@@ -125,7 +128,8 @@
     Type type = Type::DUMP;
     int timeoutArgMs = 10000;
     int priorityFlags = IServiceManager::DUMP_FLAG_PRIORITY_ALL;
-    static struct option longOptions[] = {{"pid", no_argument, 0, 0},
+    static struct option longOptions[] = {{"thread", no_argument, 0, 0},
+                                          {"pid", no_argument, 0, 0},
                                           {"priority", required_argument, 0, 0},
                                           {"proto", no_argument, 0, 0},
                                           {"skip", no_argument, 0, 0},
@@ -163,6 +167,8 @@
                 }
             } else if (!strcmp(longOptions[optionIndex].name, "pid")) {
                 type = Type::PID;
+            } else if (!strcmp(longOptions[optionIndex].name, "thread")) {
+                type = Type::THREAD;
             }
             break;
 
@@ -329,6 +335,23 @@
      return OK;
 }
 
+static status_t dumpThreadsToFd(const sp<IBinder>& service, const unique_fd& fd) {
+    pid_t pid;
+    status_t status = service->getDebugPid(&pid);
+    if (status != OK) {
+        return status;
+    }
+    BinderPidInfo pidInfo;
+    status = getBinderPidInfo(BinderDebugContext::BINDER, pid, &pidInfo);
+    if (status != OK) {
+        return status;
+    }
+    WriteStringToFd("Threads in use: " + std::to_string(pidInfo.threadUsage) + "/" +
+                        std::to_string(pidInfo.threadCount) + "\n",
+                    fd.get());
+    return OK;
+}
+
 status_t Dumpsys::startDumpThread(Type type, const String16& serviceName,
                                   const Vector<String16>& args) {
     sp<IBinder> service = sm_->checkService(serviceName);
@@ -359,6 +382,9 @@
         case Type::PID:
             err = dumpPidToFd(service, remote_end);
             break;
+        case Type::THREAD:
+            err = dumpThreadsToFd(service, remote_end);
+            break;
         default:
             std::cerr << "Unknown dump type" << static_cast<int>(type) << std::endl;
             return;
diff --git a/cmds/dumpsys/dumpsys.h b/cmds/dumpsys/dumpsys.h
index 929c55c..349947c 100644
--- a/cmds/dumpsys/dumpsys.h
+++ b/cmds/dumpsys/dumpsys.h
@@ -52,13 +52,14 @@
     static void setServiceArgs(Vector<String16>& args, bool asProto, int priorityFlags);
 
     enum class Type {
-        DUMP,  // dump using `dump` function
-        PID,   // dump pid of server only
+        DUMP,    // dump using `dump` function
+        PID,     // dump pid of server only
+        THREAD,  // dump thread usage of server only
     };
 
     /**
      * Starts a thread to connect to a service and get its dump output. The thread redirects
-     * the output to a pipe. Thread must be stopped by a subsequent callto {@code
+     * the output to a pipe. Thread must be stopped by a subsequent call to {@code
      * stopDumpThread}.
      * @param serviceName
      * @param args list of arguments to pass to service dump method.
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index 6854c75..58fec30 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -19,6 +19,7 @@
         "libbase",
         "libbinder",
         "libutils",
+        "libbinderdebug",
     ],
 
     static_libs: [
@@ -26,6 +27,4 @@
         "libgmock",
         "libserviceutils",
     ],
-
-    clang: true,
 }
diff --git a/cmds/dumpsys/tests/AndroidTest.xml b/cmds/dumpsys/tests/AndroidTest.xml
index 1a8c67f..c2351d9 100644
--- a/cmds/dumpsys/tests/AndroidTest.xml
+++ b/cmds/dumpsys/tests/AndroidTest.xml
@@ -23,4 +23,4 @@
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="dumpsys_test" />
     </test>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/cmds/dumpsys/tests/dumpsys_test.cpp b/cmds/dumpsys/tests/dumpsys_test.cpp
index 67a77f6..39af7df 100644
--- a/cmds/dumpsys/tests/dumpsys_test.cpp
+++ b/cmds/dumpsys/tests/dumpsys_test.cpp
@@ -16,12 +16,15 @@
 
 #include "../dumpsys.h"
 
+#include <regex>
 #include <vector>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
 #include <android-base/file.h>
+#include <binder/Binder.h>
+#include <binder/ProcessState.h>
 #include <serviceutils/PriorityDumper.h>
 #include <utils/String16.h>
 #include <utils/String8.h>
@@ -222,6 +225,10 @@
         EXPECT_THAT(stdout_, HasSubstr(expected));
     }
 
+    void AssertOutputFormat(const std::string format) {
+        EXPECT_THAT(stdout_, testing::MatchesRegex(format));
+    }
+
     void AssertDumped(const std::string& service, const std::string& dump) {
         EXPECT_THAT(stdout_, HasSubstr("DUMP OF SERVICE " + service + ":\n" + dump));
         EXPECT_THAT(stdout_, HasSubstr("was the duration of dumpsys " + service + ", ending at: "));
@@ -574,6 +581,30 @@
     AssertOutput(std::to_string(getpid()) + "\n");
 }
 
+// Tests 'dumpsys --thread'
+TEST_F(DumpsysTest, ListAllServicesWithThread) {
+    ExpectListServices({"Locksmith", "Valet"});
+    ExpectCheckService("Locksmith");
+    ExpectCheckService("Valet");
+
+    CallMain({"--thread"});
+
+    AssertRunningServices({"Locksmith", "Valet"});
+
+    const std::string format("(.|\n)*((Threads in use: [0-9]+/[0-9]+)?\n-(.|\n)*){2}");
+    AssertOutputFormat(format);
+}
+
+// Tests 'dumpsys --thread service_name'
+TEST_F(DumpsysTest, ListServiceWithThread) {
+    ExpectCheckService("Locksmith");
+
+    CallMain({"--thread", "Locksmith"});
+    // returns an empty string without root enabled
+    const std::string format("(^$|Threads in use: [0-9]/[0-9]+\n)");
+    AssertOutputFormat(format);
+}
+
 TEST_F(DumpsysTest, GetBytesWritten) {
     const char* serviceName = "service2";
     const char* dumpContents = "dump1";
@@ -599,3 +630,13 @@
                         /* as_proto = */ false, elapsedDuration, bytesWritten);
     EXPECT_THAT(status, Eq(INVALID_OPERATION));
 }
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    // start a binder thread pool for testing --thread option
+    android::ProcessState::self()->setThreadPoolMaxThreadCount(8);
+    ProcessState::self()->startThreadPool();
+
+    return RUN_ALL_TESTS();
+}
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index 3a87776..83f01de 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -179,6 +179,11 @@
     // want it for product APKs. Same notes as vendor above.
     TryExtraMount("product", arg[2], "/postinstall/product");
 
+    // Try to mount the system_ext partition. update_engine doesn't do this for
+    // us, but we want it for system_ext APKs. Same notes as vendor and product
+    // above.
+    TryExtraMount("system_ext", arg[2], "/postinstall/system_ext");
+
     constexpr const char* kPostInstallLinkerconfig = "/postinstall/linkerconfig";
     // Try to mount /postinstall/linkerconfig. we will set it up after performing the chroot
     if (mount("tmpfs", kPostInstallLinkerconfig, "tmpfs", 0, nullptr) != 0) {
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index d5110f6..2722e21 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -417,7 +417,7 @@
         }
     }
     out << "-->" << std::endl;
-    out << vintf::gHalManifestConverter(manifest, vintf::SerializeFlags::HALS_ONLY);
+    out << vintf::toXml(manifest, vintf::SerializeFlags::HALS_ONLY);
 }
 
 std::string ListCommand::INIT_VINTF_NOTES{
diff --git a/cmds/lshal/test.cpp b/cmds/lshal/test.cpp
index 7c1ca91..6f08f74 100644
--- a/cmds/lshal/test.cpp
+++ b/cmds/lshal/test.cpp
@@ -47,8 +47,6 @@
 using ::android::hardware::Void;
 using android::vintf::Arch;
 using android::vintf::CompatibilityMatrix;
-using android::vintf::gCompatibilityMatrixConverter;
-using android::vintf::gHalManifestConverter;
 using android::vintf::HalManifest;
 using android::vintf::Transport;
 using android::vintf::VintfObject;
@@ -510,7 +508,7 @@
 
     std::string error;
     vintf::HalManifest m;
-    EXPECT_EQ(true, vintf::gHalManifestConverter(&m, out.str(), &error))
+    EXPECT_EQ(true, vintf::fromXml(&m, out.str(), &error))
         << "--init-vintf does not emit valid HAL manifest: " << error;
 }
 
@@ -775,10 +773,10 @@
     auto deviceMatrix = std::make_shared<CompatibilityMatrix>();
     auto frameworkMatrix = std::make_shared<CompatibilityMatrix>();
 
-    ASSERT_TRUE(gHalManifestConverter(deviceManifest.get(), deviceManifestXml));
-    ASSERT_TRUE(gHalManifestConverter(frameworkManifest.get(), frameworkManifestXml));
-    ASSERT_TRUE(gCompatibilityMatrixConverter(deviceMatrix.get(), deviceMatrixXml));
-    ASSERT_TRUE(gCompatibilityMatrixConverter(frameworkMatrix.get(), frameworkMatrixXml));
+    ASSERT_TRUE(fromXml(deviceManifest.get(), deviceManifestXml));
+    ASSERT_TRUE(fromXml(frameworkManifest.get(), frameworkManifestXml));
+    ASSERT_TRUE(fromXml(deviceMatrix.get(), deviceMatrixXml));
+    ASSERT_TRUE(fromXml(frameworkMatrix.get(), frameworkMatrixXml));
 
     ON_CALL(*mockList, getDeviceManifest()).WillByDefault(Return(deviceManifest));
     ON_CALL(*mockList, getDeviceMatrix()).WillByDefault(Return(deviceMatrix));
@@ -964,7 +962,7 @@
                 "    </hal>\n"
                 "</manifest>";
         auto manifest = std::make_shared<HalManifest>();
-        EXPECT_TRUE(gHalManifestConverter(manifest.get(), mockManifestXml));
+        EXPECT_TRUE(fromXml(manifest.get(), mockManifestXml));
         EXPECT_CALL(*mockList, getDeviceManifest())
             .Times(AnyNumber())
             .WillRepeatedly(Return(manifest));
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 79fa6ba..cba8207 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -60,10 +60,6 @@
 // Currently, these are only on system android (not vendor, not host)
 // TODO(b/183654927) - move these into separate libraries
 libbinder_device_interface_sources = [
-    "AppOpsManager.cpp",
-    "IAppOpsCallback.cpp",
-    "IAppOpsService.cpp",
-
     "IPermissionController.cpp",
     "PermissionCache.cpp",
     "PermissionController.cpp",
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 1bf3d88..1388a80 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -18,6 +18,16 @@
 
 #include <binder/RpcConnection.h>
 
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include <string_view>
+
 #include <binder/Parcel.h>
 #include <binder/Stability.h>
 #include <utils/String8.h>
@@ -25,11 +35,6 @@
 #include "RpcState.h"
 #include "RpcWireFormat.h"
 
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
 #ifdef __GLIBC__
 extern "C" pid_t gettid();
 #endif
@@ -41,6 +46,7 @@
 namespace android {
 
 using base::unique_fd;
+using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
 
 RpcConnection::SocketAddress::~SocketAddress() {}
 
@@ -51,6 +57,10 @@
 }
 RpcConnection::~RpcConnection() {
     LOG_RPC_DETAIL("RpcConnection destroyed %p", this);
+
+    std::lock_guard<std::mutex> _l(mSocketMutex);
+    LOG_ALWAYS_FATAL_IF(mServers.size() != 0,
+                        "Should not be able to destroy a connection with servers in use.");
 }
 
 sp<RpcConnection> RpcConnection::make() {
@@ -61,7 +71,8 @@
 public:
     explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
         unsigned int pathLen = strlen(path) + 1;
-        LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path);
+        LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "Socket path is too long: %u %s",
+                            pathLen, path);
         memcpy(mAddr.sun_path, path, pathLen);
     }
     virtual ~UnixSocketAddress() {}
@@ -78,11 +89,11 @@
 };
 
 bool RpcConnection::setupUnixDomainServer(const char* path) {
-    return addServer(UnixSocketAddress(path));
+    return setupSocketServer(UnixSocketAddress(path));
 }
 
 bool RpcConnection::addUnixDomainClient(const char* path) {
-    return addClient(UnixSocketAddress(path));
+    return addSocketClient(UnixSocketAddress(path));
 }
 
 #ifdef __BIONIC__
@@ -97,7 +108,7 @@
             }) {}
     virtual ~VsockSocketAddress() {}
     std::string toString() const override {
-        return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str();
+        return String8::format("cid %u port %u", mAddr.svm_cid, mAddr.svm_port).c_str();
     }
     const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
     size_t addrSize() const override { return sizeof(mAddr); }
@@ -110,15 +121,91 @@
     // realizing value w/ this type at compile time to avoid ubsan abort
     constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
 
-    return addServer(VsockSocketAddress(kAnyCid, port));
+    return setupSocketServer(VsockSocketAddress(kAnyCid, port));
 }
 
 bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) {
-    return addClient(VsockSocketAddress(cid, port));
+    return addSocketClient(VsockSocketAddress(cid, port));
 }
 
 #endif // __BIONIC__
 
+class SocketAddressImpl : public RpcConnection::SocketAddress {
+public:
+    SocketAddressImpl(const sockaddr* addr, size_t size, const String8& desc)
+          : mAddr(addr), mSize(size), mDesc(desc) {}
+    [[nodiscard]] std::string toString() const override {
+        return std::string(mDesc.c_str(), mDesc.size());
+    }
+    [[nodiscard]] const sockaddr* addr() const override { return mAddr; }
+    [[nodiscard]] size_t addrSize() const override { return mSize; }
+    void set(const sockaddr* addr, size_t size) {
+        mAddr = addr;
+        mSize = size;
+    }
+
+private:
+    const sockaddr* mAddr = nullptr;
+    size_t mSize = 0;
+    String8 mDesc;
+};
+
+AddrInfo GetAddrInfo(const char* addr, unsigned int port) {
+    addrinfo hint{
+            .ai_flags = 0,
+            .ai_family = AF_UNSPEC,
+            .ai_socktype = SOCK_STREAM,
+            .ai_protocol = 0,
+    };
+    addrinfo* aiStart = nullptr;
+    if (int rc = getaddrinfo(addr, std::to_string(port).data(), &hint, &aiStart); 0 != rc) {
+        ALOGE("Unable to resolve %s:%u: %s", addr, port, gai_strerror(rc));
+        return AddrInfo(nullptr, nullptr);
+    }
+    if (aiStart == nullptr) {
+        ALOGE("Unable to resolve %s:%u: getaddrinfo returns null", addr, port);
+        return AddrInfo(nullptr, nullptr);
+    }
+    return AddrInfo(aiStart, &freeaddrinfo);
+}
+
+bool RpcConnection::setupInetServer(unsigned int port) {
+    auto aiStart = GetAddrInfo("127.0.0.1", port);
+    if (aiStart == nullptr) return false;
+    SocketAddressImpl socketAddress(nullptr, 0, String8::format("127.0.0.1:%u", port));
+    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+        socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+        if (setupSocketServer(socketAddress)) return true;
+    }
+    ALOGE("None of the socket address resolved for 127.0.0.1:%u can be set up as inet server.",
+          port);
+    return false;
+}
+
+bool RpcConnection::addInetClient(const char* addr, unsigned int port) {
+    auto aiStart = GetAddrInfo(addr, port);
+    if (aiStart == nullptr) return false;
+    SocketAddressImpl socketAddress(nullptr, 0, String8::format("%s:%u", addr, port));
+    for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
+        socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+        if (addSocketClient(socketAddress)) return true;
+    }
+    ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
+    return false;
+}
+
+bool RpcConnection::addNullDebuggingClient() {
+    unique_fd serverFd(TEMP_FAILURE_RETRY(open("/dev/null", O_WRONLY | O_CLOEXEC)));
+
+    if (serverFd == -1) {
+        ALOGE("Could not connect to /dev/null: %s", strerror(errno));
+        return false;
+    }
+
+    addClient(std::move(serverFd));
+    return true;
+}
+
 sp<IBinder> RpcConnection::getRootObject() {
     ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT);
     return state()->getRootObject(socket.fd(), sp<RpcConnection>::fromExisting(this));
@@ -139,36 +226,35 @@
 }
 
 void RpcConnection::join() {
-    // establish a connection
-    {
-        unique_fd clientFd(
-                TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
-        if (clientFd < 0) {
-            // If this log becomes confusing, should save more state from setupUnixDomainServer
-            // in order to output here.
-            ALOGE("Could not accept4 socket: %s", strerror(errno));
-            return;
-        }
-
-        LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
-
-        assignServerToThisThread(std::move(clientFd));
+    // TODO(b/185167543): do this dynamically, instead of from a static number
+    // of threads
+    unique_fd clientFd(
+            TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
+    if (clientFd < 0) {
+        // If this log becomes confusing, should save more state from setupUnixDomainServer
+        // in order to output here.
+        ALOGE("Could not accept4 socket: %s", strerror(errno));
+        return;
     }
 
-    // We may not use the connection we just established (two threads might
-    // establish connections for each other), but for now, just use one
-    // server/socket connection.
-    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::SERVER);
+    LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
+
+    // must be registered to allow arbitrary client code executing commands to
+    // be able to do nested calls (we can't only read from it)
+    sp<ConnectionSocket> socket = assignServerToThisThread(std::move(clientFd));
 
     while (true) {
         status_t error =
-                state()->getAndExecuteCommand(socket.fd(), sp<RpcConnection>::fromExisting(this));
+                state()->getAndExecuteCommand(socket->fd, sp<RpcConnection>::fromExisting(this));
 
         if (error != OK) {
             ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
-            return;
+            break;
         }
     }
+
+    LOG_ALWAYS_FATAL_IF(!removeServerSocket(socket),
+                        "bad state: socket object guaranteed to be in list");
 }
 
 void RpcConnection::setForServer(const wp<RpcServer>& server) {
@@ -179,7 +265,7 @@
     return mForServer;
 }
 
-bool RpcConnection::addServer(const SocketAddress& addr) {
+bool RpcConnection::setupSocketServer(const SocketAddress& addr) {
     LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server.");
 
     unique_fd serverFd(
@@ -205,7 +291,7 @@
     return true;
 }
 
-bool RpcConnection::addClient(const SocketAddress& addr) {
+bool RpcConnection::addSocketClient(const SocketAddress& addr) {
     unique_fd serverFd(
             TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
     if (serverFd == -1) {
@@ -222,18 +308,34 @@
 
     LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
 
-    std::lock_guard<std::mutex> _l(mSocketMutex);
-    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
-    connection->fd = std::move(serverFd);
-    mClients.push_back(connection);
+    addClient(std::move(serverFd));
     return true;
 }
 
-void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
+void RpcConnection::addClient(unique_fd&& fd) {
     std::lock_guard<std::mutex> _l(mSocketMutex);
     sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
     connection->fd = std::move(fd);
+    mClients.push_back(connection);
+}
+
+sp<RpcConnection::ConnectionSocket> RpcConnection::assignServerToThisThread(unique_fd&& fd) {
+    std::lock_guard<std::mutex> _l(mSocketMutex);
+    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
+    connection->fd = std::move(fd);
+    connection->exclusiveTid = gettid();
     mServers.push_back(connection);
+
+    return connection;
+}
+
+bool RpcConnection::removeServerSocket(const sp<ConnectionSocket>& socket) {
+    std::lock_guard<std::mutex> _l(mSocketMutex);
+    if (auto it = std::find(mServers.begin(), mServers.end(), socket); it != mServers.end()) {
+        mServers.erase(it);
+        return true;
+    }
+    return false;
 }
 
 RpcConnection::ExclusiveSocket::ExclusiveSocket(const sp<RpcConnection>& connection, SocketUse use)
@@ -248,37 +350,31 @@
 
         // CHECK FOR DEDICATED CLIENT SOCKET
         //
-        // A server/looper should always use a dedicated connection.
-        if (use != SocketUse::SERVER) {
-            findSocket(tid, &exclusive, &available, mConnection->mClients,
-                       mConnection->mClientsOffset);
+        // A server/looper should always use a dedicated connection if available
+        findSocket(tid, &exclusive, &available, mConnection->mClients, mConnection->mClientsOffset);
 
-            // WARNING: this assumes a server cannot request its client to send
-            // a transaction, as mServers is excluded below.
-            //
-            // Imagine we have more than one thread in play, and a single thread
-            // sends a synchronous, then an asynchronous command. Imagine the
-            // asynchronous command is sent on the first client socket. Then, if
-            // we naively send a synchronous command to that same socket, the
-            // thread on the far side might be busy processing the asynchronous
-            // command. So, we move to considering the second available thread
-            // for subsequent calls.
-            if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
-                mConnection->mClientsOffset =
-                        (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
-            }
+        // WARNING: this assumes a server cannot request its client to send
+        // a transaction, as mServers is excluded below.
+        //
+        // Imagine we have more than one thread in play, and a single thread
+        // sends a synchronous, then an asynchronous command. Imagine the
+        // asynchronous command is sent on the first client socket. Then, if
+        // we naively send a synchronous command to that same socket, the
+        // thread on the far side might be busy processing the asynchronous
+        // command. So, we move to considering the second available thread
+        // for subsequent calls.
+        if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
+            mConnection->mClientsOffset =
+                    (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
         }
 
-        // USE SERVING SOCKET (to start serving or for nested transaction)
+        // USE SERVING SOCKET (for nested transaction)
         //
         // asynchronous calls cannot be nested
         if (use != SocketUse::CLIENT_ASYNC) {
-            // servers should start serving on an available thread only
-            // otherwise, this should only be a nested call
-            bool useAvailable = use == SocketUse::SERVER;
-
-            findSocket(tid, &exclusive, (useAvailable ? &available : nullptr),
-                       mConnection->mServers, 0 /* index hint */);
+            // server sockets are always assigned to a thread
+            findSocket(tid, &exclusive, nullptr /*available*/, mConnection->mServers,
+                       0 /* index hint */);
         }
 
         // if our thread is already using a connection, prioritize using that
@@ -292,8 +388,6 @@
             break;
         }
 
-        LOG_ALWAYS_FATAL_IF(use == SocketUse::SERVER, "Must create connection to join one.");
-
         // in regular binder, this would usually be a deadlock :)
         LOG_ALWAYS_FATAL_IF(mConnection->mClients.size() == 0,
                             "Not a client of any connection. You must create a connection to an "
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 755ff35..d934136 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -40,7 +40,7 @@
         // We need to be able to send instructions over the socket for how to
         // connect to a different server, and we also need to let the host
         // process know that this is happening.
-        ALOGE("Canot send binder from unrelated binder RPC connection.");
+        ALOGE("Cannot send binder from unrelated binder RPC connection.");
         return INVALID_OPERATION;
     }
 
@@ -498,19 +498,20 @@
         }
     }
 
-    Parcel data;
-    // transaction->data is owned by this function. Parcel borrows this data and
-    // only holds onto it for the duration of this function call. Parcel will be
-    // deleted before the 'transactionData' object.
-    data.ipcSetDataReference(transaction->data,
-                             transactionData.size() - offsetof(RpcWireTransaction, data),
-                             nullptr /*object*/, 0 /*objectCount*/, do_nothing_to_transact_data);
-    data.markForRpc(connection);
-
     Parcel reply;
     reply.markForRpc(connection);
 
     if (replyStatus == OK) {
+        Parcel data;
+        // transaction->data is owned by this function. Parcel borrows this data and
+        // only holds onto it for the duration of this function call. Parcel will be
+        // deleted before the 'transactionData' object.
+        data.ipcSetDataReference(transaction->data,
+                                 transactionData.size() - offsetof(RpcWireTransaction, data),
+                                 nullptr /*object*/, 0 /*objectCount*/,
+                                 do_nothing_to_transact_data);
+        data.markForRpc(connection);
+
         if (target) {
             replyStatus = target->transact(transaction->code, data, &reply, transaction->flags);
         } else {
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 211790d..9578372 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -101,6 +101,10 @@
     // is for an RPC transaction).
     void markForBinder(const sp<IBinder>& binder);
 
+    // Whenever possible, markForBinder should be preferred. This method is
+    // called automatically on reply Parcels for RPC transactions.
+    void markForRpc(const sp<RpcConnection>& connection);
+
     // Whether this Parcel is written for RPC transactions (after calls to
     // markForBinder or markForRpc).
     bool isForRpc() const;
@@ -536,10 +540,6 @@
                                             const binder_size_t* objects, size_t objectsCount,
                                             release_func relFunc);
 
-    // Whenever possible, markForBinder should be preferred. This method is
-    // called automatically on reply Parcels for RPC transactions.
-    void markForRpc(const sp<RpcConnection>& connection);
-
     status_t            finishWrite(size_t len);
     void                releaseObjects();
     void                acquireObjects();
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index efa922d..2395e78 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -74,6 +74,25 @@
 #endif // __BIONIC__
 
     /**
+     * Creates an RPC server at the current port.
+     */
+    [[nodiscard]] bool setupInetServer(unsigned int port);
+
+    /**
+     * Connects to an RPC server at the given address and port.
+     */
+    [[nodiscard]] bool addInetClient(const char* addr, unsigned int port);
+
+    /**
+     * For debugging!
+     *
+     * Sets up an empty socket. All queries to this socket which require a
+     * response will never be satisfied. All data sent here will be
+     * unceremoniously cast down the bottomless pit, /dev/null.
+     */
+    [[nodiscard]] bool addNullDebuggingClient();
+
+    /**
      * Query the other side of the connection for the root object hosted by that
      * process's RpcServer (if one exists)
      */
@@ -109,10 +128,6 @@
     friend sp<RpcConnection>;
     RpcConnection();
 
-    bool addServer(const SocketAddress& address);
-    bool addClient(const SocketAddress& address);
-    void assignServerToThisThread(base::unique_fd&& fd);
-
     struct ConnectionSocket : public RefBase {
         base::unique_fd fd;
 
@@ -121,11 +136,16 @@
         std::optional<pid_t> exclusiveTid;
     };
 
+    bool setupSocketServer(const SocketAddress& address);
+    bool addSocketClient(const SocketAddress& address);
+    void addClient(base::unique_fd&& fd);
+    sp<ConnectionSocket> assignServerToThisThread(base::unique_fd&& fd);
+    bool removeServerSocket(const sp<ConnectionSocket>& socket);
+
     enum class SocketUse {
         CLIENT,
         CLIENT_ASYNC,
         CLIENT_REFCOUNT,
-        SERVER,
     };
 
     // RAII object for connection socket
diff --git a/libs/binder/include/binder/Status.h b/libs/binder/include/binder/Status.h
index c30ae01..aaafa36 100644
--- a/libs/binder/include/binder/Status.h
+++ b/libs/binder/include/binder/Status.h
@@ -91,6 +91,9 @@
     static Status fromExceptionCode(int32_t exceptionCode,
                                     const char* message);
 
+    // warning: this is still considered an error if it is constructed with a
+    // zero value error code. Please use Status::ok() instead and avoid zero
+    // error codes
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
     static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
                                            const String8& message);
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index b9adc9a..9e2050b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -173,7 +173,7 @@
  * Available since API level 29.
  *
  * \param interfaceDescriptor this is a unique identifier for the class. This is used internally for
- * sanity checks on transactions.
+ * validity checks on transactions. This should be utf-8.
  * \param onCreate see AIBinder_Class_onCreate.
  * \param onDestroy see AIBinder_Class_onDestroy.
  * \param onTransact see AIBinder_Class_onTransact.
@@ -645,7 +645,9 @@
  *
  * \return the class descriptor string. This pointer will never be null; a
  * descriptor is required to define a class. The pointer is owned by the class
- * and will remain valid as long as the class does.
+ * and will remain valid as long as the class does. For a local class, this will
+ * be the same value (not necessarily pointer equal) as is passed into
+ * AIBinder_Class_define. Format is utf-8.
  */
 const char* AIBinder_Class_getDescriptor(const AIBinder_Class* clazz) __INTRODUCED_IN(31);
 
@@ -669,7 +671,7 @@
  *
  * \return whether "lhs < rhs" is true
  */
-bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs);
+bool AIBinder_lt(const AIBinder* lhs, const AIBinder* rhs) __INTRODUCED_IN(31);
 
 /**
  * Clone an AIBinder_Weak. Useful because even if a weak binder promotes to a
@@ -683,7 +685,7 @@
  * \return clone of the input parameter. This must be deleted with
  * AIBinder_Weak_delete. Null if weak input parameter is also null.
  */
-AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak);
+AIBinder_Weak* AIBinder_Weak_clone(const AIBinder_Weak* weak) __INTRODUCED_IN(31);
 
 /**
  * Whether AIBinder_Weak is less than another.
@@ -718,7 +720,7 @@
  *
  * \return whether "lhs < rhs" is true
  */
-bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs);
+bool AIBinder_Weak_lt(const AIBinder_Weak* lhs, const AIBinder_Weak* rhs) __INTRODUCED_IN(31);
 
 __END_DECLS
 
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index e12a429..57c9013 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -65,15 +65,15 @@
         // rustified
         "--constified-enum", "android::c_interface::consts::.*",
 
-        "--whitelist-type", "android::c_interface::.*",
-        "--whitelist-type", "AStatus",
-        "--whitelist-type", "AIBinder_Class",
-        "--whitelist-type", "AIBinder",
-        "--whitelist-type", "AIBinder_Weak",
-        "--whitelist-type", "AIBinder_DeathRecipient",
-        "--whitelist-type", "AParcel",
-        "--whitelist-type", "binder_status_t",
-        "--whitelist-function", ".*",
+        "--allowlist-type", "android::c_interface::.*",
+        "--allowlist-type", "AStatus",
+        "--allowlist-type", "AIBinder_Class",
+        "--allowlist-type", "AIBinder",
+        "--allowlist-type", "AIBinder_Weak",
+        "--allowlist-type", "AIBinder_DeathRecipient",
+        "--allowlist-type", "AParcel",
+        "--allowlist-type", "binder_status_t",
+        "--allowlist-function", ".*",
     ],
     shared_libs: [
         "libbinder_ndk",
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 0bf76c6..607860f 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -114,8 +114,8 @@
     source_stem: "bindings",
     cpp_std: "gnu++17",
     bindgen_flags: [
-        "--whitelist-type", "Transaction",
-        "--whitelist-var", "TESTDATA_.*",
+        "--allowlist-type", "Transaction",
+        "--allowlist-var", "TESTDATA_.*",
     ],
 
     shared_libs: [
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index afc4b1b..f303b7c 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -151,6 +151,27 @@
     require_root: true,
 }
 
+cc_benchmark {
+    name: "binderRpcBenchmark",
+    defaults: ["binder_test_defaults"],
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
+    srcs: [
+        "binderRpcBenchmark.cpp",
+        "IBinderRpcBenchmark.aidl",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
+
 cc_test {
     name: "binderThroughputTest",
     defaults: ["binder_test_defaults"],
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/IBinderRpcBenchmark.aidl
similarity index 69%
copy from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
copy to libs/binder/tests/IBinderRpcBenchmark.aidl
index b92a6a9..1457422 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/IBinderRpcBenchmark.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -14,11 +14,7 @@
  * limitations under the License.
  */
 
-#pragma once
-
-#include <binder/Parcel.h>
-#include <fuzzer/FuzzedDataProvider.h>
-
-namespace android {
-void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
-} // namespace android
+interface IBinderRpcBenchmark {
+    @utf8InCpp String repeatString(@utf8InCpp String str);
+    IBinder repeatBinder(IBinder binder);
+}
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
new file mode 100644
index 0000000..7c82226
--- /dev/null
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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 <BnBinderRpcBenchmark.h>
+#include <android-base/logging.h>
+#include <benchmark/benchmark.h>
+#include <binder/Binder.h>
+#include <binder/RpcConnection.h>
+#include <binder/RpcServer.h>
+
+#include <thread>
+
+#include <sys/types.h>
+#include <unistd.h>
+
+using android::BBinder;
+using android::IBinder;
+using android::interface_cast;
+using android::OK;
+using android::RpcConnection;
+using android::RpcServer;
+using android::sp;
+using android::binder::Status;
+
+class MyBinderRpcBenchmark : public BnBinderRpcBenchmark {
+    Status repeatString(const std::string& str, std::string* out) override {
+        *out = str;
+        return Status::ok();
+    }
+    Status repeatBinder(const sp<IBinder>& str, sp<IBinder>* out) override {
+        *out = str;
+        return Status::ok();
+    }
+};
+
+static sp<RpcConnection> gConnection = RpcConnection::make();
+
+void BM_getRootObject(benchmark::State& state) {
+    while (state.KeepRunning()) {
+        CHECK(gConnection->getRootObject() != nullptr);
+    }
+}
+BENCHMARK(BM_getRootObject);
+
+void BM_pingTransaction(benchmark::State& state) {
+    sp<IBinder> binder = gConnection->getRootObject();
+    CHECK(binder != nullptr);
+
+    while (state.KeepRunning()) {
+        CHECK_EQ(OK, binder->pingBinder());
+    }
+}
+BENCHMARK(BM_pingTransaction);
+
+void BM_repeatString(benchmark::State& state) {
+    sp<IBinder> binder = gConnection->getRootObject();
+    CHECK(binder != nullptr);
+    sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+    CHECK(iface != nullptr);
+
+    // Googlers might see go/another-look-at-aidl-hidl-perf
+    //
+    // When I checked in July 2019, 99.5% of AIDL transactions and 99.99% of HIDL
+    // transactions were less than one page in size (system wide during a test
+    // involving media and camera). This is why this diverges from
+    // binderThroughputTest and hwbinderThroughputTest. Future consideration - get
+    // this data on continuous integration. Here we are testing sending a
+    // transaction of twice this size. In other cases, we should focus on
+    // benchmarks of particular usecases. If individual binder transactions like
+    // the ones tested here are fast, then Android performance will be dominated
+    // by how many binder calls work together (and by factors like the scheduler,
+    // thermal throttling, core choice, etc..).
+    std::string str = std::string(getpagesize() * 2, 'a');
+    CHECK_EQ(str.size(), getpagesize() * 2);
+
+    while (state.KeepRunning()) {
+        std::string out;
+        Status ret = iface->repeatString(str, &out);
+        CHECK(ret.isOk()) << ret;
+    }
+}
+BENCHMARK(BM_repeatString);
+
+void BM_repeatBinder(benchmark::State& state) {
+    sp<IBinder> binder = gConnection->getRootObject();
+    CHECK(binder != nullptr);
+    sp<IBinderRpcBenchmark> iface = interface_cast<IBinderRpcBenchmark>(binder);
+    CHECK(iface != nullptr);
+
+    while (state.KeepRunning()) {
+        // force creation of a new address
+        sp<IBinder> binder = sp<BBinder>::make();
+
+        sp<IBinder> out;
+        Status ret = iface->repeatBinder(binder, &out);
+        CHECK(ret.isOk()) << ret;
+    }
+}
+BENCHMARK(BM_repeatBinder);
+
+int main(int argc, char** argv) {
+    ::benchmark::Initialize(&argc, argv);
+    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+
+    std::string addr = std::string(getenv("TMPDIR") ?: "/tmp") + "/binderRpcBenchmark";
+    (void)unlink(addr.c_str());
+
+    std::thread([addr]() {
+        sp<RpcServer> server = RpcServer::make();
+        server->setRootObject(sp<MyBinderRpcBenchmark>::make());
+
+        server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
+
+        sp<RpcConnection> connection = server->addClientConnection();
+        CHECK(connection->setupUnixDomainServer(addr.c_str()));
+
+        connection->join();
+    }).detach();
+
+    for (size_t tries = 0; tries < 5; tries++) {
+        usleep(10000);
+        if (gConnection->addUnixDomainClient(addr.c_str())) goto success;
+    }
+    LOG(FATAL) << "Could not connect.";
+success:
+
+    ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index a51c987..ec4ced2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -199,13 +199,8 @@
 
 static std::string allocateSocketAddress() {
     static size_t id = 0;
-    static bool gUseTmp = access("/tmp/", F_OK) != -1;
-
-    if (gUseTmp) {
-        return "/tmp/binderRpcTest_" + std::to_string(id++);
-    } else {
-        return "/dev/binderRpcTest_" + std::to_string(id++);
-    }
+    std::string temp = getenv("TMPDIR") ?: "/tmp";
+    return temp + "/binderRpcTest_" + std::to_string(id++);
 };
 
 struct ProcessConnection {
@@ -262,6 +257,7 @@
 #ifdef __BIONIC__
     VSOCK,
 #endif // __BIONIC__
+    INET,
 };
 static inline std::string PrintSocketType(const testing::TestParamInfo<SocketType>& info) {
     switch (info.param) {
@@ -271,6 +267,8 @@
         case SocketType::VSOCK:
             return "vm_socket";
 #endif // __BIONIC__
+        case SocketType::INET:
+            return "inet_socket";
         default:
             LOG_ALWAYS_FATAL("Unknown socket type");
             return "";
@@ -310,6 +308,9 @@
                             CHECK(connection->setupVsockServer(port));
                             break;
 #endif // __BIONIC__
+                        case SocketType::INET:
+                            CHECK(connection->setupInetServer(port));
+                            break;
                         default:
                             LOG_ALWAYS_FATAL("Unknown socket type");
                     }
@@ -340,6 +341,9 @@
                         if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
                         break;
 #endif // __BIONIC__
+                    case SocketType::INET:
+                        if (ret.connection->addInetClient("127.0.0.1", port)) goto success;
+                        break;
                     default:
                         LOG_ALWAYS_FATAL("Unknown socket type");
                 }
@@ -857,12 +861,13 @@
 }
 
 INSTANTIATE_TEST_CASE_P(PerSocket, BinderRpc,
-                        ::testing::Values(SocketType::UNIX
+                        ::testing::ValuesIn({
+                                SocketType::UNIX,
 #ifdef __BIONIC__
-                                          ,
-                                          SocketType::VSOCK
+                                SocketType::VSOCK,
 #endif // __BIONIC__
-                                          ),
+                                SocketType::INET,
+                        }),
                         PrintSocketType);
 
 } // namespace android
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/tests/parcel_fuzzer/Android.bp
similarity index 100%
rename from libs/binder/parcel_fuzzer/Android.bp
rename to libs/binder/tests/parcel_fuzzer/Android.bp
diff --git a/libs/binder/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.cpp
rename to libs/binder/tests/parcel_fuzzer/binder.cpp
diff --git a/libs/binder/parcel_fuzzer/binder.h b/libs/binder/tests/parcel_fuzzer/binder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder.h
rename to libs/binder/tests/parcel_fuzzer/binder.h
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.cpp b/libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/binder_ndk.cpp
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.cpp
diff --git a/libs/binder/parcel_fuzzer/binder_ndk.h b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
similarity index 97%
rename from libs/binder/parcel_fuzzer/binder_ndk.h
rename to libs/binder/tests/parcel_fuzzer/binder_ndk.h
index e69d9c1..cf24ab9 100644
--- a/libs/binder/parcel_fuzzer/binder_ndk.h
+++ b/libs/binder/tests/parcel_fuzzer/binder_ndk.h
@@ -23,7 +23,7 @@
 
 // libbinder_ndk doesn't export this header which breaks down its API for NDK
 // and APEX users, but we need access to it to fuzz.
-#include "../ndk/parcel_internal.h"
+#include "../../ndk/parcel_internal.h"
 
 class NdkParcelAdapter {
 public:
diff --git a/libs/binder/parcel_fuzzer/hwbinder.cpp b/libs/binder/tests/parcel_fuzzer/hwbinder.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.cpp
rename to libs/binder/tests/parcel_fuzzer/hwbinder.cpp
diff --git a/libs/binder/parcel_fuzzer/hwbinder.h b/libs/binder/tests/parcel_fuzzer/hwbinder.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/hwbinder.h
rename to libs/binder/tests/parcel_fuzzer/hwbinder.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_fd.h
diff --git a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
similarity index 80%
rename from libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
rename to libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
index b92a6a9..749bf21 100644
--- a/libs/binder/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
+++ b/libs/binder/tests/parcel_fuzzer/include_random_parcel/fuzzbinder/random_parcel.h
@@ -20,5 +20,12 @@
 #include <fuzzer/FuzzedDataProvider.h>
 
 namespace android {
+/**
+ * Fill parcel data, including some random binder objects and FDs
+ */
 void fillRandomParcel(Parcel* p, FuzzedDataProvider&& provider);
+/**
+ * Fill parcel data, but don't fill any objects.
+ */
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider);
 } // namespace android
diff --git a/libs/binder/parcel_fuzzer/main.cpp b/libs/binder/tests/parcel_fuzzer/main.cpp
similarity index 89%
rename from libs/binder/parcel_fuzzer/main.cpp
rename to libs/binder/tests/parcel_fuzzer/main.cpp
index 78606cc..332e2ad 100644
--- a/libs/binder/parcel_fuzzer/main.cpp
+++ b/libs/binder/tests/parcel_fuzzer/main.cpp
@@ -23,6 +23,7 @@
 #include <iostream>
 
 #include <android-base/logging.h>
+#include <binder/RpcConnection.h>
 #include <fuzzbinder/random_parcel.h>
 #include <fuzzer/FuzzedDataProvider.h>
 
@@ -32,6 +33,8 @@
 #include <sys/time.h>
 
 using android::fillRandomParcel;
+using android::RpcConnection;
+using android::sp;
 
 void fillRandomParcel(::android::hardware::Parcel* p, FuzzedDataProvider&& provider) {
     // TODO: functionality to create random parcels for libhwbinder parcels
@@ -56,7 +59,18 @@
             provider.ConsumeIntegralInRange<size_t>(0, maxInstructions));
 
     P p;
-    fillRandomParcel(&p, std::move(provider));
+    if constexpr (std::is_same_v<P, android::Parcel>) {
+        if (provider.ConsumeBool()) {
+            auto connection = sp<RpcConnection>::make();
+            CHECK(connection->addNullDebuggingClient());
+            p.markForRpc(connection);
+            fillRandomParcelData(&p, std::move(provider));
+        } else {
+            fillRandomParcel(&p, std::move(provider));
+        }
+    } else {
+        fillRandomParcel(&p, std::move(provider));
+    }
 
     // since we are only using a byte to index
     CHECK(reads.size() <= 255) << reads.size();
diff --git a/libs/binder/parcel_fuzzer/parcel_fuzzer.h b/libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/parcel_fuzzer.h
rename to libs/binder/tests/parcel_fuzzer/parcel_fuzzer.h
diff --git a/libs/binder/parcel_fuzzer/random_fd.cpp b/libs/binder/tests/parcel_fuzzer/random_fd.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/random_fd.cpp
rename to libs/binder/tests/parcel_fuzzer/random_fd.cpp
diff --git a/libs/binder/parcel_fuzzer/random_parcel.cpp b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
similarity index 93%
rename from libs/binder/parcel_fuzzer/random_parcel.cpp
rename to libs/binder/tests/parcel_fuzzer/random_parcel.cpp
index 9ca4c8a..b045a22 100644
--- a/libs/binder/parcel_fuzzer/random_parcel.cpp
+++ b/libs/binder/tests/parcel_fuzzer/random_parcel.cpp
@@ -75,4 +75,9 @@
     }
 }
 
+void fillRandomParcelData(Parcel* p, FuzzedDataProvider&& provider) {
+    std::vector<uint8_t> data = provider.ConsumeBytes<uint8_t>(provider.remaining_bytes());
+    CHECK(OK == p->write(data.data(), data.size()));
+}
+
 } // namespace android
diff --git a/libs/binder/parcel_fuzzer/util.cpp b/libs/binder/tests/parcel_fuzzer/util.cpp
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.cpp
rename to libs/binder/tests/parcel_fuzzer/util.cpp
diff --git a/libs/binder/parcel_fuzzer/util.h b/libs/binder/tests/parcel_fuzzer/util.h
similarity index 100%
rename from libs/binder/parcel_fuzzer/util.h
rename to libs/binder/tests/parcel_fuzzer/util.h
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
similarity index 100%
rename from libs/binder/tests/fuzzers/Android.bp
rename to libs/binder/tests/unit_fuzzers/Android.bp
diff --git a/libs/binder/tests/fuzzers/BinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzz.cpp b/libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/BpBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/BpBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/BufferedTextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/BufferedTextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/IBinderFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/IBinderFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/IBinderFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp b/libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/MemoryDealerFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/MemoryDealerFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/PersistableBundleFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/PersistableBundleFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StabilityFuzz.cpp b/libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StabilityFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StabilityFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StabilityFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StabilityFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/StatusFuzz.cpp b/libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/StatusFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/StatusFuzzFunctions.h b/libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
similarity index 100%
rename from libs/binder/tests/fuzzers/StatusFuzzFunctions.h
rename to libs/binder/tests/unit_fuzzers/StatusFuzzFunctions.h
diff --git a/libs/binder/tests/fuzzers/TextOutputFuzz.cpp b/libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
similarity index 100%
rename from libs/binder/tests/fuzzers/TextOutputFuzz.cpp
rename to libs/binder/tests/unit_fuzzers/TextOutputFuzz.cpp
diff --git a/libs/binder/tests/fuzzers/commonFuzzHelpers.h b/libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
similarity index 100%
rename from libs/binder/tests/fuzzers/commonFuzzHelpers.h
rename to libs/binder/tests/unit_fuzzers/commonFuzzHelpers.h
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
new file mode 100644
index 0000000..dd38224
--- /dev/null
+++ b/libs/permission/Android.bp
@@ -0,0 +1,14 @@
+cc_library_shared {
+    name: "libpermission",
+    srcs: [
+        "AppOpsManager.cpp",
+        "IAppOpsCallback.cpp",
+        "IAppOpsService.cpp",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libbinder",
+        "liblog",
+        "libutils",
+    ],
+}
diff --git a/libs/binder/AppOpsManager.cpp b/libs/permission/AppOpsManager.cpp
similarity index 100%
rename from libs/binder/AppOpsManager.cpp
rename to libs/permission/AppOpsManager.cpp
diff --git a/libs/binder/IAppOpsCallback.cpp b/libs/permission/IAppOpsCallback.cpp
similarity index 100%
rename from libs/binder/IAppOpsCallback.cpp
rename to libs/permission/IAppOpsCallback.cpp
diff --git a/libs/binder/IAppOpsService.cpp b/libs/permission/IAppOpsService.cpp
similarity index 100%
rename from libs/binder/IAppOpsService.cpp
rename to libs/permission/IAppOpsService.cpp
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/permission/include/binder/AppOpsManager.h
similarity index 100%
rename from libs/binder/include/binder/AppOpsManager.h
rename to libs/permission/include/binder/AppOpsManager.h
diff --git a/libs/binder/include/binder/IAppOpsCallback.h b/libs/permission/include/binder/IAppOpsCallback.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsCallback.h
rename to libs/permission/include/binder/IAppOpsCallback.h
diff --git a/libs/binder/include/binder/IAppOpsService.h b/libs/permission/include/binder/IAppOpsService.h
similarity index 100%
rename from libs/binder/include/binder/IAppOpsService.h
rename to libs/permission/include/binder/IAppOpsService.h
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index 497c33c..edd453a 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -48,11 +48,10 @@
         "libutils",
         "liblog",
         "libhardware",
+        "libpermission",
     ],
 
     export_include_dirs: ["include"],
 
-    export_shared_lib_headers: ["libbinder", "libhardware"],
+    export_shared_lib_headers: ["libbinder", "libpermission", "libhardware"],
 }
-
-subdirs = ["tests"]
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 9aecaff..4151b45 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -54,6 +54,7 @@
         "libbinder",
         "libsensor",
         "libsensorprivacy",
+        "libpermission",
         "libprotoutil",
         "libcrypto",
         "libbase",
@@ -74,6 +75,7 @@
         "libactivitymanager_aidl",
         "libsensor",
         "libsensorprivacy",
+        "libpermission",
     ],
 }