Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e1b7e1b authored by Parth Sane's avatar Parth Sane
Browse files

Remove static list in libbinder for caching

This adds a new flag to identify Lazy services.
This flag is set when addService is called from
LazyServiceRegistrar.

This flag is then used by libbinder in a client.
When getService is called, libbinder decides if
the binder should be cached or not using this flag.

Doc: go/libbinder-cache-v2

Flag: RELEASE_LIBBINDER_REMOVE_STATIC_LIST
Test: atest binderCacheUnitTest
Bug: 333854840
Change-Id: I5fff0140f635dddb4f5a6d618f4e9abace6feb54
parent dc207544
Loading
Loading
Loading
Loading
+13 −8
Original line number Diff line number Diff line
@@ -396,7 +396,7 @@ Status ServiceManager::getService(const std::string& name, sp<IBinder>* outBinde
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
            PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));

    *outBinder = tryGetBinder(name, true);
    *outBinder = tryGetBinder(name, true).service;
    // returns ok regardless of result for legacy reasons
    return Status::ok();
}
@@ -430,13 +430,15 @@ os::Service ServiceManager::tryGetService(const std::string& name, bool startIfN
            return os::Service::make<os::Service::Tag::accessor>(nullptr);
        }
        return os::Service::make<os::Service::Tag::accessor>(
                tryGetBinder(*accessorName, startIfNotFound));
                tryGetBinder(*accessorName, startIfNotFound).service);
    } else {
        return os::Service::make<os::Service::Tag::binder>(tryGetBinder(name, startIfNotFound));
        return os::Service::make<os::Service::Tag::serviceWithMetadata>(
                tryGetBinder(name, startIfNotFound));
    }
}

sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNotFound) {
os::ServiceWithMetadata ServiceManager::tryGetBinder(const std::string& name,
                                                     bool startIfNotFound) {
    SM_PERFETTO_TRACE_FUNC(PERFETTO_TE_PROTO_FIELDS(
            PERFETTO_TE_PROTO_FIELD_CSTR(kProtoServiceName, name.c_str())));

@@ -450,13 +452,13 @@ sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNo
        if (!service->allowIsolated && is_multiuser_uid_isolated(ctx.uid)) {
            LOG(WARNING) << "Isolated app with UID " << ctx.uid << " requested '" << name
                         << "', but the service is not allowed for isolated apps.";
            return nullptr;
            return os::ServiceWithMetadata();
        }
        out = service->binder;
    }

    if (!mAccess->canFind(ctx, name)) {
        return nullptr;
        return os::ServiceWithMetadata();
    }

    if (!out && startIfNotFound) {
@@ -473,8 +475,11 @@ sp<IBinder> ServiceManager::tryGetBinder(const std::string& name, bool startIfNo
        CHECK(handleServiceClientCallback(2 /* sm + transaction */, name, false));
        service->guaranteeClient = true;
    }

    return out;
    os::ServiceWithMetadata serviceWithMetadata = os::ServiceWithMetadata();
    serviceWithMetadata.service = out;
    serviceWithMetadata.isLazyService =
            service ? service->dumpPriority & FLAG_IS_LAZY_SERVICE : false;
    return serviceWithMetadata;
}

bool isValidServiceName(const std::string& name) {
+1 −1
Original line number Diff line number Diff line
@@ -114,7 +114,7 @@ private:
    void removeClientCallback(const wp<IBinder>& who, ClientCallbackMap::iterator* it);

    os::Service tryGetService(const std::string& name, bool startIfNotFound);
    sp<IBinder> tryGetBinder(const std::string& name, bool startIfNotFound);
    os::ServiceWithMetadata tryGetBinder(const std::string& name, bool startIfNotFound);
    binder::Status canAddService(const Access::CallingContext& ctx, const std::string& name,
                                 std::optional<std::string>* accessor);
    binder::Status canFindService(const Access::CallingContext& ctx, const std::string& name,
+12 −7
Original line number Diff line number Diff line
@@ -92,6 +92,11 @@ TEST(AddService, HappyHappy) {
    auto sm = getPermissiveServiceManager();
    EXPECT_TRUE(sm->addService("foo", getBinder(), false /*allowIsolated*/,
        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());

    EXPECT_TRUE(sm->addService("lazyfoo", getBinder(), false /*allowIsolated*/,
                               IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT |
                                       IServiceManager::FLAG_IS_LAZY_SERVICE)
                        .isOk());
}

TEST(AddService, EmptyNameDisallowed) {
@@ -156,7 +161,7 @@ TEST(AddService, OverwriteExistingService) {

    Service outA;
    EXPECT_TRUE(sm->getService2("foo", &outA).isOk());
    EXPECT_EQ(serviceA, outA.get<Service::Tag::binder>());
    EXPECT_EQ(serviceA, outA.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinderA;
    EXPECT_TRUE(sm->getService("foo", &outBinderA).isOk());
    EXPECT_EQ(serviceA, outBinderA);
@@ -168,7 +173,7 @@ TEST(AddService, OverwriteExistingService) {

    Service outB;
    EXPECT_TRUE(sm->getService2("foo", &outB).isOk());
    EXPECT_EQ(serviceB, outB.get<Service::Tag::binder>());
    EXPECT_EQ(serviceB, outB.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinderB;
    EXPECT_TRUE(sm->getService("foo", &outBinderB).isOk());
    EXPECT_EQ(serviceB, outBinderB);
@@ -195,7 +200,7 @@ TEST(GetService, HappyHappy) {

    Service out;
    EXPECT_TRUE(sm->getService2("foo", &out).isOk());
    EXPECT_EQ(service, out.get<Service::Tag::binder>());
    EXPECT_EQ(service, out.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinder;
    EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
    EXPECT_EQ(service, outBinder);
@@ -206,7 +211,7 @@ TEST(GetService, NonExistant) {

    Service out;
    EXPECT_TRUE(sm->getService2("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
    EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinder;
    EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
    EXPECT_EQ(nullptr, outBinder);
@@ -227,7 +232,7 @@ TEST(GetService, NoPermissionsForGettingService) {
    Service out;
    // returns nullptr but has OK status for legacy compatibility
    EXPECT_TRUE(sm->getService2("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
    EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinder;
    EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
    EXPECT_EQ(nullptr, outBinder);
@@ -257,7 +262,7 @@ TEST(GetService, AllowedFromIsolated) {

    Service out;
    EXPECT_TRUE(sm->getService2("foo", &out).isOk());
    EXPECT_EQ(service, out.get<Service::Tag::binder>());
    EXPECT_EQ(service, out.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinder;
    EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
    EXPECT_EQ(service, outBinder);
@@ -289,7 +294,7 @@ TEST(GetService, NotAllowedFromIsolated) {
    Service out;
    // returns nullptr but has OK status for legacy compatibility
    EXPECT_TRUE(sm->getService2("foo", &out).isOk());
    EXPECT_EQ(nullptr, out.get<Service::Tag::binder>());
    EXPECT_EQ(nullptr, out.get<Service::Tag::serviceWithMetadata>().service);
    sp<IBinder> outBinder;
    EXPECT_TRUE(sm->getService("foo", &outBinder).isOk());
    EXPECT_EQ(nullptr, outBinder);
+24 −0
Original line number Diff line number Diff line
@@ -455,6 +455,28 @@ cc_library_shared {
    ],
}

soong_config_module_type {
    name: "libbinder_remove_cache_static_list_config",
    module_type: "cc_defaults",
    config_namespace: "libbinder",
    bool_variables: ["release_libbinder_remove_cache_static_list"],
    properties: [
        "cflags",
    ],
}

libbinder_remove_cache_static_list_config {
    name: "libbinder_remove_cache_static_list_flag",
    soong_config_variables: {
        release_libbinder_remove_cache_static_list: {
            cflags: ["-DLIBBINDER_REMOVE_CACHE_STATIC_LIST"],
            conditions_default: {
                cflags: ["-DNO_LIBBINDER_REMOVE_CACHE_STATIC_LIST"],
            },
        },
    },
}

soong_config_module_type {
    name: "libbinder_client_cache_config",
    module_type: "cc_defaults",
@@ -504,6 +526,7 @@ cc_defaults {
    defaults: [
        "libbinder_client_cache_flag",
        "libbinder_addservice_cache_flag",
        "libbinder_remove_cache_static_list_flag",
    ],
    srcs: [
        "BufferedTextOutput.cpp",
@@ -826,6 +849,7 @@ filegroup {
        "aidl/android/os/IServiceCallback.aidl",
        "aidl/android/os/IServiceManager.aidl",
        "aidl/android/os/Service.aidl",
        "aidl/android/os/ServiceWithMetadata.aidl",
        "aidl/android/os/ServiceDebugInfo.aidl",
    ],
    path: "aidl",
+39 −12
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include "BackendUnifiedServiceManager.h"

#include <android/os/IAccessor.h>
#include <android/os/IServiceManager.h>
#include <binder/RpcSession.h>

#if defined(__BIONIC__) && !defined(__ANDROID_VNDK__)
@@ -36,6 +37,12 @@ constexpr bool kUseCacheInAddService = true;
constexpr bool kUseCacheInAddService = false;
#endif

#ifdef LIBBINDER_REMOVE_CACHE_STATIC_LIST
constexpr bool kRemoveStaticList = true;
#else
constexpr bool kRemoveStaticList = false;
#endif

using AidlServiceManager = android::os::IServiceManager;
using android::os::IAccessor;
using binder::Status;
@@ -110,6 +117,13 @@ static const char* kStaticCachableList[] = {
        // go/keep-sorted end
};

os::ServiceWithMetadata createServiceWithMetadata(const sp<IBinder>& service, bool isLazyService) {
    os::ServiceWithMetadata out = os::ServiceWithMetadata();
    out.service = service;
    out.isLazyService = isLazyService;
    return out;
}

bool BinderCacheWithInvalidation::isClientSideCachingEnabled(const std::string& serviceName) {
    sp<ProcessState> self = ProcessState::selfOrNull();
    if (!self || self->getThreadPoolMaxTotalThreadCount() <= 0) {
@@ -132,15 +146,21 @@ Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
        return Status::ok();
    }

    if (service.getTag() == os::Service::Tag::binder) {
        return updateCache(serviceName, service.get<os::Service::Tag::binder>());
    if (service.getTag() == os::Service::Tag::serviceWithMetadata) {
        auto serviceWithMetadata = service.get<os::Service::Tag::serviceWithMetadata>();
        return updateCache(serviceName, serviceWithMetadata.service,
                           serviceWithMetadata.isLazyService);
    }
    return Status::ok();
}

Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
                                                 const sp<IBinder>& binder) {
                                                 const sp<IBinder>& binder, bool isServiceLazy) {
    std::string traceStr;
    // Don't cache if service is lazy
    if (kRemoveStaticList && isServiceLazy) {
        return Status::ok();
    }
    if (atrace_is_tag_enabled(ATRACE_TAG_AIDL)) {
        traceStr = "BinderCacheWithInvalidation::updateCache : " + serviceName;
    }
@@ -153,7 +173,9 @@ Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
        binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
                                      "BinderCacheWithInvalidation::updateCache failed: "
                                      "isBinderAlive_false");
    } else if (mCacheForGetService->isClientSideCachingEnabled(serviceName)) {
    }
    // If we reach here with kRemoveStaticList=true then we know service isn't lazy
    else if (kRemoveStaticList || mCacheForGetService->isClientSideCachingEnabled(serviceName)) {
        binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL,
                                      "BinderCacheWithInvalidation::updateCache successful");
        return mCacheForGetService->setItem(serviceName, binder);
@@ -173,7 +195,7 @@ bool BackendUnifiedServiceManager::returnIfCached(const std::string& serviceName
    sp<IBinder> item = mCacheForGetService->getItem(serviceName);
    // TODO(b/363177618): Enable caching for binders which are always null.
    if (item != nullptr && item->isBinderAlive()) {
        *_out = os::Service::make<os::Service::Tag::binder>(item);
        *_out = createServiceWithMetadata(item, false);
        return true;
    }
    return false;
@@ -188,7 +210,7 @@ Status BackendUnifiedServiceManager::getService(const ::std::string& name,
                                                sp<IBinder>* _aidl_return) {
    os::Service service;
    Status status = getService2(name, &service);
    *_aidl_return = service.get<os::Service::Tag::binder>();
    *_aidl_return = service.get<os::Service::Tag::serviceWithMetadata>().service;
    return status;
}

@@ -227,14 +249,16 @@ Status BackendUnifiedServiceManager::checkService(const ::std::string& name, os:
Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
                                                     const os::Service& in, os::Service* _out) {
    switch (in.getTag()) {
        case os::Service::Tag::binder: {
            if (in.get<os::Service::Tag::binder>() == nullptr) {
        case os::Service::Tag::serviceWithMetadata: {
            auto serviceWithMetadata = in.get<os::Service::Tag::serviceWithMetadata>();
            if (serviceWithMetadata.service == nullptr) {
                // failed to find a service. Check to see if we have any local
                // injected Accessors for this service.
                os::Service accessor;
                Status status = getInjectedAccessor(name, &accessor);
                if (!status.isOk()) {
                    *_out = os::Service::make<os::Service::Tag::binder>(nullptr);
                    *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
                            createServiceWithMetadata(nullptr, false));
                    return status;
                }
                if (accessor.getTag() == os::Service::Tag::accessor &&
@@ -255,7 +279,8 @@ Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
            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);
                *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
                        createServiceWithMetadata(nullptr, false));
                return Status::ok();
            }
            auto request = [=] {
@@ -276,7 +301,8 @@ Status BackendUnifiedServiceManager::toBinderService(const ::std::string& name,
                return Status::fromStatusT(status);
            }
            session->setSessionSpecificRoot(accessorBinder);
            *_out = os::Service::make<os::Service::Tag::binder>(session->getRootObject());
            *_out = os::Service::make<os::Service::Tag::serviceWithMetadata>(
                    createServiceWithMetadata(session->getRootObject(), false));
            return Status::ok();
        }
        default: {
@@ -291,7 +317,8 @@ Status BackendUnifiedServiceManager::addService(const ::std::string& name,
    Status status = mTheRealServiceManager->addService(name, service, allowIsolated, dumpPriority);
    // mEnableAddServiceCache is true by default.
    if (kUseCacheInAddService && mEnableAddServiceCache && status.isOk()) {
        return updateCache(name, service);
        return updateCache(name, service,
                           dumpPriority & android::os::IServiceManager::FLAG_IS_LAZY_SERVICE);
    }
    return status;
}
Loading