Merge "Update BCP computation to use derive_classpath"
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index d09d3e8..18c267d 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -47,6 +47,9 @@
         "libutils",
         "server_configurable_flags",
     ],
+    static_libs: [
+        "libasync_safe",
+    ],
     export_shared_lib_headers: [
         "libbinder",
     ],
@@ -251,6 +254,7 @@
     ],
 
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libotapreoptparameters",
     ],
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 0cf50a3..204953c 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -36,6 +36,7 @@
 #include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 #include <android-base/unique_fd.h>
+#include <async_safe/log.h>
 #include <cutils/fs.h>
 #include <cutils/properties.h>
 #include <cutils/sched_policy.h>
@@ -727,7 +728,8 @@
 
         if (flock(out_fd.get(), LOCK_EX | LOCK_NB) != 0) {
             if (errno != EWOULDBLOCK) {
-                PLOG(WARNING) << "Error locking profile " << package_name;
+                async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Error locking profile %s: %d",
+                        package_name.c_str(), errno);
             }
             // This implies that the app owning this profile is running
             // (and has acquired the lock).
@@ -735,13 +737,15 @@
             // The app never acquires the lock for the reference profiles of primary apks.
             // Only dex2oat from installd will do that. Since installd is single threaded
             // we should not see this case. Nevertheless be prepared for it.
-            PLOG(WARNING) << "Failed to flock " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Failed to flock %s: %d",
+                    package_name.c_str(), errno);
             return false;
         }
 
         bool truncated = ftruncate(out_fd.get(), 0) == 0;
         if (!truncated) {
-            PLOG(WARNING) << "Could not truncate " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Could not truncate %s: %d",
+                    package_name.c_str(), errno);
         }
 
         // Copy over data.
@@ -755,7 +759,8 @@
             write(out_fd.get(), buffer, bytes);
         }
         if (flock(out_fd.get(), LOCK_UN) != 0) {
-            PLOG(WARNING) << "Error unlocking profile " << package_name;
+            async_safe_format_log(ANDROID_LOG_WARN, LOG_TAG, "Error unlocking profile %s: %d",
+                    package_name.c_str(), errno);
         }
         // Use _exit since we don't want to run the global destructors in the child.
         // b/62597429
@@ -1513,7 +1518,8 @@
 
         // Validate the path structure.
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid, uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(kSecondaryDexDexoptAnalyzerSkippedValidatePath);
         }
 
@@ -1809,7 +1815,8 @@
         drop_capabilities(uid);
 
         if (flock(out_oat.fd(), LOCK_EX | LOCK_NB) != 0) {
-            PLOG(ERROR) << "flock(" << out_oat.path() << ") failed";
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "flock(%s) failed",
+                    out_oat.path().c_str());
             _exit(DexoptReturnCodes::kFlock);
         }
 
@@ -1904,7 +1911,8 @@
         const char* volume_uuid_cstr = volume_uuid ? volume_uuid->c_str() : nullptr;
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr,
                 uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(kReconcileSecondaryDexValidationError);
         }
 
@@ -1917,7 +1925,8 @@
             case kSecondaryDexAccessIOError: _exit(kReconcileSecondaryDexAccessIOError);
             case kSecondaryDexAccessPermissionError: _exit(kReconcileSecondaryDexValidationError);
             default:
-                LOG(ERROR) << "Unexpected result from check_secondary_dex_access: " << access_check;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                        "Unexpected result from check_secondary_dex_access: %d", access_check);
                 _exit(kReconcileSecondaryDexValidationError);
         }
 
@@ -1930,7 +1939,7 @@
             std::string error_msg;
             if (!create_secondary_dex_oat_layout(
                     dex_path,isas[i], oat_dir, oat_isa_dir, oat_path, &error_msg)) {
-                LOG(ERROR) << error_msg;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG, "%s", error_msg.c_str());
                 _exit(kReconcileSecondaryDexValidationError);
             }
 
@@ -1957,7 +1966,8 @@
             result = rmdir_if_empty(oat_dir) && result;
         }
         if (!result) {
-            PLOG(ERROR) << "Failed to clean secondary dex artifacts for location " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
         }
         _exit(result ? kReconcileSecondaryDexCleanedUp : kReconcileSecondaryDexAccessIOError);
     }
