blob: a8192377fde1a63ef39fa649b4a344f77f435919 [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"
Girish1484e5d2023-11-20 06:00:44 +000025#include "ResourceManagerServiceNew.h"
Girish6a6044d2023-11-22 21:23:14 +000026#include "ResourceTracker.h"
27#include "ServiceLog.h"
Girish1484e5d2023-11-20 06:00:44 +000028
29namespace android {
30
31ResourceManagerServiceNew::ResourceManagerServiceNew(
32 const sp<ProcessInfoInterface>& processInfo,
33 const sp<SystemCallbackInterface>& systemResource) :
34 ResourceManagerService(processInfo, systemResource) {}
35
36ResourceManagerServiceNew::~ResourceManagerServiceNew() {}
37
Girish6a6044d2023-11-22 21:23:14 +000038void ResourceManagerServiceNew::init() {
39 // Create the Resource Tracker
40 mResourceTracker = std::make_shared<ResourceTracker>(ref<ResourceManagerServiceNew>(),
41 mProcessInfo);
Girish0ac5c212023-11-23 09:14:03 +000042 setUpResourceModels();
43}
44
45void ResourceManagerServiceNew::setUpResourceModels() {
46 std::scoped_lock lock{mLock};
47 // Create/Configure the default resource model.
48 if (mDefaultResourceModel == nullptr) {
49 mDefaultResourceModel = std::make_unique<DefaultResourceModel>(
50 mResourceTracker,
51 mSupportsMultipleSecureCodecs,
52 mSupportsSecureWithNonSecureCodec);
53 } else {
54 DefaultResourceModel* resourceModel =
55 static_cast<DefaultResourceModel*>(mDefaultResourceModel.get());
56 resourceModel->config(mSupportsMultipleSecureCodecs, mSupportsSecureWithNonSecureCodec);
57 }
Girish6a6044d2023-11-22 21:23:14 +000058}
59
Girish1484e5d2023-11-20 06:00:44 +000060Status ResourceManagerServiceNew::config(const std::vector<MediaResourcePolicyParcel>& policies) {
Girish0ac5c212023-11-23 09:14:03 +000061 Status status = ResourceManagerService::config(policies);
62 // Change in the config dictates update to the resource model.
63 setUpResourceModels();
64 return status;
Girish1484e5d2023-11-20 06:00:44 +000065}
66
Girish6a6044d2023-11-22 21:23:14 +000067void ResourceManagerServiceNew::setObserverService(
68 const std::shared_ptr<ResourceObserverService>& observerService) {
69 ResourceManagerService::setObserverService(observerService);
70 mResourceTracker->setResourceObserverService(observerService);
71}
72
Girish1484e5d2023-11-20 06:00:44 +000073Status ResourceManagerServiceNew::addResource(
74 const ClientInfoParcel& clientInfo,
75 const std::shared_ptr<IResourceManagerClient>& client,
76 const std::vector<MediaResourceParcel>& resources) {
Girish6a6044d2023-11-22 21:23:14 +000077 int32_t pid = clientInfo.pid;
78 int32_t uid = clientInfo.uid;
79 int64_t clientId = clientInfo.id;
80 String8 log = String8::format("addResource(pid %d, uid %d clientId %lld, resources %s)",
81 pid, uid, (long long) clientId, getString(resources).c_str());
82 mServiceLog->add(log);
83
84 std::scoped_lock lock{mLock};
85 mResourceTracker->addResource(clientInfo, client, resources);
86 notifyResourceGranted(pid, resources);
87
88 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +000089}
90
91Status ResourceManagerServiceNew::removeResource(
92 const ClientInfoParcel& clientInfo,
93 const std::vector<MediaResourceParcel>& resources) {
Girish6a6044d2023-11-22 21:23:14 +000094 int32_t pid = clientInfo.pid;
95 int32_t uid = clientInfo.uid;
96 int64_t clientId = clientInfo.id;
97 String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld, resources %s)",
98 pid, uid, (long long) clientId, getString(resources).c_str());
99 mServiceLog->add(log);
100
101 std::scoped_lock lock{mLock};
102 mResourceTracker->removeResource(clientInfo, resources);
103 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000104}
105
106Status ResourceManagerServiceNew::removeClient(const ClientInfoParcel& clientInfo) {
Girish6a6044d2023-11-22 21:23:14 +0000107 removeResource(clientInfo, true /*checkValid*/);
108 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000109}
110
111Status ResourceManagerServiceNew::removeResource(const ClientInfoParcel& clientInfo,
112 bool checkValid) {
Girish6a6044d2023-11-22 21:23:14 +0000113 int32_t pid = clientInfo.pid;
114 int32_t uid = clientInfo.uid;
115 int64_t clientId = clientInfo.id;
116 String8 log = String8::format("removeResource(pid %d, uid %d clientId %lld)",
117 pid, uid, (long long) clientId);
118 mServiceLog->add(log);
119
120 std::scoped_lock lock{mLock};
121 if (mResourceTracker->removeResource(clientInfo, checkValid)) {
122 notifyClientReleased(clientInfo);
123 }
124 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000125}
126
127Status ResourceManagerServiceNew::reclaimResource(
128 const ClientInfoParcel& clientInfo,
129 const std::vector<MediaResourceParcel>& resources,
130 bool* _aidl_return) {
131 return ResourceManagerService::reclaimResource(clientInfo, resources, _aidl_return);
132}
133
Girish6a6044d2023-11-22 21:23:14 +0000134bool ResourceManagerServiceNew::overridePid_l(int32_t originalPid, int32_t newPid) {
135 return mResourceTracker->overridePid(originalPid, newPid);
136}
137
Girish1484e5d2023-11-20 06:00:44 +0000138Status ResourceManagerServiceNew::overridePid(int originalPid, int newPid) {
139 return ResourceManagerService::overridePid(originalPid, newPid);
140}
141
Girish6a6044d2023-11-22 21:23:14 +0000142bool ResourceManagerServiceNew::overrideProcessInfo_l(
143 const std::shared_ptr<IResourceManagerClient>& client,
144 int pid,
145 int procState,
146 int oomScore) {
147 return mResourceTracker->overrideProcessInfo(client, pid, procState, oomScore);
148}
149
Girish1484e5d2023-11-20 06:00:44 +0000150Status ResourceManagerServiceNew::overrideProcessInfo(
151 const std::shared_ptr<IResourceManagerClient>& client,
152 int pid,
153 int procState,
154 int oomScore) {
155 return ResourceManagerService::overrideProcessInfo(client, pid, procState, oomScore);
156}
157
Girish6a6044d2023-11-22 21:23:14 +0000158void ResourceManagerServiceNew::removeProcessInfoOverride(int pid) {
159 std::scoped_lock lock{mLock};
160
161 mResourceTracker->removeProcessInfoOverride(pid);
162}
163
Girish1484e5d2023-11-20 06:00:44 +0000164Status ResourceManagerServiceNew::markClientForPendingRemoval(const ClientInfoParcel& clientInfo) {
Girish6a6044d2023-11-22 21:23:14 +0000165 int32_t pid = clientInfo.pid;
166 int64_t clientId = clientInfo.id;
167 String8 log = String8::format(
168 "markClientForPendingRemoval(pid %d, clientId %lld)",
169 pid, (long long) clientId);
170 mServiceLog->add(log);
171
172 std::scoped_lock lock{mLock};
173 mResourceTracker->markClientForPendingRemoval(clientInfo);
174 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000175}
176
177Status ResourceManagerServiceNew::reclaimResourcesFromClientsPendingRemoval(int32_t pid) {
Girish6a6044d2023-11-22 21:23:14 +0000178 String8 log = String8::format("reclaimResourcesFromClientsPendingRemoval(pid %d)", pid);
179 mServiceLog->add(log);
180
181 std::vector<ClientInfo> targetClients;
182 {
183 std::scoped_lock lock{mLock};
184 mResourceTracker->getClientsMarkedPendingRemoval(pid, targetClients);
185 }
186
187 if (!targetClients.empty()) {
188 reclaimUnconditionallyFrom(targetClients);
189 }
190 return Status::ok();
Girish1484e5d2023-11-20 06:00:44 +0000191}
192
193Status ResourceManagerServiceNew::notifyClientCreated(const ClientInfoParcel& clientInfo) {
194 return ResourceManagerService::notifyClientCreated(clientInfo);
195}
196
197Status ResourceManagerServiceNew::notifyClientStarted(const ClientConfigParcel& clientConfig) {
198 return ResourceManagerService::notifyClientStarted(clientConfig);
199}
200
201Status ResourceManagerServiceNew::notifyClientStopped(const ClientConfigParcel& clientConfig) {
202 return ResourceManagerService::notifyClientStopped(clientConfig);
203}
204
205Status ResourceManagerServiceNew::notifyClientConfigChanged(
206 const ClientConfigParcel& clientConfig) {
207 return ResourceManagerService::notifyClientConfigChanged(clientConfig);
208}
209
Girish6a6044d2023-11-22 21:23:14 +0000210void ResourceManagerServiceNew::getResourceDump(std::string& resourceLog) const {
211 std::scoped_lock lock{mLock};
212 mResourceTracker->dump(resourceLog);
213}
214
Girish1484e5d2023-11-20 06:00:44 +0000215binder_status_t ResourceManagerServiceNew::dump(int fd, const char** args, uint32_t numArgs) {
216 return ResourceManagerService::dump(fd, args, numArgs);
217}
218
Girish0ac5c212023-11-23 09:14:03 +0000219bool ResourceManagerServiceNew::getTargetClients(
220 int callingPid,
221 const std::vector<MediaResourceParcel>& resources,
222 std::vector<ClientInfo>& targetClients) {
223 std::scoped_lock lock{mLock};
224 if (!mProcessInfo->isPidTrusted(callingPid)) {
225 pid_t actualCallingPid = IPCThreadState::self()->getCallingPid();
226 ALOGW("%s called with untrusted pid %d, using actual calling pid %d", __FUNCTION__,
227 callingPid, actualCallingPid);
228 callingPid = actualCallingPid;
229 }
230
231 // Use the Resource Model to get a list of all the clients that hold the
232 // needed/requested resources.
233 ReclaimRequestInfo reclaimRequestInfo{callingPid, resources};
234 std::vector<ClientInfo> clients;
235 if (!mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients)) {
236 if (clients.empty()) {
237 ALOGI("%s: There aren't any clients with given resources. Nothing to reclaim",
238 __func__);
239 return false;
240 }
241 // Since there was a conflict, we need to reclaim all elements.
242 targetClients = std::move(clients);
243 } else {
244 getClientForResource_l(reclaimRequestInfo, clients, targetClients);
245 }
246 return !targetClients.empty();
247}
248
249void ResourceManagerServiceNew::getClientForResource_l(
250 const ReclaimRequestInfo& reclaimRequestInfo,
251 const std::vector<ClientInfo>& clients,
252 std::vector<ClientInfo>& targetClients) {
253 int callingPid = reclaimRequestInfo.mCallingPid;
254
255 // Before looking into other processes, check if we have clients marked for
256 // pending removal in the same process.
257 ClientInfo targetClient;
258 for (const MediaResourceParcel& resource : reclaimRequestInfo.mResources) {
259 if (mResourceTracker->getBiggestClientPendingRemoval(callingPid, resource.type,
260 resource.subType, targetClient)) {
261 targetClients.emplace_back(targetClient);
262 return;
263 }
264 }
265
266 // Now find client(s) from a lowest priority process that has needed resources.
267 ResourceRequestInfo resourceRequestInfo {callingPid, nullptr};
268 for (const MediaResourceParcel& resource : reclaimRequestInfo.mResources) {
269 resourceRequestInfo.mResource = &resource;
270 if (getLowestPriorityProcessBiggestClient_l(resourceRequestInfo, clients, targetClient)) {
271 targetClients.emplace_back(targetClient);
272 return;
273 }
274 }
275}
276
277// Process priority (oom score) based reclaim:
278// - Find a process with lowest priority (than that of calling process).
279// - Find the bigegst client (with required resources) from that process.
280bool ResourceManagerServiceNew::getLowestPriorityProcessBiggestClient_l(
281 const ResourceRequestInfo& resourceRequestInfo,
282 const std::vector<ClientInfo>& clients,
283 ClientInfo& clientInfo) {
284 int callingPid = resourceRequestInfo.mCallingPid;
285 MediaResource::Type type = resourceRequestInfo.mResource->type;
286 MediaResource::SubType subType = resourceRequestInfo.mResource->subType;
287 int lowestPriorityPid;
288 int lowestPriority;
289 int callingPriority;
290
291 if (!mResourceTracker->getPriority(callingPid, &callingPriority)) {
292 ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
293 return false;
294 }
295
296 // Find the lowest priority process among all the clients.
297 if (!mResourceTracker->getLowestPriorityPid(clients, lowestPriorityPid, lowestPriority)) {
298 ALOGE("%s: can't find a process with lower priority than that of the process[%d:%d]",
299 __func__, callingPid, callingPriority);
300 return false;
301 }
302
303 if (lowestPriority <= callingPriority) {
304 ALOGE("%s: lowest priority %d vs caller priority %d",
305 __func__, lowestPriority, callingPriority);
306 return false;
307 }
308
309 // Get the biggest client from this process.
310 if (!mResourceTracker->getBiggestClient(lowestPriorityPid, type, subType, clientInfo)) {
311 return false;
312 }
313
314 ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)",
315 __func__, callingPid, callingPriority, lowestPriorityPid, lowestPriority);
316 return true;
317}
318
319bool ResourceManagerServiceNew::getLowestPriorityBiggestClient_l(
320 const ResourceRequestInfo& resourceRequestInfo,
321 ClientInfo& clientInfo) {
322 //NOTE: This function is used only by the test: ResourceManagerServiceTest
323 if (resourceRequestInfo.mResource == nullptr) {
324 return false;
325 }
326 std::vector<MediaResourceParcel> resources{*resourceRequestInfo.mResource};
327 ReclaimRequestInfo reclaimRequestInfo{resourceRequestInfo.mCallingPid, resources};
328 std::vector<ClientInfo> clients;
329 mDefaultResourceModel->getAllClients(reclaimRequestInfo, clients);
330 return getLowestPriorityProcessBiggestClient_l(resourceRequestInfo, clients, clientInfo);
331}
332
Girish6a6044d2023-11-22 21:23:14 +0000333bool ResourceManagerServiceNew::getPriority_l(int pid, int* priority) const {
334 return mResourceTracker->getPriority(pid, priority);
335}
336
337bool ResourceManagerServiceNew::getLowestPriorityPid_l(
338 MediaResource::Type type, MediaResource::SubType subType,
339 int* lowestPriorityPid, int* lowestPriority) {
Girish0ac5c212023-11-23 09:14:03 +0000340 //NOTE: This function is used only by the test: ResourceManagerServiceTest
Girish6a6044d2023-11-22 21:23:14 +0000341 return mResourceTracker->getLowestPriorityPid(type, subType,
342 *lowestPriorityPid,
343 *lowestPriority);
344}
345
Girish6a6044d2023-11-22 21:23:14 +0000346bool ResourceManagerServiceNew::getAllClients_l(
347 const ResourceRequestInfo& resourceRequestInfo,
348 std::vector<ClientInfo>& clientsInfo) {
Girish0ac5c212023-11-23 09:14:03 +0000349 //NOTE: This function is used only by the test: ResourceManagerServiceTest
Girish6a6044d2023-11-22 21:23:14 +0000350 MediaResource::Type type = resourceRequestInfo.mResource->type;
Girish0ac5c212023-11-23 09:14:03 +0000351 // Get the list of all clients that has requested resources.
Girish6a6044d2023-11-22 21:23:14 +0000352 std::vector<ClientInfo> clients;
353 mResourceTracker->getAllClients(resourceRequestInfo, clients);
354
355 // Check is there any high priority process holding up the resources already.
356 for (const ClientInfo& info : clients) {
357 if (!isCallingPriorityHigher_l(resourceRequestInfo.mCallingPid, info.mPid)) {
358 // some higher/equal priority process owns the resource,
359 // this request can't be fulfilled.
360 ALOGE("%s: can't reclaim resource %s from pid %d", __func__, asString(type), info.mPid);
361 return false;
362 }
363 clientsInfo.emplace_back(info);
364 }
365 if (clientsInfo.size() == 0) {
366 ALOGV("%s: didn't find any resource %s", __func__, asString(type));
367 }
368 return true;
369}
370
371std::shared_ptr<IResourceManagerClient> ResourceManagerServiceNew::getClient(
372 int pid, const int64_t& clientId) const {
373 return mResourceTracker->getClient(pid, clientId);
374}
375
376bool ResourceManagerServiceNew::removeClient(int pid, const int64_t& clientId) {
377 return mResourceTracker->removeClient(pid, clientId);
378}
379
380const std::map<int, ResourceInfos>& ResourceManagerServiceNew::getResourceMap() const {
381 return mResourceTracker->getResourceMap();
382}
383
Girish1484e5d2023-11-20 06:00:44 +0000384} // namespace android