blob: 2c8659d10853d7b8e5628fdc04409f06a6e88b88 [file] [log] [blame]
/*
* 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 <gtest/gtest.h>
#include <android/binder_process.h>
#include "ResourceManagerService.h"
#include <aidl/android/media/BnResourceManagerClient.h>
#include <media/MediaResource.h>
#include <media/MediaResourcePolicy.h>
#include <media/stagefright/foundation/ADebug.h>
#include <mediautils/ProcessInfoInterface.h>
namespace android {
using Status = ::ndk::ScopedAStatus;
using ::aidl::android::media::BnResourceManagerClient;
using ::aidl::android::media::IResourceManagerService;
using ::aidl::android::media::IResourceManagerClient;
using ::aidl::android::media::MediaResourceParcel;
static int64_t getId(const std::shared_ptr<IResourceManagerClient>& client) {
return (int64_t) client.get();
}
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;
}
virtual bool isPidTrusted(int /* pid */) {
return true;
}
virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
return true;
}
virtual bool overrideProcessInfo(
int /* pid */, int /* procState */, int /* oomScore */) {
return true;
}
virtual void removeProcessInfoOverride(int /* pid */) {
}
private:
DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
};
struct TestSystemCallback :
public ResourceManagerService::SystemCallbackInterface {
TestSystemCallback() :
mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}
enum EventType {
INVALID = -1,
VIDEO_ON = 0,
VIDEO_OFF = 1,
VIDEO_RESET = 2,
CPUSET_ENABLE = 3,
CPUSET_DISABLE = 4,
};
struct EventEntry {
EventType type;
int arg;
};
virtual void noteStartVideo(int uid) override {
mLastEvent = {EventType::VIDEO_ON, uid};
mEventCount++;
}
virtual void noteStopVideo(int uid) override {
mLastEvent = {EventType::VIDEO_OFF, uid};
mEventCount++;
}
virtual void noteResetVideo() override {
mLastEvent = {EventType::VIDEO_RESET, 0};
mEventCount++;
}
virtual bool requestCpusetBoost(bool enable) override {
mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
mEventCount++;
return true;
}
size_t eventCount() { return mEventCount; }
EventType lastEventType() { return mLastEvent.type; }
EventEntry lastEvent() { return mLastEvent; }
protected:
virtual ~TestSystemCallback() {}
private:
EventEntry mLastEvent;
size_t mEventCount;
DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
};
struct TestClient : public BnResourceManagerClient {
TestClient(int pid, int uid, int32_t clientImportance,
const std::shared_ptr<ResourceManagerService> &service)
: mPid(pid), mUid(uid), mClientImportance(clientImportance), mService(service) {}
Status reclaimResource(bool* _aidl_return) override {
ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
.uid = static_cast<int32_t>(mUid),
.id = getId(ref<TestClient>()),
.name = "none",
.importance = mClientImportance};
mService->removeClient(clientInfo);
mWasReclaimResourceCalled = true;
*_aidl_return = true;
return Status::ok();
}
Status getName(::std::string* _aidl_return) override {
*_aidl_return = "test_client";
return Status::ok();
}
bool checkIfReclaimedAndReset() {
bool wasReclaimResourceCalled = mWasReclaimResourceCalled;
mWasReclaimResourceCalled = false;
return wasReclaimResourceCalled;
}
virtual ~TestClient() {}
inline int pid() const { return mPid; }
inline int uid() const { return mUid; }
inline int32_t clientImportance() const { return mClientImportance; }
private:
bool mWasReclaimResourceCalled = false;
int mPid;
int mUid;
int32_t mClientImportance = 0;
std::shared_ptr<ResourceManagerService> mService;
DISALLOW_EVIL_CONSTRUCTORS(TestClient);
};
// [pid, uid] used by the test.
static const int kTestPid1 = 30;
static const int kTestUid1 = 1010;
static const int kTestPid2 = 20;
static const int kTestUid2 = 1011;
static const int kLowPriorityPid = 40;
static const int kMidPriorityPid = 25;
static const int kHighPriorityPid = 10;
// Client Ids used by the test.
static const int kLowPriorityClientId = 1111;
static const int kMidPriorityClientId = 2222;
static const int kHighPriorityClientId = 3333;
// Client importance used by the test.
static const int32_t kHighestCodecImportance = 0;
static const int32_t kLowestCodecImportance = 100;
static const int32_t kMidCodecImportance = 50;
using EventType = TestSystemCallback::EventType;
using EventEntry = TestSystemCallback::EventEntry;
bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
return lhs.type == rhs.type && lhs.arg == rhs.arg;
}
// The condition is expected to return a status but also update the local
// result variable.
#define CHECK_STATUS_TRUE(conditionThatUpdatesResult) \
do { \
bool result = false; \
EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
EXPECT_TRUE(result); \
} while(false)
// The condition is expected to return a status but also update the local
// result variable.
#define CHECK_STATUS_FALSE(conditionThatUpdatesResult) \
do { \
bool result = true; \
EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
EXPECT_FALSE(result); \
} while(false)
class ResourceManagerServiceTestBase : public ::testing::Test {
public:
static TestClient* toTestClient(std::shared_ptr<IResourceManagerClient> testClient) {
return static_cast<TestClient*>(testClient.get());
}
ResourceManagerServiceTestBase(bool newRM = false) : mNewRM(newRM) {
ALOGI("ResourceManagerServiceTestBase created with %s RM", newRM ? "new" : "old");
}
void SetUp() override {
// Need thread pool to receive callbacks, otherwise oneway callbacks are
// silently ignored.
ABinderProcess_startThreadPool();
mSystemCB = new TestSystemCallback();
if (mNewRM) {
mService = ResourceManagerService::CreateNew(new TestProcessInfo, mSystemCB);
} else {
mService = ResourceManagerService::Create(new TestProcessInfo, mSystemCB);
}
mTestClient1 = ::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, 0, mService);
mTestClient2 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
mTestClient3 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
}
std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid,
int32_t importance = 0) {
return ::ndk::SharedRefBase::make<TestClient>(pid, uid, importance, mService);
}
sp<TestSystemCallback> mSystemCB;
std::shared_ptr<ResourceManagerService> mService;
std::shared_ptr<IResourceManagerClient> mTestClient1;
std::shared_ptr<IResourceManagerClient> mTestClient2;
std::shared_ptr<IResourceManagerClient> mTestClient3;
protected:
static bool isEqualResources(const std::vector<MediaResourceParcel> &resources1,
const ResourceList &resources2) {
// convert resource1 to ResourceList
ResourceList r1;
for (size_t i = 0; i < resources1.size(); ++i) {
r1.addOrUpdate(resources1[i]);
}
return r1 == resources2;
}
static void expectEqResourceInfo(const ResourceInfo &info,
int uid,
std::shared_ptr<IResourceManagerClient> client,
const std::vector<MediaResourceParcel> &resources) {
EXPECT_EQ(uid, info.uid);
EXPECT_EQ(client, info.client);
EXPECT_TRUE(isEqualResources(resources, info.resources));
}
bool mNewRM = false;
};
} // namespace android