Convert IResourceManagerService to stable AIDL
Convert with minimal change to the interface itself.
Add additional test to cover DrmSessionManager's usage
of possible negative value field (which is signed now).
bug: 142396029
test: ResourceManagerService_test, DrmSessionManager_test,
CTS ResourceManagerServiceTest;
Manually check battery stats reporting.
Change-Id: I5c537a54efc2663281c96ddbdbd4ee56f23c1adf
diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 45eea0f..ae832c7 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -23,6 +23,7 @@
#include <binder/IServiceManager.h>
#include <cutils/sched_policy.h>
#include <dirent.h>
+#include <media/MediaResourcePolicy.h>
#include <media/stagefright/ProcessInfo.h>
#include <mediautils/BatteryNotifier.h>
#include <mediautils/SchedulingPolicyService.h>
@@ -37,7 +38,7 @@
namespace android {
-namespace {
+namespace media {
class DeathNotifier : public IBinder::DeathRecipient {
public:
@@ -60,20 +61,18 @@
int64_t mClientId;
};
-} // namespace
-
template <typename T>
-static String8 getString(const Vector<T> &items) {
+static String8 getString(const std::vector<T> &items) {
String8 itemsStr;
for (size_t i = 0; i < items.size(); ++i) {
- itemsStr.appendFormat("%s ", items[i].toString().string());
+ itemsStr.appendFormat("%s ", toString(items[i]).string());
}
return itemsStr;
}
static bool hasResourceType(MediaResource::Type type, const ResourceList& resources) {
for (auto it = resources.begin(); it != resources.end(); it++) {
- if (it->second.mType == type) {
+ if (it->second.type == type) {
return true;
}
}
@@ -121,15 +120,15 @@
return infos.editValueAt(index);
}
-static void notifyResourceGranted(int pid, const Vector<MediaResource> &resources) {
+static void notifyResourceGranted(int pid, const std::vector<MediaResourceParcel> &resources) {
static const char* const kServiceName = "media_resource_monitor";
sp<IBinder> binder = defaultServiceManager()->checkService(String16(kServiceName));
if (binder != NULL) {
sp<IMediaResourceMonitor> service = interface_cast<IMediaResourceMonitor>(binder);
for (size_t i = 0; i < resources.size(); ++i) {
- if (resources[i].mSubType == MediaResource::kAudioCodec) {
+ if (resources[i].subType == MediaResource::SubType::kAudioCodec) {
service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_AUDIO_CODEC);
- } else if (resources[i].mSubType == MediaResource::kVideoCodec) {
+ } else if (resources[i].subType == MediaResource::SubType::kVideoCodec) {
service->notifyResourceGranted(pid, IMediaResourceMonitor::TYPE_VIDEO_CODEC);
}
}
@@ -182,13 +181,18 @@
snprintf(buffer, SIZE, " Id: %lld\n", (long long)infos[j].clientId);
result.append(buffer);
- snprintf(buffer, SIZE, " Name: %s\n", infos[j].client->getName().string());
+ std::string clientName;
+ Status status = infos[j].client->getName(&clientName);
+ if (!status.isOk()) {
+ clientName = "<unknown client>";
+ }
+ snprintf(buffer, SIZE, " Name: %s\n", clientName.c_str());
result.append(buffer);
const ResourceList &resources = infos[j].resources;
result.append(" Resources:\n");
for (auto it = resources.begin(); it != resources.end(); it++) {
- snprintf(buffer, SIZE, " %s\n", it->second.toString().string());
+ snprintf(buffer, SIZE, " %s\n", toString(it->second).string());
result.append(buffer);
}
}
@@ -242,27 +246,28 @@
ResourceManagerService::~ResourceManagerService() {}
-void ResourceManagerService::config(const Vector<MediaResourcePolicy> &policies) {
+Status ResourceManagerService::config(const std::vector<MediaResourcePolicyParcel>& policies) {
String8 log = String8::format("config(%s)", getString(policies).string());
mServiceLog->add(log);
Mutex::Autolock lock(mLock);
for (size_t i = 0; i < policies.size(); ++i) {
- String8 type = policies[i].mType;
- String8 value = policies[i].mValue;
- if (type == kPolicySupportsMultipleSecureCodecs) {
+ const std::string &type = policies[i].type;
+ const std::string &value = policies[i].value;
+ if (type == MediaResourcePolicy::kPolicySupportsMultipleSecureCodecs()) {
mSupportsMultipleSecureCodecs = (value == "true");
- } else if (type == kPolicySupportsSecureWithNonSecureCodec) {
+ } else if (type == MediaResourcePolicy::kPolicySupportsSecureWithNonSecureCodec()) {
mSupportsSecureWithNonSecureCodec = (value == "true");
}
}
+ return Status::ok();
}
void ResourceManagerService::onFirstAdded(
- const MediaResource& resource, const ResourceInfo& clientInfo) {
+ const MediaResourceParcel& resource, const ResourceInfo& clientInfo) {
// first time added
- if (resource.mType == MediaResource::kCpuBoost
- && resource.mSubType == MediaResource::kUnspecifiedSubType) {
+ if (resource.type == MediaResource::Type::kCpuBoost
+ && resource.subType == MediaResource::SubType::kUnspecifiedSubType) {
// Request it on every new instance of kCpuBoost, as the media.codec
// could have died, if we only do it the first time subsequent instances
// never gets the boost.
@@ -270,44 +275,49 @@
ALOGW("couldn't request cpuset boost");
}
mCpuBoostCount++;
- } else if (resource.mType == MediaResource::kBattery
- && resource.mSubType == MediaResource::kVideoCodec) {
+ } else if (resource.type == MediaResource::Type::kBattery
+ && resource.subType == MediaResource::SubType::kVideoCodec) {
mSystemCB->noteStartVideo(clientInfo.uid);
}
}
void ResourceManagerService::onLastRemoved(
- const MediaResource& resource, const ResourceInfo& clientInfo) {
- if (resource.mType == MediaResource::kCpuBoost
- && resource.mSubType == MediaResource::kUnspecifiedSubType
+ const MediaResourceParcel& resource, const ResourceInfo& clientInfo) {
+ if (resource.type == MediaResource::Type::kCpuBoost
+ && resource.subType == MediaResource::SubType::kUnspecifiedSubType
&& mCpuBoostCount > 0) {
if (--mCpuBoostCount == 0) {
mSystemCB->requestCpusetBoost(false, this);
}
- } else if (resource.mType == MediaResource::kBattery
- && resource.mSubType == MediaResource::kVideoCodec) {
+ } else if (resource.type == MediaResource::Type::kBattery
+ && resource.subType == MediaResource::SubType::kVideoCodec) {
mSystemCB->noteStopVideo(clientInfo.uid);
}
}
void ResourceManagerService::mergeResources(
- MediaResource& r1, const MediaResource& r2) {
- if (r1.mType == MediaResource::kDrmSession) {
- // This means we are using a session. Each session's mValue is initialized to UINT64_MAX.
- // The oftener a session is used the lower it's mValue. During reclaim the session with
- // the highest mValue/lowest usage would be closed.
- r1.mValue -= (r1.mValue == 0 ? 0 : 1);
+ MediaResourceParcel& r1, const MediaResourceParcel& r2) {
+ // The resource entry on record is maintained to be in [0,INT64_MAX].
+ // Clamp if merging in the new resource value causes it to go out of bound.
+ // Note that the new resource value could be negative, eg.DrmSession, the
+ // value goes lower when the session is used more often. During reclaim
+ // the session with the highest value (lowest usage) would be closed.
+ if (r2.value < INT64_MAX - r1.value) {
+ r1.value += r2.value;
+ if (r1.value < 0) {
+ r1.value = 0;
+ }
} else {
- r1.mValue += r2.mValue;
+ r1.value = INT64_MAX;
}
}
-void ResourceManagerService::addResource(
- int pid,
- int uid,
+Status ResourceManagerService::addResource(
+ int32_t pid,
+ int32_t uid,
int64_t clientId,
- const sp<IResourceManagerClient> client,
- const Vector<MediaResource> &resources) {
+ const sp<IResourceManagerClient>& client,
+ const std::vector<MediaResourceParcel>& resources) {
String8 log = String8::format("addResource(pid %d, clientId %lld, resources %s)",
pid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
@@ -315,15 +325,26 @@
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
ALOGE("Rejected addResource call with invalid pid.");
- return;
+ return Status::fromServiceSpecificError(BAD_VALUE);
}
ResourceInfos& infos = getResourceInfosForEdit(pid, mMap);
ResourceInfo& info = getResourceInfoForEdit(uid, clientId, client, infos);
for (size_t i = 0; i < resources.size(); ++i) {
const auto &res = resources[i];
- const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
+ const auto resType = std::tuple(res.type, res.subType, res.id);
+
+ if (res.value < 0 && res.type != MediaResource::Type::kDrmSession) {
+ ALOGW("Ignoring request to remove negative value of non-drm resource");
+ continue;
+ }
if (info.resources.find(resType) == info.resources.end()) {
+ if (res.value <= 0) {
+ // We can't init a new entry with negative value, although it's allowed
+ // to merge in negative values after the initial add.
+ ALOGW("Ignoring request to add new resource entry with value <= 0");
+ continue;
+ }
onFirstAdded(res, info);
info.resources[resType] = res;
} else {
@@ -335,10 +356,12 @@
IInterface::asBinder(client)->linkToDeath(info.deathNotifier);
}
notifyResourceGranted(pid, resources);
+ return Status::ok();
}
-void ResourceManagerService::removeResource(int pid, int64_t clientId,
- const Vector<MediaResource> &resources) {
+Status ResourceManagerService::removeResource(
+ int32_t pid, int64_t clientId,
+ const std::vector<MediaResourceParcel>& resources) {
String8 log = String8::format("removeResource(pid %d, clientId %lld, resources %s)",
pid, (long long) clientId, getString(resources).string());
mServiceLog->add(log);
@@ -346,46 +369,51 @@
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(pid)) {
ALOGE("Rejected removeResource call with invalid pid.");
- return;
+ return Status::fromServiceSpecificError(BAD_VALUE);
}
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
- return;
+ return Status::ok();
}
ResourceInfos &infos = mMap.editValueAt(index);
index = infos.indexOfKey(clientId);
if (index < 0) {
ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
- return;
+ return Status::ok();
}
ResourceInfo &info = infos.editValueAt(index);
for (size_t i = 0; i < resources.size(); ++i) {
const auto &res = resources[i];
- const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
+ const auto resType = std::tuple(res.type, res.subType, res.id);
+
+ if (res.value < 0) {
+ ALOGW("Ignoring request to remove negative value of resource");
+ continue;
+ }
// ignore if we don't have it
if (info.resources.find(resType) != info.resources.end()) {
- MediaResource &resource = info.resources[resType];
- if (resource.mValue > res.mValue) {
- resource.mValue -= res.mValue;
+ MediaResourceParcel &resource = info.resources[resType];
+ if (resource.value > res.value) {
+ resource.value -= res.value;
} else {
- // drm sessions always take this branch because res.mValue is set
- // to UINT64_MAX
onLastRemoved(res, info);
info.resources.erase(resType);
}
}
}
+ return Status::ok();
}
-void ResourceManagerService::removeClient(int pid, int64_t clientId) {
+Status ResourceManagerService::removeClient(int32_t pid, int64_t clientId) {
removeResource(pid, clientId, true);
+ return Status::ok();
}
-void ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
+Status ResourceManagerService::removeResource(int pid, int64_t clientId, bool checkValid) {
String8 log = String8::format(
"removeResource(pid %d, clientId %lld)",
pid, (long long) clientId);
@@ -394,19 +422,19 @@
Mutex::Autolock lock(mLock);
if (checkValid && !mProcessInfo->isValidPid(pid)) {
ALOGE("Rejected removeResource call with invalid pid.");
- return;
+ return Status::fromServiceSpecificError(BAD_VALUE);
}
ssize_t index = mMap.indexOfKey(pid);
if (index < 0) {
ALOGV("removeResource: didn't find pid %d for clientId %lld", pid, (long long) clientId);
- return;
+ return Status::ok();
}
ResourceInfos &infos = mMap.editValueAt(index);
index = infos.indexOfKey(clientId);
if (index < 0) {
ALOGV("removeResource: didn't find clientId %lld", (long long) clientId);
- return;
+ return Status::ok();
}
const ResourceInfo &info = infos[index];
@@ -417,45 +445,49 @@
IInterface::asBinder(info.client)->unlinkToDeath(info.deathNotifier);
infos.removeItemsAt(index);
+ return Status::ok();
}
void ResourceManagerService::getClientForResource_l(
- int callingPid, const MediaResource *res, Vector<sp<IResourceManagerClient>> *clients) {
+ int callingPid, const MediaResourceParcel *res, Vector<sp<IResourceManagerClient>> *clients) {
if (res == NULL) {
return;
}
sp<IResourceManagerClient> client;
- if (getLowestPriorityBiggestClient_l(callingPid, res->mType, &client)) {
+ if (getLowestPriorityBiggestClient_l(callingPid, res->type, &client)) {
clients->push_back(client);
}
}
-bool ResourceManagerService::reclaimResource(
- int callingPid, const Vector<MediaResource> &resources) {
+Status ResourceManagerService::reclaimResource(
+ int32_t callingPid,
+ const std::vector<MediaResourceParcel>& resources,
+ bool* _aidl_return) {
String8 log = String8::format("reclaimResource(callingPid %d, resources %s)",
callingPid, getString(resources).string());
mServiceLog->add(log);
+ *_aidl_return = false;
Vector<sp<IResourceManagerClient>> clients;
{
Mutex::Autolock lock(mLock);
if (!mProcessInfo->isValidPid(callingPid)) {
ALOGE("Rejected reclaimResource call with invalid callingPid.");
- return false;
+ return Status::fromServiceSpecificError(BAD_VALUE);
}
- const MediaResource *secureCodec = NULL;
- const MediaResource *nonSecureCodec = NULL;
- const MediaResource *graphicMemory = NULL;
- const MediaResource *drmSession = NULL;
+ const MediaResourceParcel *secureCodec = NULL;
+ const MediaResourceParcel *nonSecureCodec = NULL;
+ const MediaResourceParcel *graphicMemory = NULL;
+ const MediaResourceParcel *drmSession = NULL;
for (size_t i = 0; i < resources.size(); ++i) {
- MediaResource::Type type = resources[i].mType;
- if (resources[i].mType == MediaResource::kSecureCodec) {
+ MediaResource::Type type = resources[i].type;
+ if (resources[i].type == MediaResource::Type::kSecureCodec) {
secureCodec = &resources[i];
- } else if (type == MediaResource::kNonSecureCodec) {
+ } else if (type == MediaResource::Type::kNonSecureCodec) {
nonSecureCodec = &resources[i];
- } else if (type == MediaResource::kGraphicMemory) {
+ } else if (type == MediaResource::Type::kGraphicMemory) {
graphicMemory = &resources[i];
- } else if (type == MediaResource::kDrmSession) {
+ } else if (type == MediaResource::Type::kDrmSession) {
drmSession = &resources[i];
}
}
@@ -463,27 +495,27 @@
// first pass to handle secure/non-secure codec conflict
if (secureCodec != NULL) {
if (!mSupportsMultipleSecureCodecs) {
- if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
- return false;
+ if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec, &clients)) {
+ return Status::ok();
}
}
if (!mSupportsSecureWithNonSecureCodec) {
- if (!getAllClients_l(callingPid, MediaResource::kNonSecureCodec, &clients)) {
- return false;
+ if (!getAllClients_l(callingPid, MediaResource::Type::kNonSecureCodec, &clients)) {
+ return Status::ok();
}
}
}
if (nonSecureCodec != NULL) {
if (!mSupportsSecureWithNonSecureCodec) {
- if (!getAllClients_l(callingPid, MediaResource::kSecureCodec, &clients)) {
- return false;
+ if (!getAllClients_l(callingPid, MediaResource::Type::kSecureCodec, &clients)) {
+ return Status::ok();
}
}
}
if (drmSession != NULL) {
getClientForResource_l(callingPid, drmSession, &clients);
if (clients.size() == 0) {
- return false;
+ return Status::ok();
}
}
@@ -501,32 +533,35 @@
if (clients.size() == 0) {
// if we are here, run the fourth pass to free one codec with the different type.
if (secureCodec != NULL) {
- MediaResource temp(MediaResource::kNonSecureCodec, 1);
+ MediaResource temp(MediaResource::Type::kNonSecureCodec, 1);
getClientForResource_l(callingPid, &temp, &clients);
}
if (nonSecureCodec != NULL) {
- MediaResource temp(MediaResource::kSecureCodec, 1);
+ MediaResource temp(MediaResource::Type::kSecureCodec, 1);
getClientForResource_l(callingPid, &temp, &clients);
}
}
}
if (clients.size() == 0) {
- return false;
+ return Status::ok();
}
sp<IResourceManagerClient> failedClient;
for (size_t i = 0; i < clients.size(); ++i) {
log = String8::format("reclaimResource from client %p", clients[i].get());
mServiceLog->add(log);
- if (!clients[i]->reclaimResource()) {
+ bool success;
+ Status status = clients[i]->reclaimResource(&success);
+ if (!status.isOk() || !success) {
failedClient = clients[i];
break;
}
}
if (failedClient == NULL) {
- return true;
+ *_aidl_return = true;
+ return Status::ok();
}
{
@@ -551,7 +586,7 @@
}
}
- return false;
+ return Status::ok();
}
bool ResourceManagerService::getAllClients_l(
@@ -666,10 +701,10 @@
for (size_t i = 0; i < infos.size(); ++i) {
const ResourceList &resources = infos[i].resources;
for (auto it = resources.begin(); it != resources.end(); it++) {
- const MediaResource &resource = it->second;
- if (resource.mType == type) {
- if (resource.mValue > largestValue) {
- largestValue = resource.mValue;
+ const MediaResourceParcel &resource = it->second;
+ if (resource.type == type) {
+ if (resource.value > largestValue) {
+ largestValue = resource.value;
clientTemp = infos[i].client;
}
}
@@ -685,4 +720,5 @@
return true;
}
+} // namespace media
} // namespace android