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