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