@@ -2030,7 +2040,8 @@
         pipe_read.reset();
 
         if (!validate_secondary_dex_path(pkgname, dex_path, volume_uuid_cstr, uid, storage_flag)) {
-            LOG(ERROR) << "Could not validate secondary dex path " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Could not validate secondary dex path %s", dex_path.c_str());
             _exit(DexoptReturnCodes::kHashValidatePath);
         }
 
@@ -2041,6 +2052,8 @@
                 _exit(0);
             }
             PLOG(ERROR) << "Failed to open secondary dex " << dex_path;
+            async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Failed to open secondary dex %s: %d", dex_path.c_str(), errno);
             _exit(DexoptReturnCodes::kHashOpenPath);
         }
 
@@ -2053,7 +2066,8 @@
             if (bytes_read == 0) {
                 break;
             } else if (bytes_read == -1) {
-                PLOG(ERROR) << "Failed to read secondary dex " << dex_path;
+                async_safe_format_log(ANDROID_LOG_ERROR, LOG_TAG,
+                        "Failed to read secondary dex %s: %d", dex_path.c_str(), errno);
                 _exit(DexoptReturnCodes::kHashReadDex);
             }
 
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index f67ab81..7082017 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -20,6 +20,7 @@
         "libcutils",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -44,6 +45,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -84,6 +86,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
@@ -124,6 +127,7 @@
         "server_configurable_flags",
     ],
     static_libs: [
+        "libasync_safe",
         "libdiskusage",
         "libinstalld",
         "liblog",
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index b429fb3..90db509 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -481,7 +481,12 @@
           name.c_str());
 
     std::thread([=] {
-        (void)base::SetProperty("ctl.interface_start", "aidl/" + name);
+        if (!base::SetProperty("ctl.interface_start", "aidl/" + name)) {
+            LOG(INFO) << "Tried to start aidl service " << name
+                      << " as a lazy service, but was unable to. Usually this happens when a "
+                         "service is not installed, but if the service is intended to be used as a "
+                         "lazy service, then it may be configured incorrectly.";
+        }
     }).detach();
 }
 
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 6eae5ef..670fd55 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -109,5 +109,10 @@
     return granted;
 }
 
+void PermissionCache::purgeCache() {
+    PermissionCache& pc(PermissionCache::getInstance());
+    pc.purge();
+}
+
 // ---------------------------------------------------------------------------
 } // namespace android
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 1388a80..2502d1b 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -19,6 +19,7 @@
 #include <binder/RpcConnection.h>
 
 #include <arpa/inet.h>
+#include <inttypes.h>
 #include <netdb.h>
 #include <netinet/in.h>
 #include <sys/socket.h>
