Support IAccessor in libbinder for RPC services

This cl sets up preconnected RPC binder for services launched with
IAccessor as a proxy.

Bug: 338541373
Test: m
Test: atest vm_accessor_test
Change-Id: Ic54732980778bc9ba8fec3395a0e98d336fea440
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 1333599..0f251d2 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -249,6 +249,25 @@
     return names;
 }
 
+static std::optional<std::string> getVintfAccessorName(const std::string& name) {
+    AidlName aname;
+    if (!AidlName::fill(name, &aname)) return std::nullopt;
+
+    std::optional<std::string> accessor;
+    forEachManifest([&](const ManifestWithDescription& mwd) {
+        mwd.manifest->forEachInstance([&](const auto& manifestInstance) {
+            if (manifestInstance.format() != vintf::HalFormat::AIDL) return true;
+            if (manifestInstance.package() != aname.package) return true;
+            if (manifestInstance.interface() != aname.iface) return true;
+            if (manifestInstance.instance() != aname.instance) return true;
+            accessor = manifestInstance.accessor();
+            return false; // break (libvintf uses opposite convention)
+        });
+        return false; // continue
+    });
+    return accessor;
+}
+
 static std::optional<ConnectionInfo> getVintfConnectionInfo(const std::string& name) {
     AidlName aname;
     if (!AidlName::fill(name, &aname)) return std::nullopt;
@@ -364,23 +383,40 @@
     }
 }
 
-Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinder) {
+Status ServiceManager::getService(const std::string& name, os::Service* outService) {
     SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
 
-    *outBinder = tryGetService(name, true);
+    *outService = tryGetService(name, true);
     // returns ok regardless of result for legacy reasons
     return Status::ok();
 }
 
-Status ServiceManager::checkService(const std::string& name, sp<IBinder>* outBinder) {
+Status ServiceManager::checkService(const std::string& name, os::Service* outService) {
     SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
 
-    *outBinder = tryGetService(name, false);
+    *outService = tryGetService(name, false);
     // returns ok regardless of result for legacy reasons
     return Status::ok();
 }
 
-sp<IBinder> ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
+os::Service ServiceManager::tryGetService(const std::string& name, bool startIfNotFound) {
+    std::optional<std::string> accessorName;
+#ifndef VENDORSERVICEMANAGER
+    accessorName = getVintfAccessorName(name);
+#endif
+    if (accessorName.has_value()) {
+        auto ctx = mAccess->getCallingContext();
+        if (!mAccess->canFind(ctx, name)) {
+            return os::Service::make<os::Service::Tag::accessor>(nullptr);
+        }
+        return os::Service::make<os::Service::Tag::accessor>(
+                tryGetBinder(*accessorName, startIfNotFound));
+    } else {
+        return os::Service::make<os::Service::Tag::binder>(tryGetBinder(name, startIfNotFound));
+    }
+}
+
+sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) {
     SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_ARG_STRING("name", name.c_str()));
 
     auto ctx = mAccess->getCallingContext();
@@ -565,8 +601,11 @@
 
     auto ctx = mAccess->getCallingContext();
 
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux");
+    // TODO(b/338541373): Implement the notification mechanism for services accessed via
+    // IAccessor.
+    std::optional<std::string> accessorName;
+    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+        return status;
     }
 
     // note - we could allow isolated apps to get notifications if we
@@ -613,8 +652,9 @@
 
     auto ctx = mAccess->getCallingContext();
 
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+    std::optional<std::string> accessorName;
+    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+        return status;
     }
 
     bool found = false;
@@ -638,8 +678,9 @@
 
     auto ctx = mAccess->getCallingContext();
 
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+    std::optional<std::string> accessorName;
+    if (auto status = canFindService(ctx, name, &accessorName); !status.isOk()) {
+        return status;
     }
 
     *outReturn = false;
@@ -662,8 +703,10 @@
 
     outReturn->clear();
 
+    std::optional<std::string> _accessorName;
     for (const std::string& instance : allInstances) {
-        if (mAccess->canFind(ctx, interface + "/" + instance)) {
+        if (auto status = canFindService(ctx, interface + "/" + instance, &_accessorName);
+            status.isOk()) {
             outReturn->push_back(instance);
         }
     }
@@ -681,8 +724,9 @@
 
     auto ctx = mAccess->getCallingContext();
 
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+    std::optional<std::string> _accessorName;
+    if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
+        return status;
     }
 
     *outReturn = std::nullopt;
