Add libbinder_ndk systemapi support for injecting RPC binder accessors

This allows libbinder_ndk to set up client connections to binder RPC
services underneath the libbinder_ndk service manager APIs.

It requires callbacks to be added to the local process to get connection
information that the client is responsible for obtaining.
Once these callbacks are added to libbinder, any client elswhere in the
process using the service manager APIs will be able to get and use a
binder for the service in the same way they do for kernel binder
services.

Test: atest binderRpcTest vm_accessor_test
Bug: 358427181
Change-Id: I528e84bac40efe13884a68ed851ecfb14dd27daa
diff --git a/libs/binder/ndk/binder_rpc.cpp b/libs/binder/ndk/binder_rpc.cpp
new file mode 100644
index 0000000..2cc5f81
--- /dev/null
+++ b/libs/binder/ndk/binder_rpc.cpp
@@ -0,0 +1,352 @@
+/*
+ * Copyright (C) 2024 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 <android/binder_rpc.h>
+#include <arpa/inet.h>
+#include <binder/IServiceManager.h>
+#include <linux/vm_sockets.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <variant>
+
+#include "ibinder_internal.h"
+#include "status_internal.h"
+
+using ::android::defaultServiceManager;
+using ::android::IBinder;
+using ::android::IServiceManager;
+using ::android::OK;
+using ::android::sp;
+using ::android::status_t;
+using ::android::String16;
+using ::android::String8;
+using ::android::binder::Status;
+
+#define LOG_ACCESSOR_DEBUG(...)
+// #define LOG_ACCESSOR_DEBUG(...) ALOGW(__VA_ARGS__)
+
+struct ABinderRpc_ConnectionInfo {
+    std::variant<sockaddr_vm, sockaddr_un, sockaddr_in> addr;
+};
+
+struct ABinderRpc_Accessor final : public ::android::RefBase {
+    static ABinderRpc_Accessor* make(const char* instance, const sp<IBinder>& binder) {
+        LOG_ALWAYS_FATAL_IF(binder == nullptr, "ABinderRpc_Accessor requires a non-null binder");
+        status_t status = android::validateAccessor(String16(instance), binder);
+        if (status != OK) {
+            ALOGE("The given binder is not a valid IAccessor for %s. Status: %s", instance,
+                  android::statusToString(status).c_str());
+            return nullptr;
+        }
+        return new ABinderRpc_Accessor(binder);
+    }
+
+    sp<IBinder> asBinder() { return mAccessorBinder; }
+
+    ~ABinderRpc_Accessor() { LOG_ACCESSOR_DEBUG("ABinderRpc_Accessor dtor"); }
+
+   private:
+    ABinderRpc_Accessor(sp<IBinder> accessor) : mAccessorBinder(accessor) {}
+    ABinderRpc_Accessor() = delete;
+    sp<IBinder> mAccessorBinder;
+};
+
+struct ABinderRpc_AccessorProvider {
+   public:
+    static ABinderRpc_AccessorProvider* make(std::weak_ptr<android::AccessorProvider> cookie) {
+        if (cookie.expired()) {
+            ALOGE("Null AccessorProvider cookie from libbinder");
+            return nullptr;
+        }
+        return new ABinderRpc_AccessorProvider(cookie);
+    }
+    std::weak_ptr<android::AccessorProvider> mProviderCookie;
+
+   private:
+    ABinderRpc_AccessorProvider() = delete;
+
+    ABinderRpc_AccessorProvider(std::weak_ptr<android::AccessorProvider> provider)
+        : mProviderCookie(provider) {}
+};
+
+struct OnDeleteProviderHolder {
+    OnDeleteProviderHolder(void* data, ABinderRpc_AccessorProviderUserData_deleteCallback onDelete)
+        : mData(data), mOnDelete(onDelete) {}
+    ~OnDeleteProviderHolder() {
+        if (mOnDelete) {
+            mOnDelete(mData);
+        }
+    }
+    void* mData;
+    ABinderRpc_AccessorProviderUserData_deleteCallback mOnDelete;
+    // needs to be copyable for std::function, but we will never copy it
+    OnDeleteProviderHolder(const OnDeleteProviderHolder&) {
+        LOG_ALWAYS_FATAL("This object can't be copied!");
+    }
+
+   private:
+    OnDeleteProviderHolder() = delete;
+};
+
+ABinderRpc_AccessorProvider* ABinderRpc_registerAccessorProvider(
+        ABinderRpc_AccessorProvider_getAccessorCallback provider, const char** instances,
+        size_t numInstances, void* data,
+        ABinderRpc_AccessorProviderUserData_deleteCallback onDelete) {
+    if (provider == nullptr) {
+        ALOGE("Null provider passed to ABinderRpc_registerAccessorProvider");
+        return nullptr;
+    }
+    if (data && onDelete == nullptr) {
+        ALOGE("If a non-null data ptr is passed to ABinderRpc_registerAccessorProvider, then a "
+              "ABinderRpc_AccessorProviderUserData_deleteCallback must alse be passed to delete "
+              "the data object once the ABinderRpc_AccessorProvider is removed.");
+        return nullptr;
+    }
+    if (numInstances == 0 || instances == nullptr) {
+        ALOGE("No instances passed to ABinderRpc_registerAccessorProvider. numInstances: %zu",
+              numInstances);
+        return nullptr;
+    }
+    std::set<std::string> instanceStrings;
+    for (size_t i = 0; i < numInstances; i++) {
+        instanceStrings.emplace(instances[i]);
+    }
+    // call the onDelete when the last reference of this goes away (when the
+    // last reference to the generate std::function goes away).
+    std::shared_ptr<OnDeleteProviderHolder> onDeleteHolder =
+            std::make_shared<OnDeleteProviderHolder>(data, onDelete);
+    android::RpcAccessorProvider generate = [provider,
+                                             onDeleteHolder](const String16& name) -> sp<IBinder> {
+        ABinderRpc_Accessor* accessor = provider(String8(name).c_str(), onDeleteHolder->mData);
+        if (accessor == nullptr) {
+            ALOGE("The supplied ABinderRpc_AccessorProvider_getAccessorCallback returned nullptr");
+            return nullptr;
+        }
+        sp<IBinder> binder = accessor->asBinder();
+        ABinderRpc_Accessor_delete(accessor);
+        return binder;
+    };
+
+    std::weak_ptr<android::AccessorProvider> cookie =
+            android::addAccessorProvider(std::move(instanceStrings), std::move(generate));
+    return ABinderRpc_AccessorProvider::make(cookie);
+}
+
+void ABinderRpc_unregisterAccessorProvider(ABinderRpc_AccessorProvider* provider) {
+    if (provider == nullptr) {
+        LOG_ALWAYS_FATAL("Attempting to remove a null ABinderRpc_AccessorProvider");
+    }
+
+    status_t status = android::removeAccessorProvider(provider->mProviderCookie);
+    // There shouldn't be a way to get here because the caller won't have a
+    // ABinderRpc_AccessorProvider* without calling ABinderRpc_registerAccessorProvider
+    LOG_ALWAYS_FATAL_IF(status == android::BAD_VALUE, "Provider (%p) is not valid. Status: %s",
+                        provider, android::statusToString(status).c_str());
+    LOG_ALWAYS_FATAL_IF(status == android::NAME_NOT_FOUND,
+                        "Provider (%p) was already unregistered. Status: %s", provider,
+                        android::statusToString(status).c_str());
+    LOG_ALWAYS_FATAL_IF(status != OK,
+                        "Unknown error when attempting to unregister ABinderRpc_AccessorProvider "
+                        "(%p). Status: %s",
+                        provider, android::statusToString(status).c_str());
+
+    delete provider;
+}
+
+struct OnDeleteConnectionInfoHolder {
+    OnDeleteConnectionInfoHolder(void* data,
+                                 ABinderRpc_ConnectionInfoProviderUserData_delete onDelete)
+        : mData(data), mOnDelete(onDelete) {}
+    ~OnDeleteConnectionInfoHolder() {
+        if (mOnDelete) {
+            mOnDelete(mData);
+        }
+    }
+    void* mData;
+    ABinderRpc_ConnectionInfoProviderUserData_delete mOnDelete;
+    // needs to be copyable for std::function, but we will never copy it
+    OnDeleteConnectionInfoHolder(const OnDeleteConnectionInfoHolder&) {
+        LOG_ALWAYS_FATAL("This object can't be copied!");
+    }
+
+   private:
+    OnDeleteConnectionInfoHolder() = delete;
+};
+
+ABinderRpc_Accessor* ABinderRpc_Accessor_new(
+        const char* instance, ABinderRpc_ConnectionInfoProvider provider, void* data,
+        ABinderRpc_ConnectionInfoProviderUserData_delete onDelete) {
+    if (instance == nullptr) {
+        ALOGE("Instance argument must be valid when calling ABinderRpc_Accessor_new");
+        return nullptr;
+    }
+    if (data && onDelete == nullptr) {
+        ALOGE("If a non-null data ptr is passed to ABinderRpc_Accessor_new, then a "
+              "ABinderRpc_ConnectionInfoProviderUserData_delete callback must alse be passed to "
+              "delete "
+              "the data object once the ABinderRpc_Accessor is deleted.");
+        return nullptr;
+    }
+    std::shared_ptr<OnDeleteConnectionInfoHolder> onDeleteHolder =
+            std::make_shared<OnDeleteConnectionInfoHolder>(data, onDelete);
+    if (provider == nullptr) {
+        ALOGE("Can't create a new ABinderRpc_Accessor without a ABinderRpc_ConnectionInfoProvider "
+              "and it is "
+              "null");
+        return nullptr;
+    }
+    android::RpcSocketAddressProvider generate = [provider, onDeleteHolder](
+                                                         const String16& name, sockaddr* outAddr,
+                                                         size_t addrLen) -> status_t {
+        std::unique_ptr<ABinderRpc_ConnectionInfo> info(
+                provider(String8(name).c_str(), onDeleteHolder->mData));
+        if (info == nullptr) {
+            ALOGE("The supplied ABinderRpc_ConnectionInfoProvider returned nullptr");
+            return android::NAME_NOT_FOUND;
+        }
+        if (auto addr = std::get_if<sockaddr_vm>(&info->addr)) {
+            LOG_ALWAYS_FATAL_IF(addr->svm_family != AF_VSOCK,
+                                "ABinderRpc_ConnectionInfo invalid family");
+            if (addrLen < sizeof(sockaddr_vm)) {
+                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_vm),
+                      addrLen);
+                return android::BAD_VALUE;
+            }
+            LOG_ACCESSOR_DEBUG(
+                    "Connection info provider found AF_VSOCK. family %d, port %d, cid %d",
+                    addr->svm_family, addr->svm_port, addr->svm_cid);
+            *reinterpret_cast<sockaddr_vm*>(outAddr) = *addr;
+        } else if (auto addr = std::get_if<sockaddr_un>(&info->addr)) {
+            LOG_ALWAYS_FATAL_IF(addr->sun_family != AF_UNIX,
+                                "ABinderRpc_ConnectionInfo invalid family");
+            if (addrLen < sizeof(sockaddr_un)) {
+                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_un),
+                      addrLen);
+                return android::BAD_VALUE;
+            }
+            *reinterpret_cast<sockaddr_un*>(outAddr) = *addr;
+        } else if (auto addr = std::get_if<sockaddr_in>(&info->addr)) {
+            LOG_ALWAYS_FATAL_IF(addr->sin_family != AF_INET,
+                                "ABinderRpc_ConnectionInfo invalid family");
+            if (addrLen < sizeof(sockaddr_in)) {
+                ALOGE("Provided outAddr is too small! Expecting %zu, got %zu", sizeof(sockaddr_in),
+                      addrLen);
+                return android::BAD_VALUE;
+            }
+            *reinterpret_cast<sockaddr_in*>(outAddr) = *addr;
+        } else {
+            LOG_ALWAYS_FATAL(
+                    "Unsupported address family type when trying to get ARpcConnection info. A "
+                    "new variant was added to the ABinderRpc_ConnectionInfo and this needs to be "
+                    "updated.");
+        }
+        return OK;
+    };
+    sp<IBinder> accessorBinder = android::createAccessor(String16(instance), std::move(generate));
+    if (accessorBinder == nullptr) {
+        ALOGE("service manager did not get us an accessor");
+        return nullptr;
+    }
+    LOG_ACCESSOR_DEBUG("service manager found an accessor, so returning one now from _new");
+    return ABinderRpc_Accessor::make(instance, accessorBinder);
+}
+
+void ABinderRpc_Accessor_delete(ABinderRpc_Accessor* accessor) {
+    delete accessor;
+}
+
+AIBinder* ABinderRpc_Accessor_asBinder(ABinderRpc_Accessor* accessor) {
+    if (!accessor) {
+        ALOGE("ABinderRpc_Accessor argument is null.");
+        return nullptr;
+    }
+
+    sp<IBinder> binder = accessor->asBinder();
+    sp<AIBinder> aBinder = ABpBinder::lookupOrCreateFromBinder(binder);
+    AIBinder* ptr = aBinder.get();
+    if (ptr == nullptr) {
+        LOG_ALWAYS_FATAL("Failed to lookupOrCreateFromBinder");
+    }
+    ptr->incStrong(nullptr);
+    return ptr;
+}
+
+ABinderRpc_Accessor* ABinderRpc_Accessor_fromBinder(const char* instance, AIBinder* binder) {
+    if (!binder) {
+        ALOGE("binder argument is null");
+        return nullptr;
+    }
+    sp<IBinder> accessorBinder = binder->getBinder();
+    if (accessorBinder) {
+        return ABinderRpc_Accessor::make(instance, accessorBinder);
+    } else {
+        ALOGE("Attempting to get an ABinderRpc_Accessor for %s but AIBinder::getBinder returned "
+              "null",
+              instance);
+        return nullptr;
+    }
+}
+
+ABinderRpc_ConnectionInfo* ABinderRpc_ConnectionInfo_new(const sockaddr* addr, socklen_t len) {
+    if (addr == nullptr || len < 0 || static_cast<size_t>(len) < sizeof(sa_family_t)) {
+        ALOGE("Invalid arguments in Arpc_Connection_new");
+        return nullptr;
+    }
+    // socklen_t was int32_t on 32-bit and uint32_t on 64 bit.
+    size_t socklen = len < 0 || static_cast<uintmax_t>(len) > SIZE_MAX ? 0 : len;
+
+    if (addr->sa_family == AF_VSOCK) {
+        if (len != sizeof(sockaddr_vm)) {
+            ALOGE("Incorrect size of %zu for AF_VSOCK sockaddr_vm. Expecting %zu", socklen,
+                  sizeof(sockaddr_vm));
+            return nullptr;
+        }
+        sockaddr_vm vm = *reinterpret_cast<const sockaddr_vm*>(addr);
+        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_VSOCK. family %d, port %d, cid %d",
+                           vm.svm_family, vm.svm_port, vm.svm_cid);
+        return new ABinderRpc_ConnectionInfo(vm);
+    } else if (addr->sa_family == AF_UNIX) {
+        if (len != sizeof(sockaddr_un)) {
+            ALOGE("Incorrect size of %zu for AF_UNIX sockaddr_un. Expecting %zu", socklen,
+                  sizeof(sockaddr_un));
+            return nullptr;
+        }
+        sockaddr_un un = *reinterpret_cast<const sockaddr_un*>(addr);
+        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_UNIX. family %d, path %s",
+                           un.sun_family, un.sun_path);
+        return new ABinderRpc_ConnectionInfo(un);
+    } else if (addr->sa_family == AF_INET) {
+        if (len != sizeof(sockaddr_in)) {
+            ALOGE("Incorrect size of %zu for AF_INET sockaddr_in. Expecting %zu", socklen,
+                  sizeof(sockaddr_in));
+            return nullptr;
+        }
+        sockaddr_in in = *reinterpret_cast<const sockaddr_in*>(addr);
+        LOG_ACCESSOR_DEBUG("Arpc_ConnectionInfo_new found AF_INET. family %d, address %s, port %d",
+                           in.sin_family, inet_ntoa(in.sin_addr), ntohs(in.sin_port));
+        return new ABinderRpc_ConnectionInfo(in);
+    }
+
+    ALOGE("ARpc APIs only support AF_VSOCK right now but the supplied sockadder::sa_family is: %hu",
+          addr->sa_family);
+    return nullptr;
+}
+
+void ABinderRpc_ConnectionInfo_delete(ABinderRpc_ConnectionInfo* info) {
+    delete info;
+}