@@ -45,9 +46,55 @@
 
 namespace android {
 
+using base::borrowed_fd;
 using base::unique_fd;
 using AddrInfo = std::unique_ptr<addrinfo, decltype(&freeaddrinfo)>;
 
+namespace {
+bool checkSockaddrSize(const char* name, size_t actual, size_t expected) {
+    if (actual >= expected) return true;
+    ALOGW("getSockaddrPort: family is %s but size is %zu < %zu", name, actual, expected);
+    return false;
+}
+
+// Get the port number of |storage| for certain families. Requires storage->sa_family to be
+// set to a known family; otherwise, return nullopt.
+std::optional<unsigned int> getSockaddrPort(const sockaddr* storage, socklen_t len) {
+    switch (storage->sa_family) {
+        case AF_INET: {
+            if (!checkSockaddrSize("INET", len, sizeof(sockaddr_in))) return std::nullopt;
+            auto inetStorage = reinterpret_cast<const sockaddr_in*>(storage);
+            return ntohs(inetStorage->sin_port);
+        }
+        default: {
+            uint16_t family = storage->sa_family;
+            ALOGW("Don't know how to infer port for family %" PRIu16, family);
+            return std::nullopt;
+        }
+    }
+}
+
+std::optional<unsigned int> getSocketPort(borrowed_fd socketfd,
+                                          const RpcConnection::SocketAddress& socketAddress) {
+    sockaddr_storage storage{};
+    socklen_t len = sizeof(storage);
+    auto storagePtr = reinterpret_cast<sockaddr*>(&storage);
+    if (0 != getsockname(socketfd.get(), storagePtr, &len)) {
+        int savedErrno = errno;
+        ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
+              strerror(savedErrno));
+        return std::nullopt;
+    }
+
+    // getsockname does not fill in family, but getSockaddrPort() needs it.
+    if (storage.ss_family == AF_UNSPEC) {
+        storage.ss_family = socketAddress.addr()->sa_family;
+    }
+    return getSockaddrPort(storagePtr, len);
+}
+
+} // namespace
+
 RpcConnection::SocketAddress::~SocketAddress() {}
 
 RpcConnection::RpcConnection() {
@@ -130,24 +177,21 @@
 
 #endif // __BIONIC__
 
-class SocketAddressImpl : public RpcConnection::SocketAddress {
+class InetSocketAddress : public RpcConnection::SocketAddress {
 public:
-    SocketAddressImpl(const sockaddr* addr, size_t size, const String8& desc)
-          : mAddr(addr), mSize(size), mDesc(desc) {}
+    InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port)
+          : mSockAddr(sockAddr), mSize(size), mAddr(addr), mPort(port) {}
     [[nodiscard]] std::string toString() const override {
-        return std::string(mDesc.c_str(), mDesc.size());
+        return String8::format("%s:%u", mAddr, mPort).c_str();
     }
-    [[nodiscard]] const sockaddr* addr() const override { return mAddr; }
+    [[nodiscard]] const sockaddr* addr() const override { return mSockAddr; }
     [[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;
+    const sockaddr* mSockAddr;
+    size_t mSize;
+    const char* mAddr;
+    unsigned int mPort;
 };
 
 AddrInfo GetAddrInfo(const char* addr, unsigned int port) {
@@ -169,15 +213,29 @@
     return AddrInfo(aiStart, &freeaddrinfo);
 }
 
-bool RpcConnection::setupInetServer(unsigned int port) {
-    auto aiStart = GetAddrInfo("127.0.0.1", port);
+bool RpcConnection::setupInetServer(unsigned int port, unsigned int* assignedPort) {
+    const char* kAddr = "127.0.0.1";
+
+    if (assignedPort != nullptr) *assignedPort = 0;
+    auto aiStart = GetAddrInfo(kAddr, 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;
+        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
+        if (!setupSocketServer(socketAddress)) {
+            continue;
+        }
+        auto realPort = getSocketPort(mServer.get(), socketAddress);
+        LOG_ALWAYS_FATAL_IF(!realPort.has_value(), "Unable to get port number after setting up %s",
+                            socketAddress.toString().c_str());
+        LOG_ALWAYS_FATAL_IF(port != 0 && *realPort != port,
+                            "Requesting inet server on %s but it is set up on %u.",
+                            socketAddress.toString().c_str(), *realPort);
+        if (assignedPort != nullptr) {
+            *assignedPort = *realPort;
+        }
+        return true;
     }
-    ALOGE("None of the socket address resolved for 127.0.0.1:%u can be set up as inet server.",
+    ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
           port);
     return false;
 }
@@ -185,9 +243,8 @@
 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);
+        InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, addr, port);
         if (addSocketClient(socketAddress)) return true;
     }
     ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 1fa37ba..9a0be92 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -30,8 +30,6 @@
 
 namespace android {
 
-using base::unique_fd;
-
 RpcServer::RpcServer() {}
 RpcServer::~RpcServer() {}
 
@@ -48,16 +46,20 @@
 
     auto connection = RpcConnection::make();
     connection->setForServer(sp<RpcServer>::fromExisting(this));
-    mConnections.push_back(connection);
+    {
+        std::lock_guard<std::mutex> _l(mLock);
+        mConnections.push_back(connection);
+    }
     return connection;
 }
 
 void RpcServer::setRootObject(const sp<IBinder>& binder) {
-    LOG_ALWAYS_FATAL_IF(mRootObject != nullptr, "There can only be one root object");
+    std::lock_guard<std::mutex> _l(mLock);
     mRootObject = binder;
 }
 
 sp<IBinder> RpcServer::getRootObject() {
+    std::lock_guard<std::mutex> _l(mLock);
     return mRootObject;
 }
 
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index 835a3a8..21aa705 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -73,6 +73,8 @@
 
     static bool checkPermission(const String16& permission,
             pid_t pid, uid_t uid);
+
+    static void purgeCache();
 };
 
 // ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/RpcConnection.h b/libs/binder/include/binder/RpcConnection.h
