From 231c3d169ad029689f9d688b68179af7e96b8d78 Mon Sep 17 00:00:00 2001 From: Ronghua Wu Date: Wed, 11 Mar 2015 15:10:32 -0700 Subject: media: add ResourceManagerService Bug: 19620911 Change-Id: Iea173d310d31781bc50effe3d9bd6553cb5139eb --- include/media/IResourceManagerClient.h | 47 +++ include/media/IResourceManagerService.h | 66 +++ include/media/MediaResource.h | 51 +++ include/media/MediaResourcePolicy.h | 45 ++ media/libmedia/Android.mk | 4 + media/libmedia/IResourceManagerClient.cpp | 70 ++++ media/libmedia/IResourceManagerService.cpp | 169 ++++++++ media/libmedia/MediaResource.cpp | 65 +++ media/libmedia/MediaResourcePolicy.cpp | 49 +++ media/mediaserver/Android.mk | 2 + services/mediaresourcemanager/Android.mk | 18 + .../ResourceManagerService.cpp | 345 +++++++++++++++ .../mediaresourcemanager/ResourceManagerService.h | 106 +++++ services/mediaresourcemanager/test/Android.mk | 25 ++ .../test/ResourceManagerService_test.cpp | 464 +++++++++++++++++++++ 15 files changed, 1526 insertions(+) create mode 100644 include/media/IResourceManagerClient.h create mode 100644 include/media/IResourceManagerService.h create mode 100644 include/media/MediaResource.h create mode 100644 include/media/MediaResourcePolicy.h create mode 100644 media/libmedia/IResourceManagerClient.cpp create mode 100644 media/libmedia/IResourceManagerService.cpp create mode 100644 media/libmedia/MediaResource.cpp create mode 100644 media/libmedia/MediaResourcePolicy.cpp create mode 100644 services/mediaresourcemanager/Android.mk create mode 100644 services/mediaresourcemanager/ResourceManagerService.cpp create mode 100644 services/mediaresourcemanager/ResourceManagerService.h create mode 100644 services/mediaresourcemanager/test/Android.mk create mode 100644 services/mediaresourcemanager/test/ResourceManagerService_test.cpp diff --git a/include/media/IResourceManagerClient.h b/include/media/IResourceManagerClient.h new file mode 100644 index 0000000..3587aea --- /dev/null +++ b/include/media/IResourceManagerClient.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 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. + */ + +#ifndef ANDROID_IRESOURCEMANAGERCLIENT_H +#define ANDROID_IRESOURCEMANAGERCLIENT_H + +#include +#include +#include + +namespace android { + +class IResourceManagerClient: public IInterface +{ +public: + DECLARE_META_INTERFACE(ResourceManagerClient); + + virtual bool reclaimResource() = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnResourceManagerClient: public BnInterface +{ +public: + virtual status_t onTransact(uint32_t code, + const Parcel &data, + Parcel *reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IRESOURCEMANAGERCLIENT_H diff --git a/include/media/IResourceManagerService.h b/include/media/IResourceManagerService.h new file mode 100644 index 0000000..067392c --- /dev/null +++ b/include/media/IResourceManagerService.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015 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. + */ + +#ifndef ANDROID_IRESOURCEMANAGERSERVICE_H +#define ANDROID_IRESOURCEMANAGERSERVICE_H + +#include // for status_t +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace android { + +class IResourceManagerService: public IInterface +{ +public: + DECLARE_META_INTERFACE(ResourceManagerService); + + virtual void config(const Vector &policies) = 0; + + virtual void addResource( + int pid, + int64_t clientId, + const sp client, + const Vector &resources) = 0; + + virtual void removeResource(int64_t clientId) = 0; + + virtual bool reclaimResource( + int callingPid, + const Vector &resources) = 0; +}; + +// ---------------------------------------------------------------------------- + +class BnResourceManagerService: public BnInterface +{ +public: + virtual status_t onTransact(uint32_t code, + const Parcel &data, + Parcel *reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IRESOURCEMANAGERSERVICE_H diff --git a/include/media/MediaResource.h b/include/media/MediaResource.h new file mode 100644 index 0000000..0b57c84 --- /dev/null +++ b/include/media/MediaResource.h @@ -0,0 +1,51 @@ +/* + * Copyright 2015 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. + */ + + +#ifndef ANDROID_MEDIA_RESOURCE_H +#define ANDROID_MEDIA_RESOURCE_H + +#include +#include + +namespace android { + +extern const char kResourceSecureCodec[]; +extern const char kResourceNonSecureCodec[]; +extern const char kResourceGraphicMemory[]; + +class MediaResource { +public: + MediaResource(); + MediaResource(String8 type, uint64_t value); + MediaResource(String8 type, String8 subType, uint64_t value); + + void readFromParcel(const Parcel &parcel); + void writeToParcel(Parcel *parcel) const; + + String8 toString() const; + + bool operator==(const MediaResource &other) const; + bool operator!=(const MediaResource &other) const; + + String8 mType; + String8 mSubType; + uint64_t mValue; +}; + +}; // namespace android + +#endif // ANDROID_MEDIA_RESOURCE_H diff --git a/include/media/MediaResourcePolicy.h b/include/media/MediaResourcePolicy.h new file mode 100644 index 0000000..1e1c341 --- /dev/null +++ b/include/media/MediaResourcePolicy.h @@ -0,0 +1,45 @@ +/* + * Copyright 2015 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. + */ + + +#ifndef ANDROID_MEDIA_RESOURCE_POLICY_H +#define ANDROID_MEDIA_RESOURCE_POLICY_H + +#include +#include + +namespace android { + +extern const char kPolicySupportsMultipleSecureCodecs[]; +extern const char kPolicySupportsSecureWithNonSecureCodec[]; + +class MediaResourcePolicy { +public: + MediaResourcePolicy(); + MediaResourcePolicy(String8 type, uint64_t value); + + void readFromParcel(const Parcel &parcel); + void writeToParcel(Parcel *parcel) const; + + String8 toString() const; + + String8 mType; + uint64_t mValue; +}; + +}; // namespace android + +#endif // ANDROID_MEDIA_RESOURCE_POLICY_H diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 5378bf2..3b260d6 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -36,6 +36,8 @@ LOCAL_SRC_FILES:= \ IMediaRecorder.cpp \ IRemoteDisplay.cpp \ IRemoteDisplayClient.cpp \ + IResourceManagerClient.cpp \ + IResourceManagerService.cpp \ IStreamSource.cpp \ MediaCodecInfo.cpp \ Metadata.cpp \ @@ -53,6 +55,8 @@ LOCAL_SRC_FILES:= \ CharacterEncodingDetector.cpp \ IMediaDeathNotifier.cpp \ MediaProfiles.cpp \ + MediaResource.cpp \ + MediaResourcePolicy.cpp \ IEffect.cpp \ IEffectClient.cpp \ AudioEffect.cpp \ diff --git a/media/libmedia/IResourceManagerClient.cpp b/media/libmedia/IResourceManagerClient.cpp new file mode 100644 index 0000000..6fa56fc --- /dev/null +++ b/media/libmedia/IResourceManagerClient.cpp @@ -0,0 +1,70 @@ +/* +** +** Copyright 2015, 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. +*/ + +#include +#include +#include + +#include + +namespace android { + +enum { + RECLAIM_RESOURCE = IBinder::FIRST_CALL_TRANSACTION, +}; + +class BpResourceManagerClient: public BpInterface +{ +public: + BpResourceManagerClient(const sp &impl) + : BpInterface(impl) + { + } + + virtual bool reclaimResource() { + Parcel data, reply; + data.writeInterfaceToken(IResourceManagerClient::getInterfaceDescriptor()); + + bool ret = false; + status_t status = remote()->transact(RECLAIM_RESOURCE, data, &reply); + if (status == NO_ERROR) { + ret = (bool)reply.readInt32(); + } + return ret; + } +}; + +IMPLEMENT_META_INTERFACE(ResourceManagerClient, "android.media.IResourceManagerClient"); + +// ---------------------------------------------------------------------- + +status_t BnResourceManagerClient::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) +{ + switch (code) { + case RECLAIM_RESOURCE: { + CHECK_INTERFACE(IResourceManagerClient, data, reply); + bool ret = reclaimResource(); + reply->writeInt32(ret); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +}; // namespace android diff --git a/media/libmedia/IResourceManagerService.cpp b/media/libmedia/IResourceManagerService.cpp new file mode 100644 index 0000000..95a2d1c --- /dev/null +++ b/media/libmedia/IResourceManagerService.cpp @@ -0,0 +1,169 @@ +/* +** +** Copyright 2015, 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 "IResourceManagerService" +#include + +#include "media/IResourceManagerService.h" + +#include + +#include +#include + +namespace android { + +enum { + CONFIG = IBinder::FIRST_CALL_TRANSACTION, + ADD_RESOURCE, + REMOVE_RESOURCE, + RECLAIM_RESOURCE, +}; + +template +static void writeToParcel(Parcel *data, const Vector &items) { + size_t size = items.size(); + size_t sizePosition = data->dataPosition(); + // truncates size, but should be okay for this usecase + data->writeUint32(static_cast(size)); + for (size_t i = 0; i < size; i++) { + size_t position = data->dataPosition(); + items[i].writeToParcel(data); + } +} + +template +static void readFromParcel(const Parcel &data, Vector *items) { + size_t size = (size_t)data.readUint32(); + for (size_t i = 0; i < size; i++) { + T item; + item.readFromParcel(data); + items->add(item); + } +} + +class BpResourceManagerService : public BpInterface +{ +public: + BpResourceManagerService(const sp &impl) + : BpInterface(impl) + { + } + + virtual void config(const Vector &policies) { + Parcel data, reply; + data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor()); + writeToParcel(&data, policies); + remote()->transact(CONFIG, data, &reply); + } + + virtual void addResource( + int pid, + int64_t clientId, + const sp client, + const Vector &resources) { + Parcel data, reply; + data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor()); + data.writeInt32(pid); + data.writeInt64(clientId); + data.writeStrongBinder(IInterface::asBinder(client)); + writeToParcel(&data, resources); + + remote()->transact(ADD_RESOURCE, data, &reply); + } + + virtual void removeResource(int64_t clientId) { + Parcel data, reply; + data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor()); + data.writeInt64(clientId); + + remote()->transact(REMOVE_RESOURCE, data, &reply); + } + + virtual bool reclaimResource(int callingPid, const Vector &resources) { + Parcel data, reply; + data.writeInterfaceToken(IResourceManagerService::getInterfaceDescriptor()); + data.writeInt32(callingPid); + writeToParcel(&data, resources); + + bool ret = false; + status_t status = remote()->transact(RECLAIM_RESOURCE, data, &reply); + if (status == NO_ERROR) { + ret = (bool)reply.readInt32(); + } + return ret; + } +}; + +IMPLEMENT_META_INTERFACE(ResourceManagerService, "android.media.IResourceManagerService"); + +// ---------------------------------------------------------------------- + + +status_t BnResourceManagerService::onTransact( + uint32_t code, const Parcel &data, Parcel *reply, uint32_t flags) +{ + switch (code) { + case CONFIG: { + CHECK_INTERFACE(IResourceManagerService, data, reply); + int pid = data.readInt32(); + sp client( + interface_cast(data.readStrongBinder())); + Vector policies; + readFromParcel(data, &policies); + config(policies); + return NO_ERROR; + } break; + + case ADD_RESOURCE: { + CHECK_INTERFACE(IResourceManagerService, data, reply); + int pid = data.readInt32(); + int64_t clientId = data.readInt64(); + sp client( + interface_cast(data.readStrongBinder())); + Vector resources; + readFromParcel(data, &resources); + addResource(pid, clientId, client, resources); + return NO_ERROR; + } break; + + case REMOVE_RESOURCE: { + CHECK_INTERFACE(IResourceManagerService, data, reply); + int64_t clientId = data.readInt64(); + removeResource(clientId); + return NO_ERROR; + } break; + + case RECLAIM_RESOURCE: { + CHECK_INTERFACE(IResourceManagerService, data, reply); + int callingPid = data.readInt32(); + Vector resources; + readFromParcel(data, &resources); + bool ret = reclaimResource(callingPid, resources); + reply->writeInt32(ret); + return NO_ERROR; + } break; + + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +// ---------------------------------------------------------------------------- + +}; // namespace android diff --git a/media/libmedia/MediaResource.cpp b/media/libmedia/MediaResource.cpp new file mode 100644 index 0000000..8be01bc --- /dev/null +++ b/media/libmedia/MediaResource.cpp @@ -0,0 +1,65 @@ +/* + * Copyright 2015 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 "MediaResource" +#include +#include + +namespace android { + +const char kResourceSecureCodec[] = "secure-codec"; +const char kResourceNonSecureCodec[] = "non-secure-codec"; +const char kResourceGraphicMemory[] = "graphic-memory"; + +MediaResource::MediaResource() : mValue(0) {} + +MediaResource::MediaResource(String8 type, uint64_t value) + : mType(type), + mValue(value) {} + +MediaResource::MediaResource(String8 type, String8 subType, uint64_t value) + : mType(type), + mSubType(subType), + mValue(value) {} + +void MediaResource::readFromParcel(const Parcel &parcel) { + mType = parcel.readString8(); + mSubType = parcel.readString8(); + mValue = parcel.readUint64(); +} + +void MediaResource::writeToParcel(Parcel *parcel) const { + parcel->writeString8(mType); + parcel->writeString8(mSubType); + parcel->writeUint64(mValue); +} + +String8 MediaResource::toString() const { + String8 str; + str.appendFormat("%s/%s:%llu", mType.string(), mSubType.string(), mValue); + return str; +} + +bool MediaResource::operator==(const MediaResource &other) const { + return (other.mType == mType) && (other.mSubType == mSubType) && (other.mValue == mValue); +} + +bool MediaResource::operator!=(const MediaResource &other) const { + return !(*this == other); +} + +}; // namespace android diff --git a/media/libmedia/MediaResourcePolicy.cpp b/media/libmedia/MediaResourcePolicy.cpp new file mode 100644 index 0000000..2bb996a --- /dev/null +++ b/media/libmedia/MediaResourcePolicy.cpp @@ -0,0 +1,49 @@ +/* + * Copyright 2015 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 "MediaResourcePolicy" +#include +#include + +namespace android { + +const char kPolicySupportsMultipleSecureCodecs[] = "supports-multiple-secure-codecs"; +const char kPolicySupportsSecureWithNonSecureCodec[] = "supports-secure-with-non-secure-codec"; + +MediaResourcePolicy::MediaResourcePolicy() : mValue(0) {} + +MediaResourcePolicy::MediaResourcePolicy(String8 type, uint64_t value) + : mType(type), + mValue(value) {} + +void MediaResourcePolicy::readFromParcel(const Parcel &parcel) { + mType = parcel.readString8(); + mValue = parcel.readUint64(); +} + +void MediaResourcePolicy::writeToParcel(Parcel *parcel) const { + parcel->writeString8(mType); + parcel->writeUint64(mValue); +} + +String8 MediaResourcePolicy::toString() const { + String8 str; + str.appendFormat("%s:%llu", mType.string(), mValue); + return str; +} + +}; // namespace android diff --git a/media/mediaserver/Android.mk b/media/mediaserver/Android.mk index 0ad0bf3..baf65f6 100644 --- a/media/mediaserver/Android.mk +++ b/media/mediaserver/Android.mk @@ -19,6 +19,7 @@ LOCAL_SHARED_LIBRARIES := \ libcamera_metadata\ libcameraservice \ libmedialogservice \ + libresourcemanagerservice \ libcutils \ libnbaio \ libmedia \ @@ -38,6 +39,7 @@ LOCAL_C_INCLUDES := \ frameworks/av/services/audioflinger \ frameworks/av/services/audiopolicy \ frameworks/av/services/camera/libcameraservice \ + frameworks/av/services/mediaresourcemanager \ $(call include-path-for, audio-utils) \ frameworks/av/services/soundtrigger \ frameworks/av/services/radio diff --git a/services/mediaresourcemanager/Android.mk b/services/mediaresourcemanager/Android.mk new file mode 100644 index 0000000..84218cf --- /dev/null +++ b/services/mediaresourcemanager/Android.mk @@ -0,0 +1,18 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ResourceManagerService.cpp + +LOCAL_SHARED_LIBRARIES := libmedia libstagefright libbinder libutils liblog + +LOCAL_MODULE:= libresourcemanagerservice + +LOCAL_32_BIT_ONLY := true + +LOCAL_C_INCLUDES += \ + $(TOPDIR)frameworks/av/include + +include $(BUILD_SHARED_LIBRARY) + +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/services/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp new file mode 100644 index 0000000..7296d47 --- /dev/null +++ b/services/mediaresourcemanager/ResourceManagerService.cpp @@ -0,0 +1,345 @@ +/* +** +** Copyright 2015, 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 "ResourceManagerService" +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ResourceManagerService.h" + +namespace android { + +template +static String8 getString(const Vector &items) { + String8 itemsStr; + for (size_t i = 0; i < items.size(); ++i) { + itemsStr.appendFormat("%s ", items[i].toString().string()); + } + return itemsStr; +} + +static bool hasResourceType(String8 type, Vector resources) { + for (size_t i = 0; i < resources.size(); ++i) { + if (resources[i].mType == type) { + return true; + } + } + return false; +} + +static bool hasResourceType(String8 type, ResourceInfos infos) { + for (size_t i = 0; i < infos.size(); ++i) { + if (hasResourceType(type, infos[i].resources)) { + return true; + } + } + return false; +} + +static ResourceInfos& getResourceInfosForEdit( + int pid, + PidResourceInfosMap& map) { + ssize_t index = map.indexOfKey(pid); + if (index < 0) { + // new pid + ResourceInfos infosForPid; + map.add(pid, infosForPid); + } + + return map.editValueFor(pid); +} + +static ResourceInfo& getResourceInfoForEdit( + int64_t clientId, + const sp client, + ResourceInfos& infos) { + for (size_t i = 0; i < infos.size(); ++i) { + if (infos[i].clientId == clientId) { + return infos.editItemAt(i); + } + } + ResourceInfo info; + info.clientId = clientId; + info.client = client; + infos.push_back(info); + return infos.editItemAt(infos.size() - 1); +} + +ResourceManagerService::ResourceManagerService() + : mProcessInfo(new ProcessInfo()), + mSupportsMultipleSecureCodecs(true), + mSupportsSecureWithNonSecureCodec(true) {} + +ResourceManagerService::ResourceManagerService(sp processInfo) + : mProcessInfo(processInfo), + mSupportsMultipleSecureCodecs(true), + mSupportsSecureWithNonSecureCodec(true) {} + +ResourceManagerService::~ResourceManagerService() {} + +void ResourceManagerService::config(const Vector &policies) { + ALOGV("config(%s)", getString(policies).string()); + + Mutex::Autolock lock(mLock); + for (size_t i = 0; i < policies.size(); ++i) { + String8 type = policies[i].mType; + uint64_t value = policies[i].mValue; + if (type == kPolicySupportsMultipleSecureCodecs) { + mSupportsMultipleSecureCodecs = (value != 0); + } else if (type == kPolicySupportsSecureWithNonSecureCodec) { + mSupportsSecureWithNonSecureCodec = (value != 0); + } + } +} + +void ResourceManagerService::addResource( + int pid, + int64_t clientId, + const sp client, + const Vector &resources) { + ALOGV("addResource(pid %d, clientId %lld, resources %s)", + pid, (long long) clientId, getString(resources).string()); + + Mutex::Autolock lock(mLock); + ResourceInfos& infos = getResourceInfosForEdit(pid, mMap); + ResourceInfo& info = getResourceInfoForEdit(clientId, client, infos); + info.resources.appendVector(resources); +} + +void ResourceManagerService::removeResource(int64_t clientId) { + ALOGV("removeResource(%lld)", (long long) clientId); + + Mutex::Autolock lock(mLock); + bool found = false; + for (size_t i = 0; i < mMap.size(); ++i) { + ResourceInfos &infos = mMap.editValueAt(i); + for (size_t j = 0; j < infos.size();) { + if (infos[j].clientId == clientId) { + j = infos.removeAt(j); + found = true; + } else { + ++j; + } + } + if (found) { + break; + } + } + if (!found) { + ALOGV("didn't find client"); + } +} + +bool ResourceManagerService::reclaimResource( + int callingPid, const Vector &resources) { + ALOGV("reclaimResource(callingPid %d, resources %s)", + callingPid, getString(resources).string()); + + Vector> clients; + { + Mutex::Autolock lock(mLock); + // first pass to handle secure/non-secure codec conflict + for (size_t i = 0; i < resources.size(); ++i) { + String8 type = resources[i].mType; + if (type == kResourceSecureCodec) { + if (!mSupportsMultipleSecureCodecs) { + if (!getAllClients_l(callingPid, String8(kResourceSecureCodec), &clients)) { + return false; + } + } + if (!mSupportsSecureWithNonSecureCodec) { + if (!getAllClients_l(callingPid, String8(kResourceNonSecureCodec), &clients)) { + return false; + } + } + } else if (type == kResourceNonSecureCodec) { + if (!mSupportsSecureWithNonSecureCodec) { + if (!getAllClients_l(callingPid, String8(kResourceSecureCodec), &clients)) { + return false; + } + } + } + } + + if (clients.size() == 0) { + // if no secure/non-secure codec conflict, run second pass to handle other resources. + for (size_t i = 0; i < resources.size(); ++i) { + String8 type = resources[i].mType; + if (type == kResourceGraphicMemory) { + sp client; + if (!getLowestPriorityBiggestClient_l(callingPid, type, &client)) { + return false; + } + clients.push_back(client); + } + } + } + } + + if (clients.size() == 0) { + return false; + } + + for (size_t i = 0; i < clients.size(); ++i) { + ALOGV("reclaimResource from client %p", clients[i].get()); + if (!clients[i]->reclaimResource()) { + return false; + } + } + return true; +} + +bool ResourceManagerService::getAllClients_l( + int callingPid, const String8 &type, Vector> *clients) { + Vector> temp; + for (size_t i = 0; i < mMap.size(); ++i) { + ResourceInfos &infos = mMap.editValueAt(i); + for (size_t j = 0; j < infos.size(); ++j) { + if (hasResourceType(type, infos[j].resources)) { + if (!isCallingPriorityHigher_l(callingPid, mMap.keyAt(i))) { + // some higher/equal priority process owns the resource, + // this request can't be fulfilled. + ALOGE("getAllClients_l: can't reclaim resource %s from pid %d", + type.string(), mMap.keyAt(i)); + return false; + } + temp.push_back(infos[j].client); + } + } + } + if (temp.size() == 0) { + ALOGV("getAllClients_l: didn't find any resource %s", type.string()); + return true; + } + clients->appendVector(temp); + return true; +} + +bool ResourceManagerService::getLowestPriorityBiggestClient_l( + int callingPid, const String8 &type, sp *client) { + int lowestPriorityPid; + int lowestPriority; + int callingPriority; + if (!mProcessInfo->getPriority(callingPid, &callingPriority)) { + ALOGE("getLowestPriorityBiggestClient_l: can't get process priority for pid %d", + callingPid); + return false; + } + if (!getLowestPriorityPid_l(type, &lowestPriorityPid, &lowestPriority)) { + return false; + } + if (lowestPriority <= callingPriority) { + ALOGE("getLowestPriorityBiggestClient_l: lowest priority %d vs caller priority %d", + lowestPriority, callingPriority); + return false; + } + + if (!getBiggestClient_l(lowestPriorityPid, type, client)) { + return false; + } + return true; +} + +bool ResourceManagerService::getLowestPriorityPid_l( + const String8 &type, int *lowestPriorityPid, int *lowestPriority) { + int pid = -1; + int priority = -1; + for (size_t i = 0; i < mMap.size(); ++i) { + if (mMap.valueAt(i).size() == 0) { + // no client on this process. + continue; + } + if (!hasResourceType(type, mMap.valueAt(i))) { + // doesn't have the requested resource type + continue; + } + int tempPid = mMap.keyAt(i); + int tempPriority; + if (!mProcessInfo->getPriority(tempPid, &tempPriority)) { + ALOGV("getLowestPriorityPid_l: can't get priority of pid %d, skipped", tempPid); + // TODO: remove this pid from mMap? + continue; + } + if (pid == -1 || tempPriority > priority) { + // initial the value + pid = tempPid; + priority = tempPriority; + } + } + if (pid != -1) { + *lowestPriorityPid = pid; + *lowestPriority = priority; + } + return (pid != -1); +} + +bool ResourceManagerService::isCallingPriorityHigher_l(int callingPid, int pid) { + int callingPidPriority; + if (!mProcessInfo->getPriority(callingPid, &callingPidPriority)) { + return false; + } + + int priority; + if (!mProcessInfo->getPriority(pid, &priority)) { + return false; + } + + return (callingPidPriority < priority); +} + +bool ResourceManagerService::getBiggestClient_l( + int pid, const String8 &type, sp *client) { + ssize_t index = mMap.indexOfKey(pid); + if (index < 0) { + ALOGE("getBiggestClient_l: can't find resource info for pid %d", pid); + return false; + } + + sp clientTemp; + uint64_t largestValue = 0; + const ResourceInfos &infos = mMap.valueAt(index); + for (size_t i = 0; i < infos.size(); ++i) { + Vector resources = infos[i].resources; + for (size_t j = 0; j < resources.size(); ++j) { + if (resources[j].mType == type) { + if (resources[j].mValue > largestValue) { + largestValue = resources[j].mValue; + clientTemp = infos[i].client; + } + } + } + } + + if (clientTemp == NULL) { + ALOGE("getBiggestClient_l: can't find resource type %s for pid %d", type.string(), pid); + return false; + } + + *client = clientTemp; + return true; +} + +} // namespace android diff --git a/services/mediaresourcemanager/ResourceManagerService.h b/services/mediaresourcemanager/ResourceManagerService.h new file mode 100644 index 0000000..2ed9bf8 --- /dev/null +++ b/services/mediaresourcemanager/ResourceManagerService.h @@ -0,0 +1,106 @@ +/* +** +** Copyright 2015, 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. +*/ + +#ifndef ANDROID_RESOURCEMANAGERSERVICE_H +#define ANDROID_RESOURCEMANAGERSERVICE_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace android { + +struct ProcessInfoInterface; + +struct ResourceInfo { + int64_t clientId; + sp client; + Vector resources; +}; + +typedef Vector ResourceInfos; +typedef KeyedVector PidResourceInfosMap; + +class ResourceManagerService + : public BinderService, + public BnResourceManagerService +{ +public: + static char const *getServiceName() { return "media.resource_manager"; } + + ResourceManagerService(); + ResourceManagerService(sp processInfo); + + // IResourceManagerService interface + virtual void config(const Vector &policies); + + virtual void addResource( + int pid, + int64_t clientId, + const sp client, + const Vector &resources); + + virtual void removeResource(int64_t clientId); + + virtual bool reclaimResource(int callingPid, const Vector &resources); + +protected: + virtual ~ResourceManagerService(); + +private: + friend class ResourceManagerServiceTest; + + // Gets the list of all the clients who own the specified resource type. + // Returns false if any client belongs to a process with higher priority than the + // calling process. The clients will remain unchanged if returns false. + bool getAllClients_l(int callingPid, const String8 &type, + Vector> *clients); + + // Gets the client who owns specified resource type from lowest possible priority process. + // Returns false if the calling process priority is not higher than the lowest process + // priority. The client will remain unchanged if returns false. + bool getLowestPriorityBiggestClient_l(int callingPid, const String8 &type, + sp *client); + + // Gets lowest priority process that has the specified resource type. + // Returns false if failed. The output parameters will remain unchanged if failed. + bool getLowestPriorityPid_l(const String8 &type, int *pid, int *priority); + + // Gets the client who owns biggest piece of specified resource type from pid. + // Returns false if failed. The client will remain unchanged if failed. + bool getBiggestClient_l(int pid, const String8 &type, sp *client); + + bool isCallingPriorityHigher_l(int callingPid, int pid); + + mutable Mutex mLock; + sp mProcessInfo; + PidResourceInfosMap mMap; + bool mSupportsMultipleSecureCodecs; + bool mSupportsSecureWithNonSecureCodec; +}; + +// ---------------------------------------------------------------------------- + +}; // namespace android + +#endif // ANDROID_RESOURCEMANAGERSERVICE_H diff --git a/services/mediaresourcemanager/test/Android.mk b/services/mediaresourcemanager/test/Android.mk new file mode 100644 index 0000000..228b62a --- /dev/null +++ b/services/mediaresourcemanager/test/Android.mk @@ -0,0 +1,25 @@ +# Build the unit tests. +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := ResourceManagerService_test + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := \ + ResourceManagerService_test.cpp \ + +LOCAL_SHARED_LIBRARIES := \ + libbinder \ + liblog \ + libmedia \ + libresourcemanagerservice \ + libutils \ + +LOCAL_C_INCLUDES := \ + frameworks/av/include \ + frameworks/av/services/mediaresourcemanager \ + +LOCAL_32_BIT_ONLY := true + +include $(BUILD_NATIVE_TEST) diff --git a/services/mediaresourcemanager/test/ResourceManagerService_test.cpp b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp new file mode 100644 index 0000000..b73e1bc --- /dev/null +++ b/services/mediaresourcemanager/test/ResourceManagerService_test.cpp @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2015 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 "ResourceManagerService_test" +#include + +#include + +#include "ResourceManagerService.h" +#include +#include +#include +#include +#include + +namespace android { + +struct TestProcessInfo : public ProcessInfoInterface { + TestProcessInfo() {} + virtual ~TestProcessInfo() {} + + virtual bool getPriority(int pid, int *priority) { + // For testing, use pid as priority. + // Lower the value higher the priority. + *priority = pid; + return true; + } + +private: + DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo); +}; + +struct TestClient : public BnResourceManagerClient { + TestClient(sp service) + : mReclaimed(false), mService(service) {} + + virtual bool reclaimResource() { + sp client(this); + mService->removeResource((int64_t) client.get()); + mReclaimed = true; + return true; + } + + bool reclaimed() const { + return mReclaimed; + } + + void reset() { + mReclaimed = false; + } + +protected: + virtual ~TestClient() {} + +private: + bool mReclaimed; + sp mService; + DISALLOW_EVIL_CONSTRUCTORS(TestClient); +}; + +static const int kTestPid1 = 30; +static const int kTestPid2 = 20; + +class ResourceManagerServiceTest : public ::testing::Test { +public: + ResourceManagerServiceTest() + : mService(new ResourceManagerService(new TestProcessInfo)), + mTestClient1(new TestClient(mService)), + mTestClient2(new TestClient(mService)), + mTestClient3(new TestClient(mService)) { + } + +protected: + static bool isEqualResources(const Vector &resources1, + const Vector &resources2) { + if (resources1.size() != resources2.size()) { + return false; + } + for (size_t i = 0; i < resources1.size(); ++i) { + if (resources1[i] != resources2[i]) { + return false; + } + } + return true; + } + + static void expectEqResourceInfo(const ResourceInfo &info, sp client, + const Vector &resources) { + EXPECT_EQ(client, info.client); + EXPECT_TRUE(isEqualResources(resources, info.resources)); + } + + void verifyClients(bool c1, bool c2, bool c3) { + TestClient *client1 = static_cast(mTestClient1.get()); + TestClient *client2 = static_cast(mTestClient2.get()); + TestClient *client3 = static_cast(mTestClient3.get()); + + EXPECT_EQ(c1, client1->reclaimed()); + EXPECT_EQ(c2, client2->reclaimed()); + EXPECT_EQ(c3, client3->reclaimed()); + + client1->reset(); + client2->reset(); + client3->reset(); + } + + void addResource() { + // kTestPid1 mTestClient1 + Vector resources1; + resources1.push_back(MediaResource(String8(kResourceSecureCodec), 1)); + mService->addResource(kTestPid1, (int64_t) mTestClient1.get(), mTestClient1, resources1); + resources1.push_back(MediaResource(String8(kResourceGraphicMemory), 200)); + Vector resources11; + resources11.push_back(MediaResource(String8(kResourceGraphicMemory), 200)); + mService->addResource(kTestPid1, (int64_t) mTestClient1.get(), mTestClient1, resources11); + + // kTestPid2 mTestClient2 + Vector resources2; + resources2.push_back(MediaResource(String8(kResourceNonSecureCodec), 1)); + resources2.push_back(MediaResource(String8(kResourceGraphicMemory), 300)); + mService->addResource(kTestPid2, (int64_t) mTestClient2.get(), mTestClient2, resources2); + + // kTestPid2 mTestClient3 + Vector resources3; + mService->addResource(kTestPid2, (int64_t) mTestClient3.get(), mTestClient3, resources3); + resources3.push_back(MediaResource(String8(kResourceSecureCodec), 1)); + resources3.push_back(MediaResource(String8(kResourceGraphicMemory), 100)); + mService->addResource(kTestPid2, (int64_t) mTestClient3.get(), mTestClient3, resources3); + + const PidResourceInfosMap &map = mService->mMap; + EXPECT_EQ(2u, map.size()); + ssize_t index1 = map.indexOfKey(kTestPid1); + ASSERT_GE(index1, 0); + const ResourceInfos &infos1 = map[index1]; + EXPECT_EQ(1u, infos1.size()); + expectEqResourceInfo(infos1[0], mTestClient1, resources1); + + ssize_t index2 = map.indexOfKey(kTestPid2); + ASSERT_GE(index2, 0); + const ResourceInfos &infos2 = map[index2]; + EXPECT_EQ(2u, infos2.size()); + expectEqResourceInfo(infos2[0], mTestClient2, resources2); + expectEqResourceInfo(infos2[1], mTestClient3, resources3); + } + + void testConfig() { + EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs); + EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec); + + Vector policies1; + policies1.push_back(MediaResourcePolicy(String8(kPolicySupportsMultipleSecureCodecs), 1)); + policies1.push_back( + MediaResourcePolicy(String8(kPolicySupportsSecureWithNonSecureCodec), 0)); + mService->config(policies1); + EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs); + EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec); + + Vector policies2; + policies2.push_back(MediaResourcePolicy(String8(kPolicySupportsMultipleSecureCodecs), 0)); + policies2.push_back( + MediaResourcePolicy(String8(kPolicySupportsSecureWithNonSecureCodec), 1)); + mService->config(policies2); + EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs); + EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec); + } + + void testRemoveResource() { + addResource(); + + mService->removeResource((int64_t) mTestClient2.get()); + + const PidResourceInfosMap &map = mService->mMap; + EXPECT_EQ(2u, map.size()); + const ResourceInfos &infos1 = map.valueFor(kTestPid1); + const ResourceInfos &infos2 = map.valueFor(kTestPid2); + EXPECT_EQ(1u, infos1.size()); + EXPECT_EQ(1u, infos2.size()); + // mTestClient2 has been removed. + EXPECT_EQ(mTestClient3, infos2[0].client); + } + + void testGetAllClients() { + addResource(); + + String8 type = String8(kResourceSecureCodec); + String8 unknowType = String8("unknowType"); + Vector > clients; + int lowPriorityPid = 100; + EXPECT_FALSE(mService->getAllClients_l(lowPriorityPid, type, &clients)); + int midPriorityPid = 25; + EXPECT_FALSE(mService->getAllClients_l(lowPriorityPid, type, &clients)); + int highPriorityPid = 10; + EXPECT_TRUE(mService->getAllClients_l(10, unknowType, &clients)); + EXPECT_TRUE(mService->getAllClients_l(10, type, &clients)); + + EXPECT_EQ(2u, clients.size()); + EXPECT_EQ(mTestClient3, clients[0]); + EXPECT_EQ(mTestClient1, clients[1]); + } + + void testReclaimResourceSecure() { + Vector resources; + resources.push_back(MediaResource(String8(kResourceSecureCodec), 1)); + resources.push_back(MediaResource(String8(kResourceGraphicMemory), 150)); + + // ### secure codec can't coexist and secure codec can coexist with non-secure codec ### + { + addResource(); + mService->mSupportsMultipleSecureCodecs = false; + mService->mSupportsSecureWithNonSecureCodec = true; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + EXPECT_FALSE(mService->reclaimResource(25, resources)); + + // reclaim all secure codecs + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(true, false, true); + + // call again should reclaim one largest graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, true, false); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + + // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ### + { + addResource(); + mService->mSupportsMultipleSecureCodecs = false; + mService->mSupportsSecureWithNonSecureCodec = false; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + EXPECT_FALSE(mService->reclaimResource(25, resources)); + + // reclaim all secure and non-secure codecs + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(true, true, true); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + + + // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ### + { + addResource(); + mService->mSupportsMultipleSecureCodecs = true; + mService->mSupportsSecureWithNonSecureCodec = false; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + EXPECT_FALSE(mService->reclaimResource(25, resources)); + + // reclaim all non-secure codecs + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, true, false); + + // call again should reclaim one largest graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(true, false, false); + + // call again should reclaim another largest graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, false, true); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + + // ### secure codecs can coexist and secure codec can coexist with non-secure codec ### + { + addResource(); + mService->mSupportsMultipleSecureCodecs = true; + mService->mSupportsSecureWithNonSecureCodec = true; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + + EXPECT_TRUE(mService->reclaimResource(10, resources)); + // one largest graphic memory from lowest process got reclaimed + verifyClients(true, false, false); + + // call again should reclaim another graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, true, false); + + // call again should reclaim another graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, false, true); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + } + + void testReclaimResourceNonSecure() { + Vector resources; + resources.push_back(MediaResource(String8(kResourceNonSecureCodec), 1)); + resources.push_back(MediaResource(String8(kResourceGraphicMemory), 150)); + + // ### secure codec can't coexist with non-secure codec ### + { + addResource(); + mService->mSupportsSecureWithNonSecureCodec = false; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + EXPECT_FALSE(mService->reclaimResource(25, resources)); + + // reclaim all secure codecs + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(true, false, true); + + // call again should reclaim one graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, true, false); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + + + // ### secure codec can coexist with non-secure codec ### + { + addResource(); + mService->mSupportsSecureWithNonSecureCodec = true; + + // priority too low + EXPECT_FALSE(mService->reclaimResource(40, resources)); + + EXPECT_TRUE(mService->reclaimResource(10, resources)); + // one largest graphic memory from lowest process got reclaimed + verifyClients(true, false, false); + + // call again should reclaim another graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, true, false); + + // call again should reclaim another graphic memory from lowest process + EXPECT_TRUE(mService->reclaimResource(10, resources)); + verifyClients(false, false, true); + + // nothing left + EXPECT_FALSE(mService->reclaimResource(10, resources)); + } + } + + void testGetLowestPriorityBiggestClient() { + String8 type = String8(kResourceGraphicMemory); + sp client; + EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(10, type, &client)); + + addResource(); + + EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(100, type, &client)); + EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(10, type, &client)); + + // kTestPid1 is the lowest priority process with kResourceGraphicMemory. + // mTestClient1 has the largest kResourceGraphicMemory within kTestPid1. + EXPECT_EQ(mTestClient1, client); + } + + void testGetLowestPriorityPid() { + int pid; + int priority; + TestProcessInfo processInfo; + + String8 type = String8(kResourceGraphicMemory); + EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority)); + + addResource(); + + EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority)); + EXPECT_EQ(kTestPid1, pid); + int priority1; + processInfo.getPriority(kTestPid1, &priority1); + EXPECT_EQ(priority1, priority); + + type = String8(kResourceNonSecureCodec); + EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority)); + EXPECT_EQ(kTestPid2, pid); + int priority2; + processInfo.getPriority(kTestPid2, &priority2); + EXPECT_EQ(priority2, priority); + } + + void testGetBiggestClient() { + String8 type = String8(kResourceGraphicMemory); + sp client; + EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client)); + + addResource(); + + EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client)); + EXPECT_EQ(mTestClient2, client); + } + + void testIsCallingPriorityHigher() { + EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100)); + EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100)); + EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100)); + } + + sp mService; + sp mTestClient1; + sp mTestClient2; + sp mTestClient3; +}; + +TEST_F(ResourceManagerServiceTest, config) { + testConfig(); +} + +TEST_F(ResourceManagerServiceTest, addResource) { + addResource(); +} + +TEST_F(ResourceManagerServiceTest, removeResource) { + testRemoveResource(); +} + +TEST_F(ResourceManagerServiceTest, reclaimResource) { + testReclaimResourceSecure(); + testReclaimResourceNonSecure(); +} + +TEST_F(ResourceManagerServiceTest, getAllClients_l) { + testGetAllClients(); +} + +TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) { + testGetLowestPriorityBiggestClient(); +} + +TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) { + testGetLowestPriorityPid(); +} + +TEST_F(ResourceManagerServiceTest, getBiggestClient_l) { + testGetBiggestClient(); +} + +TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) { + testIsCallingPriorityHigher(); +} + +} // namespace android -- cgit v1.1