@@ -706,8 +750,9 @@
 
     outReturn->clear();
 
+    std::optional<std::string> _accessorName;
     for (const std::string& name : apexUpdatableNames) {
-        if (mAccess->canFind(ctx, name)) {
+        if (auto status = canFindService(ctx, name, &_accessorName); status.isOk()) {
             outReturn->push_back(name);
         }
     }
@@ -724,8 +769,9 @@
 
     auto ctx = mAccess->getCallingContext();
 
-    if (!mAccess->canFind(ctx, name)) {
-        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied.");
+    std::optional<std::string> _accessorName;
+    if (auto status = canFindService(ctx, name, &_accessorName); !status.isOk()) {
+        return status;
     }
 
     *outReturn = std::nullopt;
@@ -1032,6 +1078,23 @@
     return Status::ok();
 }
 
+Status ServiceManager::canFindService(const Access::CallingContext& ctx, const std::string& name,
+                                      std::optional<std::string>* accessor) {
+    if (!mAccess->canFind(ctx, name)) {
+        return Status::fromExceptionCode(Status::EX_SECURITY, "SELinux denied for service.");
+    }
+#ifndef VENDORSERVICEMANAGER
+    *accessor = getVintfAccessorName(name);
+#endif
+    if (accessor->has_value()) {
+        if (!mAccess->canFind(ctx, accessor->value())) {
+            return Status::fromExceptionCode(Status::EX_SECURITY,
+                                             "SELinux denied for the accessor of the service.");
+        }
+    }
+    return Status::ok();
+}
+
 Status ServiceManager::getServiceDebugInfo(std::vector<ServiceDebugInfo>* outReturn) {
     SM_PERFETTO_TRACE_FUNC();
     if (!mAccess->canList(mAccess->getCallingContext())) {
diff --git a/cmds/servicemanager/ServiceManager.h b/cmds/servicemanager/ServiceManager.h
index 1536014..18bae68 100644
--- a/cmds/servicemanager/ServiceManager.h
+++ b/cmds/servicemanager/ServiceManager.h
@@ -44,8 +44,8 @@
     ~ServiceManager();
 
     // getService will try to start any services it cannot find
-    binder::Status getService(const std::string& name, sp<IBinder>* outBinder) override;
-    binder::Status checkService(const std::string& name, sp<IBinder>* outBinder) override;
+    binder::Status getService(const std::string& name, os::Service* outService) override;
+    binder::Status checkService(const std::string& name, os::Service* outService) override;
     binder::Status addService(const std::string& name, const sp<IBinder>& binder,
                               bool allowIsolated, int32_t dumpPriority) override;
     binder::Status listServices(int32_t dumpPriority, std::vector<std::string>* outList) override;
@@ -112,7 +112,10 @@
     // this updates the iterator to the next location
     void removeClientCallback(const wp<IBinder>& who, ClientCallbackMap::iterator* it);
 
-    sp<IBinder> tryGetService(const std::string& name, bool startIfNotFound);
+    os::Service tryGetService(const std::string& name, bool startIfNotFound);
+    sp<IBinder> tryGetBinder(const std::string& name, bool startIfNotFound);
+    binder::Status canFindService(const Access::CallingContext& ctx, const std::string& name,
+                                  std::optional<std::string>* accessor);
 
     ServiceMap mNameToService;
     ServiceCallbackMap mNameToRegistrationCallback;
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index b575053..9d22641 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -38,6 +38,7 @@
 using android::binder::Status;
 using android::os::BnServiceCallback;
 using android::os::IServiceManager;
+using android::os::Service;
 using testing::_;
 using testing::ElementsAre;
 using testing::NiceMock;
@@ -153,18 +154,18 @@
     EXPECT_TRUE(sm->addService("foo", serviceA, false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> outA;
+    Service outA;
     EXPECT_TRUE(sm->getService("foo", &outA).isOk());
-    EXPECT_EQ(serviceA, outA);
+    EXPECT_EQ(serviceA, outA.get<Service::Tag::binder>());
 
     // serviceA should be overwritten by serviceB
     sp<IBinder> serviceB = getBinder();
     EXPECT_TRUE(sm->addService("foo", serviceB, false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> outB;
+    Service outB;
     EXPECT_TRUE(sm->getService("foo", &outB).isOk());
-    EXPECT_EQ(serviceB, outB);
+    EXPECT_EQ(serviceB, outB.get<Service::Tag::binder>());
 }
 
 TEST(AddService, NoPermissions) {
@@ -186,17 +187,17 @@
     EXPECT_TRUE(sm->addService("foo", service, false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> out;
+    Service out;
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(service, out);
+    EXPECT_EQ(service, out.get<Service::Tag::binder>());
 }
 
 TEST(GetService, NonExistant) {
     auto sm = getPermissiveServiceManager();
 
-    sp<IBinder> out;
+    Service out;
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
+    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
 }
 
 TEST(GetService, NoPermissionsForGettingService) {
@@ -211,10 +212,10 @@
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> out;
+    Service out;
     // returns nullptr but has OK status for legacy compatibility
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
+    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
 }
 
 TEST(GetService, AllowedFromIsolated) {
@@ -236,9 +237,9 @@
     EXPECT_TRUE(sm->addService("foo", service, true /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> out;
+    Service out;
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(service, out.get());
+    EXPECT_EQ(service, out.get<Service::Tag::binder>());
 }
 
 TEST(GetService, NotAllowedFromIsolated) {
@@ -261,10 +262,10 @@
     EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 
-    sp<IBinder> out;
+    Service out;
     // returns nullptr but has OK status for legacy compatibility
     EXPECT_TRUE(sm->getService("foo", &out).isOk());
-    EXPECT_EQ(nullptr, out.get());
+    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
 }
 
 TEST(ListServices, NoPermissions) {
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index cdc7166..02c0fa6 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -771,11 +771,41 @@
         "aidl/android/os/IClientCallback.aidl",
         "aidl/android/os/IServiceCallback.aidl",
         "aidl/android/os/IServiceManager.aidl",
+        "aidl/android/os/Service.aidl",
         "aidl/android/os/ServiceDebugInfo.aidl",
+        ":libbinder_accessor_aidl",
     ],
     path: "aidl",
 }
 
+filegroup {
+    name: "libbinder_accessor_aidl",
+    srcs: [
+        "aidl/android/os/IAccessor.aidl",
+    ],
+    path: "aidl",
+}
+
+// TODO(b/353492849): Make this interface private to libbinder.
+aidl_interface {
+    name: "android.os.accessor",
+    srcs: [":libbinder_accessor_aidl"],
+    unstable: true,
+    backend: {
+        rust: {
+            enabled: true,
+            apex_available: [
+                "com.android.virt",
+            ],
+        },
+    },
+    visibility: [
+        ":__subpackages__",
+        "//system/tools/aidl:__subpackages__",
+        "//packages/modules/Virtualization:__subpackages__",
+    ],
+}
+
 aidl_interface {
     name: "packagemanager_aidl",
     unstable: true,
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index b0d3048..0bf3cad 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -15,6 +15,9 @@
  */
 #include "BackendUnifiedServiceManager.h"
 
+#include <android/os/IAccessor.h>
+#include <binder/RpcSession.h>
+
 #if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
 #include <android-base/properties.h>
 #endif
@@ -22,6 +25,7 @@
 namespace android {
 
 using AidlServiceManager = android::os::IServiceManager;
+using IAccessor = android::os::IAccessor;
 
 BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp<AidlServiceManager>& impl)
       : mTheRealServiceManager(impl) {}
@@ -30,13 +34,57 @@
     return mTheRealServiceManager;
 }
 binder::Status BackendUnifiedServiceManager::getService(const ::std::string& name,
-                                                        sp<IBinder>* _aidl_return) {
-    return mTheRealServiceManager->getService(name, _aidl_return);
+                                                        os::Service* _out) {
+    os::Service service;
+    binder::Status status = mTheRealServiceManager->getService(name, &service);
+    toBinderService(service, _out);
+    return status;
 }
+
 binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
-                                                          sp<IBinder>* _aidl_return) {
-    return mTheRealServiceManager->checkService(name, _aidl_return);
+                                                          os::Service* _out) {
+    os::Service service;
+    binder::Status status = mTheRealServiceManager->checkService(name, &service);
+    toBinderService(service, _out);
+    return status;
 }
+
+void BackendUnifiedServiceManager::toBinderService(const os::Service& in, os::Service* _out) {
+    switch (in.getTag()) {
+        case os::Service::Tag::binder: {
+            *_out = in;
+            break;
+        }
+        case os::Service::Tag::accessor: {
+            sp<IBinder> accessorBinder = in.get<os::Service::Tag::accessor>();
+            sp<IAccessor> accessor = interface_cast<IAccessor>(accessorBinder);
+            if (accessor == nullptr) {
+                ALOGE("Service#accessor doesn't have accessor. VM is maybe starting...");
+                *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
+                break;
+            }
+            auto request = [=] {
+                os::ParcelFileDescriptor fd;
+                binder::Status ret = accessor->addConnection(&fd);
+                if (ret.isOk()) {
+                    return base::unique_fd(fd.release());
+                } else {
+                    ALOGE("Failed to connect to RpcSession: %s", ret.toString8().c_str());
+                    return base::unique_fd(-1);
+                }
+            };
+            auto session = RpcSession::make();
+            session->setupPreconnectedClient(base::unique_fd{}, request);
+            session->setSessionSpecificRoot(accessorBinder);
+            *_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
+            break;
+        }
+        default: {
+            LOG_ALWAYS_FATAL("Unknown service type: %d", in.getTag());
+        }
+    }
+}
+
 binder::Status BackendUnifiedServiceManager::addService(const ::std::string& name,
                                                         const sp<IBinder>& service,
                                                         bool allowIsolated, int32_t dumpPriority) {
diff --git a/libs/binder/BackendUnifiedServiceManager.h b/libs/binder/BackendUnifiedServiceManager.h
index d72b5bb..4715be4 100644
--- a/libs/binder/BackendUnifiedServiceManager.h
+++ b/libs/binder/BackendUnifiedServiceManager.h
@@ -26,8 +26,8 @@
     explicit BackendUnifiedServiceManager(const sp<os::IServiceManager>& impl);
 
     sp<os::IServiceManager> getImpl();
-    binder::Status getService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
-    binder::Status checkService(const ::std::string& name, sp<IBinder>* _aidl_return) override;
+    binder::Status getService(const ::std::string& name, os::Service* out) override;
+    binder::Status checkService(const ::std::string& name, os::Service* out) override;
     binder::Status addService(const ::std::string& name, const sp<IBinder>& service,
                               bool allowIsolated, int32_t dumpPriority) override;
     binder::Status listServices(int32_t dumpPriority,
@@ -60,6 +60,7 @@
 
 private:
     sp<os::IServiceManager> mTheRealServiceManager;
+    void toBinderService(const os::Service& in, os::Service* _out);
 };
 
 sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager();
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index 17e522d..12a18f2 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -26,6 +26,7 @@
 
 #include <android-base/properties.h>
 #include <android/os/BnServiceCallback.h>
+#include <android/os/IAccessor.h>
 #include <android/os/IServiceManager.h>
 #include <binder/IPCThreadState.h>
 #include <binder/Parcel.h>
@@ -57,6 +58,8 @@
 
 using AidlServiceManager = android::os::IServiceManager;
 using android::binder::Status;
+using android::os::IAccessor;
+using android::os::Service;
 
 // libbinder's IServiceManager.h can't rely on the values generated by AIDL
 // because many places use its headers via include_dirs (meaning, without
@@ -139,7 +142,10 @@
     // When implementing ServiceManagerShim, use realGetService instead of
     // mUnifiedServiceManager->getService so that it can be overridden in ServiceManagerHostShim.
     virtual Status realGetService(const std::string& name, sp<IBinder>* _aidl_return) {
-        return mUnifiedServiceManager->getService(name, _aidl_return);
+        Service service;
+        Status status = mUnifiedServiceManager->getService(name, &service);
+        *_aidl_return = service.get<Service::Tag::binder>();
+        return status;
     }
 };
 
@@ -327,11 +333,11 @@
 
 sp<IBinder> ServiceManagerShim::checkService(const String16& name) const
 {
-    sp<IBinder> ret;
+    Service ret;
     if (!mUnifiedServiceManager->checkService(String8(name).c_str(), &ret).isOk()) {
         return nullptr;
     }
-    return ret;
+    return ret.get<Service::Tag::binder>();
 }
 
 status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 16a7f9f..21dc5c1 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -801,6 +801,10 @@
     return true;
 }
 
+void RpcSession::setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot) {
+    mSessionSpecificRootObject = sessionSpecificRoot;
+}
+
 sp<RpcSession::RpcConnection> RpcSession::assignIncomingConnectionToThisThread(
         std::unique_ptr<RpcTransport> rpcTransport) {
     RpcMutexLockGuard _l(mMutex);
diff --git a/libs/binder/aidl/android/os/IAccessor.aidl b/libs/binder/aidl/android/os/IAccessor.aidl
new file mode 100644
index 0000000..a3134a3
--- /dev/null
+++ b/libs/binder/aidl/android/os/IAccessor.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface for accessing the RPC server of a service.
+ *
+ * @hide
+ */
+interface IAccessor {
+    /**
+     * Adds a connection to the RPC server of the service managed by the IAccessor.
+     *
+     * This method can be called multiple times to establish multiple distinct
+     * connections to the same RPC server.
+     *
+     * @return A file descriptor connected to the RPC session of the service managed
+     *         by IAccessor.
+     */
+    ParcelFileDescriptor addConnection();
+
+    // TODO(b/350941051): Add API for debugging.
+}
diff --git a/libs/binder/aidl/android/os/IServiceManager.aidl b/libs/binder/aidl/android/os/IServiceManager.aidl
index 0fb1615..ac95188 100644
--- a/libs/binder/aidl/android/os/IServiceManager.aidl
+++ b/libs/binder/aidl/android/os/IServiceManager.aidl
@@ -18,6 +18,7 @@
 
 import android.os.IClientCallback;
 import android.os.IServiceCallback;
+import android.os.Service;
 import android.os.ServiceDebugInfo;
 import android.os.ConnectionInfo;
 
@@ -61,7 +62,7 @@
      * Returns null if the service does not exist.
      */
     @UnsupportedAppUsage
-    @nullable IBinder getService(@utf8InCpp String name);
+    Service getService(@utf8InCpp String name);
 
     /**
      * Retrieve an existing service called @a name from the service
@@ -69,7 +70,7 @@
      * exist.
      */
     @UnsupportedAppUsage
-    @nullable IBinder checkService(@utf8InCpp String name);
+    Service checkService(@utf8InCpp String name);
 
     /**
      * Place a new @a service called @a name into the service
diff --git a/libs/binder/aidl/android/os/Service.aidl b/libs/binder/aidl/android/os/Service.aidl
new file mode 100644
index 0000000..4c52109
--- /dev/null
+++ b/libs/binder/aidl/android/os/Service.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package android.os;
+
+/**
+ * Service is a union of different service types that can be returned
+ * by the internal {@link ServiceManager#getService(name)} API.
+ *
+ * @hide
+ */
+union Service {
+    @nullable IBinder binder;
+    @nullable IBinder accessor;
+}
\ No newline at end of file
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index 40102bb..af37bf2 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -220,6 +220,12 @@
     // internal only
     LIBBINDER_EXPORTED const std::unique_ptr<RpcState>& state() { return mRpcBinderState; }
 
+    /**
+     * Sets the session-specific root object. This is the object that will be used to attach
+     * the IAccessor binder to the RpcSession when a binder is set up via accessor.
+     */
+    LIBBINDER_EXPORTED void setSessionSpecificRoot(const sp<IBinder>& sessionSpecificRoot);
+
 private:
     friend sp<RpcSession>;
     friend RpcServer;
diff --git a/libs/binder/servicedispatcher.cpp b/libs/binder/servicedispatcher.cpp
index 18b178b..201dfbc 100644
--- a/libs/binder/servicedispatcher.cpp
+++ b/libs/binder/servicedispatcher.cpp
@@ -118,13 +118,11 @@
 class ServiceManagerProxyToNative : public android::os::BnServiceManager {
 public:
     ServiceManagerProxyToNative(const sp<android::os::IServiceManager>& impl) : mImpl(impl) {}
-    android::binder::Status getService(const std::string&,
-                                       android::sp<android::IBinder>*) override {
+    android::binder::Status getService(const std::string&, android::os::Service*) override {
         // We can't send BpBinder for regular binder over RPC.
         return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
     }
-    android::binder::Status checkService(const std::string&,
-                                         android::sp<android::IBinder>*) override {
+    android::binder::Status checkService(const std::string&, android::os::Service*) override {
         // We can't send BpBinder for regular binder over RPC.
         return android::binder::Status::fromStatusT(android::INVALID_OPERATION);
     }