index 2395e78..09aed13 100644
--- a/libs/binder/include/binder/RpcConnection.h
+++ b/libs/binder/include/binder/RpcConnection.h
@@ -74,9 +74,15 @@
 #endif // __BIONIC__
 
     /**
-     * Creates an RPC server at the current port.
+     * Creates an RPC server at the current port using IPv4.
+     *
+     * TODO(b/182914638): IPv6 support
+     *
+     * Set |port| to 0 to pick an ephemeral port; see discussion of
+     * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
+     * will be set to the picked port number, if it is not null.
      */
-    [[nodiscard]] bool setupInetServer(unsigned int port);
+    [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
 
     /**
      * Connects to an RPC server at the given address and port.
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index d29b651..a665fad 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -21,6 +21,8 @@
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
 
+#include <mutex>
+
 // WARNING: This is a feature which is still in development, and it is subject
 // to radical change. Any production use of this may subject your code to any
 // number of problems.
@@ -30,9 +32,6 @@
 /**
  * This represents a server of an interface, which may be connected to by any
  * number of clients over sockets.
- *
- * This object is not (currently) thread safe. All calls to it are expected to
- * happen at process startup.
  */
 class RpcServer final : public virtual RefBase {
 public:
@@ -51,16 +50,8 @@
     sp<RpcConnection> addClientConnection();
 
     /**
-     * Allowing a server to explicitly drop clients would be easy to add here,
-     * but it is not currently implemented, since users of this functionality
-     * could not use similar functionality if they are running under real
-     * binder.
-     */
-    // void drop(const sp<RpcConnection>& connection);
-
-    /**
      * The root object can be retrieved by any client, without any
-     * authentication.
+     * authentication. TODO(b/183988761)
      */
     void setRootObject(const sp<IBinder>& binder);
 
@@ -77,8 +68,8 @@
 
     bool mAgreedExperimental = false;
 
+    std::mutex mLock;
     sp<IBinder> mRootObject;
-
     std::vector<sp<RpcConnection>> mConnections; // per-client
 };
 
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index eb103d3..b03e24c 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -55,7 +55,9 @@
     defaults: ["libbinder_ndk_host_user"],
     host_supported: true,
 
-    llndk_stubs: "libbinder_ndk.llndk",
+    llndk: {
+        symbol_file: "libbinder_ndk.map.txt",
+    },
 
     export_include_dirs: [
         "include_cpp",
@@ -192,13 +194,3 @@
     symbol_file: "libbinder_ndk.map.txt",
     first_version: "29",
 }
-
-llndk_library {
-    name: "libbinder_ndk.llndk",
-    symbol_file: "libbinder_ndk.map.txt",
-    export_include_dirs: [
-        "include_cpp",
-        "include_ndk",
-        "include_platform",
-    ],
-}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index f303b7c..c0f7c99 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -35,6 +35,7 @@
     name: "binderDriverInterfaceTest_IPC_32",
     defaults: ["binder_test_defaults"],
     srcs: ["binderDriverInterfaceTest.cpp"],
+    header_libs: ["libbinder_headers"],
     compile_multilib: "32",
     multilib: { lib32: { suffix: "" } },
     cflags: ["-DBINDER_IPC_32BIT=1"],
@@ -49,7 +50,7 @@
             cflags: ["-DBINDER_IPC_32BIT=1"],
         },
     },
