• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
19 #define ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
20 
21 #include <map>
22 #include <set>
23 #include <memory>
24 #include <vector>
25 
26 #include <aidl/android/media/BnResourceManagerService.h>
27 #include <media/MediaResource.h>
28 #include <utils/String8.h>
29 
30 namespace android {
31 
32 class ResourceManagerService;
33 
34 /*
35  * Death Notifier to track IResourceManagerClient's death.
36  */
37 class DeathNotifier : public std::enable_shared_from_this<DeathNotifier> {
38 
39     // BinderDiedContext defines the cookie that is passed as DeathRecipient.
40     // Since this can maintain more context than a raw pointer, we can
41     // validate the scope of DeathNotifier, before deferencing it upon the binder death.
42     struct BinderDiedContext {
43         std::weak_ptr<DeathNotifier> mDeathNotifier;
44     };
45 public:
46     static std::shared_ptr<DeathNotifier> Create(
47         const std::shared_ptr<::aidl::android::media::IResourceManagerClient>& client,
48         const std::weak_ptr<ResourceManagerService>& service,
49         const ::aidl::android::media::ClientInfoParcel& clientInfo,
50         bool overrideProcessInfo = false);
51 
52     DeathNotifier(const std::shared_ptr<::aidl::android::media::IResourceManagerClient>& client,
53                   const std::weak_ptr<ResourceManagerService>& service,
54                   const ::aidl::android::media::ClientInfoParcel& clientInfo);
55 
~DeathNotifier()56     virtual ~DeathNotifier() {
57         unlink();
58     }
59 
60     // Implement death recipient
61     static void BinderDiedCallback(void* cookie);
62     static void BinderUnlinkedCallback(void* cookie);
63     virtual void binderDied();
64 
65 private:
link()66     void link() {
67         // Create the context that is passed as cookie to the binder death notification.
68         // The context gets deleted at BinderUnlinkedCallback.
69         mCookie = new BinderDiedContext{.mDeathNotifier = weak_from_this()};
70         // Register for the callbacks by linking to death notification.
71         AIBinder_linkToDeath(mClient->asBinder().get(), mDeathRecipient.get(), mCookie);
72     }
73 
unlink()74     void unlink() {
75         if (mClient != nullptr) {
76             // Unlink from the death notification.
77             AIBinder_unlinkToDeath(mClient->asBinder().get(), mDeathRecipient.get(), mCookie);
78             mClient = nullptr;
79         }
80     }
81 
82 protected:
83     std::shared_ptr<::aidl::android::media::IResourceManagerClient> mClient;
84     std::weak_ptr<ResourceManagerService> mService;
85     const ::aidl::android::media::ClientInfoParcel mClientInfo;
86     BinderDiedContext* mCookie;
87     ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
88 };
89 
90 class OverrideProcessInfoDeathNotifier : public DeathNotifier {
91 public:
OverrideProcessInfoDeathNotifier(const std::shared_ptr<::aidl::android::media::IResourceManagerClient> & client,const std::weak_ptr<ResourceManagerService> & service,const::aidl::android::media::ClientInfoParcel & clientInfo)92     OverrideProcessInfoDeathNotifier(
93         const std::shared_ptr<::aidl::android::media::IResourceManagerClient>& client,
94         const std::weak_ptr<ResourceManagerService>& service,
95         const ::aidl::android::media::ClientInfoParcel& clientInfo)
96             : DeathNotifier(client, service, clientInfo) {}
97 
~OverrideProcessInfoDeathNotifier()98     virtual ~OverrideProcessInfoDeathNotifier() {}
99 
100     virtual void binderDied();
101 };
102 
103 // Encapsulate Resource List as vector of resources instead of map.
104 // Since the number of resource is very limited, maintaining it as
105 // std::vector helps with both performance and memory requiremnts.
106 struct ResourceList {
107     // Add or Update an entry into ResourceList.
108     // If a new entry is added, isNewEntry will be set to true upon return
109     // returns true on successful update, false otherwise.
110     bool add(const ::aidl::android::media::MediaResourceParcel& res, bool* isNewEntry = nullptr);
111 
112     // reduce the resource usage by subtracting the resource value.
113     // If the resource value is 0 after reducing the resource usage,
114     // that entry will be removed and removedEntryValue is set to the
115     // value before it was removed upon return otherwise it will be set to -1.
116     // returns true on successful removal of the resource, false otherwise.
117     bool remove(const ::aidl::android::media::MediaResourceParcel& res,
118                 long* removedEntryValue = nullptr);
119 
120     // updates the resource usage by performing one of the following operations:
121     //  - If the resource is already there:
122     //    - If the new value is 0, remove the entry.
123     //      Also, returns the removed entry through removedEntryValue (if valid)
124     //    - Else update the resource value with the new value
125     //    - return true
126     //  - Else, add it as a new entry and return false.
127     bool update(const ::aidl::android::media::MediaResourceParcel& res,
128                 long* removedEntryValue = nullptr);
129 
130     // Returns true if there aren't any resource entries.
emptyResourceList131     bool empty() const {
132         return mResourceList.empty();
133     }
134 
135     // Returns resource list as a non-modifiable vectors
getResourcesResourceList136     const std::vector<::aidl::android::media::MediaResourceParcel>& getResources() const {
137         return mResourceList;
138     }
139 
140     // Converts resource list into string format
141     std::string toString() const;
142 
143     // BEGIN: Test only function
144     // Check if two resource lists are the same.
145     bool operator==(const ResourceList& rhs) const;
146 
147     // Add or Update an entry into ResourceList.
148     void addOrUpdate(const ::aidl::android::media::MediaResourceParcel& res);
149     // END: Test only function
150 
151 private:
152     std::vector<::aidl::android::media::MediaResourceParcel> mResourceList;
153 };
154 
155 // Encapsulation for Resource Info, that contains
156 // - pid of the app
157 // - uid of the app
158 // - client id
159 // - name of the client (specifically for the codec)
160 // - the client associted with it
161 // - death notifier for the (above) client
162 // - list of resources associated with it
163 // - A flag that marks whether this resource is pending to be removed.
164 struct ResourceInfo {
165     pid_t pid;
166     uid_t uid;
167     int64_t clientId;
168     std::string name;
169     std::shared_ptr<::aidl::android::media::IResourceManagerClient> client;
170     std::shared_ptr<DeathNotifier> deathNotifier = nullptr;
171     ResourceList resources;
172     bool pendingRemoval{false};
173     uint32_t importance = 0;
174 };
175 
176 /*
177  * Resource Reclaim request info that encapsulates
178  *  - the calling/requesting process pid.
179  *  - id of the client that made reclaim request.
180  *  - the calling/requesting client's importance.
181  *  - the list of resources requesting (to be reclaimed from others)
182  */
183 struct ReclaimRequestInfo {
184     int mCallingPid = -1;
185     int64_t mClientId = 0;
186     uint32_t mCallingClientImportance = 0;
187     const std::vector<::aidl::android::media::MediaResourceParcel>& mResources;
188 };
189 
190 /*
191  * Resource request info that encapsulates
192  *  - the calling/requesting process pid.
193  *  - the calling/requesting client's id.
194  *  - the resource requesting (to be reclaimed from others)
195  */
196 struct ResourceRequestInfo {
197     // pid of the calling/requesting process.
198     int mCallingPid = -1;
199     // id of the calling/requesting client.
200     int64_t mClientId = 0;
201     // resources requested.
202     const ::aidl::android::media::MediaResourceParcel* mResource;
203 };
204 
205 /*
206  * Structure that defines the Client - a possible target to relcaim from.
207  * This encapsulates pid, uid of the process and the client id
208  * based on the reclaim policy.
209  */
210 struct ClientInfo {
211     // pid of the process.
212     pid_t mPid = -1;
213     // uid of the process.
214     uid_t mUid = -1;
215     // Client Id.
216     int64_t mClientId = -1;
217     ClientInfo(pid_t pid = -1, uid_t uid = -1, const int64_t& clientId = -1)
mPidClientInfo218         : mPid(pid), mUid(uid), mClientId(clientId) {}
219 };
220 
221 // Map of Resource information index through the client id.
222 typedef std::map<int64_t, ResourceInfo> ResourceInfos;
223 
224 // Map of Resource information indexed through the process id.
225 typedef std::map<int, ResourceInfos> PidResourceInfosMap;
226 
227 // templated function to stringify the given vector of items.
228 template <typename T>
getString(const std::vector<T> & items)229 String8 getString(const std::vector<T>& items) {
230     String8 itemsStr;
231     for (size_t i = 0; i < items.size(); ++i) {
232         itemsStr.appendFormat("%s ", toString(items[i]).c_str());
233     }
234     return itemsStr;
235 }
236 
237 // Bunch of utility functions that looks for a specific Resource.
238 
239 //Check whether a given resource (of type and subtype) is found in given resource parcel.
240 bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
241                      const ::aidl::android::media::MediaResourceParcel& resource);
242 
243 //Check whether a given resource (of type and subtype) is found in given resource list.
244 bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
245                      const ResourceList& resources);
246 
247 //Check whether a given resource (of type and subtype) is found in given resource info list.
248 bool hasResourceType(MediaResource::Type type, MediaResource::SubType subType,
249                      const ResourceInfos& infos);
250 
251 // Return modifiable list of ResourceInfo for a given process (look up by pid)
252 // from the map of ResourceInfos.
253 ResourceInfos& getResourceInfosForEdit(int pid, PidResourceInfosMap& map);
254 
255 // Return modifiable ResourceInfo for a given process (look up by pid)
256 // from the map of ResourceInfos.
257 // If the item is not in the map, create one and add it to the map.
258 ResourceInfo& getResourceInfoForEdit(
259         const aidl::android::media::ClientInfoParcel& clientInfo,
260         const std::shared_ptr<aidl::android::media::IResourceManagerClient>& client,
261         ResourceInfos& infos);
262 
263 // Merge resources from r2 into r1.
264 void mergeResources(::aidl::android::media::MediaResourceParcel& r1,
265                     const ::aidl::android::media::MediaResourceParcel& r2);
266 
267 // To notify the media_resource_monitor about the resource being granted.
268 void notifyResourceGranted(
269         int pid,
270         const std::vector<::aidl::android::media::MediaResourceParcel>& resources);
271 
272 } // namespace android
273 
274 #endif //ANDROID_MEDIA_RESOURCEMANAGERSERVICEUTILS_H_
275