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     if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
314         pid_t callingPid = IPCThreadState::self()->getCallingPid();
315         uid_t callingUid = IPCThreadState::self()->getCallingUid();
316         ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
317                 __FUNCTION__, pid, uid, callingPid, callingUid);
318         pid = callingPid;
319         uid = callingUid;
320     }
321     ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
322     ResourceInfo& info = getResourceInfoForEdit(clientInfo, client, infos);
323     ResourceList resourceAdded;
324 
325     for (size_t i = 0; i < resources.size(); ++i) {
326         const auto &res = resources[i];
327 
328         if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
329             ALOGW("Ignoring request to remove negative value of non-drm resource");
330             continue;
331         }
332         bool isNewEntry = false;
333         if (!info.resources.add(res, &isNewEntry)) {
334             continue;
335         }
336         if (isNewEntry) {
337             onFirstAdded(res, info.uid);
338         }
339 
340         // Add it to the list of added resources for observers.
341         resourceAdded.add(res);
342     }
343     if (info.deathNotifier == nullptr && client != nullptr) {
344         info.deathNotifier = DeathNotifier::Create(
345             client, ref<ResourceManagerService>(), clientInfo);
346     }
347     if (mObserverService != nullptr && !resourceAdded.empty()) {
348         mObserverService->onResourceAdded(uid, pid, resourceAdded);
349     }
350     notifyResourceGranted(pid, resources);
351 
352     return Status::ok();
353 }
354 
removeResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources)355 Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo,
356         const std::vector<MediaResourceParcel>& resources) {
357     int32_t pid = clientInfo.pid;
358     int32_t uid = clientInfo.uid;
359     int64_t clientId = clientInfo.id;
360     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
361             pid, uid, (long long) clientId, getString(resources).c_str());
362     mServiceLog->add(log);
363 
364     std::scoped_lock lock{mLock};
365     if (!mProcessInfo->isPidTrusted(pid)) {
366         pid_t callingPid = IPCThreadState::self()->getCallingPid();
367         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
368                 pid, callingPid);
369         pid = callingPid;
370     }
371     PidResourceInfosMap::iterator found = mMap.find(pid);
372     if (found == mMap.end()) {
373         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
374         return Status::ok();
375     }
376     ResourceInfos& infos = found->second;
377 
378     ResourceInfos::iterator foundClient = infos.find(clientId);
379     if (foundClient == infos.end()) {
380         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
381         return Status::ok();
382     }
383 
384     ResourceInfo& info = foundClient->second;
385     ResourceList resourceRemoved;
386     for (size_t i = 0; i < resources.size(); ++i) {
387         const auto &res = resources[i];
388 
389         if (res.value < 0) {
390             ALOGW("Ignoring request to remove negative value of resource");
391             continue;
392         }
393 
394         long removedEntryValue = -1;
395         if (info.resources.remove(res, &removedEntryValue)) {
396             MediaResourceParcel actualRemoved = res;
397             if (removedEntryValue != -1) {
398                 onLastRemoved(res, info.uid);
399                 actualRemoved.value = removedEntryValue;
400             }
401 
402             // Add it to the list of removed resources for observers.
403             resourceRemoved.add(actualRemoved);
404         }
405     }
406     if (mObserverService != nullptr && !resourceRemoved.empty()) {
407         mObserverService->onResourceRemoved(info.uid, pid, resourceRemoved);
408     }
409     return Status::ok();
410 }
411 
removeClient(const ClientInfoParcel & clientInfo)412 Status ResourceManagerService::removeClient(const ClientInfoParcel& clientInfo) {
413     removeResource(clientInfo, true /*checkValid*/);
414     return Status::ok();
415 }
416 
removeResource(const ClientInfoParcel & clientInfo,bool checkValid)417 Status ResourceManagerService::removeResource(const ClientInfoParcel& clientInfo, bool checkValid) {
418     int32_t pid = clientInfo.pid;
419     int32_t uid = clientInfo.uid;
420     int64_t clientId = clientInfo.id;
421     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
422             pid, uid, (long long) clientId);
423     mServiceLog->add(log);
424 
425     std::scoped_lock lock{mLock};
426     if (checkValid && !mProcessInfo->isPidTrusted(pid)) {
427         pid_t callingPid = IPCThreadState::self()->getCallingPid();
428         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
429                 pid, callingPid);
430         pid = callingPid;
431     }
432     PidResourceInfosMap::iterator found = mMap.find(pid);
433     if (found == mMap.end()) {
434         ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
435         return Status::ok();
436     }
437     ResourceInfos& infos = found->second;
438 
439     ResourceInfos::iterator foundClient = infos.find(clientId);
440     if (foundClient == infos.end()) {
441         ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
442         return Status::ok();
443     }
444 
445     const ResourceInfo& info = foundClient->second;
446     for (const MediaResourceParcel& res : info.resources.getResources()) {
447         onLastRemoved(res, info.uid);
448     }
449 
450     // Since this client has been removed, update the metrics collector.
451     mResourceManagerMetrics->notifyClientReleased(clientInfo);
452 
453     if (mObserverService != nullptr && !info.resources.empty()) {
454         mObserverService->onResourceRemoved(info.uid, pid, info.resources);
455     }
456 
457     infos.erase(foundClient);
458     return Status::ok();
459 }
460 
getClientForResource_l(const ResourceRequestInfo & resourceRequestInfo,std::vector<ClientInfo> & clientsInfo)461 void ResourceManagerService::getClientForResource_l(
462         const ResourceRequestInfo& resourceRequestInfo,
463         std::vector<ClientInfo>& clientsInfo) {
464     int callingPid = resourceRequestInfo.mCallingPid;
465     const MediaResourceParcel* res = resourceRequestInfo.mResource;
466     if (res == NULL) {
467         return;
468     }
469 
470     // Before looking into other processes, check if we have clients marked for
471     // pending removal in the same process.
472     ClientInfo clientInfo;
473     if (getBiggestClientPendingRemoval_l(callingPid, res->type, res->subType, clientInfo)) {
474         clientsInfo.emplace_back(clientInfo);
475         return;
476     }
477 
478     // Now find client(s) from a lowest priority process that has needed resources.
479     if (getLowestPriorityBiggestClient_l(resourceRequestInfo, clientInfo)) {
480         clientsInfo.push_back(clientInfo);
481     }
482 }
483 
getTargetClients(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources,std::vector<ClientInfo> & targetClients)484 bool ResourceManagerService::getTargetClients(
485         const ClientInfoParcel& clientInfo,
486         const std::vector<MediaResourceParcel>& resources,
487         std::vector<ClientInfo>& targetClients) {
488     int32_t callingPid = clientInfo.pid;
489     int64_t clientId = clientInfo.id;
490     std::scoped_lock lock{mLock};
491     if (!mProcessInfo->isPidTrusted(callingPid)) {
492         pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
493         ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
494                 callingPid, actualCallingPid);
495         callingPid = actualCallingPid;
496     }
497     const MediaResourceParcel *secureCodec = NULL;
498     const MediaResourceParcel *nonSecureCodec = NULL;
499     const MediaResourceParcel *graphicMemory = NULL;
500     const MediaResourceParcel *drmSession = NULL;
501     for (size_t i = 0; i < resources.size(); ++i) {
502         switch (resources[i].type) {
503             case MediaResource::Type::kSecureCodec:
504                 secureCodec = &resources[i];
505                 break;
506             case MediaResource::Type::kNonSecureCodec:
507                 nonSecureCodec = &resources[i];
508                 break;
509             case MediaResource::Type::kGraphicMemory:
510                 graphicMemory = &resources[i];
511                 break;
512             case MediaResource::Type::kDrmSession:
513                 drmSession = &resources[i];
514                 break;
515             default:
516                 break;
517         }
518     }
519 
520     // first pass to handle secure/non-secure codec conflict
521     if (secureCodec != NULL) {
522         MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
523                                           .subType = secureCodec->subType};
524         ResourceRequestInfo resourceRequestInfo{callingPid, clientId, &mediaResource};
525         if (!mSupportsMultipleSecureCodecs) {
526             if (!getAllClients_l(resourceRequestInfo, targetClients)) {
527                 return false;
528             }
529         }
530         if (!mSupportsSecureWithNonSecureCodec) {
531             mediaResource.type = MediaResource::Type::kNonSecureCodec;
532             if (!getAllClients_l(resourceRequestInfo, targetClients)) {
533                 return false;
534             }
535         }
536     }
537     if (nonSecureCodec != NULL) {
538         if (!mSupportsSecureWithNonSecureCodec) {
539             MediaResourceParcel mediaResource{.type = MediaResource::Type::kSecureCodec,
540                                               .subType = nonSecureCodec->subType};
541             ResourceRequestInfo resourceRequestInfo{callingPid, clientId, &mediaResource};
542             if (!getAllClients_l(resourceRequestInfo, targetClients)) {
543                 return false;
544             }
545         }
546     }
547 
548     if (drmSession != NULL) {
549         ResourceRequestInfo resourceRequestInfo{callingPid, clientId, drmSession};
550         getClientForResource_l(resourceRequestInfo, targetClients);
551         if (targetClients.size() == 0) {
552             return false;
553         }
554     }
555 
556     if (targetClients.size() == 0 && graphicMemory != nullptr) {
557         // if no secure/non-secure codec conflict, run second pass to handle other resources.
558         ResourceRequestInfo resourceRequestInfo{callingPid, clientId, graphicMemory};
559         getClientForResource_l(resourceRequestInfo, targetClients);
560     }
561 
562     if (targetClients.size() == 0) {
563         // if we are here, run the third pass to free one codec with the same type.
564         if (secureCodec != nullptr) {
565             ResourceRequestInfo resourceRequestInfo{callingPid, clientId, secureCodec};
566             getClientForResource_l(resourceRequestInfo, targetClients);
567         }
568         if (nonSecureCodec != nullptr) {
569             ResourceRequestInfo resourceRequestInfo{callingPid, clientId, nonSecureCodec};
570             getClientForResource_l(resourceRequestInfo, targetClients);
571         }
572     }
573 
574     if (targetClients.size() == 0) {
575         // if we are here, run the fourth pass to free one codec with the different type.
576         if (secureCodec != nullptr) {
577             MediaResource temp(MediaResource::Type::kNonSecureCodec, secureCodec->subType, 1);
578             ResourceRequestInfo resourceRequestInfo{callingPid, clientId, &temp};
579             getClientForResource_l(resourceRequestInfo, targetClients);
580         }
581         if (nonSecureCodec != nullptr) {
582             MediaResource temp(MediaResource::Type::kSecureCodec, nonSecureCodec->subType, 1);
583             ResourceRequestInfo resourceRequestInfo{callingPid, clientId, &temp};
584             getClientForResource_l(resourceRequestInfo, targetClients);
585         }
586     }
587 
588     return !targetClients.empty();
589 }
590 
reclaimResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources,bool * _aidl_return)591 Status ResourceManagerService::reclaimResource(const ClientInfoParcel& clientInfo,
592         const std::vector<MediaResourceParcel>& resources, bool* _aidl_return) {
593     std::string clientName = clientInfo.name;
594     String8 log = String8::format("reclaimResource(callingPid %d, uid %d resources %s)",
595             clientInfo.pid, clientInfo.uid, getString(resources).c_str());
596     mServiceLog->add(log);
597     *_aidl_return = false;
598 
599     // Check if there are any resources to be reclaimed before processing.
600     if (resources.empty()) {
601         // Invalid reclaim request. So no need to log.
602         return Status::ok();
603     }
604 
605     std::vector<ClientInfo> targetClients;
606     if (getTargetClients(clientInfo, resources, targetClients)) {
607         // Reclaim all the target clients.
608         *_aidl_return = reclaimUnconditionallyFrom(targetClients);
609     } else {
610         // No clients to reclaim from.
611         ALOGI("%s: There aren't any clients to reclaim from", __func__);
612         // We need to log this failed reclaim as "no clients to reclaim from".
613         targetClients.clear();
614     }
615 
616     // Log Reclaim Pushed Atom to statsd
617     pushReclaimAtom(clientInfo, targetClients, *_aidl_return);
618 
619     return Status::ok();
620 }
621 
pushReclaimAtom(const ClientInfoParcel & clientInfo,const std::vector<ClientInfo> & targetClients,bool reclaimed)622 void ResourceManagerService::pushReclaimAtom(const ClientInfoParcel& clientInfo,
623                                              const std::vector<ClientInfo>& targetClients,
624                                              bool reclaimed) {
625     int32_t callingPid = clientInfo.pid;
626     int requesterPriority = -1;
627     getPriority_l(callingPid, &requesterPriority);
628     std::vector<int> priorities;
629     priorities.push_back(requesterPriority);
630 
631     for (const ClientInfo& targetClient : targetClients) {
632         int targetPriority = -1;
633         getPriority_l(targetClient.mPid, &targetPriority);
634         priorities.push_back(targetPriority);
635     }
636     mResourceManagerMetrics->pushReclaimAtom(clientInfo, priorities, targetClients, reclaimed);
637 }
638 
getClient_l(int pid,const int64_t & clientId) const639 std::shared_ptr<IResourceManagerClient> ResourceManagerService::getClient_l(
640         int pid, const int64_t& clientId) const {
641     std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
642     if (found == mMap.end()) {
643         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
644         return nullptr;
645     }
646 
647     const ResourceInfos& infos = found->second;
648     ResourceInfos::const_iterator foundClient = infos.find(clientId);
649     if (foundClient == infos.end()) {
650         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
651         return nullptr;
652     }
653 
654     return foundClient->second.client;
655 }
656 
removeClient_l(int pid,const int64_t & clientId)657 bool ResourceManagerService::removeClient_l(int pid, const int64_t& clientId) {
658     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
659     if (found == mMap.end()) {
660         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
661         return false;
662     }
663 
664     ResourceInfos& infos = found->second;
665     ResourceInfos::iterator foundClient = infos.find(clientId);
666     if (foundClient == infos.end()) {
667         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
668         return false;
669     }
670 
671     infos.erase(foundClient);
672     return true;
673 }
674 
reclaimUnconditionallyFrom(const std::vector<ClientInfo> & targetClients)675 bool ResourceManagerService::reclaimUnconditionallyFrom(
676         const std::vector<ClientInfo>& targetClients) {
677     if (targetClients.size() == 0) {
678         return false;
679     }
680 
681     int64_t failedClientId = -1;
682     int32_t failedClientPid = -1;
683     for (const ClientInfo& targetClient : targetClients) {
684         std::shared_ptr<IResourceManagerClient> client = nullptr;
685         {
686             std::scoped_lock lock{mLock};
687             client = getClient_l(targetClient.mPid, targetClient.mClientId);
688         }
689         if (client == nullptr) {
690             // skip already released clients.
691             continue;
692         }
693         String8 log = String8::format("reclaimResource from client %p", client.get());
694         mServiceLog->add(log);
695         bool success;
696         Status status = client->reclaimResource(&success);
697         if (!status.isOk() || !success) {
698             failedClientId = targetClient.mClientId;
699             failedClientPid = targetClient.mPid;
700             break;
701         }
702     }
703 
704     if (failedClientId == -1) {
705         return true;
706     }
707 
708     {
709         std::scoped_lock lock{mLock};
710         bool found = removeClient_l(failedClientPid, failedClientId);
711         if (found) {
712             ALOGW("Failed to reclaim resources from client with pid %d", failedClientPid);
713         } else {
714             ALOGW("Failed to reclaim resources from unlocateable client");
715         }
716     }
717 
718     return false;
719 }
720 
overridePid_l(int32_t originalPid,int32_t newPid)721 bool ResourceManagerService::overridePid_l(int32_t originalPid, int32_t newPid) {
722     mOverridePidMap.erase(originalPid);
723     if (newPid != -1) {
724         mOverridePidMap.emplace(originalPid, newPid);
725         return true;
726     }
727 
728     return false;
729 }
730 
overridePid(int originalPid,int newPid)731 Status ResourceManagerService::overridePid(int originalPid, int newPid) {
732     String8 log = String8::format("overridePid(originalPid %d, newPid %d)",
733             originalPid, newPid);
734     mServiceLog->add(log);
735 
736     // allow if this is called from the same process or the process has
737     // permission.
738     if ((AIBinder_getCallingPid() != getpid()) &&
739         (checkCallingPermission(String16(
740              "android.permission.MEDIA_RESOURCE_OVERRIDE_PID")) == false)) {
741       ALOGE(
742           "Permission Denial: can't access overridePid method from pid=%d, "
743           "self pid=%d\n",
744           AIBinder_getCallingPid(), getpid());
745       return Status::fromServiceSpecificError(PERMISSION_DENIED);
746     }
747 
748     {
749         std::scoped_lock lock{mLock};
750         if (overridePid_l(originalPid, newPid)) {
751             mResourceManagerMetrics->addPid(newPid);
752         }
753     }
754 
755     return Status::ok();
756 }
757 
overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)758 bool ResourceManagerService::overrideProcessInfo_l(
759         const std::shared_ptr<IResourceManagerClient>& client,
760         int pid,
761         int procState,
762         int oomScore) {
763     removeProcessInfoOverride_l(pid);
764 
765     if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
766         // Override value is rejected by ProcessInfo.
767         return false;
768     }
769 
770     ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
771                                 .uid = 0,
772                                 .id = 0,
773                                 .name = "<unknown client>"};
774     auto deathNotifier = DeathNotifier::Create(
775         client, ref<ResourceManagerService>(), clientInfo, true);
776 
777     mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});
778     return true;
779 }
780 
overrideProcessInfo(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)781 Status ResourceManagerService::overrideProcessInfo(
782         const std::shared_ptr<IResourceManagerClient>& client, int pid, int procState,
783         int oomScore) {
784     String8 log = String8::format("overrideProcessInfo(pid %d, procState %d, oomScore %d)",
785             pid, procState, oomScore);
786     mServiceLog->add(log);
787 
788     // Only allow the override if the caller already can access process state and oom scores.
789     int callingPid = AIBinder_getCallingPid();
790     if (callingPid != getpid() && (callingPid != pid || !checkCallingPermission(String16(
791             "android.permission.GET_PROCESS_STATE_AND_OOM_SCORE")))) {
792         ALOGE("Permission Denial: overrideProcessInfo method from pid=%d", callingPid);
793         return Status::fromServiceSpecificError(PERMISSION_DENIED);
794     }
795 
796     if (client == nullptr) {
797         return Status::fromServiceSpecificError(BAD_VALUE);
798     }
799 
800     std::scoped_lock lock{mLock};
801     if (!overrideProcessInfo_l(client, pid, procState, oomScore)) {
802         // Override value is rejected by ProcessInfo.
803         return Status::fromServiceSpecificError(BAD_VALUE);
804     }
805     return Status::ok();
806 
807 }
808 
removeProcessInfoOverride(int pid)809 void ResourceManagerService::removeProcessInfoOverride(int pid) {
810     std::scoped_lock lock{mLock};
811 
812     removeProcessInfoOverride_l(pid);
813 }
814 
removeProcessInfoOverride_l(int pid)815 void ResourceManagerService::removeProcessInfoOverride_l(int pid) {
816     auto it = mProcessInfoOverrideMap.find(pid);
817     if (it == mProcessInfoOverrideMap.end()) {
818         return;
819     }
820 
821     mProcessInfo->removeProcessInfoOverride(pid);
822     mProcessInfoOverrideMap.erase(pid);
823 }
824 
markClientForPendingRemoval(const ClientInfoParcel & clientInfo)825 Status ResourceManagerService::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
826     int32_t pid = clientInfo.pid;
827     int64_t clientId = clientInfo.id;
828     String8 log = String8::format(
829             "markClientForPendingRemoval(pid %d, clientId %lld)",
830             pid, (long long) clientId);
831     mServiceLog->add(log);
832 
833     std::scoped_lock lock{mLock};
834     if (!mProcessInfo->isPidTrusted(pid)) {
835         pid_t callingPid = IPCThreadState::self()->getCallingPid();
836         ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
837                 pid, callingPid);
838         pid = callingPid;
839     }
840     PidResourceInfosMap::iterator found = mMap.find(pid);
841     if (found == mMap.end()) {
842         ALOGV("markClientForPendingRemoval: didn't find pid %d for clientId %lld",
843               pid, (long long)clientId);
844         return Status::ok();
845     }
846     ResourceInfos& infos = found->second;
847 
848     ResourceInfos::iterator foundClient = infos.find(clientId);
849     if (foundClient == infos.end()) {
850         ALOGV("markClientForPendingRemoval: didn't find clientId %lld", (long long) clientId);
851         return Status::ok();
852     }
853 
854     ResourceInfo& info = foundClient->second;
855     info.pendingRemoval = true;
856     return Status::ok();
857 }
858 
reclaimResourcesFromClientsPendingRemoval(int32_t pid)859 Status ResourceManagerService::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
860     String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
861     mServiceLog->add(log);
862 
863     std::vector<ClientInfo> targetClients;
864     {
865         std::scoped_lock lock{mLock};
866         if (!mProcessInfo->isPidTrusted(pid)) {
867             pid_t callingPid = IPCThreadState::self()->getCallingPid();
868             ALOGW("%s called with untrusted pid %d, using calling pid %d", __FUNCTION__,
869                     pid, callingPid);
870             pid = callingPid;
871         }
872 
873         for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
874                                          MediaResource::Type::kNonSecureCodec,
875                                          MediaResource::Type::kGraphicMemory,
876                                          MediaResource::Type::kDrmSession}) {
877             switch (type) {
878                 // Codec resources are segregated by audio, video and image domains.
879                 case MediaResource::Type::kSecureCodec:
880                 case MediaResource::Type::kNonSecureCodec:
881                     for (MediaResource::SubType subType : {MediaResource::SubType::kHwAudioCodec,
882                                                            MediaResource::SubType::kSwAudioCodec,
883                                                            MediaResource::SubType::kHwVideoCodec,
884                                                            MediaResource::SubType::kSwVideoCodec,
885                                                            MediaResource::SubType::kHwImageCodec,
886                                                            MediaResource::SubType::kSwImageCodec}) {
887                         ClientInfo clientInfo;
888                         if (getBiggestClientPendingRemoval_l(pid, type, subType, clientInfo)) {
889                             targetClients.emplace_back(clientInfo);
890                             continue;
891                         }
892                     }
893                     break;
894                 // Non-codec resources are shared by audio, video and image codecs (no subtype).
895                 default:
896                     ClientInfo clientInfo;
897                     if (getBiggestClientPendingRemoval_l(pid, type,
898                             MediaResource::SubType::kUnspecifiedSubType, clientInfo)) {
899                         targetClients.emplace_back(clientInfo);
900                     }
901                     break;
902             }
903         }
904     }
905 
906     if (!targetClients.empty()) {
907         reclaimUnconditionallyFrom(targetClients);
908     }
909     return Status::ok();
910 }
911 
getPriority_l(int pid,int * priority) const912 bool ResourceManagerService::getPriority_l(int pid, int* priority) const {
913     int newPid = pid;
914 
915     std::map<int, int>::const_iterator found = mOverridePidMap.find(pid);
916     if (found != mOverridePidMap.end()) {
917         newPid = found->second;
918         ALOGD("getPriority_l: use override pid %d instead original pid %d",
919                 newPid, pid);
920     }
921 
922     return mProcessInfo->getPriority(newPid, priority);
923 }
924 
getAllClients_l(const ResourceRequestInfo & resourceRequestInfo,std::vector<ClientInfo> & clientsInfo)925 bool ResourceManagerService::getAllClients_l(
926         const ResourceRequestInfo& resourceRequestInfo,
927         std::vector<ClientInfo>& clientsInfo) {
928     MediaResource::Type type = resourceRequestInfo.mResource->type;
929     MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
930 
931     for (auto& [pid, infos] : mMap) {
932         for (const auto& [id, info] : infos) {
933             if (pid == resourceRequestInfo.mCallingPid && id == resourceRequestInfo.mClientId) {
934                 ALOGI("%s: Skip the client[%jd] for which the resource request is made",
935                       __func__, id);
936                 continue;
937             }
938             if (hasResourceType(type, subType, info.resources)) {
939                 if (!isCallingPriorityHigher_l(resourceRequestInfo.mCallingPid, pid)) {
940                     // some higher/equal priority process owns the resource,
941                     // this request can't be fulfilled.
942                     ALOGE("%s: can't reclaim resource %s from pid %d",
943                           __func__, asString(type), pid);
944                     clientsInfo.clear();
945                     return false;
946                 }
947                 clientsInfo.emplace_back(pid, info.uid, info.clientId);
948             }
949         }
950     }
951     if (clientsInfo.size() == 0) {
952         ALOGV("%s: didn't find any resource %s", __func__, asString(type));
953     }
954     return true;
955 }
956 
957 // Process priority (oom score) based reclaim:
958 //   - Find a process with lowest priority (than that of calling process).
959 //   - Find the bigegst client (with required resources) from that process.
getLowestPriorityBiggestClient_l(const ResourceRequestInfo & resourceRequestInfo,ClientInfo & clientInfo)960 bool ResourceManagerService::getLowestPriorityBiggestClient_l(
961         const ResourceRequestInfo& resourceRequestInfo,
962         ClientInfo& clientInfo) {
963     int callingPid = resourceRequestInfo.mCallingPid;
964     MediaResource::Type type = resourceRequestInfo.mResource->type;
965     MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
966     int lowestPriorityPid;
967     int lowestPriority;
968     int callingPriority;
969 
970     if (!getPriority_l(callingPid, &callingPriority)) {
971         ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
972         return false;
973     }
974     if (!getLowestPriorityPid_l(type, subType, &lowestPriorityPid, &lowestPriority)) {
975         return false;
976     }
977     if (lowestPriority <= callingPriority) {
978         ALOGE("%s: lowest priority %d vs caller priority %d",
979               __func__, lowestPriority, callingPriority);
980         return false;
981     }
982 
983     if (!getBiggestClient_l(lowestPriorityPid, type, subType, clientInfo)) {
984         return false;
985     }
986 
987     ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)",
988           __func__, callingPid, callingPriority, lowestPriorityPid, lowestPriority);
989     return true;
990 }
991 
getLowestPriorityPid_l(MediaResource::Type type,MediaResource::SubType subType,int * lowestPriorityPid,int * lowestPriority)992 bool ResourceManagerService::getLowestPriorityPid_l(MediaResource::Type type,
993         MediaResource::SubType subType, int *lowestPriorityPid, int *lowestPriority) {
994     int pid = -1;
995     int priority = -1;
996     for (auto& [tempPid, infos] : mMap) {
997         if (infos.size() == 0) {
998             // no client on this process.
999             continue;
1000         }
1001         if (!hasResourceType(type, subType, infos)) {
1002             // doesn't have the requested resource type
1003             continue;
1004         }
1005         int tempPriority = -1;
1006         if (!getPriority_l(tempPid, &tempPriority)) {
1007             ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid);
1008             // TODO: remove this pid from mMap?
1009             continue;
1010         }
1011         if (pid == -1 || tempPriority > priority) {
1012             // initial the value
1013             pid = tempPid;
1014             priority = tempPriority;
1015         }
1016     }
1017     if (pid != -1) {
1018         *lowestPriorityPid = pid;
1019         *lowestPriority = priority;
1020     }
1021     return (pid != -1);
1022 }
1023 
isCallingPriorityHigher_l(int callingPid,int pid)1024 bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) {
1025     int callingPidPriority;
1026     if (!getPriority_l(callingPid, &callingPidPriority)) {
1027         return false;
1028     }
1029 
1030     int priority;
1031     if (!getPriority_l(pid, &priority)) {
1032         return false;
1033     }
1034 
1035     return (callingPidPriority < priority);
1036 }
1037 
getBiggestClientPendingRemoval_l(int pid,MediaResource::Type type,MediaResource::SubType subType,ClientInfo & clientInfo)1038 bool ResourceManagerService::getBiggestClientPendingRemoval_l(int pid, MediaResource::Type type,
1039         MediaResource::SubType subType, ClientInfo& clientInfo) {
1040     return getBiggestClient_l(pid, type, subType, clientInfo, true /* pendingRemovalOnly */);
1041 }
1042 
getBiggestClient_l(int pid,MediaResource::Type type,MediaResource::SubType subType,ClientInfo & clientInfo,bool pendingRemovalOnly)1043 bool ResourceManagerService::getBiggestClient_l(int pid, MediaResource::Type type,
1044         MediaResource::SubType subType, ClientInfo& clientInfo, bool pendingRemovalOnly) {
1045     PidResourceInfosMap::iterator found = mMap.find(pid);
1046     if (found == mMap.end()) {
1047         ALOGE_IF(!pendingRemovalOnly,
1048                  "getBiggestClient_l: can't find resource info for pid %d", pid);
1049         return false;
1050     }
1051 
1052     uid_t   uid = -1;
1053     int64_t clientId = -1;
1054     uint64_t largestValue = 0;
1055     const ResourceInfos& infos = found->second;
1056     for (const auto& [id, info] : infos) {
1057         const ResourceList& resources = info.resources;
1058         if (pendingRemovalOnly && !info.pendingRemoval) {
1059             continue;
1060         }
1061         for (const MediaResourceParcel& resource : resources.getResources()) {
1062             if (hasResourceType(type, subType, resource)) {
1063                 if (resource.value > largestValue) {
1064                     largestValue = resource.value;
1065                     clientId = info.clientId;
1066                     uid = info.uid;
1067                 }
1068             }
1069         }
1070     }
1071 
1072     if (clientId == -1) {
1073         ALOGE_IF(!pendingRemovalOnly,
1074                  "getBiggestClient_l: can't find resource type %s and subtype %s for pid %d",
1075                  asString(type), asString(subType), pid);
1076         return false;
1077     }
1078 
1079     clientInfo.mPid = pid;
1080     clientInfo.mUid = uid;
1081     clientInfo.mClientId = clientId;
1082     return true;
1083 }
1084 
notifyClientCreated(const ClientInfoParcel & clientInfo)1085 Status ResourceManagerService::notifyClientCreated(const ClientInfoParcel& clientInfo) {
1086     mResourceManagerMetrics->notifyClientCreated(clientInfo);
1087     return Status::ok();
1088 }
1089 
notifyClientStarted(const ClientConfigParcel & clientConfig)1090 Status ResourceManagerService::notifyClientStarted(const ClientConfigParcel& clientConfig) {
1091     mResourceManagerMetrics->notifyClientStarted(clientConfig);
1092     return Status::ok();
1093 }
1094 
notifyClientStopped(const ClientConfigParcel & clientConfig)1095 Status ResourceManagerService::notifyClientStopped(const ClientConfigParcel& clientConfig) {
1096     mResourceManagerMetrics->notifyClientStopped(clientConfig);
1097     return Status::ok();
1098 }
1099 
notifyClientConfigChanged(const ClientConfigParcel & clientConfig)1100 Status ResourceManagerService::notifyClientConfigChanged(const ClientConfigParcel& clientConfig) {
1101     mResourceManagerMetrics->notifyClientConfigChanged(clientConfig);
1102     return Status::ok();
1103 }
1104 
getPeakConcurrentPixelCount(int pid) const1105 long ResourceManagerService::getPeakConcurrentPixelCount(int pid) const {
1106     return mResourceManagerMetrics->getPeakConcurrentPixelCount(pid);
1107 }
1108 
getCurrentConcurrentPixelCount(int pid) const1109 long ResourceManagerService::getCurrentConcurrentPixelCount(int pid) const {
1110     return mResourceManagerMetrics->getCurrentConcurrentPixelCount(pid);
1111 }
1112 
notifyClientReleased(const ClientInfoParcel & clientInfo)1113 void ResourceManagerService::notifyClientReleased(const ClientInfoParcel& clientInfo) {
1114     mResourceManagerMetrics->notifyClientReleased(clientInfo);
1115 }
1116 
1117 } // namespace android
1118