• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 **
3 ** Copyright 2015, 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 "ResourceManagerService"
20 #include <utils/Log.h>
21 
22 #include <android/binder_manager.h>
23 #include <android/binder_process.h>
24 #include <binder/IPCThreadState.h>
25 #include <binder/IServiceManager.h>
26 #include <cutils/sched_policy.h>
27 #include <dirent.h>
28 #include <media/MediaResourcePolicy.h>
29 #include <media/stagefright/foundation/ABase.h>
30 #include <mediautils/BatteryNotifier.h>
31 #include <mediautils/ProcessInfo.h>
32 #include <mediautils/SchedulingPolicyService.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <unistd.h>
38 
39 #include "IMediaResourceMonitor.h"
40 #include "ResourceManagerMetrics.h"
41 #include "ResourceManagerService.h"
42 #include "ResourceObserverService.h"
43 #include "ServiceLog.h"
44 
45 namespace android {
46 
47 //static
48 std::mutex ResourceManagerService::sCookieLock;
49 //static
50 uintptr_t ResourceManagerService::sCookieCounter = 0;
51 //static
52 std::map<uintptr_t, sp<DeathNotifier> > ResourceManagerService::sCookieToDeathNotifierMap;
53 
54 class DeathNotifier : public RefBase {
55 public:
56     DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
57                   const ClientInfoParcel& clientInfo);
58 
~DeathNotifier()59     virtual ~DeathNotifier() {}
60 
61     // Implement death recipient
62     static void BinderDiedCallback(void* cookie);
63     virtual void binderDied();
64 
65 protected:
66     std::weak_ptr<ResourceManagerService> mService;
67     const ClientInfoParcel mClientInfo;
68 };
69 
DeathNotifier(const std::shared_ptr<ResourceManagerService> & service,const ClientInfoParcel & clientInfo)70 DeathNotifier::DeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
71                              const ClientInfoParcel& clientInfo)
72     : mService(service), mClientInfo(clientInfo) {}
73 
74 //static
BinderDiedCallback(void * cookie)75 void DeathNotifier::BinderDiedCallback(void* cookie) {
76     sp<DeathNotifier> notifier;
77     {
78         std::scoped_lock lock{ResourceManagerService::sCookieLock};
79         auto it = ResourceManagerService::sCookieToDeathNotifierMap.find(
80                 reinterpret_cast<uintptr_t>(cookie));
81         if (it == ResourceManagerService::sCookieToDeathNotifierMap.end()) {
82             return;
83         }
84         notifier = it->second;
85     }
86     if (notifier.get() != nullptr) {
87         notifier->binderDied();
88     }
89 }
90 
binderDied()91 void DeathNotifier::binderDied() {
92     // Don't check for pid validity since we know it's already dead.
93     std::shared_ptr<ResourceManagerService> service = mService.lock();
94     if (service == nullptr) {
95         ALOGW("ResourceManagerService is dead as well.");
96         return;
97     }
98 
99     service->overridePid(mClientInfo.pid, -1);
100     // thiz is freed in the call below, so it must be last call referring thiz
101     service->removeResource(mClientInfo, false /*checkValid*/);
102 }
103 
104 class OverrideProcessInfoDeathNotifier : public DeathNotifier {
105 public:
OverrideProcessInfoDeathNotifier(const std::shared_ptr<ResourceManagerService> & service,const ClientInfoParcel & clientInfo)106     OverrideProcessInfoDeathNotifier(const std::shared_ptr<ResourceManagerService> &service,
107                                      const ClientInfoParcel& clientInfo)
108             : DeathNotifier(service, clientInfo) {}
109 
~OverrideProcessInfoDeathNotifier()110     virtual ~OverrideProcessInfoDeathNotifier() {}
111 
112     virtual void binderDied();
113 };
114 
binderDied()115 void OverrideProcessInfoDeathNotifier::binderDied() {
116     // Don't check for pid validity since we know it's already dead.
117     std::shared_ptr<ResourceManagerService> service = mService.lock();
118     if (service == nullptr) {
119         ALOGW("ResourceManagerService is dead as well.");
120         return;
121     }
122 
123     service->removeProcessInfoOverride(mClientInfo.pid);
124 }
125 
126 template <typename T>
getString(const std::vector<T> & items)127 static String8 getString(const std::vector<T> &items) {
128     String8 itemsStr;
129     for (size_t i = 0; i < items.size(); ++i) {
130         itemsStr.appendFormat("%s ", toString(items[i]).string());
131     }
132     return itemsStr;
133 }
134 
hasResourceType(MediaResource::Type type,MediaResource::SubType subType,MediaResourceParcel resource)135 static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
136         MediaResourceParcel resource) {
137     if (type != resource.type) {
138       return false;
139     }
140     switch (type) {
141         // Codec subtypes (e.g. video vs. audio) are each considered separate resources, so
142         // compare the subtypes as well.
143         case MediaResource::Type::kSecureCodec:
144         case MediaResource::Type::kNonSecureCodec:
145             if (resource.subType == subType) {
146                 return true;
147             }
148             break;
149         // Non-codec resources are not segregated by the subtype (e.g. video vs. audio).
150         default:
151             return true;
152     }
153     return false;
154 }
155 
hasResourceType(MediaResource::Type type,MediaResource::SubType subType,const ResourceList & resources)156 static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
157         const ResourceList& resources) {
158     for (auto it = resources.begin(); it != resources.end(); it++) {
159         if (hasResourceType(type, subType, it->second)) {
160             return true;
161         }
162     }
163     return false;
164 }
165 
hasResourceType(MediaResource::Type type,MediaResource::SubType subType,const ResourceInfos & infos)166 static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
167         const ResourceInfos& infos) {
168     for (size_t i = 0; i < infos.size(); ++i) {
169         if (hasResourceType(type, subType, infos[i].resources)) {
170             return true;
171         }
172     }
173     return false;
174 }
175 
getResourceInfosForEdit(int pid,PidResourceInfosMap & map)176 static ResourceInfos& getResourceInfosForEdit(int pid, PidResourceInfosMap& map) {
177     ssize_t index = map.indexOfKey(pid);
178     if (index < 0) {
179         // new pid
180         ResourceInfos infosForPid;
181         map.add(pid, infosForPid);
182     }
183 
184     return map.editValueFor(pid);
185 }
186 
getResourceInfoForEdit(uid_t uid,int64_t clientId,const std::string & name,const std::shared_ptr<IResourceManagerClient> & client,ResourceInfos & infos)187 static ResourceInfo& getResourceInfoForEdit(uid_t uid, int64_t clientId,
188                                             const std::string& name,
189         const std::shared_ptr<IResourceManagerClient>& client, ResourceInfos& infos) {
190     ssize_t index = infos.indexOfKey(clientId);
191 
192     if (index < 0) {
193         ResourceInfo info;
194         info.uid = uid;
195         info.clientId = clientId;
196         if (name.empty()) {
197             info.name = "<unknown client>";
198         } else {
199             info.name = name;
200         }
201         info.client = client;
202         info.cookie = 0;
203         info.pendingRemoval = false;
204 
205         index = infos.add(clientId, info);
206     }
207 
208     return infos.editValueAt(index);
209 }
210 
notifyResourceGranted(int pid,const std::vector<MediaResourceParcel> & resources)211 static void notifyResourceGranted(int pid, const std::vector<MediaResourceParcel> &resources) {
212     static const char* const kServiceName = "media_resource_monitor";
213     sp<IBinder> binder = defaultServiceManager()->checkService(String16(kServiceName));
214     if (binder != NULL) {
215         sp<IMediaResourceMonitor> service = interface_cast<IMediaResourceMonitor>(binder);
216         for (size_t i = 0; i < resources.size(); ++i) {
217             switch (resources[i].subType) {
218                 case MediaResource::SubType::kAudioCodec:
219                     service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_AUDIO_CODEC);
220                     break;
221                 case MediaResource::SubType::kVideoCodec:
222                     service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_VIDEO_CODEC);
223                     break;
224                 case MediaResource::SubType::kImageCodec:
225                     service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_IMAGE_CODEC);
226                     break;
227                 case MediaResource::SubType::kUnspecifiedSubType:
228                     break;
229             }
230         }
231     }
232 }
233 
dump(int fd,const char **,uint32_t)234 binder_status_t ResourceManagerService::dump(int fd, const char** /*args*/, uint32_t /*numArgs*/) {
235     String8 result;
236 
237     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
238         result.format("Permission Denial: "
239                 "can't dump ResourceManagerService from pid=%d, uid=%d\n",
240                 AIBinder_getCallingPid(),
241                 AIBinder_getCallingUid());
242         write(fd, result.string(), result.size());
243         return PERMISSION_DENIED;
244     }
245 
246     PidResourceInfosMap mapCopy;
247     bool supportsMultipleSecureCodecs;
248     bool supportsSecureWithNonSecureCodec;
249     std::map<int, int> overridePidMapCopy;
250     String8 serviceLog;
251     {
252         Mutex::Autolock lock(mLock);
253         mapCopy = mMap;  // Shadow copy, real copy will happen on write.
254         supportsMultipleSecureCodecs = mSupportsMultipleSecureCodecs;
255         supportsSecureWithNonSecureCodec = mSupportsSecureWithNonSecureCodec;
256         serviceLog = mServiceLog->toString("    " /* linePrefix */);
257         overridePidMapCopy = mOverridePidMap;
258     }
259 
260     const size_t SIZE = 256;
261     char buffer[SIZE];
262     snprintf(buffer, SIZE, "ResourceManagerService: %p\n", this);
263     result.append(buffer);
264     result.append("  Policies:\n");
265     snprintf(buffer, SIZE, "    SupportsMultipleSecureCodecs: %d\n", supportsMultipleSecureCodecs);
266     result.append(buffer);
267     snprintf(buffer, SIZE, "    SupportsSecureWithNonSecureCodec: %d\n",
268             supportsSecureWithNonSecureCodec);
269     result.append(buffer);
270 
271     result.append("  Processes:\n");
272     for (size_t i = 0; i < mapCopy.size(); ++i) {
273         int pid = mapCopy.keyAt(i);
274         snprintf(buffer, SIZE, "    Pid: %d\n", pid);
275         result.append(buffer);
276         int priority = 0;
277         if (getPriority_l(pid, &priority)) {
278             snprintf(buffer, SIZE, "    Priority: %d\n", priority);
279         } else {
280             snprintf(buffer, SIZE, "    Priority: <unknown>\n");
281         }
282         result.append(buffer);
283 
284         const ResourceInfos &infos = mapCopy.valueAt(i);
285         for (size_t j = 0; j < infos.size(); ++j) {
286             result.append("      Client:\n");
287             snprintf(buffer, SIZE, "        Id: %lld\n", (long long)infos[j].clientId);
288             result.append(buffer);
289 
290             std::string clientName = infos[j].name;
291             snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
292             result.append(buffer);
293 
294             const ResourceList &resources = infos[j].resources;
295             result.append("        Resources:\n");
296             for (auto it = resources.begin(); it != resources.end(); it++) {
297                 snprintf(buffer, SIZE, "          %s\n", toString(it->second).string());
298                 result.append(buffer);
299             }
300         }
301     }
302     result.append("  Process Pid override:\n");
303     for (auto it = overridePidMapCopy.begin(); it != overridePidMapCopy.end(); ++it) {
304         snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n",
305             it->first, it->second);
306         result.append(buffer);
307     }
308     result.append("  Events logs (most recent at top):\n");
309     result.append(serviceLog);
310 
311     write(fd, result.string(), result.size());
312     return OK;
313 }
314 
315 struct SystemCallbackImpl : public ResourceManagerService::SystemCallbackInterface {
SystemCallbackImplandroid::SystemCallbackImpl316     SystemCallbackImpl() : mClientToken(new BBinder()) {}
317 
noteStartVideoandroid::SystemCallbackImpl318     virtual void noteStartVideo(int uid) override {
319         BatteryNotifier::getInstance().noteStartVideo(uid);
320     }
noteStopVideoandroid::SystemCallbackImpl321     virtual void noteStopVideo(int uid) override {
322         BatteryNotifier::getInstance().noteStopVideo(uid);
323     }
noteResetVideoandroid::SystemCallbackImpl324     virtual void noteResetVideo() override {
325         BatteryNotifier::getInstance().noteResetVideo();
326     }
requestCpusetBoostandroid::SystemCallbackImpl327     virtual bool requestCpusetBoost(bool enable) override {
328         return android::requestCpusetBoost(enable, mClientToken);
329     }
330 
331 protected:
~SystemCallbackImplandroid::SystemCallbackImpl332     virtual ~SystemCallbackImpl() {}
333 
334 private:
335     DISALLOW_EVIL_CONSTRUCTORS(SystemCallbackImpl);
336     sp<IBinder> mClientToken;
337 };
338 
ResourceManagerService()339 ResourceManagerService::ResourceManagerService()
340     : ResourceManagerService(new ProcessInfo(), new SystemCallbackImpl()) {}
341 
ResourceManagerService(const sp<ProcessInfoInterface> & processInfo,const sp<SystemCallbackInterface> & systemResource)342 ResourceManagerService::ResourceManagerService(const sp<ProcessInfoInterface> &processInfo,
343         const sp<SystemCallbackInterface> &systemResource)
344     : mProcessInfo(processInfo),
345       mSystemCB(systemResource),
346       mServiceLog(new ServiceLog()),
347       mSupportsMultipleSecureCodecs(true),
348       mSupportsSecureWithNonSecureCodec(true),
349       mCpuBoostCount(0),
350       mDeathRecipient(AIBinder_DeathRecipient_new(DeathNotifier::BinderDiedCallback)) {
351     mSystemCB->noteResetVideo();
352     // Create ResourceManagerMetrics that handles all the metrics.
353     mResourceManagerMetrics = std::make_unique<ResourceManagerMetrics>(mProcessInfo);
354 }
355 
356 //static
instantiate()357 void ResourceManagerService::instantiate() {
358     std::shared_ptr<ResourceManagerService> service =
359             ::ndk::SharedRefBase::make<ResourceManagerService>();
360     binder_status_t status =
361                         AServiceManager_addServiceWithFlags(
362                         service->asBinder().get(), getServiceName(),
363                         AServiceManager_AddServiceFlag::ADD_SERVICE_ALLOW_ISOLATED);
364     if (status != STATUS_OK) {
365         return;
366     }
367 
368     std::shared_ptr<ResourceObserverService> observerService =
369             ResourceObserverService::instantiate();
370 
371     if (observerService != nullptr) {
372         service->setObserverService(observerService);
373     }
374     // TODO: mediaserver main() is already starting the thread pool,
375     // move this to mediaserver main() when other services in mediaserver
376     // are converted to ndk-platform aidl.
377     //ABinderProcess_startThreadPool();
378 }
379 
~ResourceManagerService()380 ResourceManagerService::~ResourceManagerService() {}
381 
setObserverService(const std::shared_ptr<ResourceObserverService> & observerService)382 void ResourceManagerService::setObserverService(
383         const std::shared_ptr<ResourceObserverService>& observerService) {
384     mObserverService = observerService;
385 }
386 
config(const std::vector<MediaResourcePolicyParcel> & policies)387 Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
388     String8 log = String8::format("config(%s)", getString(policies).string());
389     mServiceLog->add(log);
390 
391     Mutex::Autolock lock(mLock);
392     for (size_t i = 0; i < policies.size(); ++i) {
393         const std::string &type = policies[i].type;
394         const std::string &value = policies[i].value;
395         if (type == MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs()) {
396             mSupportsMultipleSecureCodecs = (value == "true");
397         } else if (type == MediaResourcePolicy::kPolicySupportsSecureWithNonSecureCodec()) {
398             mSupportsSecureWithNonSecureCodec = (value == "true");
399         }
400     }
401     return Status::ok();
402 }
403 
onFirstAdded(const MediaResourceParcel & resource,const ResourceInfo & clientInfo)404 void ResourceManagerService::onFirstAdded(const MediaResourceParcel& resource,
405         const ResourceInfo& clientInfo) {
406     // first time added
407     if (resource.type == MediaResource::Type::kCpuBoost
408      && resource.subType == MediaResource::SubType::kUnspecifiedSubType) {
409         // Request it on every new instance of kCpuBoost, as the media.codec
410         // could have died, if we only do it the first time subsequent instances
411         // never gets the boost.
412         if (mSystemCB->requestCpusetBoost(true) != OK) {
413             ALOGW("couldn't request cpuset boost");
414         }
415         mCpuBoostCount++;
416     } else if (resource.type == MediaResource::Type::kBattery
417             && resource.subType == MediaResource::SubType::kVideoCodec) {
418         mSystemCB->noteStartVideo(clientInfo.uid);
419     }
420 }
421 
onLastRemoved(const MediaResourceParcel & resource,const ResourceInfo & clientInfo)422 void ResourceManagerService::onLastRemoved(const MediaResourceParcel& resource,
423         const ResourceInfo& clientInfo) {
424     if (resource.type == MediaResource::Type::kCpuBoost
425             && resource.subType == MediaResource::SubType::kUnspecifiedSubType
426             && mCpuBoostCount > 0) {
427         if (--mCpuBoostCount == 0) {
428             mSystemCB->requestCpusetBoost(false);
429         }
430     } else if (resource.type == MediaResource::Type::kBattery
431             && resource.subType == MediaResource::SubType::kVideoCodec) {
432         mSystemCB->noteStopVideo(clientInfo.uid);
433     }
434 }
435 
mergeResources(MediaResourceParcel & r1,const MediaResourceParcel & r2)436 void ResourceManagerService::mergeResources(MediaResourceParcel& r1,
437         const MediaResourceParcel& r2) {
438     // The resource entry on record is maintained to be in [0,INT64_MAX].
439     // Clamp if merging in the new resource value causes it to go out of bound.
440     // Note that the new resource value could be negative, eg.DrmSession, the
441     // value goes lower when the session is used more often. During reclaim
442     // the session with the highest value (lowest usage) would be closed.
443     if (r2.value < INT64_MAX - r1.value) {
444         r1.value += r2.value;
445         if (r1.value < 0) {
446             r1.value = 0;
447         }
448     } else {
449         r1.value = INT64_MAX;
450     }
451 }
452 
addResource(const ClientInfoParcel & clientInfo,const std::shared_ptr<IResourceManagerClient> & client,const std::vector<MediaResourceParcel> & resources)453 Status ResourceManagerService::addResource(const ClientInfoParcel& clientInfo,
454         const std::shared_ptr<IResourceManagerClient>& client,
455         const std::vector<MediaResourceParcel>& resources) {
456     int32_t pid = clientInfo.pid;
457     int32_t uid = clientInfo.uid;
458     int64_t clientId = clientInfo.id;
459     const std::string& name = clientInfo.name;
460     String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
461             pid, uid, (long long) clientId, getString(resources).string());
462     mServiceLog->add(log);
463 
464     Mutex::Autolock lock(mLock);
465     if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
466         pid_t callingPid = IPCThreadState::self()->getCallingPid();
467         uid_t callingUid = IPCThreadState::self()->getCallingUid();
468         ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
469                 __FUNCTION__, pid, uid, callingPid, callingUid);
470         pid = callingPid;
471         uid = callingUid;
472     }
473     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
474     ResourceInfo& info = getResourceInfoForEdit(uid, clientId, name, client, infos);
475     ResourceList resourceAdded;
476 
477     for (size_t i = 0; i < resources.size(); ++i) {
478         const auto &res = resources[i];
479         const auto resType = std::tuple(res.type, res.subType, res.id);
480 
481         if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
482             ALOGW("Ignoring request to remove negative value of non-drm resource");
483             continue;
484         }
485         if (info.resources.find(resType) == info.resources.end()) {
486             if (res.value <= 0) {
487                 // We can't init a new entry with negative value, although it's allowed
488                 // to merge in negative values after the initial add.
489                 ALOGW("Ignoring request to add new resource entry with value <= 0");
490                 continue;
491             }
492             onFirstAdded(res, info);
493             info.resources[resType] = res;
494         } else {
495             mergeResources(info.resources[resType], res);
496         }
497         // Add it to the list of added resources for observers.
498         auto it = resourceAdded.find(resType);
499         if (it == resourceAdded.end()) {
500             resourceAdded[resType] = res;
501         } else {
502             mergeResources(it->second, res);
503         }
504     }
505     if (info.cookie == 0 && client != nullptr) {
506         info.cookie = addCookieAndLink_l(client,
507                 new DeathNotifier(ref<ResourceManagerService>(), clientInfo));
508     }
509     if (mObserverService != nullptr && !resourceAdded.empty()) {
510         mObserverService->onResourceAdded(uid, pid, resourceAdded);
511     }
512     notifyResourceGranted(pid, resources);
513 
514     return Status::ok();
515 }
516 
removeResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources)517 Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
518         const std::vector<MediaResourceParcel>& resources) {
519     int32_t pid = clientInfo.pid;
520     int32_t uid = clientInfo.uid;
521     int64_t clientId = clientInfo.id;
522     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
523             pid, uid, (long long) clientId, getString(resources).string());
524     mServiceLog->add(log);
525 
526     Mutex::Autolock lock(mLock);
527     if (!mProcessInfo->isPidTrusted(pid)) {
528         pid_t callingPid = IPCThreadState::self()->getCallingPid();
529         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
530                 pid, callingPid);
531         pid = callingPid;
532     }
533     ssize_t index = mMap.indexOfKey(pid);
534     if (index < 0) {
535         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
536         return Status::ok();
537     }
538     ResourceInfos &infos = mMap.editValueAt(index);
539 
540     index = infos.indexOfKey(clientId);
541     if (index < 0) {
542         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
543         return Status::ok();
544     }
545 
546     ResourceInfo &info = infos.editValueAt(index);
547     ResourceList resourceRemoved;
548     for (size_t i = 0; i < resources.size(); ++i) {
549         const auto &res = resources[i];
550         const auto resType = std::tuple(res.type, res.subType, res.id);
551 
552         if (res.value < 0) {
553             ALOGW("Ignoring request to remove negative value of resource");
554             continue;
555         }
556         // ignore if we don't have it
557         if (info.resources.find(resType) != info.resources.end()) {
558             MediaResourceParcel &resource = info.resources[resType];
559             MediaResourceParcel actualRemoved = res;
560             if (resource.value > res.value) {
561                 resource.value -= res.value;
562             } else {
563                 onLastRemoved(res, info);
564                 actualRemoved.value = resource.value;
565                 info.resources.erase(resType);
566             }
567 
568             // Add it to the list of removed resources for observers.
569             auto it = resourceRemoved.find(resType);
570             if (it == resourceRemoved.end()) {
571                 resourceRemoved[resType] = actualRemoved;
572             } else {
573                 mergeResources(it->second, actualRemoved);
574             }
575         }
576     }
577     if (mObserverService != nullptr && !resourceRemoved.empty()) {
578         mObserverService->onResourceRemoved(info.uid, pid, resourceRemoved);
579     }
580     return Status::ok();
581 }
582 
removeClient(const ClientInfoParcel & clientInfo)583 Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
584     removeResource(clientInfo, true /*checkValid*/);
585     return Status::ok();
586 }
587 
removeResource(const ClientInfoParcel & clientInfo,bool checkValid)588 Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
589     int32_t pid = clientInfo.pid;
590     int32_t uid = clientInfo.uid;
591     int64_t clientId = clientInfo.id;
592     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
593             pid, uid, (long long) clientId);
594     mServiceLog->add(log);
595 
596     Mutex::Autolock lock(mLock);
597     if (checkValid && !mProcessInfo->isPidTrusted(pid)) {
598         pid_t callingPid = IPCThreadState::self()->getCallingPid();
599         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
600                 pid, callingPid);
601         pid = callingPid;
602     }
603     ssize_t index = mMap.indexOfKey(pid);
604     if (index < 0) {
605         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
606         return Status::ok();
607     }
608     ResourceInfos &infos = mMap.editValueAt(index);
609 
610     index = infos.indexOfKey(clientId);
611     if (index < 0) {
612         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
613         return Status::ok();
614     }
615 
616     const ResourceInfo &info = infos[index];
617     for (auto it = info.resources.begin(); it != info.resources.end(); it++) {
618         onLastRemoved(it->second, info);
619     }
620 
621     // Since this client has been removed, update the metrics collector.
622     mResourceManagerMetrics->notifyClientReleased(clientInfo);
623 
624     removeCookieAndUnlink_l(info.client, info.cookie);
625 
626     if (mObserverService != nullptr && !info.resources.empty()) {
627         mObserverService->onResourceRemoved(info.uid, pid, info.resources);
628     }
629 
630     infos.removeItemsAt(index);
631     return Status::ok();
632 }
633 
getClientForResource_l(int callingPid,const MediaResourceParcel * res,PidUidVector * idVector,Vector<std::shared_ptr<IResourceManagerClient>> * clients)634 void ResourceManagerService::getClientForResource_l(int callingPid,
635         const MediaResourceParcel *res,
636         PidUidVector* idVector,
637         Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
638     if (res == NULL) {
639         return;
640     }
641     std::shared_ptr<IResourceManagerClient> client;
642     if (getLowestPriorityBiggestClient_l(callingPid, res->type, res->subType, idVector, &client)) {
643         clients->push_back(client);
644     }
645 }
646 
reclaimResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources,bool * _aidl_return)647 Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
648         const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
649     int32_t callingPid = clientInfo.pid;
650     std::string clientName = clientInfo.name;
651     String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
652             callingPid, clientInfo.uid, getString(resources).string());
653     mServiceLog->add(log);
654     *_aidl_return = false;
655 
656     Vector<std::shared_ptr<IResourceManagerClient>> clients;
657     PidUidVector idVector;
658     {
659         Mutex::Autolock lock(mLock);
660         if (!mProcessInfo->isPidTrusted(callingPid)) {
661             pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
662             ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
663                     callingPid, actualCallingPid);
664             callingPid = actualCallingPid;
665         }
666         const MediaResourceParcel *secureCodec = NULL;
667         const MediaResourceParcel *nonSecureCodec = NULL;
668         const MediaResourceParcel *graphicMemory = NULL;
669         const MediaResourceParcel *drmSession = NULL;
670         for (size_t i = 0; i < resources.size(); ++i) {
671             switch (resources[i].type) {
672                 case MediaResource::Type::kSecureCodec:
673                     secureCodec = &resources[i];
674                     break;
675                 case MediaResource::Type::kNonSecureCodec:
676                     nonSecureCodec = &resources[i];
677                     break;
678                 case MediaResource::Type::kGraphicMemory:
679                     graphicMemory = &resources[i];
680                     break;
681                 case MediaResource::Type::kDrmSession:
682                     drmSession = &resources[i];
683                     break;
684                 default:
685                     break;
686             }
687         }
688 
689         // first pass to handle secure/non-secure codec conflict
690         if (secureCodec != NULL) {
691             if (!mSupportsMultipleSecureCodecs) {
692                 if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
693                             secureCodec->subType, &idVector, &clients)) {
694                     return Status::ok();
695                 }
696             }
697             if (!mSupportsSecureWithNonSecureCodec) {
698                 if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec,
699                             secureCodec->subType, &idVector, &clients)) {
700                     return Status::ok();
701                 }
702             }
703         }
704         if (nonSecureCodec != NULL) {
705             if (!mSupportsSecureWithNonSecureCodec) {
706                 if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec,
707                         nonSecureCodec->subType, &idVector, &clients)) {
708                     return Status::ok();
709                 }
710             }
711         }
712         if (drmSession != NULL) {
713             getClientForResource_l(callingPid, drmSession, &idVector, &clients);
714             if (clients.size() == 0) {
715                 return Status::ok();
716             }
717         }
718 
719         if (clients.size() == 0) {
720             // if no secure/non-secure codec conflict, run second pass to handle other resources.
721             getClientForResource_l(callingPid, graphicMemory, &idVector, &clients);
722         }
723 
724         if (clients.size() == 0) {
725             // if we are here, run the third pass to free one codec with the same type.
726             getClientForResource_l(callingPid, secureCodec, &idVector, &clients);
727             getClientForResource_l(callingPid, nonSecureCodec, &idVector, &clients);
728         }
729 
730         if (clients.size() == 0) {
731             // if we are here, run the fourth pass to free one codec with the different type.
732             if (secureCodec != NULL) {
733                 MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
734                 getClientForResource_l(callingPid, &temp, &idVector, &clients);
735             }
736             if (nonSecureCodec != NULL) {
737                 MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
738                 getClientForResource_l(callingPid, &temp, &idVector, &clients);
739             }
740         }
741     }
742 
743     *_aidl_return = reclaimUnconditionallyFrom(clients);
744 
745     // Log Reclaim Pushed Atom to statsd
746     pushReclaimAtom(clientInfo, clients, idVector, *_aidl_return);
747 
748     return Status::ok();
749 }
750 
pushReclaimAtom(const ClientInfoParcel & clientInfo,const Vector<std::shared_ptr<IResourceManagerClient>> & clients,const PidUidVector & idVector,bool reclaimed)751 void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
752                         const Vector<std::shared_ptr<IResourceManagerClient>>& clients,
753                         const PidUidVector& idVector, bool reclaimed) {
754     int32_t callingPid = clientInfo.pid;
755     int requesterPriority = -1;
756     getPriority_l(callingPid, &requesterPriority);
757     std::vector<int> priorities;
758     priorities.push_back(requesterPriority);
759 
760     for (PidUidVector::const_reference id : idVector) {
761         int targetPriority = -1;
762         getPriority_l(id.first, &targetPriority);
763         priorities.push_back(targetPriority);
764     }
765     mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, clients,
766                                              idVector, reclaimed);
767 }
768 
reclaimUnconditionallyFrom(const Vector<std::shared_ptr<IResourceManagerClient>> & clients)769 bool ResourceManagerService::reclaimUnconditionallyFrom(
770         const Vector<std::shared_ptr<IResourceManagerClient>> &clients) {
771     if (clients.size() == 0) {
772         return false;
773     }
774 
775     std::shared_ptr<IResourceManagerClient> failedClient;
776     for (size_t i = 0; i < clients.size(); ++i) {
777         String8 log = String8::format("reclaimResource from client %p", clients[i].get());
778         mServiceLog->add(log);
779         bool success;
780         Status status = clients[i]->reclaimResource(&success);
781         if (!status.isOk() || !success) {
782             failedClient = clients[i];
783             break;
784         }
785     }
786 
787     if (failedClient == NULL) {
788         return true;
789     }
790 
791     int failedClientPid = -1;
792     {
793         Mutex::Autolock lock(mLock);
794         bool found = false;
795         for (size_t i = 0; i < mMap.size(); ++i) {
796             ResourceInfos &infos = mMap.editValueAt(i);
797             for (size_t j = 0; j < infos.size();) {
798                 if (infos[j].client == failedClient) {
799                     j = infos.removeItemsAt(j);
800                     found = true;
801                 } else {
802                     ++j;
803                 }
804             }
805             if (found) {
806                 failedClientPid = mMap.keyAt(i);
807                 break;
808             }
809         }
810         if (found) {
811             ALOGW("Failed to reclaim resources from client with pid %d", failedClientPid);
812         } else {
813             ALOGW("Failed to reclaim resources from unlocateable client");
814         }
815     }
816 
817     return false;
818 }
819 
overridePid(int originalPid,int newPid)820 Status ResourceManagerService::overridePid(int originalPid, int newPid) {
821     String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
822             originalPid, newPid);
823     mServiceLog->add(log);
824 
825     // allow if this is called from the same process or the process has
826     // permission.
827     if ((AIBinder_getCallingPid() != getpid()) &&
828         (checkCallingPermission(String16(
829              "android.permission.MEDIA_RESOURCE_OVERRIDE_PID")) == false)) {
830       ALOGE(
831           "Permission Denial: can't access overridePid method from pid=%d, "
832           "self pid=%d\n",
833           AIBinder_getCallingPid(), getpid());
834       return Status::fromServiceSpecificError(PERMISSION_DENIED);
835     }
836 
837     {
838         Mutex::Autolock lock(mLock);
839         mOverridePidMap.erase(originalPid);
840         if (newPid != -1) {
841             mOverridePidMap.emplace(originalPid, newPid);
842             mResourceManagerMetrics->addPid(newPid);
843         }
844     }
845 
846     return Status::ok();
847 }
848 
overrideProcessInfo(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)849 Status ResourceManagerService::overrideProcessInfo(
850         const std::shared_ptr<IResourceManagerClient>& client, int pid, int procState,
851         int oomScore) {
852     String8 log = String8::format("overrideProcessInfo(pid %d, procState %d, oomScore %d)",
853             pid, procState, oomScore);
854     mServiceLog->add(log);
855 
856     // Only allow the override if the caller already can access process state and oom scores.
857     int callingPid = AIBinder_getCallingPid();
858     if (callingPid != getpid() && (callingPid != pid || !checkCallingPermission(String16(
859             "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE")))) {
860         ALOGE("Permission Denial: overrideProcessInfo method from pid=%d", callingPid);
861         return Status::fromServiceSpecificError(PERMISSION_DENIED);
862     }
863 
864     if (client == nullptr) {
865         return Status::fromServiceSpecificError(BAD_VALUE);
866     }
867 
868     Mutex::Autolock lock(mLock);
869     removeProcessInfoOverride_l(pid);
870 
871     if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
872         // Override value is rejected by ProcessInfo.
873         return Status::fromServiceSpecificError(BAD_VALUE);
874     }
875 
876     ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
877                                 .uid = 0,
878                                 .id = 0,
879                                 .name = "<unknown client>"};
880     uintptr_t cookie = addCookieAndLink_l(client,
881             new OverrideProcessInfoDeathNotifier(ref<ResourceManagerService>(), clientInfo));
882 
883     mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{cookie, client});
884 
885     return Status::ok();
886 }
887 
addCookieAndLink_l(const std::shared_ptr<IResourceManagerClient> & client,const sp<DeathNotifier> & notifier)888 uintptr_t ResourceManagerService::addCookieAndLink_l(
889         const std::shared_ptr<IResourceManagerClient>& client, const sp<DeathNotifier>& notifier) {
890     if (client == nullptr) {
891         return 0;
892     }
893     std::scoped_lock lock{sCookieLock};
894 
895     uintptr_t cookie;
896     // Need to skip cookie 0 (if it wraps around). ResourceInfo has cookie initialized to 0
897     // indicating the death notifier is not created yet.
898     while ((cookie = ++sCookieCounter) == 0);
899     AIBinder_linkToDeath(client->asBinder().get(), mDeathRecipient.get(), (void*)cookie);
900     sCookieToDeathNotifierMap.emplace(cookie, notifier);
901 
902     return cookie;
903 }
904 
removeCookieAndUnlink_l(const std::shared_ptr<IResourceManagerClient> & client,uintptr_t cookie)905 void ResourceManagerService::removeCookieAndUnlink_l(
906          const std::shared_ptr<IResourceManagerClient>& client, uintptr_t cookie) {
907     std::scoped_lock lock{sCookieLock};
908     if (client != nullptr) {
909         AIBinder_unlinkToDeath(client->asBinder().get(), mDeathRecipient.get(), (void*)cookie);
910     }
911     sCookieToDeathNotifierMap.erase(cookie);
912 }
913 
removeProcessInfoOverride(int pid)914 void ResourceManagerService::removeProcessInfoOverride(int pid) {
915     Mutex::Autolock lock(mLock);
916 
917     removeProcessInfoOverride_l(pid);
918 }
919 
removeProcessInfoOverride_l(int pid)920 void ResourceManagerService::removeProcessInfoOverride_l(int pid) {
921     auto it = mProcessInfoOverrideMap.find(pid);
922     if (it == mProcessInfoOverrideMap.end()) {
923         return;
924     }
925 
926     mProcessInfo->removeProcessInfoOverride(pid);
927 
928     removeCookieAndUnlink_l(it->second.client, it->second.cookie);
929 
930     mProcessInfoOverrideMap.erase(pid);
931 }
932 
markClientForPendingRemoval(const ClientInfoParcel & clientInfo)933 Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
934     int32_t pid = clientInfo.pid;
935     int64_t clientId = clientInfo.id;
936     String8 log = String8::format(
937             "markClientForPendingRemoval(pid %d, clientId %lld)",
938             pid, (long long) clientId);
939     mServiceLog->add(log);
940 
941     Mutex::Autolock lock(mLock);
942     if (!mProcessInfo->isPidTrusted(pid)) {
943         pid_t callingPid = IPCThreadState::self()->getCallingPid();
944         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
945                 pid, callingPid);
946         pid = callingPid;
947     }
948     ssize_t index = mMap.indexOfKey(pid);
949     if (index < 0) {
950         ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld",
951               pid, (long long)clientId);
952         return Status::ok();
953     }
954     ResourceInfos &infos = mMap.editValueAt(index);
955 
956     index = infos.indexOfKey(clientId);
957     if (index < 0) {
958         ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId);
959         return Status::ok();
960     }
961 
962     ResourceInfo &info = infos.editValueAt(index);
963     info.pendingRemoval = true;
964     return Status::ok();
965 }
966 
reclaimResourcesFromClientsPendingRemoval(int32_t pid)967 Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
968     String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
969     mServiceLog->add(log);
970 
971     Vector<std::shared_ptr<IResourceManagerClient>> clients;
972     {
973         Mutex::Autolock lock(mLock);
974         if (!mProcessInfo->isPidTrusted(pid)) {
975             pid_t callingPid = IPCThreadState::self()->getCallingPid();
976             ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
977                     pid, callingPid);
978             pid = callingPid;
979         }
980 
981         for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
982                                          MediaResource::Type::kNonSecureCodec,
983                                          MediaResource::Type::kGraphicMemory,
984                                          MediaResource::Type::kDrmSession}) {
985             switch (type) {
986                 // Codec resources are segregated by audio, video and image domains.
987                 case MediaResource::Type::kSecureCodec:
988                 case MediaResource::Type::kNonSecureCodec:
989                     for (MediaResource::SubType subType : {MediaResource::SubType::kAudioCodec,
990                                                            MediaResource::SubType::kVideoCodec,
991                                                            MediaResource::SubType::kImageCodec}) {
992                         std::shared_ptr<IResourceManagerClient> client;
993                         uid_t uid = 0;
994                         if (getBiggestClientPendingRemoval_l(pid, type, subType, uid, &client)) {
995                             clients.add(client);
996                             continue;
997                         }
998                     }
999                     break;
1000                 // Non-codec resources are shared by audio, video and image codecs (no subtype).
1001                 default:
1002                     std::shared_ptr<IResourceManagerClient> client;
1003                     uid_t uid = 0;
1004                     if (getBiggestClientPendingRemoval_l(pid, type,
1005                             MediaResource::SubType::kUnspecifiedSubType, uid, &client)) {
1006                         clients.add(client);
1007                     }
1008                     break;
1009             }
1010         }
1011     }
1012 
1013     if (!clients.empty()) {
1014         reclaimUnconditionallyFrom(clients);
1015     }
1016     return Status::ok();
1017 }
1018 
getPriority_l(int pid,int * priority)1019 bool ResourceManagerService::getPriority_l(int pid, int* priority) {
1020     int newPid = pid;
1021 
1022     if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
1023         newPid = mOverridePidMap[pid];
1024         ALOGD("getPriority_l: use override pid %d instead original pid %d",
1025                 newPid, pid);
1026     }
1027 
1028     return mProcessInfo->getPriority(newPid, priority);
1029 }
1030 
getAllClients_l(int callingPid,MediaResource::Type type,MediaResource::SubType subType,PidUidVector * idVector,Vector<std::shared_ptr<IResourceManagerClient>> * clients)1031 bool ResourceManagerService::getAllClients_l(int callingPid, MediaResource::Type type,
1032         MediaResource::SubType subType,
1033         PidUidVector* idVector,
1034         Vector<std::shared_ptr<IResourceManagerClient>> *clients) {
1035     Vector<std::shared_ptr<IResourceManagerClient>> temp;
1036     PidUidVector tempIdList;
1037 
1038     for (size_t i = 0; i < mMap.size(); ++i) {
1039         ResourceInfos &infos = mMap.editValueAt(i);
1040         for (size_t j = 0; j < infos.size(); ++j) {
1041             if (hasResourceType(type, subType, infos[j].resources)) {
1042                 if (!isCallingPriorityHigher_l(callingPid, mMap.keyAt(i))) {
1043                     // some higher/equal priority process owns the resource,
1044                     // this request can't be fulfilled.
1045                     ALOGE("getAllClients_l: can't reclaim resource %s from pid %d",
1046                             asString(type), mMap.keyAt(i));
1047                     return false;
1048                 }
1049                 temp.push_back(infos[j].client);
1050                 tempIdList.emplace_back(mMap.keyAt(i), infos[j].uid);
1051             }
1052         }
1053     }
1054     if (temp.size() == 0) {
1055         ALOGV("getAllClients_l: didn't find any resource %s", asString(type));
1056         return true;
1057     }
1058     clients->appendVector(temp);
1059     idVector->insert(std::end(*idVector), std::begin(tempIdList), std::end(tempIdList));
1060     return true;
1061 }
1062 
getLowestPriorityBiggestClient_l(int callingPid,MediaResource::Type type,MediaResource::SubType subType,PidUidVector * idVector,std::shared_ptr<IResourceManagerClient> * client)1063 bool ResourceManagerService::getLowestPriorityBiggestClient_l(int callingPid,
1064         MediaResource::Type type,
1065         MediaResource::SubType subType,
1066         PidUidVector* idVector,
1067         std::shared_ptr<IResourceManagerClient> *client) {
1068     int lowestPriorityPid;
1069     int lowestPriority;
1070     int callingPriority;
1071     uid_t uid = 0;
1072 
1073     // Before looking into other processes, check if we have clients marked for
1074     // pending removal in the same process.
1075     if (getBiggestClientPendingRemoval_l(callingPid, type, subType, uid, client)) {
1076         idVector->emplace_back(callingPid, uid);
1077         return true;
1078     }
1079     if (!getPriority_l(callingPid, &callingPriority)) {
1080         ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d",
1081                 callingPid);
1082         return false;
1083     }
1084     if (!getLowestPriorityPid_l(type, subType, &lowestPriorityPid, &lowestPriority)) {
1085         return false;
1086     }
1087     if (lowestPriority <= callingPriority) {
1088         ALOGE("getLowestPriorityBiggestClient_l: lowest priority %d vs caller priority %d",
1089                 lowestPriority, callingPriority);
1090         return false;
1091     }
1092 
1093     if (!getBiggestClient_l(lowestPriorityPid, type, subType, uid, client)) {
1094         return false;
1095     }
1096 
1097     idVector->emplace_back(lowestPriorityPid, uid);
1098     return true;
1099 }
1100 
getLowestPriorityPid_l(MediaResource::Type type,MediaResource::SubType subType,int * lowestPriorityPid,int * lowestPriority)1101 bool ResourceManagerService::getLowestPriorityPid_l(MediaResource::Type type,
1102         MediaResource::SubType subType, int *lowestPriorityPid, int *lowestPriority) {
1103     int pid = -1;
1104     int priority = -1;
1105     for (size_t i = 0; i < mMap.size(); ++i) {
1106         if (mMap.valueAt(i).size() == 0) {
1107             // no client on this process.
1108             continue;
1109         }
1110         if (!hasResourceType(type, subType, mMap.valueAt(i))) {
1111             // doesn't have the requested resource type
1112             continue;
1113         }
1114         int tempPid = mMap.keyAt(i);
1115         int tempPriority;
1116         if (!getPriority_l(tempPid, &tempPriority)) {
1117             ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
1118             // TODO: remove this pid from mMap?
1119             continue;
1120         }
1121         if (pid == -1 || tempPriority > priority) {
1122             // initial the value
1123             pid = tempPid;
1124             priority = tempPriority;
1125         }
1126     }
1127     if (pid != -1) {
1128         *lowestPriorityPid = pid;
1129         *lowestPriority = priority;
1130     }
1131     return (pid != -1);
1132 }
1133 
isCallingPriorityHigher_l(int callingPid,int pid)1134 bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
1135     int callingPidPriority;
1136     if (!getPriority_l(callingPid, &callingPidPriority)) {
1137         return false;
1138     }
1139 
1140     int priority;
1141     if (!getPriority_l(pid, &priority)) {
1142         return false;
1143     }
1144 
1145     return (callingPidPriority < priority);
1146 }
1147 
getBiggestClientPendingRemoval_l(int pid,MediaResource::Type type,MediaResource::SubType subType,uid_t & uid,std::shared_ptr<IResourceManagerClient> * client)1148 bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
1149         MediaResource::SubType subType, uid_t& uid,
1150         std::shared_ptr<IResourceManagerClient> *client) {
1151     return getBiggestClient_l(pid, type, subType, uid, client, true /* pendingRemovalOnly */);
1152 }
1153 
getBiggestClient_l(int pid,MediaResource::Type type,MediaResource::SubType subType,uid_t & uid,std::shared_ptr<IResourceManagerClient> * client,bool pendingRemovalOnly)1154 bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
1155         MediaResource::SubType subType, uid_t& uid,
1156         std::shared_ptr<IResourceManagerClient> *client,
1157         bool pendingRemovalOnly) {
1158     ssize_t index = mMap.indexOfKey(pid);
1159     if (index < 0) {
1160         ALOGE_IF(!pendingRemovalOnly,
1161                  "getBiggestClient_l: can't find resource info for pid %d", pid);
1162         return false;
1163     }
1164 
1165     std::shared_ptr<IResourceManagerClient> clientTemp;
1166     uint64_t largestValue = 0;
1167     const ResourceInfos &infos = mMap.valueAt(index);
1168     for (size_t i = 0; i < infos.size(); ++i) {
1169         const ResourceList &resources = infos[i].resources;
1170         if (pendingRemovalOnly && !infos[i].pendingRemoval) {
1171             continue;
1172         }
1173         for (auto it = resources.begin(); it != resources.end(); it++) {
1174             const MediaResourceParcel &resource = it->second;
1175             if (hasResourceType(type, subType, resource)) {
1176                 if (resource.value > largestValue) {
1177                     largestValue = resource.value;
1178                     clientTemp = infos[i].client;
1179                     uid = infos[i].uid;
1180                 }
1181             }
1182         }
1183     }
1184 
1185     if (clientTemp == NULL) {
1186         ALOGE_IF(!pendingRemovalOnly,
1187                  "getBiggestClient_l: can't find resource type %s and subtype %s for pid %d",
1188                  asString(type), asString(subType), pid);
1189         return false;
1190     }
1191 
1192     *client = clientTemp;
1193     return true;
1194 }
1195 
notifyClientCreated(const ClientInfoParcel & clientInfo)1196 Status ResourceManagerService::notifyClientCreated(const ClientInfoParcel& clientInfo) {
1197     mResourceManagerMetrics->notifyClientCreated(clientInfo);
1198     return Status::ok();
1199 }
1200 
notifyClientStarted(const ClientConfigParcel & clientConfig)1201 Status ResourceManagerService::notifyClientStarted(const ClientConfigParcel& clientConfig) {
1202     mResourceManagerMetrics->notifyClientStarted(clientConfig);
1203     return Status::ok();
1204 }
1205 
notifyClientStopped(const ClientConfigParcel & clientConfig)1206 Status ResourceManagerService::notifyClientStopped(const ClientConfigParcel& clientConfig) {
1207     mResourceManagerMetrics->notifyClientStopped(clientConfig);
1208     return Status::ok();
1209 }
1210 
notifyClientConfigChanged(const ClientConfigParcel & clientConfig)1211 Status ResourceManagerService::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
1212     mResourceManagerMetrics->notifyClientConfigChanged(clientConfig);
1213     return Status::ok();
1214 }
1215 
getPeakConcurrentPixelCount(int pid) const1216 long ResourceManagerService::getPeakConcurrentPixelCount(int pid) const {
1217     return mResourceManagerMetrics->getPeakConcurrentPixelCount(pid);
1218 }
1219 
getCurrentConcurrentPixelCount(int pid) const1220 long ResourceManagerService::getCurrentConcurrentPixelCount(int pid) const {
1221     return mResourceManagerMetrics->getCurrentConcurrentPixelCount(pid);
1222 }
1223 
1224 } // namespace android
1225