• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ResourceManagerServiceNew"
20 #include <utils/Log.h>
21 #include <binder/IPCThreadState.h>
22 #include <mediautils/ProcessInfo.h>
23 
24 #include <android_media_codec.h>
25 
26 #include "DefaultResourceModel.h"
27 #include "ClientImportanceReclaimPolicy.h"
28 #include "ProcessPriorityReclaimPolicy.h"
29 #include "ResourceManagerServiceNew.h"
30 #include "ResourceTracker.h"
31 #include "ServiceLog.h"
32 
33 namespace android {
34 
ResourceManagerServiceNew(const sp<ProcessInfoInterface> & processInfo,const sp<SystemCallbackInterface> & systemResource)35 ResourceManagerServiceNew::ResourceManagerServiceNew(
36         const sp<ProcessInfoInterface>& processInfo,
37         const sp<SystemCallbackInterface>& systemResource) :
38   ResourceManagerService(processInfo, systemResource) {}
39 
~ResourceManagerServiceNew()40 ResourceManagerServiceNew::~ResourceManagerServiceNew() {}
41 
init()42 void ResourceManagerServiceNew::init() {
43     // Create the Resource Tracker
44     mResourceTracker = std::make_shared<ResourceTracker>(ref<ResourceManagerServiceNew>(),
45                                                          mProcessInfo);
46     setUpResourceModels();
47     setUpReclaimPolicies();
48 }
49 
setUpResourceModels()50 void ResourceManagerServiceNew::setUpResourceModels() {
51     std::scoped_lock lock{mLock};
52     // Create/Configure the default resource model.
53     if (mDefaultResourceModel == nullptr) {
54         mDefaultResourceModel = std::make_unique<DefaultResourceModel>(
55                 mResourceTracker,
56                 mSupportsMultipleSecureCodecs,
57                 mSupportsSecureWithNonSecureCodec);
58     } else {
59         DefaultResourceModel* resourceModel =
60             static_cast<DefaultResourceModel*>(mDefaultResourceModel.get());
61         resourceModel->config(mSupportsMultipleSecureCodecs, mSupportsSecureWithNonSecureCodec);
62     }
63 }
64 
setUpReclaimPolicies()65 void ResourceManagerServiceNew::setUpReclaimPolicies() {
66     mReclaimPolicies.clear();
67     // Add Reclaim policies based on:
68     // - the Process priority (oom score)
69     // - the client/codec importance.
70     setReclaimPolicy(true /* processPriority */, true /* clientImportance */);
71 }
72 
config(const std::vector<MediaResourcePolicyParcel> & policies)73 Status ResourceManagerServiceNew::config(const std::vector<MediaResourcePolicyParcel>& policies) {
74     Status status = ResourceManagerService::config(policies);
75     // Change in the config dictates update to the resource model.
76     setUpResourceModels();
77     return status;
78 }
79 
setObserverService(const std::shared_ptr<ResourceObserverService> & observerService)80 void ResourceManagerServiceNew::setObserverService(
81         const std::shared_ptr<ResourceObserverService>& observerService) {
82     ResourceManagerService::setObserverService(observerService);
83     mResourceTracker->setResourceObserverService(observerService);
84 }
85 
addResource(const ClientInfoParcel & clientInfo,const std::shared_ptr<IResourceManagerClient> & client,const std::vector<MediaResourceParcel> & resources)86 Status ResourceManagerServiceNew::addResource(
87         const ClientInfoParcel& clientInfo,
88         const std::shared_ptr<IResourceManagerClient>& client,
89         const std::vector<MediaResourceParcel>& resources) {
90     int32_t pid = clientInfo.pid;
91     int32_t uid = clientInfo.uid;
92     int64_t clientId = clientInfo.id;
93     String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
94             pid, uid, (long long) clientId, getString(resources).c_str());
95     mServiceLog->add(log);
96 
97     std::scoped_lock lock{mLock};
98     mResourceTracker->addResource(clientInfo, client, resources);
99     notifyResourceGranted(pid, resources);
100 
101     return Status::ok();
102 }
103 
removeResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources)104 Status ResourceManagerServiceNew::removeResource(
105         const ClientInfoParcel& clientInfo,
106         const std::vector<MediaResourceParcel>& resources) {
107     int32_t pid = clientInfo.pid;
108     int32_t uid = clientInfo.uid;
109     int64_t clientId = clientInfo.id;
110     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
111             pid, uid, (long long) clientId, getString(resources).c_str());
112     mServiceLog->add(log);
113 
114     std::scoped_lock lock{mLock};
115     mResourceTracker->removeResource(clientInfo, resources);
116     return Status::ok();
117 }
118 
removeClient(const ClientInfoParcel & clientInfo)119 Status ResourceManagerServiceNew::removeClient(const ClientInfoParcel& clientInfo) {
120     removeResource(clientInfo, true /*checkValid*/);
121     return Status::ok();
122 }
123 
removeResource(const ClientInfoParcel & clientInfo,bool checkValid)124 Status ResourceManagerServiceNew::removeResource(const ClientInfoParcel& clientInfo,
125                                                  bool checkValid) {
126     int32_t pid = clientInfo.pid;
127     int32_t uid = clientInfo.uid;
128     int64_t clientId = clientInfo.id;
129     String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
130             pid, uid, (long long) clientId);
131     mServiceLog->add(log);
132 
133     std::scoped_lock lock{mLock};
134     if (mResourceTracker->removeResource(clientInfo, checkValid)) {
135         notifyClientReleased(clientInfo);
136     }
137     return Status::ok();
138 }
139 
reclaimResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources,bool * _aidl_return)140 Status ResourceManagerServiceNew::reclaimResource(
141         const ClientInfoParcel& clientInfo,
142         const std::vector<MediaResourceParcel>& resources,
143         bool* _aidl_return) {
144     return ResourceManagerService::reclaimResource(clientInfo, resources, _aidl_return);
145 }
146 
overridePid_l(int32_t originalPid,int32_t newPid)147 bool ResourceManagerServiceNew::overridePid_l(int32_t originalPid, int32_t newPid) {
148     return mResourceTracker->overridePid(originalPid, newPid);
149 }
150 
overridePid(int originalPid,int newPid)151 Status ResourceManagerServiceNew::overridePid(int originalPid, int newPid) {
152     return ResourceManagerService::overridePid(originalPid, newPid);
153 }
154 
overrideProcessInfo_l(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)155 bool ResourceManagerServiceNew::overrideProcessInfo_l(
156         const std::shared_ptr<IResourceManagerClient>& client,
157         int pid,
158         int procState,
159         int oomScore) {
160     return mResourceTracker->overrideProcessInfo(client, pid, procState, oomScore);
161 }
162 
overrideProcessInfo(const std::shared_ptr<IResourceManagerClient> & client,int pid,int procState,int oomScore)163 Status ResourceManagerServiceNew::overrideProcessInfo(
164         const std::shared_ptr<IResourceManagerClient>& client,
165         int pid,
166         int procState,
167         int oomScore) {
168     return ResourceManagerService::overrideProcessInfo(client, pid, procState, oomScore);
169 }
170 
removeProcessInfoOverride(int pid)171 void ResourceManagerServiceNew::removeProcessInfoOverride(int pid) {
172     std::scoped_lock lock{mLock};
173 
174     mResourceTracker->removeProcessInfoOverride(pid);
175 }
176 
markClientForPendingRemoval(const ClientInfoParcel & clientInfo)177 Status ResourceManagerServiceNew::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
178     int32_t pid = clientInfo.pid;
179     int64_t clientId = clientInfo.id;
180     String8 log = String8::format(
181             "markClientForPendingRemoval(pid %d, clientId %lld)",
182             pid, (long long) clientId);
183     mServiceLog->add(log);
184 
185     std::scoped_lock lock{mLock};
186     mResourceTracker->markClientForPendingRemoval(clientInfo);
187     return Status::ok();
188 }
189 
reclaimResourcesFromClientsPendingRemoval(int32_t pid)190 Status ResourceManagerServiceNew::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
191     String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
192     mServiceLog->add(log);
193 
194     std::vector<ClientInfo> targetClients;
195     {
196         std::scoped_lock lock{mLock};
197         mResourceTracker->getClientsMarkedPendingRemoval(pid, targetClients);
198     }
199 
200     if (!targetClients.empty()) {
201         reclaimUnconditionallyFrom(targetClients);
202     }
203     return Status::ok();
204 }
205 
notifyClientCreated(const ClientInfoParcel & clientInfo)206 Status ResourceManagerServiceNew::notifyClientCreated(const ClientInfoParcel& clientInfo) {
207     return ResourceManagerService::notifyClientCreated(clientInfo);
208 }
209 
notifyClientStarted(const ClientConfigParcel & clientConfig)210 Status ResourceManagerServiceNew::notifyClientStarted(const ClientConfigParcel& clientConfig) {
211     return ResourceManagerService::notifyClientStarted(clientConfig);
212 }
213 
notifyClientStopped(const ClientConfigParcel & clientConfig)214 Status ResourceManagerServiceNew::notifyClientStopped(const ClientConfigParcel& clientConfig) {
215     return ResourceManagerService::notifyClientStopped(clientConfig);
216 }
217 
notifyClientConfigChanged(const ClientConfigParcel & clientConfig)218 Status ResourceManagerServiceNew::notifyClientConfigChanged(
219         const ClientConfigParcel& clientConfig) {
220     {
221         // Update the ResourceTracker about the change in the configuration.
222         std::scoped_lock lock{mLock};
223         mResourceTracker->updateClientImportance(clientConfig.clientInfo);
224     }
225     return ResourceManagerService::notifyClientConfigChanged(clientConfig);
226 }
227 
getMediaResourceUsageReport(std::vector<MediaResourceParcel> * resources)228 Status ResourceManagerServiceNew::getMediaResourceUsageReport(
229         std::vector<MediaResourceParcel>* resources) {
230     if (!resources) {
231         return Status::fromStatus(INVALID_OPERATION);
232     }
233 
234     resources->clear();
235     if (!android::media::codec::codec_availability() ||
236         !android::media::codec::codec_availability_support()) {
237         return Status::fromStatus(INVALID_OPERATION);
238     }
239 
240     std::scoped_lock lock{mLock};
241     mResourceTracker->getMediaResourceUsageReport(resources);
242 
243     return Status::ok();
244 }
245 
updateResource(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources)246 Status ResourceManagerServiceNew::updateResource(
247         const ClientInfoParcel& clientInfo,
248         const std::vector<MediaResourceParcel>& resources) {
249     int32_t pid = clientInfo.pid;
250     int32_t uid = clientInfo.uid;
251     int64_t clientId = clientInfo.id;
252     String8 log = String8::format("updateResource(pid %d, uid %d clientId %lld, resources %s)",
253             pid, uid, (long long) clientId, getString(resources).c_str());
254     mServiceLog->add(log);
255 
256     std::scoped_lock lock{mLock};
257     mResourceTracker->updateResource(clientInfo, resources);
258 
259     return Status::ok();
260 }
261 
getResourceDump(std::string & resourceLog) const262 void ResourceManagerServiceNew::getResourceDump(std::string& resourceLog) const {
263     std::scoped_lock lock{mLock};
264     mResourceTracker->dump(resourceLog);
265 }
266 
dump(int fd,const char ** args,uint32_t numArgs)267 binder_status_t ResourceManagerServiceNew::dump(int fd, const char** args, uint32_t numArgs) {
268     return ResourceManagerService::dump(fd, args, numArgs);
269 }
270 
getTargetClients(const ClientInfoParcel & clientInfo,const std::vector<MediaResourceParcel> & resources,std::vector<ClientInfo> & targetClients)271 bool ResourceManagerServiceNew::getTargetClients(
272         const ClientInfoParcel& clientInfo,
273         const std::vector<MediaResourceParcel>& resources,
274         std::vector<ClientInfo>& targetClients) {
275     int32_t callingPid = clientInfo.pid;
276     std::scoped_lock lock{mLock};
277     if (!mProcessInfo->isPidTrusted(callingPid)) {
278         pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
279         ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
280                 callingPid, actualCallingPid);
281         callingPid = actualCallingPid;
282     }
283 
284     // Use the Resource Model to get a list of all the clients that hold the
285     // needed/requested resources.
286     uint32_t callingImportance = std::max(0, clientInfo.importance);
287     ReclaimRequestInfo reclaimRequestInfo{callingPid, clientInfo.id, callingImportance, resources};
288     std::vector<ClientInfo> clients;
289     if (!mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients)) {
290         if (clients.empty()) {
291             ALOGI("%s: There aren't any clients with given resources. Nothing to reclaim",
292                   __func__);
293             return false;
294         }
295         // Since there was a conflict, we need to reclaim all clients.
296         targetClients = std::move(clients);
297     } else {
298         // Select a client among those have the needed resources.
299         getClientForResource_l(reclaimRequestInfo, clients, targetClients);
300     }
301     return !targetClients.empty();
302 }
303 
getClientForResource_l(const ReclaimRequestInfo & reclaimRequestInfo,const std::vector<ClientInfo> & clients,std::vector<ClientInfo> & targetClients)304 void ResourceManagerServiceNew::getClientForResource_l(
305         const ReclaimRequestInfo& reclaimRequestInfo,
306         const std::vector<ClientInfo>& clients,
307         std::vector<ClientInfo>& targetClients) {
308     int callingPid = reclaimRequestInfo.mCallingPid;
309 
310     // Before looking into other processes, check if we have clients marked for
311     // pending removal in the same process.
312     ClientInfo targetClient;
313     for (const MediaResourceParcel& resource : reclaimRequestInfo.mResources) {
314         if (mResourceTracker->getBiggestClientPendingRemoval(callingPid, resource.type,
315                                                              resource.subType, targetClient)) {
316             targetClients.emplace_back(targetClient);
317             return;
318         }
319     }
320 
321     // Run through all the reclaim policies until a client to reclaim from is identified.
322     for (std::unique_ptr<IReclaimPolicy>& reclaimPolicy : mReclaimPolicies) {
323         if (reclaimPolicy->getClients(reclaimRequestInfo, clients, targetClients)) {
324             return;
325         }
326     }
327 }
328 
getLowestPriorityBiggestClient_l(const ResourceRequestInfo & resourceRequestInfo,ClientInfo & clientInfo)329 bool ResourceManagerServiceNew::getLowestPriorityBiggestClient_l(
330         const ResourceRequestInfo& resourceRequestInfo,
331         ClientInfo& clientInfo) {
332     //NOTE: This function is used only by the test: ResourceManagerServiceTest
333     if (resourceRequestInfo.mResource == nullptr) {
334         return false;
335     }
336 
337     // Use the DefaultResourceModel to get all the clients with the resources requested.
338     std::vector<MediaResourceParcel> resources{*resourceRequestInfo.mResource};
339     ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid,
340                                           resourceRequestInfo.mClientId,
341                                           0, // default importance
342                                           resources};
343     std::vector<ClientInfo> clients;
344     mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients);
345 
346     // Use the ProcessPriorityReclaimPolicy to select a client to reclaim from.
347     std::unique_ptr<IReclaimPolicy> reclaimPolicy
348         = std::make_unique<ProcessPriorityReclaimPolicy>(mResourceTracker);
349     std::vector<ClientInfo> targetClients;
350     if (reclaimPolicy->getClients(reclaimRequestInfo, clients, targetClients)) {
351         if (!targetClients.empty()) {
352             clientInfo = targetClients[0];
353             return true;
354         }
355     }
356 
357     return false;
358 }
359 
getPriority_l(int pid,int * priority) const360 bool ResourceManagerServiceNew::getPriority_l(int pid, int* priority) const {
361     return mResourceTracker->getPriority(pid, priority);
362 }
363 
getLowestPriorityPid_l(MediaResource::Type type,MediaResource::SubType subType,int * lowestPriorityPid,int * lowestPriority)364 bool ResourceManagerServiceNew::getLowestPriorityPid_l(
365         MediaResource::Type type, MediaResource::SubType subType,
366         int* lowestPriorityPid, int* lowestPriority) {
367     //NOTE: This function is used only by the test: ResourceManagerServiceTest
368     return mResourceTracker->getLowestPriorityPid(type, subType,
369                                                   *lowestPriorityPid,
370                                                   *lowestPriority);
371 }
372 
getAllClients_l(const ResourceRequestInfo & resourceRequestInfo,std::vector<ClientInfo> & clientsInfo)373 bool ResourceManagerServiceNew::getAllClients_l(
374         const ResourceRequestInfo& resourceRequestInfo,
375         std::vector<ClientInfo>& clientsInfo) {
376     //NOTE: This function is used only by the test: ResourceManagerServiceTest
377     MediaResource::Type type = resourceRequestInfo.mResource->type;
378     // Get the list of all clients that has requested resources.
379     std::vector<ClientInfo> clients;
380     mResourceTracker->getAllClients(resourceRequestInfo, clients);
381 
382     // Check is there any high priority process holding up the resources already.
383     for (const ClientInfo& info : clients) {
384         if (!isCallingPriorityHigher_l(resourceRequestInfo.mCallingPid, info.mPid)) {
385             // some higher/equal priority process owns the resource,
386             // this request can't be fulfilled.
387             ALOGE("%s: can't reclaim resource %s from pid %d", __func__, asString(type), info.mPid);
388             return false;
389         }
390         clientsInfo.emplace_back(info);
391     }
392     if (clientsInfo.size() == 0) {
393         ALOGV("%s: didn't find any resource %s", __func__, asString(type));
394     }
395     return true;
396 }
397 
getClient_l(int pid,const int64_t & clientId) const398 std::shared_ptr<IResourceManagerClient> ResourceManagerServiceNew::getClient_l(
399         int pid, const int64_t& clientId) const {
400     return mResourceTracker->getClient(pid, clientId);
401 }
402 
removeClient_l(int pid,const int64_t & clientId)403 bool ResourceManagerServiceNew::removeClient_l(int pid, const int64_t& clientId) {
404     return mResourceTracker->removeClient(pid, clientId);
405 }
406 
getResourceMap() const407 const std::map<int, ResourceInfos>& ResourceManagerServiceNew::getResourceMap() const {
408     return mResourceTracker->getResourceMap();
409 }
410 
setReclaimPolicy(bool processPriority,bool clientImportance)411 void ResourceManagerServiceNew::setReclaimPolicy(bool processPriority, bool clientImportance) {
412     mReclaimPolicies.clear();
413     if (processPriority) {
414         // Process priority (oom score) as the Default reclaim policy.
415         mReclaimPolicies.push_back(std::make_unique<ProcessPriorityReclaimPolicy>(
416             mResourceTracker));
417     }
418     if (clientImportance) {
419         mReclaimPolicies.push_back(std::make_unique<ClientImportanceReclaimPolicy>(
420             mResourceTracker));
421     }
422 }
423 
424 } // namespace android
425