1 /**
2  *
3  * Copyright 2020, The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 //#define LOG_NDEBUG 0
19 #define LOG_TAG "ResourceObserverService"
20 #include <utils/Log.h>
21 
22 #include <android/binder_manager.h>
23 #include <android/binder_process.h>
24 #include <binder/IServiceManager.h>
25 #include <utils/String16.h>
26 #include <aidl/android/media/MediaResourceParcel.h>
27 
28 #include "ResourceObserverService.h"
29 
30 namespace android {
31 
32 using ::aidl::android::media::MediaResourceParcel;
33 using ::aidl::android::media::MediaObservableEvent;
34 
35 // MediaObservableEvent will be used as uint64_t flags.
36 static_assert(sizeof(MediaObservableEvent) == sizeof(uint64_t));
37 
38 static std::vector<MediaObservableEvent> sEvents = {
39         MediaObservableEvent::kBusy,
40         MediaObservableEvent::kIdle,
41 };
42 
getObservableType(const MediaResourceParcel & res)43 static MediaObservableType getObservableType(const MediaResourceParcel& res) {
44     if (res.subType == MediaResourceSubType::kHwVideoCodec ||
45         res.subType == MediaResourceSubType::kSwVideoCodec) {
46         if (res.type == MediaResourceType::kNonSecureCodec) {
47             return MediaObservableType::kVideoNonSecureCodec;
48         }
49         if (res.type == MediaResourceType::kSecureCodec) {
50             return MediaObservableType::kVideoSecureCodec;
51         }
52     }
53     return MediaObservableType::kInvalid;
54 }
55 
56 //static
57 std::mutex ResourceObserverService::sDeathRecipientLock;
58 //static
59 std::map<uintptr_t, std::shared_ptr<ResourceObserverService::DeathRecipient> >
60 ResourceObserverService::sDeathRecipientMap;
61 
62 struct ResourceObserverService::DeathRecipient {
DeathRecipientandroid::ResourceObserverService::DeathRecipient63     DeathRecipient(ResourceObserverService* _service,
64             const std::shared_ptr<IResourceObserver>& _observer)
65         : service(_service), observer(_observer) {}
~DeathRecipientandroid::ResourceObserverService::DeathRecipient66     ~DeathRecipient() {}
67 
binderDiedandroid::ResourceObserverService::DeathRecipient68     void binderDied() {
69         if (service != nullptr) {
70             service->unregisterObserver(observer);
71         }
72     }
73 
74     ResourceObserverService* service;
75     std::shared_ptr<IResourceObserver> observer;
76 };
77 
78 // static
BinderDiedCallback(void * cookie)79 void ResourceObserverService::BinderDiedCallback(void* cookie) {
80     uintptr_t id = reinterpret_cast<uintptr_t>(cookie);
81 
82     ALOGW("Observer %lld is dead", (long long)id);
83 
84     std::shared_ptr<DeathRecipient> recipient;
85 
86     {
87         std::scoped_lock lock{sDeathRecipientLock};
88 
89         auto it = sDeathRecipientMap.find(id);
90         if (it != sDeathRecipientMap.end()) {
91             recipient = it->second;
92         }
93     }
94 
95     if (recipient != nullptr) {
96         recipient->binderDied();
97     }
98 }
99 
100 //static
instantiate()101 std::shared_ptr<ResourceObserverService> ResourceObserverService::instantiate() {
102     std::shared_ptr<ResourceObserverService> observerService =
103             ::ndk::SharedRefBase::make<ResourceObserverService>();
104     binder_status_t status = AServiceManager_addServiceWithFlags(
105       observerService->asBinder().get(),ResourceObserverService::getServiceName(),
106       AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
107 
108     if (status != STATUS_OK) {
109         return nullptr;
110     }
111     return observerService;
112 }
113 
ResourceObserverService()114 ResourceObserverService::ResourceObserverService()
115     : mDeathRecipient(AIBinder_DeathRecipient_new(BinderDiedCallback)) {}
116 
dump(int fd,const char **,uint32_t)117 binder_status_t ResourceObserverService::dump(
118         int fd, const char** /*args*/, uint32_t /*numArgs*/) {
119     String8 result;
120 
121     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
122         result.format("Permission Denial: "
123                 "can't dump ResourceManagerService from pid=%d, uid=%d\n",
124                 AIBinder_getCallingPid(),
125                 AIBinder_getCallingUid());
126         write(fd, result.c_str(), result.size());
127         return PERMISSION_DENIED;
128     }
129 
130     result.appendFormat("ResourceObserverService: %p\n", this);
131     result.appendFormat("  Registered Observers: %zu\n", mObserverInfoMap.size());
132 
133     {
134         std::scoped_lock lock{mObserverLock};
135 
136         for (auto &observer : mObserverInfoMap) {
137             result.appendFormat("    Observer %p:\n", observer.second.binder.get());
138             for (auto &observable : observer.second.filters) {
139                 String8 enabledEventsStr;
140                 for (auto &event : sEvents) {
141                     if (((uint64_t)observable.eventFilter & (uint64_t)event) != 0) {
142                         if (!enabledEventsStr.empty()) {
143                             enabledEventsStr.append("|");
144                         }
145                         enabledEventsStr.append(toString(event).c_str());
146                     }
147                 }
148                 result.appendFormat("      %s: %s\n",
149                         toString(observable.type).c_str(), enabledEventsStr.c_str());
150             }
151         }
152     }
153 
154     write(fd, result.c_str(), result.size());
155     return OK;
156 }
157 
registerObserver(const std::shared_ptr<IResourceObserver> & in_observer,const std::vector<MediaObservableFilter> & in_filters)158 Status ResourceObserverService::registerObserver(
159         const std::shared_ptr<IResourceObserver>& in_observer,
160         const std::vector<MediaObservableFilter>& in_filters) {
161     if ((getpid() != AIBinder_getCallingPid()) &&
162             checkCallingPermission(
163             String16("android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER")) == false) {
164         ALOGE("Permission Denial: "
165                 "can't registerObserver from pid=%d, uid=%d\n",
166                 AIBinder_getCallingPid(),
167                 AIBinder_getCallingUid());
168         return Status::fromServiceSpecificError(PERMISSION_DENIED);
169     }
170 
171     if (in_observer == nullptr) {
172         return Status::fromServiceSpecificError(BAD_VALUE);
173     }
174 
175     ::ndk::SpAIBinder binder = in_observer->asBinder();
176 
177     {
178         std::scoped_lock lock{mObserverLock};
179 
180         if (mObserverInfoMap.find((uintptr_t)binder.get()) != mObserverInfoMap.end()) {
181             return Status::fromServiceSpecificError(ALREADY_EXISTS);
182         }
183 
184         if (in_filters.empty()) {
185             return Status::fromServiceSpecificError(BAD_VALUE);
186         }
187 
188         // Add observer info.
189         mObserverInfoMap.emplace((uintptr_t)binder.get(),
190                 ObserverInfo{binder, in_observer, in_filters});
191 
192         // Add observer to observable->subscribers map.
193         for (auto &filter : in_filters) {
194             for (auto &event : sEvents) {
195                 if (!((uint64_t)filter.eventFilter & (uint64_t)event)) {
196                     continue;
197                 }
198                 MediaObservableFilter key{filter.type, event};
199                 mObservableToSubscribersMap[key].emplace((uintptr_t)binder.get(), in_observer);
200             }
201         }
202     }
203 
204     // Add death binder and link.
205     uintptr_t cookie = (uintptr_t)binder.get();
206     {
207         std::scoped_lock lock{sDeathRecipientLock};
208         sDeathRecipientMap.emplace(
209                 cookie, std::make_shared<DeathRecipient>(this, in_observer));
210     }
211 
212     AIBinder_linkToDeath(binder.get(), mDeathRecipient.get(),
213                          reinterpret_cast<void*>(cookie));
214 
215     return Status::ok();
216 }
217 
unregisterObserver(const std::shared_ptr<IResourceObserver> & in_observer)218 Status ResourceObserverService::unregisterObserver(
219         const std::shared_ptr<IResourceObserver>& in_observer) {
220     if ((getpid() != AIBinder_getCallingPid()) &&
221             checkCallingPermission(
222             String16("android.permission.REGISTER_MEDIA_RESOURCE_OBSERVER")) == false) {
223         ALOGE("Permission Denial: "
224                 "can't unregisterObserver from pid=%d, uid=%d\n",
225                 AIBinder_getCallingPid(),
226                 AIBinder_getCallingUid());
227         return Status::fromServiceSpecificError(PERMISSION_DENIED);
228     }
229 
230     if (in_observer == nullptr) {
231         return Status::fromServiceSpecificError(BAD_VALUE);
232     }
233 
234     ::ndk::SpAIBinder binder = in_observer->asBinder();
235 
236     {
237         std::scoped_lock lock{mObserverLock};
238 
239         auto it = mObserverInfoMap.find((uintptr_t)binder.get());
240         if (it == mObserverInfoMap.end()) {
241             return Status::fromServiceSpecificError(NAME_NOT_FOUND);
242         }
243 
244         // Remove observer from observable->subscribers map.
245         for (auto &filter : it->second.filters) {
246             for (auto &event : sEvents) {
247                 if (!((uint64_t)filter.eventFilter & (uint64_t)event)) {
248                     continue;
249                 }
250                 MediaObservableFilter key{filter.type, event};
251                 mObservableToSubscribersMap[key].erase((uintptr_t)binder.get());
252 
253                 //Remove the entry if there's no more subscribers.
254                 if (mObservableToSubscribersMap[key].empty()) {
255                     mObservableToSubscribersMap.erase(key);
256                 }
257             }
258         }
259 
260         // Remove observer info.
261         mObserverInfoMap.erase(it);
262     }
263 
264     // Unlink and remove death binder.
265     uintptr_t cookie = (uintptr_t)binder.get();
266     AIBinder_unlinkToDeath(binder.get(), mDeathRecipient.get(),
267             reinterpret_cast<void*>(cookie));
268 
269     {
270         std::scoped_lock lock{sDeathRecipientLock};
271         sDeathRecipientMap.erase(cookie);
272     }
273 
274     return Status::ok();
275 }
276 
notifyObservers(MediaObservableEvent event,int uid,int pid,const ResourceList & resources)277 void ResourceObserverService::notifyObservers(
278         MediaObservableEvent event, int uid, int pid, const ResourceList &resources) {
279     struct CalleeInfo {
280         std::shared_ptr<IResourceObserver> observer;
281         std::vector<MediaObservableParcel> monitors;
282     };
283     // Build a consolidated list of observers to call with their respective observables.
284     std::map<uintptr_t, CalleeInfo> calleeList;
285 
286     {
287         std::scoped_lock lock{mObserverLock};
288 
289         for (const MediaResourceParcel& res : resources.getResources()) {
290             // Skip if this resource doesn't map to any observable type.
291             MediaObservableType observableType = getObservableType(res);
292             if (observableType == MediaObservableType::kInvalid) {
293                 continue;
294             }
295             MediaObservableFilter key{observableType, event};
296             // Skip if no one subscribed to this observable.
297             auto observableIt = mObservableToSubscribersMap.find(key);
298             if (observableIt == mObservableToSubscribersMap.end()) {
299                 continue;
300             }
301             // Loop through all subsribers.
302             for (auto &subscriber : observableIt->second) {
303                 auto calleeIt = calleeList.find(subscriber.first);
304                 if (calleeIt == calleeList.end()) {
305                     calleeList.emplace(subscriber.first, CalleeInfo{
306                         subscriber.second, {{observableType, res.value}}});
307                 } else {
308                     calleeIt->second.monitors.push_back({observableType, res.value});
309                 }
310             }
311         }
312     }
313 
314     // Finally call the observers about the status change.
315     for (auto &calleeInfo : calleeList) {
316         calleeInfo.second.observer->onStatusChanged(
317                 event, uid, pid, calleeInfo.second.monitors);
318     }
319 }
320 
onResourceAdded(int uid,int pid,const ResourceList & resources)321 void ResourceObserverService::onResourceAdded(
322         int uid, int pid, const ResourceList &resources) {
323     notifyObservers(MediaObservableEvent::kBusy, uid, pid, resources);
324 }
325 
onResourceRemoved(int uid,int pid,const ResourceList & resources)326 void ResourceObserverService::onResourceRemoved(
327         int uid, int pid, const ResourceList &resources) {
328     notifyObservers(MediaObservableEvent::kIdle, uid, pid, resources);
329 }
330 
331 } // namespace android
332