blob: de682f8e489cf539b6f1e375068ac9a1f22c7147 [file] [log] [blame]
Girish27365ed2023-10-11 20:20:55 +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 "ResourceManagerServiceUtils"
20#include <utils/Log.h>
21
22#include "ResourceManagerService.h"
23#include "ResourceManagerServiceUtils.h"
24
25namespace android {
26
Girishab17b0f2023-11-20 06:00:44 +000027// Bunch of utility functions that looks for a specific Resource.
28// Check whether a given resource (of type and subtype) is found in given resource parcel.
Girish27365ed2023-10-11 20:20:55 +000029bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
Girishab17b0f2023-11-20 06:00:44 +000030 const MediaResourceParcel& resource) {
Girish27365ed2023-10-11 20:20:55 +000031 if (type != resource.type) {
32 return false;
33 }
34 switch (type) {
Girishab17b0f2023-11-20 06:00:44 +000035 // Codec subtypes (e.g. video vs. audio and hw vs. sw) are each considered separate resources,
36 // so compare the subtypes as well.
37 case MediaResource::Type::kSecureCodec:
38 case MediaResource::Type::kNonSecureCodec:
39 if (resource.subType == subType) {
Girish27365ed2023-10-11 20:20:55 +000040 return true;
Girishab17b0f2023-11-20 06:00:44 +000041 }
42 break;
43 // Non-codec resources are not segregated by the subtype (e.g. video vs. audio).
44 default:
45 return true;
Girish27365ed2023-10-11 20:20:55 +000046 }
47 return false;
48}
49
Girishab17b0f2023-11-20 06:00:44 +000050// Check whether a given resource (of type and subtype) is found in given resource list.
Girish27365ed2023-10-11 20:20:55 +000051bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
Girishab17b0f2023-11-20 06:00:44 +000052 const ResourceList& resources) {
Girish27365ed2023-10-11 20:20:55 +000053 for (auto it = resources.begin(); it != resources.end(); it++) {
54 if (hasResourceType(type, subType, it->second)) {
55 return true;
56 }
57 }
58 return false;
59}
60
Girishab17b0f2023-11-20 06:00:44 +000061// Check whether a given resource (of type and subtype) is found in given resource info list.
Girish27365ed2023-10-11 20:20:55 +000062bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
Girishab17b0f2023-11-20 06:00:44 +000063 const ResourceInfos& infos) {
Girish27365ed2023-10-11 20:20:55 +000064 for (const auto& [id, info] : infos) {
65 if (hasResourceType(type, subType, info.resources)) {
66 return true;
67 }
68 }
69 return false;
70}
71
72ResourceInfos& getResourceInfosForEdit(int pid, PidResourceInfosMap& map) {
73 PidResourceInfosMap::iterator found = map.find(pid);
74 if (found == map.end()) {
75 // new pid
76 ResourceInfos infosForPid;
77 auto [it, inserted] = map.emplace(pid, infosForPid);
78 found = it;
79 }
80
81 return found->second;
82}
83
Girishab17b0f2023-11-20 06:00:44 +000084// Return modifiable ResourceInfo for a given client (look up by client id)
85// from the map of ResourceInfos.
86// If the item is not in the map, create one and add it to the map.
Girish27365ed2023-10-11 20:20:55 +000087ResourceInfo& getResourceInfoForEdit(const ClientInfoParcel& clientInfo,
Girishab17b0f2023-11-20 06:00:44 +000088 const std::shared_ptr<IResourceManagerClient>& client,
89 ResourceInfos& infos) {
Girish27365ed2023-10-11 20:20:55 +000090 ResourceInfos::iterator found = infos.find(clientInfo.id);
91
92 if (found == infos.end()) {
Girishab17b0f2023-11-20 06:00:44 +000093 ResourceInfo info{.pid = clientInfo.pid,
94 .uid = static_cast<uid_t>(clientInfo.uid),
Girish27365ed2023-10-11 20:20:55 +000095 .clientId = clientInfo.id,
96 .name = clientInfo.name.empty()? "<unknown client>" : clientInfo.name,
97 .client = client,
98 .deathNotifier = nullptr,
99 .pendingRemoval = false};
100 auto [it, inserted] = infos.emplace(clientInfo.id, info);
101 found = it;
102 }
103
104 return found->second;
105}
106
Girishab17b0f2023-11-20 06:00:44 +0000107// Merge resources from r2 into r1.
108void mergeResources(MediaResourceParcel& r1, const MediaResourceParcel& r2) {
109 // The resource entry on record is maintained to be in [0,INT64_MAX].
110 // Clamp if merging in the new resource value causes it to go out of bound.
111 // Note that the new resource value could be negative, eg.DrmSession, the
112 // value goes lower when the session is used more often. During reclaim
113 // the session with the highest value (lowest usage) would be closed.
114 if (r2.value < INT64_MAX - r1.value) {
115 r1.value += r2.value;
116 if (r1.value < 0) {
117 r1.value = 0;
118 }
119 } else {
120 r1.value = INT64_MAX;
121 }
122}
123
124///////////////////////////////////////////////////////////////////////
125////////////// Death Notifier implementation ////////////////////////
126///////////////////////////////////////////////////////////////////////
127
128DeathNotifier::DeathNotifier(const std::shared_ptr<IResourceManagerClient>& client,
129 const std::weak_ptr<ResourceManagerService>& service,
130 const ClientInfoParcel& clientInfo)
131 : mClient(client), mService(service), mClientInfo(clientInfo),
132 mCookie(nullptr),
133 mDeathRecipient(::ndk::ScopedAIBinder_DeathRecipient(
134 AIBinder_DeathRecipient_new(BinderDiedCallback))) {
135 // Setting callback notification when DeathRecipient gets deleted.
136 AIBinder_DeathRecipient_setOnUnlinked(mDeathRecipient.get(), BinderUnlinkedCallback);
137}
138
139//static
140void DeathNotifier::BinderUnlinkedCallback(void* cookie) {
141 BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie);
142 // Since we don't need the context anymore, we are deleting it now.
143 delete context;
144}
145
146//static
147void DeathNotifier::BinderDiedCallback(void* cookie) {
148 BinderDiedContext* context = reinterpret_cast<BinderDiedContext*>(cookie);
149
150 // Validate the context and check if the DeathNotifier object is still in scope.
151 if (context != nullptr) {
152 std::shared_ptr<DeathNotifier> thiz = context->mDeathNotifier.lock();
153 if (thiz != nullptr) {
154 thiz->binderDied();
155 } else {
156 ALOGI("DeathNotifier is out of scope already");
157 }
158 }
159}
160
161void DeathNotifier::binderDied() {
162 // Don't check for pid validity since we know it's already dead.
163 std::shared_ptr<ResourceManagerService> service = mService.lock();
164 if (service == nullptr) {
165 ALOGW("ResourceManagerService is dead as well.");
166 return;
167 }
168
169 service->overridePid(mClientInfo.pid, -1);
170 // thiz is freed in the call below, so it must be last call referring thiz
171 service->removeResource(mClientInfo, false /*checkValid*/);
172}
173
174void OverrideProcessInfoDeathNotifier::binderDied() {
175 // Don't check for pid validity since we know it's already dead.
176 std::shared_ptr<ResourceManagerService> service = mService.lock();
177 if (service == nullptr) {
178 ALOGW("ResourceManagerService is dead as well.");
179 return;
180 }
181
182 service->removeProcessInfoOverride(mClientInfo.pid);
183}
184
185std::shared_ptr<DeathNotifier> DeathNotifier::Create(
186 const std::shared_ptr<IResourceManagerClient>& client,
187 const std::weak_ptr<ResourceManagerService>& service,
188 const ClientInfoParcel& clientInfo,
189 bool overrideProcessInfo) {
190 std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
191 if (overrideProcessInfo) {
192 deathNotifier = std::make_shared<OverrideProcessInfoDeathNotifier>(
193 client, service, clientInfo);
194 } else {
195 deathNotifier = std::make_shared<DeathNotifier>(client, service, clientInfo);
196 }
197
198 if (deathNotifier) {
199 deathNotifier->link();
200 }
201
202 return deathNotifier;
203}
204
Girish27365ed2023-10-11 20:20:55 +0000205} // namespace android