1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright 2023, The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ProcessPriorityReclaimPolicy"
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include "ResourceTracker.h"
23*ec779b8eSAndroid Build Coastguard Worker #include "ResourceManagerService.h"
24*ec779b8eSAndroid Build Coastguard Worker #include "ProcessPriorityReclaimPolicy.h"
25*ec779b8eSAndroid Build Coastguard Worker
26*ec779b8eSAndroid Build Coastguard Worker namespace android {
27*ec779b8eSAndroid Build Coastguard Worker
28*ec779b8eSAndroid Build Coastguard Worker using aidl::android::media::IResourceManagerClient;
29*ec779b8eSAndroid Build Coastguard Worker
ProcessPriorityReclaimPolicy(const std::shared_ptr<ResourceTracker> & resourceTracker)30*ec779b8eSAndroid Build Coastguard Worker ProcessPriorityReclaimPolicy::ProcessPriorityReclaimPolicy(
31*ec779b8eSAndroid Build Coastguard Worker const std::shared_ptr<ResourceTracker>& resourceTracker)
32*ec779b8eSAndroid Build Coastguard Worker : mResourceTracker(resourceTracker) {
33*ec779b8eSAndroid Build Coastguard Worker }
34*ec779b8eSAndroid Build Coastguard Worker
~ProcessPriorityReclaimPolicy()35*ec779b8eSAndroid Build Coastguard Worker ProcessPriorityReclaimPolicy::~ProcessPriorityReclaimPolicy() {
36*ec779b8eSAndroid Build Coastguard Worker }
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker // Process priority (oom score) based reclaim:
39*ec779b8eSAndroid Build Coastguard Worker // - Find a process with lowest priority (than that of calling process).
40*ec779b8eSAndroid Build Coastguard Worker // - Find the bigegst client (with required resources) from that process.
getClients(const ReclaimRequestInfo & reclaimRequestInfo,const std::vector<ClientInfo> & clients,std::vector<ClientInfo> & targetClients)41*ec779b8eSAndroid Build Coastguard Worker bool ProcessPriorityReclaimPolicy::getClients(const ReclaimRequestInfo& reclaimRequestInfo,
42*ec779b8eSAndroid Build Coastguard Worker const std::vector<ClientInfo>& clients,
43*ec779b8eSAndroid Build Coastguard Worker std::vector<ClientInfo>& targetClients) {
44*ec779b8eSAndroid Build Coastguard Worker // NOTE: This is the behavior of the existing reclaim policy.
45*ec779b8eSAndroid Build Coastguard Worker // We can alter it to select more than one client to reclaim from, depending
46*ec779b8eSAndroid Build Coastguard Worker // on the reclaim polocy.
47*ec779b8eSAndroid Build Coastguard Worker
48*ec779b8eSAndroid Build Coastguard Worker MediaResource::Type type = reclaimRequestInfo.mResources[0].type;
49*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType subType = reclaimRequestInfo.mResources[0].subType;
50*ec779b8eSAndroid Build Coastguard Worker // Find one client to reclaim the needed resources from.
51*ec779b8eSAndroid Build Coastguard Worker // 1. Get the priority of the (reclaim) requesting process.
52*ec779b8eSAndroid Build Coastguard Worker int callingPid = reclaimRequestInfo.mCallingPid;
53*ec779b8eSAndroid Build Coastguard Worker int callingPriority = -1;
54*ec779b8eSAndroid Build Coastguard Worker if (!mResourceTracker->getPriority(callingPid, &callingPriority)) {
55*ec779b8eSAndroid Build Coastguard Worker ALOGE("%s: can't get process priority for pid %d", __func__, callingPid);
56*ec779b8eSAndroid Build Coastguard Worker return false;
57*ec779b8eSAndroid Build Coastguard Worker }
58*ec779b8eSAndroid Build Coastguard Worker
59*ec779b8eSAndroid Build Coastguard Worker ClientInfo clientInfo;
60*ec779b8eSAndroid Build Coastguard Worker // 2 Look to find the biggest client from the lowest priority process that
61*ec779b8eSAndroid Build Coastguard Worker // has the other resources and with the given primary type.
62*ec779b8eSAndroid Build Coastguard Worker bool found = false;
63*ec779b8eSAndroid Build Coastguard Worker int lowestPriority = -1;
64*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType primarySubType = subType;
65*ec779b8eSAndroid Build Coastguard Worker for (size_t index = 1; !found && (index < reclaimRequestInfo.mResources.size()); index++) {
66*ec779b8eSAndroid Build Coastguard Worker MediaResource::Type type = reclaimRequestInfo.mResources[index].type;
67*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType subType = reclaimRequestInfo.mResources[index].subType;
68*ec779b8eSAndroid Build Coastguard Worker found = getBiggestClientFromLowestPriority(callingPid, callingPriority,
69*ec779b8eSAndroid Build Coastguard Worker type, subType, primarySubType,
70*ec779b8eSAndroid Build Coastguard Worker clients, clientInfo, lowestPriority);
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker // 3 If we haven't found a client yet, then select the biggest client of primary type.
73*ec779b8eSAndroid Build Coastguard Worker if (!found) {
74*ec779b8eSAndroid Build Coastguard Worker found = getBiggestClientFromLowestPriority(callingPid, callingPriority,
75*ec779b8eSAndroid Build Coastguard Worker type, subType,
76*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType::kUnspecifiedSubType,
77*ec779b8eSAndroid Build Coastguard Worker clients, clientInfo, lowestPriority);
78*ec779b8eSAndroid Build Coastguard Worker }
79*ec779b8eSAndroid Build Coastguard Worker // 4 If we haven't found a client yet, then select the biggest client of different type.
80*ec779b8eSAndroid Build Coastguard Worker // This is applicable for code type only.
81*ec779b8eSAndroid Build Coastguard Worker if (!found) {
82*ec779b8eSAndroid Build Coastguard Worker if (type != MediaResource::Type::kSecureCodec &&
83*ec779b8eSAndroid Build Coastguard Worker type != MediaResource::Type::kNonSecureCodec) {
84*ec779b8eSAndroid Build Coastguard Worker return false;
85*ec779b8eSAndroid Build Coastguard Worker }
86*ec779b8eSAndroid Build Coastguard Worker MediaResourceType otherType = (type == MediaResource::Type::kSecureCodec) ?
87*ec779b8eSAndroid Build Coastguard Worker MediaResource::Type::kNonSecureCodec : MediaResource::Type::kSecureCodec;
88*ec779b8eSAndroid Build Coastguard Worker if (!getBiggestClientFromLowestPriority(callingPid, callingPriority,
89*ec779b8eSAndroid Build Coastguard Worker otherType, subType,
90*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType::kUnspecifiedSubType,
91*ec779b8eSAndroid Build Coastguard Worker clients, clientInfo, lowestPriority)) {
92*ec779b8eSAndroid Build Coastguard Worker return false;
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker }
95*ec779b8eSAndroid Build Coastguard Worker
96*ec779b8eSAndroid Build Coastguard Worker targetClients.emplace_back(clientInfo);
97*ec779b8eSAndroid Build Coastguard Worker ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)",
98*ec779b8eSAndroid Build Coastguard Worker __func__, callingPid, callingPriority, clientInfo.mPid, lowestPriority);
99*ec779b8eSAndroid Build Coastguard Worker
100*ec779b8eSAndroid Build Coastguard Worker return true;
101*ec779b8eSAndroid Build Coastguard Worker }
102*ec779b8eSAndroid Build Coastguard Worker
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*ec779b8eSAndroid Build Coastguard Worker bool ProcessPriorityReclaimPolicy::getBiggestClientFromLowestPriority(
104*ec779b8eSAndroid Build Coastguard Worker pid_t callingPid,
105*ec779b8eSAndroid Build Coastguard Worker int callingPriority,
106*ec779b8eSAndroid Build Coastguard Worker MediaResource::Type type, MediaResource::SubType subType,
107*ec779b8eSAndroid Build Coastguard Worker MediaResource::SubType primarySubType,
108*ec779b8eSAndroid Build Coastguard Worker const std::vector<ClientInfo>& clients,
109*ec779b8eSAndroid Build Coastguard Worker ClientInfo& targetClient,
110*ec779b8eSAndroid Build Coastguard Worker int& lowestPriority) {
111*ec779b8eSAndroid Build Coastguard Worker // 1. Find the lowest priority process among all the clients with the
112*ec779b8eSAndroid Build Coastguard Worker // requested resource type.
113*ec779b8eSAndroid Build Coastguard Worker int lowestPriorityPid = -1;
114*ec779b8eSAndroid Build Coastguard Worker lowestPriority = -1;
115*ec779b8eSAndroid Build Coastguard Worker if (!mResourceTracker->getLowestPriorityPid(type, subType, primarySubType, clients,
116*ec779b8eSAndroid Build Coastguard Worker lowestPriorityPid, lowestPriority)) {
117*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: can't find a process with lower priority than that of the process[%d:%d]",
118*ec779b8eSAndroid Build Coastguard Worker __func__, callingPid, callingPriority);
119*ec779b8eSAndroid Build Coastguard Worker return false;
120*ec779b8eSAndroid Build Coastguard Worker }
121*ec779b8eSAndroid Build Coastguard Worker
122*ec779b8eSAndroid Build Coastguard Worker // 2. Make sure that the priority of the target process is less than
123*ec779b8eSAndroid Build Coastguard Worker // requesting process.
124*ec779b8eSAndroid Build Coastguard Worker if (lowestPriority <= callingPriority) {
125*ec779b8eSAndroid Build Coastguard Worker ALOGD("%s: lowest priority %d vs caller priority %d",
126*ec779b8eSAndroid Build Coastguard Worker __func__, lowestPriority, callingPriority);
127*ec779b8eSAndroid Build Coastguard Worker return false;
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker
130*ec779b8eSAndroid Build Coastguard Worker // 3. Look to find the biggest client from that process for the given resources
131*ec779b8eSAndroid Build Coastguard Worker return mResourceTracker->getBiggestClient(lowestPriorityPid, type, subType,
132*ec779b8eSAndroid Build Coastguard Worker clients, targetClient, primarySubType);
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker
135*ec779b8eSAndroid Build Coastguard Worker } // namespace android
136