blob: 2f93571070bf91b3340095a88a190d159b798d1b [file] [log] [blame]
Girish6a6044d2023-11-22 21:23:14 +00001/*
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
28namespace android {
29
Girish0ac5c212023-11-23 09:14:03 +000030inline 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.
37static 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 (auto it = resources.begin(); it != resources.end(); it++) {
43 if (hasResourceType(type, subType, it->second)) {
44 foundResource = true;
45 } else if (it->second.subType == primarySubType) {
46 matchedPrimary = true;
47 } else if (isHwCodec(it->second.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.
58inline 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
Girish6a6044d2023-11-22 21:23:14 +000069ResourceTracker::ResourceTracker(const std::shared_ptr<ResourceManagerServiceNew>& service,
70 const sp<ProcessInfoInterface>& processInfo) :
71 mService(service),
72 mProcessInfo(processInfo) {
73}
74
75ResourceTracker::~ResourceTracker() {
76}
77
78void ResourceTracker::setResourceObserverService(
79 const std::shared_ptr<ResourceObserverService>& observerService) {
80 mObserverService = observerService;
81}
82
83ResourceInfos& 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
95bool 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 const auto resType = std::tuple(res.type, res.subType, res.id);
115
116 if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
117 ALOGV("%s: Ignoring request to remove negative value of non-drm resource", __func__);
118 continue;
119 }
120 if (info.resources.find(resType) == info.resources.end()) {
121 if (res.value <= 0) {
122 // We can't init a new entry with negative value, although it's allowed
123 // to merge in negative values after the initial add.
124 ALOGV("%s: Ignoring request to add new resource entry with value <= 0", __func__);
125 continue;
126 }
127 onFirstAdded(res, info.uid);
128 info.resources[resType] = res;
129 } else {
130 mergeResources(info.resources[resType], res);
131 }
132 // Add it to the list of added resources for observers.
133 auto it = resourceAdded.find(resType);
134 if (it == resourceAdded.end()) {
135 resourceAdded[resType] = res;
136 } else {
137 mergeResources(it->second, res);
138 }
139 }
140 if (info.deathNotifier == nullptr && client != nullptr) {
141 info.deathNotifier = DeathNotifier::Create(client, mService, clientInfo);
142 }
143 if (mObserverService != nullptr && !resourceAdded.empty()) {
144 mObserverService->onResourceAdded(uid, pid, resourceAdded);
145 }
146
147 return !resourceAdded.empty();
148}
149
150bool ResourceTracker::removeResource(const ClientInfoParcel& clientInfo,
151 const std::vector<MediaResourceParcel>& resources) {
152 int32_t pid = clientInfo.pid;
153 int64_t clientId = clientInfo.id;
154
155 if (!mProcessInfo->isPidTrusted(pid)) {
156 pid_t callingPid = IPCThreadState::self()->getCallingPid();
157 ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
158 pid, callingPid);
159 pid = callingPid;
160 }
161 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
162 if (found == mMap.end()) {
163 ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
164 return false;
165 }
166
167 ResourceInfos& infos = found->second;
168 ResourceInfos::iterator foundClient = infos.find(clientId);
169 if (foundClient == infos.end()) {
170 ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
171 return false;
172 }
173
174 ResourceInfo& info = foundClient->second;
175 ResourceList resourceRemoved;
176 for (const MediaResourceParcel& res : resources) {
177 const auto resType = std::tuple(res.type, res.subType, res.id);
178
179 if (res.value < 0) {
180 ALOGV("%s: Ignoring request to remove negative value of resource", __func__);
181 continue;
182 }
183 // ignore if we don't have it
184 if (info.resources.find(resType) != info.resources.end()) {
185 MediaResourceParcel& resource = info.resources[resType];
186 MediaResourceParcel actualRemoved = res;
187 if (resource.value > res.value) {
188 resource.value -= res.value;
189 } else {
190 onLastRemoved(res, info.uid);
191 actualRemoved.value = resource.value;
192 info.resources.erase(resType);
193 }
194
195 // Add it to the list of removed resources for observers.
196 auto it = resourceRemoved.find(resType);
197 if (it == resourceRemoved.end()) {
198 resourceRemoved[resType] = actualRemoved;
199 } else {
200 mergeResources(it->second, actualRemoved);
201 }
202 }
203 }
204 if (mObserverService != nullptr && !resourceRemoved.empty()) {
205 mObserverService->onResourceRemoved(info.uid, pid, resourceRemoved);
206 }
207 return true;
208}
209
210bool ResourceTracker::removeResource(const ClientInfoParcel& clientInfo, bool validateCallingPid) {
211 int32_t pid = clientInfo.pid;
212 int64_t clientId = clientInfo.id;
213
214 if (validateCallingPid && !mProcessInfo->isPidTrusted(pid)) {
215 pid_t callingPid = IPCThreadState::self()->getCallingPid();
216 ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
217 pid, callingPid);
218 pid = callingPid;
219 }
220 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
221 if (found == mMap.end()) {
222 ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
223 return false;
224 }
225
226 ResourceInfos& infos = found->second;
227 ResourceInfos::iterator foundClient = infos.find(clientId);
228 if (foundClient == infos.end()) {
229 ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
230 return false;
231 }
232
233 const ResourceInfo& info = foundClient->second;
234 for (auto& [resType, resParcel] : info.resources) {
235 onLastRemoved(resParcel, info.uid);
236 }
237
238 if (mObserverService != nullptr && !info.resources.empty()) {
239 mObserverService->onResourceRemoved(info.uid, pid, info.resources);
240 }
241
242 infos.erase(foundClient);
243 return true;
244}
245
246std::shared_ptr<IResourceManagerClient> ResourceTracker::getClient(
247 int pid, const int64_t& clientId) const {
248 std::map<int, ResourceInfos>::const_iterator found = mMap.find(pid);
249 if (found == mMap.end()) {
250 ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
251 return nullptr;
252 }
253
254 const ResourceInfos& infos = found->second;
255 ResourceInfos::const_iterator foundClient = infos.find(clientId);
256 if (foundClient == infos.end()) {
257 ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
258 return nullptr;
259 }
260
261 return foundClient->second.client;
262}
263
264bool ResourceTracker::removeClient(int pid, const int64_t& clientId) {
265 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
266 if (found == mMap.end()) {
267 ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long) clientId);
268 return false;
269 }
270
271 ResourceInfos& infos = found->second;
272 ResourceInfos::iterator foundClient = infos.find(clientId);
273 if (foundClient == infos.end()) {
274 ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
275 return false;
276 }
277
278 infos.erase(foundClient);
279 return true;
280}
281
282bool ResourceTracker::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
283 int32_t pid = clientInfo.pid;
284 int64_t clientId = clientInfo.id;
285
286 if (!mProcessInfo->isPidTrusted(pid)) {
287 pid_t callingPid = IPCThreadState::self()->getCallingPid();
288 ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__,
289 pid, callingPid);
290 pid = callingPid;
291 }
292 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
293 if (found == mMap.end()) {
294 ALOGV("%s: didn't find pid %d for clientId %lld", __func__, pid, (long long)clientId);
295 return false;
296 }
297
298 ResourceInfos& infos = found->second;
299 ResourceInfos::iterator foundClient = infos.find(clientId);
300 if (foundClient == infos.end()) {
301 ALOGV("%s: didn't find clientId %lld", __func__, (long long) clientId);
302 return false;
303 }
304
305 ResourceInfo& info = foundClient->second;
306 info.pendingRemoval = true;
307 return true;
308}
309
310bool ResourceTracker::getClientsMarkedPendingRemoval(int32_t pid,
311 std::vector<ClientInfo>& targetClients) {
312 if (!mProcessInfo->isPidTrusted(pid)) {
313 pid_t callingPid = IPCThreadState::self()->getCallingPid();
314 ALOGW("%s called with untrusted pid %d, using calling pid %d", __func__, pid, callingPid);
315 pid = callingPid;
316 }
317
318 // Go through all the MediaResource types (and corresponding subtypes for
319 // each, if applicable) and see if the process (with given pid) holds any
320 // such resources that are marked as pending removal.
321 // Since the use-case of this function is to get all such resources (pending
322 // removal) and reclaim them all - the order in which we look for the
323 // resource type doesn't matter.
324 for (MediaResource::Type type : {MediaResource::Type::kSecureCodec,
325 MediaResource::Type::kNonSecureCodec,
326 MediaResource::Type::kGraphicMemory,
327 MediaResource::Type::kDrmSession}) {
328 switch (type) {
329 // Codec resources are segregated by audio, video and image domains.
330 case MediaResource::Type::kSecureCodec:
331 case MediaResource::Type::kNonSecureCodec:
332 for (MediaResource::SubType subType : {MediaResource::SubType::kHwAudioCodec,
333 MediaResource::SubType::kSwAudioCodec,
334 MediaResource::SubType::kHwVideoCodec,
335 MediaResource::SubType::kSwVideoCodec,
336 MediaResource::SubType::kHwImageCodec,
337 MediaResource::SubType::kSwImageCodec}) {
338 ClientInfo clientInfo;
Girish0ac5c212023-11-23 09:14:03 +0000339 if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
340 if (!contains(targetClients, clientInfo.mClientId)) {
341 targetClients.emplace_back(clientInfo);
342 }
Girish6a6044d2023-11-22 21:23:14 +0000343 continue;
344 }
345 }
346 break;
347 // Non-codec resources are shared by audio, video and image codecs (no subtype).
348 default:
349 ClientInfo clientInfo;
350 MediaResource::SubType subType = MediaResource::SubType::kUnspecifiedSubType;
Girish0ac5c212023-11-23 09:14:03 +0000351 if (getBiggestClientPendingRemoval(pid, type, subType, clientInfo)) {
352 if (!contains(targetClients, clientInfo.mClientId)) {
353 targetClients.emplace_back(clientInfo);
354 }
Girish6a6044d2023-11-22 21:23:14 +0000355 }
356 break;
357 }
358 }
359
360 return true;
361}
362
363bool ResourceTracker::overridePid(int originalPid, int newPid) {
364 mOverridePidMap.erase(originalPid);
365 if (newPid != -1) {
366 mOverridePidMap.emplace(originalPid, newPid);
367 return true;
368 }
369 return false;
370}
371
372bool ResourceTracker::overrideProcessInfo(const std::shared_ptr<IResourceManagerClient>& client,
373 int pid, int procState, int oomScore) {
374 removeProcessInfoOverride(pid);
375
376 if (!mProcessInfo->overrideProcessInfo(pid, procState, oomScore)) {
377 // Override value is rejected by ProcessInfo.
378 return false;
379 }
380
381 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
382 .uid = 0,
383 .id = 0,
384 .name = "<unknown client>"};
385 std::shared_ptr<DeathNotifier> deathNotifier =
386 DeathNotifier::Create(client, mService, clientInfo, true);
387
388 mProcessInfoOverrideMap.emplace(pid, ProcessInfoOverride{deathNotifier, client});
389
390 return true;
391}
392
393void ResourceTracker::removeProcessInfoOverride(int pid) {
394 auto it = mProcessInfoOverrideMap.find(pid);
395 if (it == mProcessInfoOverrideMap.end()) {
396 return;
397 }
398
399 mProcessInfo->removeProcessInfoOverride(pid);
400 mProcessInfoOverrideMap.erase(pid);
401}
402
403bool ResourceTracker::getAllClients(const ResourceRequestInfo& resourceRequestInfo,
Girish0ac5c212023-11-23 09:14:03 +0000404 std::vector<ClientInfo>& clients,
405 MediaResource::SubType primarySubType) {
Girish6a6044d2023-11-22 21:23:14 +0000406 MediaResource::Type type = resourceRequestInfo.mResource->type;
407 MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
408 bool foundClient = false;
409
410 for (auto& [pid, /* ResourceInfos */ infos] : mMap) {
411 for (auto& [id, /* ResourceInfo */ info] : infos) {
Girish0ac5c212023-11-23 09:14:03 +0000412 if (hasResourceType(type, subType, info.resources, primarySubType)) {
413 if (!contains(clients, info.clientId)) {
414 clients.emplace_back(info.pid, info.uid, info.clientId);
415 foundClient = true;
416 }
Girish6a6044d2023-11-22 21:23:14 +0000417 }
418 }
419 }
420
421 return foundClient;
422}
423
424bool ResourceTracker::getLowestPriorityPid(MediaResource::Type type, MediaResource::SubType subType,
425 int& lowestPriorityPid, int& lowestPriority) {
426 int pid = -1;
427 int priority = -1;
428 for (auto& [tempPid, /* ResourceInfos */ infos] : mMap) {
429 if (infos.size() == 0) {
430 // no client on this process.
431 continue;
432 }
433 if (!hasResourceType(type, subType, infos)) {
434 // doesn't have the requested resource type
435 continue;
436 }
437 int tempPriority = -1;
438 if (!getPriority(tempPid, &tempPriority)) {
439 ALOGV("%s: can't get priority of pid %d, skipped", __func__, tempPid);
440 // TODO: remove this pid from mMap?
441 continue;
442 }
443 if (pid == -1 || tempPriority > priority) {
444 // initial the value
445 pid = tempPid;
446 priority = tempPriority;
447 }
448 }
449
450 bool success = (pid != -1);
451
452 if (success) {
453 lowestPriorityPid = pid;
454 lowestPriority = priority;
455 }
456 return success;
457}
458
Girish0ac5c212023-11-23 09:14:03 +0000459bool ResourceTracker::getLowestPriorityPid(const std::vector<ClientInfo>& clients,
460 int& lowestPriorityPid, int& lowestPriority) {
461 int pid = -1;
462 int priority = -1;
463 for (const ClientInfo& client : clients) {
464 int tempPriority = -1;
465 if (!getPriority(client.mPid, &tempPriority)) {
466 ALOGV("%s: can't get priority of pid %d, skipped", __func__, client.mPid);
467 // TODO: remove this pid from mMap?
468 continue;
469 }
470 if (pid == -1 || tempPriority > priority) {
471 // initial the value
472 pid = client.mPid;
473 priority = tempPriority;
474 }
475 }
476
477 bool success = (pid != -1);
478
479 if (success) {
480 lowestPriorityPid = pid;
481 lowestPriority = priority;
482 }
483 return success;
484}
485
486bool ResourceTracker::getBiggestClientPendingRemoval(int pid, MediaResource::Type type,
487 MediaResource::SubType subType,
488 ClientInfo& clientInfo) {
Girish6a6044d2023-11-22 21:23:14 +0000489 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
490 if (found == mMap.end()) {
Girish6a6044d2023-11-22 21:23:14 +0000491 return false;
492 }
493
494 uid_t uid = -1;
495 int64_t clientId = -1;
496 uint64_t largestValue = 0;
497 const ResourceInfos& infos = found->second;
498 for (const auto& [id, /* ResourceInfo */ info] : infos) {
499 const ResourceList& resources = info.resources;
Girish0ac5c212023-11-23 09:14:03 +0000500 // Skip if the client is not marked pending removal.
501 if (!info.pendingRemoval) {
Girish6a6044d2023-11-22 21:23:14 +0000502 continue;
503 }
504 for (auto it = resources.begin(); it != resources.end(); it++) {
Girish0ac5c212023-11-23 09:14:03 +0000505 const MediaResourceParcel& resource = it->second;
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
526bool ResourceTracker::getBiggestClient(int pid, MediaResource::Type type,
527 MediaResource::SubType subType,
528 ClientInfo& clientInfo) {
529 std::map<int, ResourceInfos>::iterator found = mMap.find(pid);
530 if (found == mMap.end()) {
531 ALOGE("%s: can't find resource info for pid %d", __func__, pid);
532 return false;
533 }
534
535 uid_t uid = -1;
536 int64_t clientId = -1;
537 uint64_t largestValue = 0;
538 const ResourceInfos& infos = found->second;
539 for (const auto& [id, info] : infos) {
540 const ResourceList& resources = info.resources;
541 for (auto it = resources.begin(); it != resources.end(); it++) {
Girish6a6044d2023-11-22 21:23:14 +0000542 const MediaResourceParcel &resource = it->second;
543 if (hasResourceType(type, subType, resource)) {
544 if (resource.value > largestValue) {
545 largestValue = resource.value;
546 clientId = info.clientId;
547 uid = info.uid;
548 }
549 }
550 }
551 }
552
553 if (clientId == -1) {
Girish0ac5c212023-11-23 09:14:03 +0000554 ALOGE("%s: can't find resource type %s and subtype %s for pid %d",
555 __func__, asString(type), asString(subType), pid);
Girish6a6044d2023-11-22 21:23:14 +0000556 return false;
557 }
558
559 clientInfo.mPid = pid;
560 clientInfo.mUid = uid;
561 clientInfo.mClientId = clientId;
562 return true;
563}
564
565void ResourceTracker::dump(std::string& resourceLogs) {
566 const size_t SIZE = 256;
567 char buffer[SIZE];
568 resourceLogs.append(" Processes:\n");
569 for (const auto& [pid, /* ResourceInfos */ infos] : mMap) {
570 snprintf(buffer, SIZE, " Pid: %d\n", pid);
571 resourceLogs.append(buffer);
572 int priority = 0;
573 if (getPriority(pid, &priority)) {
574 snprintf(buffer, SIZE, " Priority: %d\n", priority);
575 } else {
576 snprintf(buffer, SIZE, " Priority: <unknown>\n");
577 }
578 resourceLogs.append(buffer);
579
580 for (const auto& [infoKey, /* ResourceInfo */ info] : infos) {
581 resourceLogs.append(" Client:\n");
582 snprintf(buffer, SIZE, " Id: %lld\n", (long long)info.clientId);
583 resourceLogs.append(buffer);
584
585 std::string clientName = info.name;
586 snprintf(buffer, SIZE, " Name: %s\n", clientName.c_str());
587 resourceLogs.append(buffer);
588
589 const ResourceList& resources = info.resources;
590 resourceLogs.append(" Resources:\n");
591 for (auto it = resources.begin(); it != resources.end(); it++) {
592 snprintf(buffer, SIZE, " %s\n", toString(it->second).c_str());
593 resourceLogs.append(buffer);
594 }
595 }
596 }
597 resourceLogs.append(" Process Pid override:\n");
598 for (const auto& [oldPid, newPid] : mOverridePidMap) {
599 snprintf(buffer, SIZE, " Original Pid: %d, Override Pid: %d\n", oldPid, newPid);
600 resourceLogs.append(buffer);
601 }
602}
603
604void ResourceTracker::onFirstAdded(const MediaResourceParcel& resource, uid_t uid) {
605 std::shared_ptr<ResourceManagerServiceNew> service = mService.lock();
606 if (service == nullptr) {
607 ALOGW("%s: ResourceManagerService is invalid!", __func__);
608 return;
609 }
610
611 service->onFirstAdded(resource, uid);
612}
613
614void ResourceTracker::onLastRemoved(const MediaResourceParcel& resource, uid_t uid) {
615 std::shared_ptr<ResourceManagerServiceNew> service = mService.lock();
616 if (service == nullptr) {
617 ALOGW("%s: ResourceManagerService is invalid!", __func__);
618 return;
619 }
620
621 service->onLastRemoved(resource, uid);
622}
623
624bool ResourceTracker::getPriority(int pid, int* priority) {
625 int newPid = pid;
626
627 if (mOverridePidMap.find(pid) != mOverridePidMap.end()) {
628 newPid = mOverridePidMap[pid];
629 ALOGD("%s: use override pid %d instead original pid %d", __func__, newPid, pid);
630 }
631
632 return mProcessInfo->getPriority(newPid, priority);
633}
634
635bool ResourceTracker::getNonConflictingClients(const ResourceRequestInfo& resourceRequestInfo,
636 std::vector<ClientInfo>& clients) {
637 MediaResource::Type type = resourceRequestInfo.mResource->type;
638 MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
639 for (auto& [pid, /* ResourceInfos */ infos] : mMap) {
640 for (const auto& [id, /* ResourceInfo */ info] : infos) {
641 if (hasResourceType(type, subType, info.resources)) {
642 if (!isCallingPriorityHigher(resourceRequestInfo.mCallingPid, pid)) {
643 // some higher/equal priority process owns the resource,
644 // this is a conflict.
645 ALOGE("%s: The resource (%s) request from pid %d is conflicting",
646 __func__, asString(type), pid);
647 clients.clear();
648 return false;
649 } else {
650 clients.emplace_back(info.pid, info.uid, info.clientId);
651 }
652 }
653 }
654 }
655
656 return true;
657}
658
659bool ResourceTracker::isCallingPriorityHigher(int callingPid, int pid) {
660 int callingPidPriority;
661 if (!getPriority(callingPid, &callingPidPriority)) {
662 return false;
663 }
664
665 int priority;
666 if (!getPriority(pid, &priority)) {
667 return false;
668 }
669
670 return (callingPidPriority < priority);
671}
672
673} // namespace android