1 /*
2 * Copyright 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <gtest/gtest.h>
18 #include <android/binder_process.h>
19
20 #include "ResourceManagerService.h"
21 #include <aidl/android/media/BnResourceManagerClient.h>
22 #include <media/MediaResource.h>
23 #include <media/MediaResourcePolicy.h>
24 #include <media/stagefright/foundation/ADebug.h>
25 #include <mediautils/ProcessInfoInterface.h>
26
27 namespace android {
28
29 using Status = ::ndk::ScopedAStatus;
30 using ::aidl::android::media::BnResourceManagerClient;
31 using ::aidl::android::media::IResourceManagerService;
32 using ::aidl::android::media::IResourceManagerClient;
33 using ::aidl::android::media::MediaResourceParcel;
34
getId(const std::shared_ptr<IResourceManagerClient> & client)35 static int64_t getId(const std::shared_ptr<IResourceManagerClient>& client) {
36 return (int64_t) client.get();
37 }
38
39 struct TestProcessInfo : public ProcessInfoInterface {
TestProcessInfoTestProcessInfo40 TestProcessInfo() {}
~TestProcessInfoTestProcessInfo41 virtual ~TestProcessInfo() {}
42
getPriorityTestProcessInfo43 virtual bool getPriority(int pid, int *priority) {
44 // For testing, use pid as priority.
45 // Lower the value higher the priority.
46 *priority = pid;
47 return true;
48 }
49
isPidTrustedTestProcessInfo50 virtual bool isPidTrusted(int /* pid */) {
51 return true;
52 }
53
isPidUidTrustedTestProcessInfo54 virtual bool isPidUidTrusted(int /* pid */, int /* uid */) {
55 return true;
56 }
57
overrideProcessInfoTestProcessInfo58 virtual bool overrideProcessInfo(
59 int /* pid */, int /* procState */, int /* oomScore */) {
60 return true;
61 }
62
removeProcessInfoOverrideTestProcessInfo63 virtual void removeProcessInfoOverride(int /* pid */) {
64 }
65
66 private:
67 DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
68 };
69
70 struct TestSystemCallback :
71 public ResourceManagerService::SystemCallbackInterface {
TestSystemCallbackTestSystemCallback72 TestSystemCallback() :
73 mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}
74
75 enum EventType {
76 INVALID = -1,
77 VIDEO_ON = 0,
78 VIDEO_OFF = 1,
79 VIDEO_RESET = 2,
80 CPUSET_ENABLE = 3,
81 CPUSET_DISABLE = 4,
82 };
83
84 struct EventEntry {
85 EventType type;
86 int arg;
87 };
88
noteStartVideoTestSystemCallback89 virtual void noteStartVideo(int uid) override {
90 mLastEvent = {EventType::VIDEO_ON, uid};
91 mEventCount++;
92 }
93
noteStopVideoTestSystemCallback94 virtual void noteStopVideo(int uid) override {
95 mLastEvent = {EventType::VIDEO_OFF, uid};
96 mEventCount++;
97 }
98
noteResetVideoTestSystemCallback99 virtual void noteResetVideo() override {
100 mLastEvent = {EventType::VIDEO_RESET, 0};
101 mEventCount++;
102 }
103
requestCpusetBoostTestSystemCallback104 virtual bool requestCpusetBoost(bool enable) override {
105 mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
106 mEventCount++;
107 return true;
108 }
109
eventCountTestSystemCallback110 size_t eventCount() { return mEventCount; }
lastEventTypeTestSystemCallback111 EventType lastEventType() { return mLastEvent.type; }
lastEventTestSystemCallback112 EventEntry lastEvent() { return mLastEvent; }
113
114 protected:
~TestSystemCallbackTestSystemCallback115 virtual ~TestSystemCallback() {}
116
117 private:
118 EventEntry mLastEvent;
119 size_t mEventCount;
120
121 DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
122 };
123
124
125 struct TestClient : public BnResourceManagerClient {
TestClientTestClient126 TestClient(int pid, int uid, int32_t clientImportance,
127 const std::shared_ptr<ResourceManagerService> &service)
128 : mPid(pid), mUid(uid), mClientImportance(clientImportance), mService(service) {}
129
reclaimResourceTestClient130 Status reclaimResource(bool* _aidl_return) override {
131 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(mPid),
132 .uid = static_cast<int32_t>(mUid),
133 .id = getId(ref<TestClient>()),
134 .name = "none",
135 .importance = mClientImportance};
136 mService->removeClient(clientInfo);
137 mWasReclaimResourceCalled = true;
138 *_aidl_return = true;
139 return Status::ok();
140 }
141
getNameTestClient142 Status getName(::std::string* _aidl_return) override {
143 *_aidl_return = "test_client";
144 return Status::ok();
145 }
146
checkIfReclaimedAndResetTestClient147 bool checkIfReclaimedAndReset() {
148 bool wasReclaimResourceCalled = mWasReclaimResourceCalled;
149 mWasReclaimResourceCalled = false;
150 return wasReclaimResourceCalled;
151 }
152
~TestClientTestClient153 virtual ~TestClient() {}
154
pidTestClient155 inline int pid() const { return mPid; }
uidTestClient156 inline int uid() const { return mUid; }
clientImportanceTestClient157 inline int32_t clientImportance() const { return mClientImportance; }
158
159 private:
160 bool mWasReclaimResourceCalled = false;
161 int mPid;
162 int mUid;
163 int32_t mClientImportance = 0;
164 std::shared_ptr<ResourceManagerService> mService;
165 DISALLOW_EVIL_CONSTRUCTORS(TestClient);
166 };
167
168 // [pid, uid] used by the test.
169 static const int kTestPid1 = 30;
170 static const int kTestUid1 = 1010;
171
172 static const int kTestPid2 = 20;
173 static const int kTestUid2 = 1011;
174
175 static const int kLowPriorityPid = 40;
176 static const int kMidPriorityPid = 25;
177 static const int kHighPriorityPid = 10;
178
179 // Client Ids used by the test.
180 static const int kLowPriorityClientId = 1111;
181 static const int kMidPriorityClientId = 2222;
182 static const int kHighPriorityClientId = 3333;
183
184 // Client importance used by the test.
185 static const int32_t kHighestCodecImportance = 0;
186 static const int32_t kLowestCodecImportance = 100;
187 static const int32_t kMidCodecImportance = 50;
188
189 using EventType = TestSystemCallback::EventType;
190 using EventEntry = TestSystemCallback::EventEntry;
191 bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
192 return lhs.type == rhs.type && lhs.arg == rhs.arg;
193 }
194
195 // The condition is expected to return a status but also update the local
196 // result variable.
197 #define CHECK_STATUS_TRUE(conditionThatUpdatesResult) \
198 do { \
199 bool result = false; \
200 EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
201 EXPECT_TRUE(result); \
202 } while(false)
203
204 // The condition is expected to return a status but also update the local
205 // result variable.
206 #define CHECK_STATUS_FALSE(conditionThatUpdatesResult) \
207 do { \
208 bool result = true; \
209 EXPECT_TRUE((conditionThatUpdatesResult).isOk()); \
210 EXPECT_FALSE(result); \
211 } while(false)
212
213 class ResourceManagerServiceTestBase : public ::testing::Test {
214 public:
toTestClient(std::shared_ptr<IResourceManagerClient> testClient)215 static TestClient* toTestClient(std::shared_ptr<IResourceManagerClient> testClient) {
216 return static_cast<TestClient*>(testClient.get());
217 }
218
mNewRM(newRM)219 ResourceManagerServiceTestBase(bool newRM = false) : mNewRM(newRM) {
220 ALOGI("ResourceManagerServiceTestBase created with %s RM", newRM ? "new" : "old");
221 }
222
SetUp()223 void SetUp() override {
224 // Need thread pool to receive callbacks, otherwise oneway callbacks are
225 // silently ignored.
226 ABinderProcess_startThreadPool();
227 mSystemCB = new TestSystemCallback();
228 if (mNewRM) {
229 mService = ResourceManagerService::CreateNew(new TestProcessInfo, mSystemCB);
230 } else {
231 mService = ResourceManagerService::Create(new TestProcessInfo, mSystemCB);
232 }
233 mTestClient1 = ::ndk::SharedRefBase::make<TestClient>(kTestPid1, kTestUid1, 0, mService);
234 mTestClient2 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
235 mTestClient3 = ::ndk::SharedRefBase::make<TestClient>(kTestPid2, kTestUid2, 0, mService);
236 }
237
238 std::shared_ptr<IResourceManagerClient> createTestClient(int pid, int uid,
239 int32_t importance = 0) {
240 return ::ndk::SharedRefBase::make<TestClient>(pid, uid, importance, mService);
241 }
242
243 sp<TestSystemCallback> mSystemCB;
244 std::shared_ptr<ResourceManagerService> mService;
245 std::shared_ptr<IResourceManagerClient> mTestClient1;
246 std::shared_ptr<IResourceManagerClient> mTestClient2;
247 std::shared_ptr<IResourceManagerClient> mTestClient3;
248
249 protected:
isEqualResources(const std::vector<MediaResourceParcel> & resources1,const ResourceList & resources2)250 static bool isEqualResources(const std::vector<MediaResourceParcel> &resources1,
251 const ResourceList &resources2) {
252 // convert resource1 to ResourceList
253 ResourceList r1;
254 for (size_t i = 0; i < resources1.size(); ++i) {
255 r1.addOrUpdate(resources1[i]);
256 }
257 return r1 == resources2;
258 }
259
expectEqResourceInfo(const ResourceInfo & info,int uid,std::shared_ptr<IResourceManagerClient> client,const std::vector<MediaResourceParcel> & resources)260 static void expectEqResourceInfo(const ResourceInfo &info,
261 int uid,
262 std::shared_ptr<IResourceManagerClient> client,
263 const std::vector<MediaResourceParcel> &resources) {
264 EXPECT_EQ(uid, info.uid);
265 EXPECT_EQ(client, info.client);
266 EXPECT_TRUE(isEqualResources(resources, info.resources));
267 }
268
269 bool mNewRM = false;
270 };
271
272 } // namespace android
273