Add a cache to getService with invalidation
Test: atest binderCacheUnitTest
Bug: 333854840
Flag: LIBBINDER_CLIENT_CACHE
Change-Id: I1b4e8482817c422850aed7359beaf7174b55445e
diff --git a/libs/binder/BackendUnifiedServiceManager.cpp b/libs/binder/BackendUnifiedServiceManager.cpp
index fee36da..5680798 100644
--- a/libs/binder/BackendUnifiedServiceManager.cpp
+++ b/libs/binder/BackendUnifiedServiceManager.cpp
@@ -24,11 +24,111 @@
namespace android {
+#ifdef LIBBINDER_CLIENT_CACHE
+constexpr bool kUseCache = true;
+#else
+constexpr bool kUseCache = false;
+#endif
+
using AidlServiceManager = android::os::IServiceManager;
using IAccessor = android::os::IAccessor;
+static const char* kStaticCachableList[] = {
+ "activity",
+ "android.hardware.thermal.IThermal/default",
+ "android.hardware.power.IPower/default",
+ "android.frameworks.stats.IStats/default",
+ "android.system.suspend.ISystemSuspend/default",
+ "appops",
+ "audio",
+ "batterystats",
+ "carrier_config",
+ "connectivity",
+ "content_capture",
+ "device_policy",
+ "display",
+ "dropbox",
+ "econtroller",
+ "isub",
+ "legacy_permission",
+ "location",
+ "media.extractor",
+ "media.metrics",
+ "media.player",
+ "media.resource_manager",
+ "netd_listener",
+ "netstats",
+ "network_management",
+ "nfc",
+ "package_native",
+ "performance_hint",
+ "permission",
+ "permissionmgr",
+ "permission_checker",
+ "phone",
+ "platform_compat",
+ "power",
+ "role",
+ "sensorservice",
+ "statscompanion",
+ "telephony.registry",
+ "thermalservice",
+ "time_detector",
+ "trust",
+ "uimode",
+ "virtualdevice",
+ "virtualdevice_native",
+ "webviewupdate",
+};
+
+bool BinderCacheWithInvalidation::isClientSideCachingEnabled(const std::string& serviceName) {
+ if (ProcessState::self()->getThreadPoolMaxTotalThreadCount() <= 0) {
+ ALOGW("Thread Pool max thread count is 0. Cannot cache binder as linkToDeath cannot be "
+ "implemented. serviceName: %s",
+ serviceName.c_str());
+ return false;
+ }
+ for (const char* name : kStaticCachableList) {
+ if (name == serviceName) {
+ return true;
+ }
+ }
+ return false;
+}
+
+binder::Status BackendUnifiedServiceManager::updateCache(const std::string& serviceName,
+ const os::Service& service) {
+ if (!kUseCache) {
+ return binder::Status::ok();
+ }
+ if (service.getTag() == os::Service::Tag::binder) {
+ sp<IBinder> binder = service.get<os::Service::Tag::binder>();
+ if (binder && mCacheForGetService->isClientSideCachingEnabled(serviceName) &&
+ binder->isBinderAlive()) {
+ return mCacheForGetService->setItem(serviceName, binder);
+ }
+ }
+ return binder::Status::ok();
+}
+
+bool BackendUnifiedServiceManager::returnIfCached(const std::string& serviceName,
+ os::Service* _out) {
+ if (!kUseCache) {
+ return false;
+ }
+ 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);
+ return true;
+ }
+ return false;
+}
+
BackendUnifiedServiceManager::BackendUnifiedServiceManager(const sp<AidlServiceManager>& impl)
- : mTheRealServiceManager(impl) {}
+ : mTheRealServiceManager(impl) {
+ mCacheForGetService = std::make_shared<BinderCacheWithInvalidation>();
+}
sp<AidlServiceManager> BackendUnifiedServiceManager::getImpl() {
return mTheRealServiceManager;
@@ -44,10 +144,17 @@
binder::Status BackendUnifiedServiceManager::getService2(const ::std::string& name,
os::Service* _out) {
+ if (returnIfCached(name, _out)) {
+ return binder::Status::ok();
+ }
os::Service service;
binder::Status status = mTheRealServiceManager->getService2(name, &service);
+
if (status.isOk()) {
- return toBinderService(name, service, _out);
+ status = toBinderService(name, service, _out);
+ if (status.isOk()) {
+ return updateCache(name, service);
+ }
}
return status;
}
@@ -55,9 +162,16 @@
binder::Status BackendUnifiedServiceManager::checkService(const ::std::string& name,
os::Service* _out) {
os::Service service;
+ if (returnIfCached(name, _out)) {
+ return binder::Status::ok();
+ }
+
binder::Status status = mTheRealServiceManager->checkService(name, &service);
if (status.isOk()) {
- return toBinderService(name, service, _out);
+ status = toBinderService(name, service, _out);
+ if (status.isOk()) {
+ return updateCache(name, service);
+ }
}
return status;
}