blob: 5b776a6b520b000e16e7cfc98a556f82c6d415f7 [file] [log] [blame]
/*
**
** 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 <utils/Log.h>
#include "ResourceTracker.h"
#include "ResourceManagerService.h"
#include "ProcessPriorityReclaimPolicy.h"
namespace android {
using aidl::android::media::IResourceManagerClient;
ProcessPriorityReclaimPolicy::ProcessPriorityReclaimPolicy(
const std::shared_ptr<ResourceTracker>& 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<ClientInfo>& clients,
std::vector<ClientInfo>& 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<ClientInfo>& 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