-
+    header_libs: ["libbinder_headers"],
     srcs: ["binderDriverInterfaceTest.cpp"],
     test_suites: ["device-tests", "vts"],
 }
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index dd68fdb..ce69ea2 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -17,6 +17,7 @@
 #include <BnBinderRpcSession.h>
 #include <BnBinderRpcTest.h>
 #include <aidl/IBinderRpcTest.h>
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_libbinder.h>
@@ -176,14 +177,27 @@
 };
 sp<IBinder> MyBinderRpcTest::mHeldBinder;
 
+class Pipe {
+public:
+    Pipe() { CHECK(android::base::Pipe(&mRead, &mWrite)); }
+    Pipe(Pipe&&) = default;
+    android::base::borrowed_fd readEnd() { return mRead; }
+    android::base::borrowed_fd writeEnd() { return mWrite; }
+
+private:
+    android::base::unique_fd mRead;
+    android::base::unique_fd mWrite;
+};
+
 class Process {
 public:
-    Process(const std::function<void()>& f) {
+    Process(Process&&) = default;
+    Process(const std::function<void(Pipe*)>& f) {
         if (0 == (mPid = fork())) {
             // racey: assume parent doesn't crash before this is set
             prctl(PR_SET_PDEATHSIG, SIGHUP);
 
-            f();
+            f(&mPipe);
         }
     }
     ~Process() {
@@ -191,9 +205,11 @@
             kill(mPid, SIGKILL);
         }
     }
+    Pipe* getPipe() { return &mPipe; }
 
 private:
     pid_t mPid = 0;
+    Pipe mPipe;
 };
 
 static std::string allocateSocketAddress() {
@@ -215,6 +231,7 @@
     // whether connection should be invalidated by end of run
     bool expectInvalid = false;
 
+    ProcessConnection(ProcessConnection&&) = default;
     ~ProcessConnection() {
         rootBinder = nullptr;
         EXPECT_NE(nullptr, connection);
@@ -238,6 +255,7 @@
     // pre-casted root object
     sp<IBinderRpcTest> rootIface;
 
+    BinderRpcTestProcessConnection(BinderRpcTestProcessConnection&&) = default;
     ~BinderRpcTestProcessConnection() {
         if (!proc.expectInvalid) {
             int32_t remoteBinders = 0;
@@ -286,11 +304,11 @@
 
         std::string addr = allocateSocketAddress();
         unlink(addr.c_str());
-        static unsigned int port = 3456;
-        port++;
+        static unsigned int vsockPort = 3456;
+        vsockPort++;
 
         auto ret = ProcessConnection{
-                .host = Process([&] {
+                .host = Process([&](Pipe* pipe) {
                     sp<RpcServer> server = RpcServer::make();
 
                     server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
@@ -304,12 +322,17 @@
                             break;
 #ifdef __BIONIC__
                         case SocketType::VSOCK:
-                            CHECK(connection->setupVsockServer(port));
+                            CHECK(connection->setupVsockServer(vsockPort));
                             break;
 #endif // __BIONIC__
-                        case SocketType::INET:
-                            CHECK(connection->setupInetServer(port));
+                        case SocketType::INET: {
+                            unsigned int outPort = 0;
+                            CHECK(connection->setupInetServer(0, &outPort));
+                            CHECK_NE(0, outPort);
+                            CHECK(android::base::WriteFully(pipe->writeEnd(), &outPort,
+                                                            sizeof(outPort)));
                             break;
+                        }
                         default:
                             LOG_ALWAYS_FATAL("Unknown socket type");
                     }
@@ -327,6 +350,13 @@
                 .connection = RpcConnection::make(),
         };
 
+        unsigned int inetPort = 0;
+        if (socketType == SocketType::INET) {
+            CHECK(android::base::ReadFully(ret.host.getPipe()->readEnd(), &inetPort,
+                                           sizeof(inetPort)));
+            CHECK_NE(0, inetPort);
+        }
+
         // create remainder of connections
         for (size_t i = 0; i < numThreads; i++) {
             for (size_t tries = 0; tries < 5; tries++) {
@@ -337,11 +367,12 @@
                         break;
 #ifdef __BIONIC__
                     case SocketType::VSOCK:
-                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, port)) goto success;
+                        if (ret.connection->addVsockClient(VMADDR_CID_LOCAL, vsockPort))
+                            goto success;
                         break;
 #endif // __BIONIC__
                     case SocketType::INET:
-                        if (ret.connection->addInetClient("127.0.0.1", port)) goto success;
+                        if (ret.connection->addInetClient("127.0.0.1", inetPort)) goto success;
                         break;
                     default:
                         LOG_ALWAYS_FATAL("Unknown socket type");
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 8675439..9286009 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -60,7 +60,13 @@
 
 cc_library {
     name: "libnativewindow",
-    llndk_stubs: "libnativewindow.llndk",
+    llndk: {
+        symbol_file: "libnativewindow.map.txt",
+        unversioned: true,
+        override_export_include_dirs: [
+            "include"
+        ],
+    },
     export_include_dirs: [
         "include",
         "include-private",
@@ -115,11 +121,4 @@
     },
 }
 
-llndk_library {
-    name: "libnativewindow.llndk",
-    symbol_file: "libnativewindow.map.txt",
-    unversioned: true,
-    export_include_dirs: ["include"],
-}
-
 subdirs = ["tests"]
diff --git a/opengl/Android.bp b/opengl/Android.bp
index 748f795..16ce15b 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -68,11 +68,9 @@
     name: "gl_headers",
     vendor_available: true,
     export_include_dirs: ["include"],
-}
-
-llndk_headers {
-    name: "gl_llndk_headers",
-    export_include_dirs: ["include"],
+    llndk: {
+        llndk_headers: true,
+    },
 }
 
 subdirs = [
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 3ee0faf..daaaf88 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -142,7 +142,12 @@
 cc_library_shared {
     name: "libEGL",
     defaults: ["egl_libs_defaults"],
-    llndk_stubs: "libEGL.llndk",
+    llndk: {
+        symbol_file: "libEGL.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: [
         "EGL/egl_tls.cpp",
         "EGL/egl_cache.cpp",
@@ -208,7 +213,12 @@
 cc_library_shared {
     name: "libGLESv1_CM",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv1_CM.llndk",
+    llndk: {
+        symbol_file: "libGLESv1_CM.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES_CM/gl.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv1\""],
     version_script: "libGLESv1_CM.map.txt",
@@ -220,7 +230,12 @@
 cc_library_shared {
     name: "libGLESv2",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv2.llndk",
+    llndk: {
+        symbol_file: "libGLESv2.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv2\""],
 
@@ -235,31 +250,12 @@
 cc_library_shared {
     name: "libGLESv3",
     defaults: ["gles_libs_defaults"],
-    llndk_stubs: "libGLESv3.llndk",
+    llndk: {
+        symbol_file: "libGLESv3.map.txt",
+        export_llndk_headers: ["gl_headers"],
+        // Don't export EGL/include from the LLNDK variant.
+        override_export_include_dirs: [],
+    },
     srcs: ["GLES2/gl2.cpp"],
     cflags: ["-DLOG_TAG=\"libGLESv3\""],
 }
-
-llndk_library {
-    name: "libEGL.llndk",
-    symbol_file: "libEGL.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv1_CM.llndk",
-    symbol_file: "libGLESv1_CM.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv2.llndk",
-    symbol_file: "libGLESv2.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
-    name: "libGLESv3.llndk",
-    symbol_file: "libGLESv3.map.txt",
-    export_llndk_headers: ["gl_llndk_headers"],
-}
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 67cd875..440c5b1 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -29,17 +29,14 @@
     unversioned_until: "current",
 }
 
-llndk_library {
-    name: "libvulkan.llndk",
-    symbol_file: "libvulkan.map.txt",
-    export_llndk_headers: [
-        "vulkan_headers_llndk",
-    ],
-}
-
 cc_library_shared {
     name: "libvulkan",
-    llndk_stubs: "libvulkan.llndk",
+    llndk: {
+        symbol_file: "libvulkan.map.txt",
+        export_llndk_headers: [
+            "vulkan_headers",
+        ],
+    },
     clang: true,
     sanitize: {
         misc_undefined: ["integer"],