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