1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <android/os/BnServiceManager.h> 19 #include <android/os/IServiceManager.h> 20 #include <binder/IPCThreadState.h> 21 #include <binder/Trace.h> 22 #include <map> 23 #include <memory> 24 25 namespace android { 26 27 class BinderCacheWithInvalidation 28 : public std::enable_shared_from_this<BinderCacheWithInvalidation> { 29 class BinderInvalidation : public IBinder::DeathRecipient { 30 public: BinderInvalidation(std::weak_ptr<BinderCacheWithInvalidation> cache,const std::string & key)31 BinderInvalidation(std::weak_ptr<BinderCacheWithInvalidation> cache, const std::string& key) 32 : mCache(cache), mKey(key) {} 33 binderDied(const wp<IBinder> & who)34 void binderDied(const wp<IBinder>& who) override { 35 sp<IBinder> binder = who.promote(); 36 if (std::shared_ptr<BinderCacheWithInvalidation> cache = mCache.lock()) { 37 cache->removeItem(mKey, binder); 38 } else { 39 ALOGI("Binder Cache pointer expired: %s", mKey.c_str()); 40 } 41 } 42 43 private: 44 std::weak_ptr<BinderCacheWithInvalidation> mCache; 45 std::string mKey; 46 }; 47 struct Entry { 48 sp<IBinder> service; 49 sp<BinderInvalidation> deathRecipient; 50 }; 51 52 public: getItem(const std::string & key)53 sp<IBinder> getItem(const std::string& key) const { 54 std::lock_guard<std::mutex> lock(mCacheMutex); 55 56 if (auto it = mCache.find(key); it != mCache.end()) { 57 return it->second.service; 58 } 59 return nullptr; 60 } 61 removeItem(const std::string & key,const sp<IBinder> & who)62 bool removeItem(const std::string& key, const sp<IBinder>& who) { 63 std::string traceStr; 64 uint64_t tag = ATRACE_TAG_AIDL; 65 if (atrace_is_tag_enabled(tag)) { 66 traceStr = "BinderCacheWithInvalidation::removeItem " + key; 67 } 68 binder::ScopedTrace aidlTrace(tag, traceStr.c_str()); 69 std::lock_guard<std::mutex> lock(mCacheMutex); 70 if (auto it = mCache.find(key); it != mCache.end()) { 71 if (it->second.service == who) { 72 status_t result = who->unlinkToDeath(it->second.deathRecipient); 73 if (result != DEAD_OBJECT) { 74 ALOGW("Unlinking to dead binder resulted in: %d", result); 75 } 76 mCache.erase(key); 77 return true; 78 } 79 } 80 return false; 81 } 82 setItem(const std::string & key,const sp<IBinder> & item)83 binder::Status setItem(const std::string& key, const sp<IBinder>& item) { 84 sp<BinderInvalidation> deathRecipient = 85 sp<BinderInvalidation>::make(shared_from_this(), key); 86 87 // linkToDeath if binder is a remote binder. 88 if (item->localBinder() == nullptr) { 89 status_t status = item->linkToDeath(deathRecipient); 90 if (status != android::OK) { 91 std::string traceStr; 92 uint64_t tag = ATRACE_TAG_AIDL; 93 if (atrace_is_tag_enabled(tag)) { 94 traceStr = 95 "BinderCacheWithInvalidation::setItem Failed LinkToDeath for service " + 96 key + " : " + std::to_string(status); 97 } 98 binder::ScopedTrace aidlTrace(tag, traceStr.c_str()); 99 100 ALOGE("Failed to linkToDeath binder for service %s. Error: %d", key.c_str(), 101 status); 102 return binder::Status::fromStatusT(status); 103 } 104 } 105 binder::ScopedTrace aidlTrace(ATRACE_TAG_AIDL, 106 "BinderCacheWithInvalidation::setItem Successfully Cached"); 107 std::lock_guard<std::mutex> lock(mCacheMutex); 108 mCache[key] = {.service = item, .deathRecipient = deathRecipient}; 109 return binder::Status::ok(); 110 } 111 112 bool isClientSideCachingEnabled(const std::string& serviceName); 113 114 private: 115 std::map<std::string, Entry> mCache; 116 mutable std::mutex mCacheMutex; 117 }; 118 119 class BackendUnifiedServiceManager : public android::os::BnServiceManager { 120 public: 121 explicit BackendUnifiedServiceManager(const sp<os::IServiceManager>& impl); 122 123 binder::Status getService(const ::std::string& name, sp<IBinder>* _aidl_return) override; 124 binder::Status getService2(const ::std::string& name, os::Service* out) override; 125 binder::Status checkService(const ::std::string& name, os::Service* out) override; 126 binder::Status addService(const ::std::string& name, const sp<IBinder>& service, 127 bool allowIsolated, int32_t dumpPriority) override; 128 binder::Status listServices(int32_t dumpPriority, 129 ::std::vector<::std::string>* _aidl_return) override; 130 binder::Status registerForNotifications(const ::std::string& name, 131 const sp<os::IServiceCallback>& callback) override; 132 binder::Status unregisterForNotifications(const ::std::string& name, 133 const sp<os::IServiceCallback>& callback) override; 134 binder::Status isDeclared(const ::std::string& name, bool* _aidl_return) override; 135 binder::Status getDeclaredInstances(const ::std::string& iface, 136 ::std::vector<::std::string>* _aidl_return) override; 137 binder::Status updatableViaApex(const ::std::string& name, 138 ::std::optional<::std::string>* _aidl_return) override; 139 binder::Status getUpdatableNames(const ::std::string& apexName, 140 ::std::vector<::std::string>* _aidl_return) override; 141 binder::Status getConnectionInfo(const ::std::string& name, 142 ::std::optional<os::ConnectionInfo>* _aidl_return) override; 143 binder::Status registerClientCallback(const ::std::string& name, const sp<IBinder>& service, 144 const sp<os::IClientCallback>& callback) override; 145 binder::Status tryUnregisterService(const ::std::string& name, 146 const sp<IBinder>& service) override; 147 binder::Status getServiceDebugInfo(::std::vector<os::ServiceDebugInfo>* _aidl_return) override; 148 enableAddServiceCache(bool value)149 void enableAddServiceCache(bool value) { mEnableAddServiceCache = value; } 150 // for legacy ABI getInterfaceDescriptor()151 const String16& getInterfaceDescriptor() const override { 152 return mTheRealServiceManager->getInterfaceDescriptor(); 153 } 154 155 private: 156 bool mEnableAddServiceCache = true; 157 std::shared_ptr<BinderCacheWithInvalidation> mCacheForGetService; 158 sp<os::IServiceManager> mTheRealServiceManager; 159 binder::Status toBinderService(const ::std::string& name, const os::Service& in, 160 os::Service* _out); 161 binder::Status updateCache(const std::string& serviceName, const os::Service& service); 162 binder::Status updateCache(const std::string& serviceName, const sp<IBinder>& binder, 163 bool isLazyService); 164 bool returnIfCached(const std::string& serviceName, os::Service* _out); 165 }; 166 167 sp<BackendUnifiedServiceManager> getBackendUnifiedServiceManager(); 168 169 android::binder::Status getInjectedAccessor(const std::string& name, android::os::Service* service); 170 171 } // namespace android 172