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