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 "ProcessPriorityReclaimPolicy"
20 #include <utils/Log.h>
21
22 #include "ResourceTracker.h"
23 #include "ResourceManagerService.h"
24 #include "ProcessPriorityReclaimPolicy.h"
25
26 namespace android {
27
28 using aidl::android::media::IResourceManagerClient;
29
ProcessPriorityReclaimPolicy(const std::shared_ptr<ResourceTracker> & resourceTracker)30 ProcessPriorityReclaimPolicy::ProcessPriorityReclaimPolicy(
31 const std::shared_ptr<ResourceTracker>& resourceTracker)
32 : mResourceTracker(resourceTracker) {
33 }
34
~ProcessPriorityReclaimPolicy()35 ProcessPriorityReclaimPolicy::~ProcessPriorityReclaimPolicy() {
36 }
37
38 // Process priority (oom score) based reclaim:
39 // - Find a process with lowest priority (than that of calling process).
40 // - Find the bigegst client (with required resources) from that process.
getClients(const ReclaimRequestInfo & reclaimRequestInfo,const std::vector<ClientInfo> & clients,std::vector<ClientInfo> & targetClients)41 bool ProcessPriorityReclaimPolicy::getClients(const ReclaimRequestInfo& reclaimRequestInfo,
42 const std::vector<ClientInfo>& clients,
43 std::vector<ClientInfo>& targetClients) {
44 // NOTE: This is the behavior of the existing reclaim policy.
45 // We can alter it to select more than one client to reclaim from, depending
46 // on the reclaim polocy.
47
48 MediaResource::Type type = reclaimRequestInfo.mResources[0].type;
49 MediaResource::SubType subType = reclaimRequestInfo.mResources[0].subType;
50 // Find one client to reclaim the needed resources from.
51 // 1. Get the priority of the (reclaim) requesting process.
52 int callingPid = reclaimRequestInfo.mCallingPid;
53 int callingPriority = -1;
54 if (!mResourceTracker->getPriority(callingPid, &callingPriority)) {
55 ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
56 return false;
57 }
58
59 ClientInfo clientInfo;
60 // 2 Look to find the biggest client from the lowest priority process that
61 // has the other resources and with the given primary type.
62 bool found = false;
63 int lowestPriority = -1;
64 MediaResource::SubType primarySubType = subType;
65 for (size_t index = 1; !found && (index < reclaimRequestInfo.mResources.size()); index++) {
66 MediaResource::Type type = reclaimRequestInfo.mResources[index].type;
67 MediaResource::SubType subType = reclaimRequestInfo.mResources[index].subType;
68 found = getBiggestClientFromLowestPriority(callingPid, callingPriority,
69 type, subType, primarySubType,
70 clients, clientInfo, lowestPriority);
71 }
72 // 3 If we haven't found a client yet, then select the biggest client of primary type.
73 if (!found) {
74 found = getBiggestClientFromLowestPriority(callingPid, callingPriority,
75 type, subType,
76 MediaResource::SubType::kUnspecifiedSubType,
77 clients, clientInfo, lowestPriority);
78 }
79 // 4 If we haven't found a client yet, then select the biggest client of different type.
80 // This is applicable for code type only.
81 if (!found) {
82 if (type != MediaResource::Type::kSecureCodec &&
83 type != MediaResource::Type::kNonSecureCodec) {
84 return false;
85 }
86 MediaResourceType otherType = (type == MediaResource::Type::kSecureCodec) ?
87 MediaResource::Type::kNonSecureCodec : MediaResource::Type::kSecureCodec;
88 if (!getBiggestClientFromLowestPriority(callingPid, callingPriority,
89 otherType, subType,
90 MediaResource::SubType::kUnspecifiedSubType,
91 clients, clientInfo, lowestPriority)) {
92 return false;
93 }
94 }
95
96 targetClients.emplace_back(clientInfo);
97 ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)",
98 __func__, callingPid, callingPriority, clientInfo.mPid, lowestPriority);
99
100 return true;
101 }
102
getBiggestClientFromLowestPriority(pid_t callingPid,int callingPriority,MediaResource::Type type,MediaResource::SubType subType,MediaResource::SubType primarySubType,const std::vector<ClientInfo> & clients,ClientInfo & targetClient,int & lowestPriority)103 bool ProcessPriorityReclaimPolicy::getBiggestClientFromLowestPriority(
104 pid_t callingPid,
105 int callingPriority,
106 MediaResource::Type type, MediaResource::SubType subType,
107 MediaResource::SubType primarySubType,
108 const std::vector<ClientInfo>& clients,
109 ClientInfo& targetClient,
110 int& lowestPriority) {
111 // 1. Find the lowest priority process among all the clients with the
112 // requested resource type.
113 int lowestPriorityPid = -1;
114 lowestPriority = -1;
115 if (!mResourceTracker->getLowestPriorityPid(type, subType, primarySubType, clients,
116 lowestPriorityPid, lowestPriority)) {
117 ALOGD("%s: can't find a process with lower priority than that of the process[%d:%d]",
118 __func__, callingPid, callingPriority);
119 return false;
120 }
121
122 // 2. Make sure that the priority of the target process is less than
123 // requesting process.
124 if (lowestPriority <= callingPriority) {
125 ALOGD("%s: lowest priority %d vs caller priority %d",
126 __func__, lowestPriority, callingPriority);
127 return false;
128 }
129
130 // 3. Look to find the biggest client from that process for the given resources
131 return mResourceTracker->getBiggestClient(lowestPriorityPid, type, subType,
132 clients, targetClient, primarySubType);
133 }
134
135 } // namespace android
136