/* ** ** Copyright 2023, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "ProcessPriorityReclaimPolicy" #include #include "ResourceTracker.h" #include "ResourceManagerService.h" #include "ProcessPriorityReclaimPolicy.h" namespace android { using aidl::android::media::IResourceManagerClient; ProcessPriorityReclaimPolicy::ProcessPriorityReclaimPolicy( const std::shared_ptr& resourceTracker) : mResourceTracker(resourceTracker) { } ProcessPriorityReclaimPolicy::~ProcessPriorityReclaimPolicy() { } // Process priority (oom score) based reclaim: // - Find a process with lowest priority (than that of calling process). // - Find the bigegst client (with required resources) from that process. bool ProcessPriorityReclaimPolicy::getClients(const ReclaimRequestInfo& reclaimRequestInfo, const std::vector& clients, std::vector& targetClients) { // NOTE: This is the behavior of the existing reclaim policy. // We can alter it to select more than one client to reclaim from, depending // on the reclaim polocy. MediaResource::Type type = reclaimRequestInfo.mResources[0].type; MediaResource::SubType subType = reclaimRequestInfo.mResources[0].subType; // Find one client to reclaim the needed resources from. // 1. Get the priority of the (reclaim) requesting process. int callingPid = reclaimRequestInfo.mCallingPid; int callingPriority = -1; if (!mResourceTracker->getPriority(callingPid, &callingPriority)) { ALOGE("%s: can't get process priority for pid %d", __func__, callingPid); return false; } ClientInfo clientInfo; // 2 Look to find the biggest client from the lowest priority process that // has the other resources and with the given primary type. bool found = false; int lowestPriority = -1; MediaResource::SubType primarySubType = subType; for (size_t index = 1; !found && (index < reclaimRequestInfo.mResources.size()); index++) { MediaResource::Type type = reclaimRequestInfo.mResources[index].type; MediaResource::SubType subType = reclaimRequestInfo.mResources[index].subType; found = getBiggestClientFromLowestPriority(callingPid, callingPriority, type, subType, primarySubType, clients, clientInfo, lowestPriority); } // 3 If we haven't found a client yet, then select the biggest client of primary type. if (!found) { found = getBiggestClientFromLowestPriority(callingPid, callingPriority, type, subType, MediaResource::SubType::kUnspecifiedSubType, clients, clientInfo, lowestPriority); } // 4 If we haven't found a client yet, then select the biggest client of different type. // This is applicable for code type only. if (!found) { if (type != MediaResource::Type::kSecureCodec && type != MediaResource::Type::kNonSecureCodec) { return false; } MediaResourceType otherType = (type == MediaResource::Type::kSecureCodec) ? MediaResource::Type::kNonSecureCodec : MediaResource::Type::kSecureCodec; if (!getBiggestClientFromLowestPriority(callingPid, callingPriority, otherType, subType, MediaResource::SubType::kUnspecifiedSubType, clients, clientInfo, lowestPriority)) { return false; } } targetClients.emplace_back(clientInfo); ALOGI("%s: CallingProcess(%d:%d) will reclaim from the lowestPriorityProcess(%d:%d)", __func__, callingPid, callingPriority, clientInfo.mPid, lowestPriority); return true; } bool ProcessPriorityReclaimPolicy::getBiggestClientFromLowestPriority( pid_t callingPid, int callingPriority, MediaResource::Type type, MediaResource::SubType subType, MediaResource::SubType primarySubType, const std::vector& clients, ClientInfo& targetClient, int& lowestPriority) { // 1. Find the lowest priority process among all the clients with the // requested resource type. int lowestPriorityPid = -1; lowestPriority = -1; if (!mResourceTracker->getLowestPriorityPid(type, subType, primarySubType, clients, lowestPriorityPid, lowestPriority)) { ALOGD("%s: can't find a process with lower priority than that of the process[%d:%d]", __func__, callingPid, callingPriority); return false; } // 2. Make sure that the priority of the target process is less than // requesting process. if (lowestPriority <= callingPriority) { ALOGD("%s: lowest priority %d vs caller priority %d", __func__, lowestPriority, callingPriority); return false; } // 3. Look to find the biggest client from that process for the given resources return mResourceTracker->getBiggestClient(lowestPriorityPid, type, subType, clients, targetClient, primarySubType); } } // namespace android