blob: 0a0a8f44c67f4b75fedbfdca72fcef8159e8d73d [file] [log] [blame]
Girish1484e5d2023-11-20 06:00:44 +00001/*
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>
Girish0ac5c212023-11-23 09:14:03 +000021#include <binder/IPCThreadState.h>
22#include <mediautils/ProcessInfo.h>
Girish1484e5d2023-11-20 06:00:44 +000023
Girish0ac5c212023-11-23 09:14:03 +000024#include "DefaultResourceModel.h"
Girish88a83502023-11-23 11:23:07 +000025#include "ClientImportanceReclaimPolicy.h"
Girish6c16adb2023-11-23 10:16:47 +000026#include "ProcessPriorityReclaimPolicy.h"
Girish1484e5d2023-11-20 06:00:44 +000027#include "ResourceManagerServiceNew.h"
Girish6a6044d2023-11-22 21:23:14 +000028#include "ResourceTracker.h"
29#include "ServiceLog.h"
Girish1484e5d2023-11-20 06:00:44 +000030
31namespace android {
32
33ResourceManagerServiceNew::ResourceManagerServiceNew(
34 const sp<ProcessInfoInterface>& processInfo,
35 const sp<SystemCallbackInterface>& systemResource) :
36 ResourceManagerService(processInfo, systemResource) {}
37
38ResourceManagerServiceNew::~ResourceManagerServiceNew() {}
39
Girish6a6044d2023-11-22 21:23:14 +000040void ResourceManagerServiceNew::init() {
41 // Create the Resource Tracker
42 mResourceTracker = std::make_shared<ResourceTracker>(ref<ResourceManagerServiceNew>(),
43 mProcessInfo);
Girish0ac5c212023-11-23 09:14:03 +000044 setUpResourceModels();
Girish6c16adb2023-11-23 10:16:47 +000045 setUpReclaimPolicies();
Girish0ac5c212023-11-23 09:14:03 +000046}
47
48void 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 }
Girish6a6044d2023-11-22 21:23:14 +000061}
62
Girish6c16adb2023-11-23 10:16:47 +000063void ResourceManagerServiceNew::setUpReclaimPolicies() {
64 mReclaimPolicies.clear();
Girish88a83502023-11-23 11:23:07 +000065 // Add Reclaim policies based on:
66 // - the Process priority (oom score)
67 // - the client/codec importance.
68 setReclaimPolicy(true /* processPriority */, true /* clientImportance */);
Girish6c16adb2023-11-23 10:16:47 +000069}
70
Girish1484e5d2023-11-20 06:00:44 +000071Status ResourceManagerServiceNew::config(const std::vector<MediaResourcePolicyParcel>& policies) {
Girish0ac5c212023-11-23 09:14:03 +000072 Status status = ResourceManagerService::config(policies);
73 // Change in the config dictates update to the resource model.
74 setUpResourceModels();
75 return status;
Girish1484e5d2023-11-20 06:00:44 +000076}
77
Girish6a6044d2023-11-22 21:23:14 +000078void ResourceManagerServiceNew::setObserverService(
79 const std::shared_ptr<ResourceObserverService>& observerService) {
80 ResourceManagerService::setObserverService(observerService);
81 mResourceTracker->setResourceObserverService(observerService);
82}
83
Girish1484e5d2023-11-20 06:00:44 +000084Status ResourceManagerServiceNew::addResource(
85 const ClientInfoParcel& clientInfo,
86 const std::shared_ptr<IResourceManagerClient>& client,
87 const std::vector<MediaResourceParcel>& resources) {
Girish6a6044d2023-11-22 21:23:14 +000088 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();
Girish1484e5d2023-11-20 06:00:44 +0000100}
101
102Status ResourceManagerServiceNew::removeResource(
103 const ClientInfoParcel& clientInfo,
104 const std::vector<MediaResourceParcel>& resources) {
Girish6a6044d2023-11-22 21:23:14 +0000105 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();
Girish1484e5d2023-11-20 06:00:44 +0000115}
116
117Status ResourceManagerServiceNew::removeClient(const ClientInfoParcel& clientInfo) {
Girish6a6044d2023-11-22 21:23:14 +0000118 removeResource(clientInfo, true /*checkValid*/);
119 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000120}
121
122Status ResourceManagerServiceNew::removeResource(const ClientInfoParcel& clientInfo,
123 bool checkValid) {
Girish6a6044d2023-11-22 21:23:14 +0000124 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();
Girish1484e5d2023-11-20 06:00:44 +0000136}
137
138Status 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
Girish6a6044d2023-11-22 21:23:14 +0000145bool ResourceManagerServiceNew::overridePid_l(int32_t originalPid, int32_t newPid) {
146 return mResourceTracker->overridePid(originalPid, newPid);
147}
148
Girish1484e5d2023-11-20 06:00:44 +0000149Status ResourceManagerServiceNew::overridePid(int originalPid, int newPid) {
150 return ResourceManagerService::overridePid(originalPid, newPid);
151}
152
Girish6a6044d2023-11-22 21:23:14 +0000153bool 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
Girish1484e5d2023-11-20 06:00:44 +0000161Status 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
Girish6a6044d2023-11-22 21:23:14 +0000169void ResourceManagerServiceNew::removeProcessInfoOverride(int pid) {
170 std::scoped_lock lock{mLock};
171
172 mResourceTracker->removeProcessInfoOverride(pid);
173}
174
Girish1484e5d2023-11-20 06:00:44 +0000175Status ResourceManagerServiceNew::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
Girish6a6044d2023-11-22 21:23:14 +0000176 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();
Girish1484e5d2023-11-20 06:00:44 +0000186}
187
188Status ResourceManagerServiceNew::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
Girish6a6044d2023-11-22 21:23:14 +0000189 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();
Girish1484e5d2023-11-20 06:00:44 +0000202}
203
204Status ResourceManagerServiceNew::notifyClientCreated(const ClientInfoParcel& clientInfo) {
205 return ResourceManagerService::notifyClientCreated(clientInfo);
206}
207
208Status ResourceManagerServiceNew::notifyClientStarted(const ClientConfigParcel& clientConfig) {
209 return ResourceManagerService::notifyClientStarted(clientConfig);
210}
211
212Status ResourceManagerServiceNew::notifyClientStopped(const ClientConfigParcel& clientConfig) {
213 return ResourceManagerService::notifyClientStopped(clientConfig);
214}
215
216Status ResourceManagerServiceNew::notifyClientConfigChanged(
217 const ClientConfigParcel& clientConfig) {
Girish88a83502023-11-23 11:23:07 +0000218 {
219 // Update the ResourceTracker about the change in the configuration.
220 std::scoped_lock lock{mLock};
221 mResourceTracker->updateResource(clientConfig.clientInfo);
222 }
Girish1484e5d2023-11-20 06:00:44 +0000223 return ResourceManagerService::notifyClientConfigChanged(clientConfig);
224}
225
Girish6a6044d2023-11-22 21:23:14 +0000226void ResourceManagerServiceNew::getResourceDump(std::string& resourceLog) const {
227 std::scoped_lock lock{mLock};
228 mResourceTracker->dump(resourceLog);
229}
230
Girish1484e5d2023-11-20 06:00:44 +0000231binder_status_t ResourceManagerServiceNew::dump(int fd, const char** args, uint32_t numArgs) {
232 return ResourceManagerService::dump(fd, args, numArgs);
233}
234
Girish0ac5c212023-11-23 09:14:03 +0000235bool ResourceManagerServiceNew::getTargetClients(
Girish88a83502023-11-23 11:23:07 +0000236 const ClientInfoParcel& clientInfo,
Girish0ac5c212023-11-23 09:14:03 +0000237 const std::vector<MediaResourceParcel>& resources,
238 std::vector<ClientInfo>& targetClients) {
Girish88a83502023-11-23 11:23:07 +0000239 int32_t callingPid = clientInfo.pid;
Girish0ac5c212023-11-23 09:14:03 +0000240 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.
Girish88a83502023-11-23 11:23:07 +0000250 uint32_t callingImportance = std::max(0, clientInfo.importance);
Girish1c682402024-01-31 21:03:51 +0000251 ReclaimRequestInfo reclaimRequestInfo{callingPid, clientInfo.id, callingImportance, resources};
Girish0ac5c212023-11-23 09:14:03 +0000252 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 }
Girish88a83502023-11-23 11:23:07 +0000259 // Since there was a conflict, we need to reclaim all clients.
Girish0ac5c212023-11-23 09:14:03 +0000260 targetClients = std::move(clients);
261 } else {
Girish6c16adb2023-11-23 10:16:47 +0000262 // Select a client among those have the needed resources.
Girish0ac5c212023-11-23 09:14:03 +0000263 getClientForResource_l(reclaimRequestInfo, clients, targetClients);
264 }
265 return !targetClients.empty();
266}
267
268void 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
Girish6c16adb2023-11-23 10:16:47 +0000285 // 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)) {
Girish0ac5c212023-11-23 09:14:03 +0000288 return;
289 }
290 }
291}
292
Girish0ac5c212023-11-23 09:14:03 +0000293bool 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 }
Girish6c16adb2023-11-23 10:16:47 +0000300
301 // Use the DefaultResourceModel to get all the clients with the resources requested.
Girish0ac5c212023-11-23 09:14:03 +0000302 std::vector<MediaResourceParcel> resources{*resourceRequestInfo.mResource};
Girish1c682402024-01-31 21:03:51 +0000303 ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid,
304 resourceRequestInfo.mClientId,
305 0, // default importance
306 resources};
Girish0ac5c212023-11-23 09:14:03 +0000307 std::vector<ClientInfo> clients;
308 mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients);
Girish6c16adb2023-11-23 10:16:47 +0000309
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;
Girish0ac5c212023-11-23 09:14:03 +0000322}
323
Girish6a6044d2023-11-22 21:23:14 +0000324bool ResourceManagerServiceNew::getPriority_l(int pid, int* priority) const {
325 return mResourceTracker->getPriority(pid, priority);
326}
327
328bool ResourceManagerServiceNew::getLowestPriorityPid_l(
329 MediaResource::Type type, MediaResource::SubType subType,
330 int* lowestPriorityPid, int* lowestPriority) {
Girish0ac5c212023-11-23 09:14:03 +0000331 //NOTE: This function is used only by the test: ResourceManagerServiceTest
Girish6a6044d2023-11-22 21:23:14 +0000332 return mResourceTracker->getLowestPriorityPid(type, subType,
333 *lowestPriorityPid,
334 *lowestPriority);
335}
336
Girish6a6044d2023-11-22 21:23:14 +0000337bool ResourceManagerServiceNew::getAllClients_l(
338 const ResourceRequestInfo& resourceRequestInfo,
339 std::vector<ClientInfo>& clientsInfo) {
Girish0ac5c212023-11-23 09:14:03 +0000340 //NOTE: This function is used only by the test: ResourceManagerServiceTest
Girish6a6044d2023-11-22 21:23:14 +0000341 MediaResource::Type type = resourceRequestInfo.mResource->type;
Girish0ac5c212023-11-23 09:14:03 +0000342 // Get the list of all clients that has requested resources.
Girish6a6044d2023-11-22 21:23:14 +0000343 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
Girishe8305272023-12-18 19:17:58 +0000362std::shared_ptr<IResourceManagerClient> ResourceManagerServiceNew::getClient_l(
Girish6a6044d2023-11-22 21:23:14 +0000363 int pid, const int64_t& clientId) const {
364 return mResourceTracker->getClient(pid, clientId);
365}
366
Girishe8305272023-12-18 19:17:58 +0000367bool ResourceManagerServiceNew::removeClient_l(int pid, const int64_t& clientId) {
Girish6a6044d2023-11-22 21:23:14 +0000368 return mResourceTracker->removeClient(pid, clientId);
369}
370
371const std::map<int, ResourceInfos>& ResourceManagerServiceNew::getResourceMap() const {
372 return mResourceTracker->getResourceMap();
373}
374
Girish88a83502023-11-23 11:23:07 +0000375void 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
Girish1484e5d2023-11-20 06:00:44 +0000388} // namespace android