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