xref: /aosp_15_r20/frameworks/native/libs/binder/BackendUnifiedServiceManager.h (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
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