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