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