1 /*
2 **
3 ** Copyright 2023, 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 "ResourceTracker"
20 #include <utils/Log.h>
21 
22 #include <binder/IPCThreadState.h>
23 #include <mediautils/ProcessInfo.h>
24 #include "ResourceTracker.h"
25 #include "ResourceManagerServiceNew.h"
26 #include "ResourceObserverService.h"
27 
28 namespace android {
29 
isHwCodec(MediaResource::SubType subType)30 inline bool isHwCodec(MediaResource::SubType subType) {
31     return subType == MediaResource::SubType::kHwImageCodec ||
32            subType == MediaResource::SubType::kHwVideoCodec;
33 }
34 
35 // Check whether a given resource (of type and subtype) is found in given resource list
36 // that also has the given Primary SubType.
hasResourceType(MediaResource::Type type,MediaResource::SubType subType,const ResourceList & resources,MediaResource::SubType primarySubType)37 static bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
38                             const ResourceList& resources, MediaResource::SubType primarySubType) {
39     bool foundResource = false;
40     bool matchedPrimary =
41         (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
42     for (const MediaResourceParcel& res : resources.getResources()) {
43         if (hasResourceType(type, subType, res)) {
44             foundResource = true;
45         } else if (res.subType == primarySubType) {
46             matchedPrimary = true;
47         } else if (isHwCodec(res.subType) == isHwCodec(primarySubType)) {
48             matchedPrimary = true;
49         }
50         if (matchedPrimary && foundResource) {
51             return true;
52         }
53     }
54     return false;
55 }
56 
57 // See if the given client is already in the list of clients.
contains(const std::vector<ClientInfo> & clients,const int64_t & clientId)58 inline bool contains(const std::vector<ClientInfo>& clients, const int64_t& clientId) {
59     std::vector<ClientInfo>::const_iterator found =
60         std::find_if(clients.begin(), clients.end(),
61                      [clientId](const ClientInfo& client) -> bool {
62                          return client.mClientId == clientId;
63                      });
64 
65     return found != clients.end();
66 }
67 
68 
ResourceTracker(const std::shared_ptr<ResourceManagerServiceNew> & service,const sp<ProcessInfoInterface> & processInfo)69 ResourceTracker::ResourceTracker(const std::shared_ptr<ResourceManagerServiceNew>& service,
70                                  const sp<ProcessInfoInterface>& processInfo) :
71         mService(service),
72         mProcessInfo(processInfo) {
73 }
74 
~ResourceTracker()75 ResourceTracker::~ResourceTracker() {
76 }
77 
setResourceObserverService(const std::shared_ptr<ResourceObserverService> & observerService)78 void ResourceTracker::setResourceObserverService(
79         const std::shared_ptr<ResourceObserverService>& observerService) {
80     mObserverService = observerService;
81 }
82 
getResourceInfosForEdit(int pid)83 ResourceInfos& ResourceTracker::getResourceInfosForEdit(int pid) {
84     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
85     if (found == mMap.end()) {
86         // new pid
87         ResourceInfos infosForPid;
88         auto [it, inserted] = mMap.emplace(pid, infosForPid);
89         found = it;
90     }
91 
92     return found->second;
93 }
94 
addResource(const ClientInfoParcel & clientInfo,const std::shared_ptr<IResourceManagerClient> & client,const std::vector<MediaResourceParcel> & resources)95 bool ResourceTracker::addResource(const ClientInfoParcel& clientInfo,
96                                   const std::shared_ptr<IResourceManagerClient>& client,
97                                   const std::vector<MediaResourceParcel>& resources) {
98     int32_t pid = clientInfo.pid;
99     int32_t uid = clientInfo.uid;
100 
101     if (!mProcessInfo->isPidUidTrusted(pid, uid)) {
102         pid_t callingPid = IPCThreadState::self()->getCallingPid();
103         uid_t callingUid = IPCThreadState::self()->getCallingUid();
104         ALOGW("%s called with untrusted pid %d or uid %d, using calling pid %d, uid %d",
105                 __func__, pid, uid, callingPid, callingUid);
106         pid = callingPid;
107         uid = callingUid;
108     }
109     ResourceInfos& infos = getResourceInfosForEdit(pid);
110     ResourceInfo& info = getResourceInfoForEdit(clientInfo, client, infos);
111     ResourceList resourceAdded;
112 
113     for (const MediaResourceParcel& res : resources) {
114         if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
115             ALOGV("%s: Ignoring request to remove negative value of non-drm resource", __func__);
116             continue;
117         }
118         bool isNewEntry = false;
119         if (!info.resources.add(res, &isNewEntry)) {
120             continue;
121         }
122         if (isNewEntry) {
123             onFirstAdded(res, info.uid);
124         }
125 
126         // Add it to the list of added resources for observers.
127         resourceAdded.add(res);
128     }
129     if (info.deathNotifier == nullptr && client != nullptr) {
130         info.deathNotifier = DeathNotifier::Create(client, mService, clientInfo);
131     }
132     if (mObserverService != nullptr && !resourceAdded.empty()) {
133         mObserverService->onResourceAdded(uid, pid, resourceAdded);
134     }
135 
136     return !resourceAdded.empty();
137 }
138 
updateResource(const aidl::android::media::ClientInfoParcel & clientInfo)139 bool ResourceTracker::updateResource(const aidl::android::media::ClientInfoParcel& clientInfo) {
140     ResourceInfos& infos = getResourceInfosForEdit(clientInfo.pid);
141 
142     ResourceInfos::iterator found = infos.find(clientInfo.id);
143     if (found == infos.end()) {
144         return false;
145     }
146     // Update the client importance.
147     found->second.importance = std::max(0, clientInfo.importance);
148     return true;
149 }
150 
removeResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources)151 bool ResourceTracker::removeResource(const ClientInfoParcel& clientInfo,
152                                      const std::vector<MediaResourceParcel>& resources) {
153     int32_t pid = clientInfo.pid;
154     int64_t clientId = clientInfo.id;
155 
156     if (!mProcessInfo->isPidTrusted(pid)) {
157         pid_t callingPid = IPCThreadState::self()->getCallingPid();
158         ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
159                 pid, callingPid);
160         pid = callingPid;
161     }
162     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
163     if (found == mMap.end()) {
164         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
165         return false;
166     }
167 
168     ResourceInfos& infos = found->second;
169     ResourceInfos::iterator foundClient = infos.find(clientId);
170     if (foundClient == infos.end()) {
171         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
172         return false;
173     }
174 
175     ResourceInfo& info = foundClient->second;
176     ResourceList resourceRemoved;
177     for (const MediaResourceParcel& res : resources) {
178         if (res.value < 0) {
179             ALOGV("%s: Ignoring request to remove negative value of resource", __func__);
180             continue;
181         }
182 
183         long removedEntryValue = -1;
184         if (info.resources.remove(res, &removedEntryValue)) {
185             MediaResourceParcel actualRemoved = res;
186             if (removedEntryValue != -1) {
187                 onLastRemoved(res, info.uid);
188                 actualRemoved.value = removedEntryValue;
189             }
190 
191             // Add it to the list of removed resources for observers.
192             resourceRemoved.add(actualRemoved);
193         }
194     }
195     if (mObserverService != nullptr && !resourceRemoved.empty()) {
196         mObserverService->onResourceRemoved(info.uid, pid, resourceRemoved);
197     }
198     return true;
199 }
200 
removeResource(const ClientInfoParcel & clientInfo,bool validateCallingPid)201 bool ResourceTracker::removeResource(const ClientInfoParcel& clientInfo, bool validateCallingPid) {
202     int32_t pid = clientInfo.pid;
203     int64_t clientId = clientInfo.id;
204 
205     if (validateCallingPid && !mProcessInfo->isPidTrusted(pid)) {
206         pid_t callingPid = IPCThreadState::self()->getCallingPid();
207         ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
208                 pid, callingPid);
209         pid = callingPid;
210     }
211     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
212     if (found == mMap.end()) {
213         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
214         return false;
215     }
216 
217     ResourceInfos& infos = found->second;
218     ResourceInfos::iterator foundClient = infos.find(clientId);
219     if (foundClient == infos.end()) {
220         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
221         return false;
222     }
223 
224     const ResourceInfo& info = foundClient->second;
225     for (const MediaResourceParcel& res : info.resources.getResources()) {
226         onLastRemoved(res, info.uid);
227     }
228 
229     if (mObserverService != nullptr && !info.resources.empty()) {
230         mObserverService->onResourceRemoved(info.uid, pid, info.resources);
231     }
232 
233     infos.erase(foundClient);
234     return true;
235 }
236 
getClient(int pid,const int64_t & clientId) const237 std::shared_ptr<IResourceManagerClient> ResourceTracker::getClient(
238         int pid, const int64_t& clientId) const {
239     std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
240     if (found == mMap.end()) {
241         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
242         return nullptr;
243     }
244 
245     const ResourceInfos& infos = found->second;
246     ResourceInfos::const_iterator foundClient = infos.find(clientId);
247     if (foundClient == infos.end()) {
248         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
249         return nullptr;
250     }
251 
252     return foundClient->second.client;
253 }
254 
removeClient(int pid,const int64_t & clientId)255 bool ResourceTracker::removeClient(int pid, const int64_t& clientId) {
256     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
257     if (found == mMap.end()) {
258         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
259         return false;
260     }
261 
262     ResourceInfos& infos = found->second;
263     ResourceInfos::iterator foundClient = infos.find(clientId);
264     if (foundClient == infos.end()) {
265         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
266         return false;
267     }
268 
269     infos.erase(foundClient);
270     return true;
271 }
272 
markClientForPendingRemoval(const ClientInfoParcel & clientInfo)273 bool ResourceTracker::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
274     int32_t pid = clientInfo.pid;
275     int64_t clientId = clientInfo.id;
276 
277     if (!mProcessInfo->isPidTrusted(pid)) {
278         pid_t callingPid = IPCThreadState::self()->getCallingPid();
279         ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
280                 pid, callingPid);
281         pid = callingPid;
282     }
283     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
284     if (found == mMap.end()) {
285         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long)clientId);
286         return false;
287     }
288 
289     ResourceInfos& infos = found->second;
290     ResourceInfos::iterator foundClient = infos.find(clientId);
291     if (foundClient == infos.end()) {
292         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
293         return false;
294     }
295 
296     ResourceInfo& info = foundClient->second;
297     info.pendingRemoval = true;
298     return true;
299 }
300 
getClientsMarkedPendingRemoval(int32_t pid,std::vector<ClientInfo> & targetClients)301 bool ResourceTracker::getClientsMarkedPendingRemoval(int32_t pid,
302                                                      std::vector<ClientInfo>& targetClients) {
303     if (!mProcessInfo->isPidTrusted(pid)) {
304         pid_t callingPid = IPCThreadState::self()->getCallingPid();
305         ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__, pid, callingPid);
306         pid = callingPid;
307     }
308 
309     // Go through all the MediaResource types (and corresponding subtypes for
310     // each, if applicable) and see if the process (with given pid) holds any
311     // such resources that are marked as pending removal.
312     // Since the use-case of this function is to get all such resources (pending
313     // removal) and reclaim them all - the order in which we look for the
314     // resource type doesn't matter.
315     for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
316                                      MediaResource::Type::kNonSecureCodec,
317                                      MediaResource::Type::kGraphicMemory,
318                                      MediaResource::Type::kDrmSession}) {
319         switch (type) {
320         // Codec resources are segregated by audio, video and image domains.
321         case MediaResource::Type::kSecureCodec:
322         case MediaResource::Type::kNonSecureCodec:
323             for (MediaResource::SubType subType : {MediaResource::SubType::kHwAudioCodec,
324                                                    MediaResource::SubType::kSwAudioCodec,
325                                                    MediaResource::SubType::kHwVideoCodec,
326                                                    MediaResource::SubType::kSwVideoCodec,
327                                                    MediaResource::SubType::kHwImageCodec,
328                                                    MediaResource::SubType::kSwImageCodec}) {
329                 ClientInfo clientInfo;
330                 if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
331                     if (!contains(targetClients, clientInfo.mClientId)) {
332                         targetClients.emplace_back(clientInfo);
333                     }
334                     continue;
335                 }
336             }
337             break;
338         // Non-codec resources are shared by audio, video and image codecs (no subtype).
339         default:
340             ClientInfo clientInfo;
341             MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
342             if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
343                 if (!contains(targetClients, clientInfo.mClientId)) {
344                     targetClients.emplace_back(clientInfo);
345                 }
346             }
347             break;
348         }
349     }
350 
351     return true;
352 }
353 
overridePid(int originalPid,int newPid)354 bool ResourceTracker::overridePid(int originalPid, int newPid) {
355     mOverridePidMap.erase(originalPid);
356     if (newPid != -1) {
357         mOverridePidMap.emplace(originalPid, newPid);
358         return true;
359     }
360     return false;
361 }
362 
overrideProcessInfo(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)363 bool ResourceTracker::overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client,
364                                           int pid, int procState, int oomScore) {
365     removeProcessInfoOverride(pid);
366 
367     if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
368         // Override value is rejected by ProcessInfo.
369         return false;
370     }
371 
372     ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
373                                 .uid = 0,
374                                 .id = 0,
375                                 .name = "<unknown client>"};
376     std::shared_ptr<DeathNotifier> deathNotifier =
377         DeathNotifier::Create(client, mService, clientInfo, true);
378 
379     mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});
380 
381     return true;
382 }
383 
removeProcessInfoOverride(int pid)384 void ResourceTracker::removeProcessInfoOverride(int pid) {
385     auto it = mProcessInfoOverrideMap.find(pid);
386     if (it == mProcessInfoOverrideMap.end()) {
387         return;
388     }
389 
390     mProcessInfo->removeProcessInfoOverride(pid);
391     mProcessInfoOverrideMap.erase(pid);
392 }
393 
getAllClients(const ResourceRequestInfo & resourceRequestInfo,std::vector<ClientInfo> & clients,MediaResource::SubType primarySubType)394 bool ResourceTracker::getAllClients(const ResourceRequestInfo& resourceRequestInfo,
395                                     std::vector<ClientInfo>& clients,
396                                     MediaResource::SubType primarySubType) {
397     MediaResource::Type type = resourceRequestInfo.mResource->type;
398     MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
399     bool foundClient = false;
400 
401     for (auto& [pid, /* ResourceInfos */ infos] : mMap) {
402         for (auto& [id, /* ResourceInfo */ info] : infos) {
403             if (hasResourceType(type, subType, info.resources, primarySubType)) {
404                 if (!contains(clients, info.clientId)) {
405                     clients.emplace_back(info.pid, info.uid, info.clientId);
406                     foundClient = true;
407                 }
408             }
409         }
410     }
411 
412     return foundClient;
413 }
414 
getLowestPriorityPid(MediaResource::Type type,MediaResource::SubType subType,int & lowestPriorityPid,int & lowestPriority)415 bool ResourceTracker::getLowestPriorityPid(MediaResource::Type type, MediaResource::SubType subType,
416                                            int& lowestPriorityPid, int& lowestPriority) {
417     int pid = -1;
418     int priority = -1;
419     for (auto& [tempPid, /* ResourceInfos */ infos] : mMap) {
420         if (infos.size() == 0) {
421             // no client on this process.
422             continue;
423         }
424         if (!hasResourceType(type, subType, infos)) {
425             // doesn't have the requested resource type
426             continue;
427         }
428         int tempPriority = -1;
429         if (!getPriority(tempPid, &tempPriority)) {
430             ALOGV("%s: can't get priority of pid %d, skipped", __func__, tempPid);
431             // TODO: remove this pid from mMap?
432             continue;
433         }
434         if (pid == -1 || tempPriority > priority) {
435             // initial the value
436             pid = tempPid;
437             priority = tempPriority;
438         }
439     }
440 
441     bool success = (pid != -1);
442 
443     if (success) {
444         lowestPriorityPid = pid;
445         lowestPriority = priority;
446     }
447     return success;
448 }
449 
getLowestPriorityPid(MediaResource::Type type,MediaResource::SubType subType,MediaResource::SubType primarySubType,const std::vector<ClientInfo> & clients,int & lowestPriorityPid,int & lowestPriority)450 bool ResourceTracker::getLowestPriorityPid(MediaResource::Type type, MediaResource::SubType subType,
451                                            MediaResource::SubType primarySubType,
452                                            const std::vector<ClientInfo>& clients,
453                                            int& lowestPriorityPid, int& lowestPriority) {
454     int pid = -1;
455     int priority = -1;
456     for (const ClientInfo& client : clients) {
457         const ResourceInfo* info = getResourceInfo(client.mPid, client.mClientId);
458         if (info == nullptr) {
459             continue;
460         }
461         if (!hasResourceType(type, subType, info->resources, primarySubType)) {
462             // doesn't have the requested resource type
463             continue;
464         }
465         int tempPriority = -1;
466         if (!getPriority(client.mPid, &tempPriority)) {
467             ALOGV("%s: can't get priority of pid %d, skipped", __func__, client.mPid);
468             // TODO: remove this pid from mMap?
469             continue;
470         }
471         if (pid == -1 || tempPriority > priority) {
472             // initial the value
473             pid = client.mPid;
474             priority = tempPriority;
475         }
476     }
477 
478     bool success = (pid != -1);
479 
480     if (success) {
481         lowestPriorityPid = pid;
482         lowestPriority = priority;
483     }
484     return success;
485 }
486 
getBiggestClientPendingRemoval(int pid,MediaResource::Type type,MediaResource::SubType subType,ClientInfo & clientInfo)487 bool ResourceTracker::getBiggestClientPendingRemoval(int pid, MediaResource::Type type,
488                                                      MediaResource::SubType subType,
489                                                      ClientInfo& clientInfo) {
490     std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
491     if (found == mMap.end()) {
492         return false;
493     }
494 
495     uid_t   uid = -1;
496     int64_t clientId = -1;
497     uint64_t largestValue = 0;
498     const ResourceInfos& infos = found->second;
499     for (const auto& [id, /* ResourceInfo */ info] : infos) {
500         const ResourceList& resources = info.resources;
501         // Skip if the client is not marked pending removal.
502         if (!info.pendingRemoval) {
503             continue;
504         }
505         for (const MediaResourceParcel& resource : resources.getResources()) {
506             if (hasResourceType(type, subType, resource)) {
507                 if (resource.value > largestValue) {
508                     largestValue = resource.value;
509                     clientId = info.clientId;
510                     uid = info.uid;
511                 }
512             }
513         }
514     }
515 
516     if (clientId == -1) {
517         return false;
518     }
519 
520     clientInfo.mPid = pid;
521     clientInfo.mUid = uid;
522     clientInfo.mClientId = clientId;
523     return true;
524 }
525 
getBiggestClient(int targetPid,MediaResource::Type type,MediaResource::SubType subType,const std::vector<ClientInfo> & clients,ClientInfo & clientInfo,MediaResource::SubType primarySubType)526 bool ResourceTracker::getBiggestClient(int targetPid,
527                                        MediaResource::Type type, MediaResource::SubType subType,
528                                        const std::vector<ClientInfo>& clients,
529                                        ClientInfo& clientInfo,
530                                        MediaResource::SubType primarySubType) {
531     uid_t   uid = -1;
532     int64_t clientId = -1;
533     uint64_t largestValue = 0;
534 
535     for (const ClientInfo& client : clients) {
536         // Skip the clients that doesn't belong go the targetPid
537         if (client.mPid != targetPid) {
538             continue;
539         }
540         const ResourceInfo* info = getResourceInfo(client.mPid, client.mClientId);
541         if (info == nullptr) {
542             continue;
543         }
544 
545         const ResourceList& resources = info->resources;
546         bool matchedPrimary =
547             (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
548         for (const MediaResourceParcel& resource : resources.getResources()) {
549             if (resource.subType == primarySubType) {
550                 matchedPrimary = true;
551                 break;
552             } else if (isHwCodec(resource.subType) == isHwCodec(primarySubType)) {
553                 matchedPrimary = true;
554                 break;
555             }
556         }
557         // Primary type doesn't match, skip the client
558         if (!matchedPrimary) {
559             continue;
560         }
561         for (const MediaResourceParcel& resource : resources.getResources()) {
562             if (hasResourceType(type, subType, resource)) {
563                 if (resource.value > largestValue) {
564                     largestValue = resource.value;
565                     clientId = info->clientId;
566                     uid = info->uid;
567                 }
568             }
569         }
570     }
571 
572     if (clientId == -1) {
573         ALOGE("%s: can't find resource type %s and subtype %s for pid %d",
574                  __func__, asString(type), asString(subType), targetPid);
575         return false;
576     }
577 
578     clientInfo.mPid = targetPid;
579     clientInfo.mUid = uid;
580     clientInfo.mClientId = clientId;
581     return true;
582 }
583 
getLeastImportantBiggestClient(int targetPid,int32_t importance,MediaResource::Type type,MediaResource::SubType subType,MediaResource::SubType primarySubType,const std::vector<ClientInfo> & clients,ClientInfo & clientInfo)584 bool ResourceTracker::getLeastImportantBiggestClient(int targetPid, int32_t importance,
585                                                      MediaResource::Type type,
586                                                      MediaResource::SubType subType,
587                                                      MediaResource::SubType primarySubType,
588                                                      const std::vector<ClientInfo>& clients,
589                                                      ClientInfo& clientInfo) {
590     uid_t   uid = -1;
591     int64_t clientId = -1;
592     uint64_t largestValue = 0;
593 
594     for (const ClientInfo& client : clients) {
595         // Skip the clients that doesn't belong go the targetPid
596         if (client.mPid != targetPid) {
597             continue;
598         }
599         const ResourceInfo* info = getResourceInfo(client.mPid, client.mClientId);
600         if (info == nullptr) {
601             continue;
602         }
603 
604         // Make sure the importance is lower.
605         if (info->importance <= importance) {
606             continue;
607         }
608         const ResourceList& resources = info->resources;
609         bool matchedPrimary =
610             (primarySubType == MediaResource::SubType::kUnspecifiedSubType) ?  true : false;
611         for (const MediaResourceParcel& resource : resources.getResources()) {
612             if (resource.subType == primarySubType) {
613                 matchedPrimary = true;
614             } else if (isHwCodec(resource.subType) == isHwCodec(primarySubType)) {
615                 matchedPrimary = true;
616             }
617         }
618         // Primary type doesn't match, skip the client
619         if (!matchedPrimary) {
620             continue;
621         }
622         for (const MediaResourceParcel& resource : resources.getResources()) {
623             if (hasResourceType(type, subType, resource)) {
624                 if (resource.value > largestValue) {
625                     largestValue = resource.value;
626                     clientId = info->clientId;
627                     uid = info->uid;
628                 }
629             }
630         }
631     }
632 
633     if (clientId == -1) {
634         ALOGE("%s: can't find resource type %s and subtype %s for pid %d",
635                  __func__, asString(type), asString(subType), targetPid);
636         return false;
637     }
638 
639     clientInfo.mPid = targetPid;
640     clientInfo.mUid = uid;
641     clientInfo.mClientId = clientId;
642     return true;
643 }
644 
dump(std::string & resourceLogs)645 void ResourceTracker::dump(std::string& resourceLogs) {
646     const size_t SIZE = 256;
647     char buffer[SIZE];
648     resourceLogs.append("  Processes:\n");
649     for (const auto& [pid, /* ResourceInfos */ infos] : mMap) {
650         snprintf(buffer, SIZE, "    Pid: %d\n", pid);
651         resourceLogs.append(buffer);
652         int priority = 0;
653         if (getPriority(pid, &priority)) {
654             snprintf(buffer, SIZE, "    Priority: %d\n", priority);
655         } else {
656             snprintf(buffer, SIZE, "    Priority: <unknown>\n");
657         }
658         resourceLogs.append(buffer);
659 
660         for (const auto& [infoKey, /* ResourceInfo */ info] : infos) {
661             resourceLogs.append("      Client:\n");
662             snprintf(buffer, SIZE, "        Id: %lld\n", (long long)info.clientId);
663             resourceLogs.append(buffer);
664 
665             std::string clientName = info.name;
666             snprintf(buffer, SIZE, "        Name: %s\n", clientName.c_str());
667             resourceLogs.append(buffer);
668 
669             const ResourceList& resources = info.resources;
670             resourceLogs.append("        Resources:\n");
671             resourceLogs.append(resources.toString());
672         }
673     }
674     resourceLogs.append("  Process Pid override:\n");
675     for (const auto& [oldPid, newPid] : mOverridePidMap) {
676         snprintf(buffer, SIZE, "    Original Pid: %d,  Override Pid: %d\n", oldPid, newPid);
677         resourceLogs.append(buffer);
678     }
679 }
680 
onFirstAdded(const MediaResourceParcel & resource,uid_t uid)681 void ResourceTracker::onFirstAdded(const MediaResourceParcel& resource, uid_t uid) {
682     std::shared_ptr<ResourceManagerServiceNew> service = mService.lock();
683     if (service == nullptr) {
684         ALOGW("%s: ResourceManagerService is invalid!", __func__);
685         return;
686     }
687 
688     service->onFirstAdded(resource, uid);
689 }
690 
onLastRemoved(const MediaResourceParcel & resource,uid_t uid)691 void ResourceTracker::onLastRemoved(const MediaResourceParcel& resource, uid_t uid) {
692     std::shared_ptr<ResourceManagerServiceNew> service = mService.lock();
693     if (service == nullptr) {
694         ALOGW("%s: ResourceManagerService is invalid!", __func__);
695         return;
696     }
697 
698     service->onLastRemoved(resource, uid);
699 }
700 
getPriority(int pid,int * priority)701 bool ResourceTracker::getPriority(int pid, int* priority) {
702     int newPid = pid;
703 
704     if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
705         newPid = mOverridePidMap[pid];
706         ALOGD("%s: use override pid %d instead original pid %d", __func__, newPid, pid);
707     }
708 
709     return mProcessInfo->getPriority(newPid, priority);
710 }
711 
getNonConflictingClients(const ResourceRequestInfo & resourceRequestInfo,std::vector<ClientInfo> & clients)712 bool ResourceTracker::getNonConflictingClients(const ResourceRequestInfo& resourceRequestInfo,
713                                                std::vector<ClientInfo>& clients) {
714     MediaResource::Type type = resourceRequestInfo.mResource->type;
715     MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
716     for (auto& [pid, /* ResourceInfos */ infos] : mMap) {
717         for (const auto& [id, /* ResourceInfo */ info] : infos) {
718             if (pid == resourceRequestInfo.mCallingPid && id == resourceRequestInfo.mClientId) {
719                 ALOGI("%s: Skip the client[%jd] for which the resource request is made",
720                       __func__, id);
721                 continue;
722             }
723             if (hasResourceType(type, subType, info.resources)) {
724                 if (!isCallingPriorityHigher(resourceRequestInfo.mCallingPid, pid)) {
725                     // some higher/equal priority process owns the resource,
726                     // this is a conflict.
727                     ALOGE("%s: The resource (%s) request from pid %d is conflicting",
728                           __func__, asString(type), pid);
729                     clients.clear();
730                     return false;
731                 } else {
732                     if (!contains(clients, info.clientId)) {
733                         clients.emplace_back(info.pid, info.uid, info.clientId);
734                     }
735                 }
736             }
737         }
738     }
739 
740     return true;
741 }
742 
getResourceInfo(int pid,const int64_t & clientId) const743 const ResourceInfo* ResourceTracker::getResourceInfo(int pid, const int64_t& clientId) const {
744     std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
745     if (found == mMap.end()) {
746         ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
747         return nullptr;
748     }
749 
750     const ResourceInfos& infos = found->second;
751     ResourceInfos::const_iterator foundClient = infos.find(clientId);
752     if (foundClient == infos.end()) {
753         ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
754         return nullptr;
755     }
756 
757     return &foundClient->second;
758 }
759 
isCallingPriorityHigher(int callingPid,int pid)760 bool ResourceTracker::isCallingPriorityHigher(int callingPid, int pid) {
761     int callingPidPriority;
762     if (!getPriority(callingPid, &callingPidPriority)) {
763         return false;
764     }
765 
766     int priority;
767     if (!getPriority(pid, &priority)) {
768         return false;
769     }
770 
771     return (callingPidPriority < priority);
772 }
773 
774 } // namespace android
775