blob: 9e14151eb6c418edb2b90da8f77e6cf62dc05559 [file] [log] [blame]
Ronghua Wu231c3d12015-03-11 15:10:32 -07001/*
Ronghua Wu67e7f542015-03-13 10:47:08 -07002 * Copyright 2015 The Android Open Source Project
Ronghua Wu231c3d12015-03-11 15:10:32 -07003 *
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//#define LOG_NDEBUG 0
18#define LOG_TAG "ResourceManagerService_test"
19#include <utils/Log.h>
20
21#include <gtest/gtest.h>
22
23#include "ResourceManagerService.h"
24#include <media/IResourceManagerService.h>
25#include <media/MediaResource.h>
26#include <media/MediaResourcePolicy.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/ProcessInfoInterface.h>
29
30namespace android {
31
Chih-Hung Hsieh51873d82016-08-09 14:18:51 -070032static int64_t getId(const sp<IResourceManagerClient>& client) {
Ronghua Wu37c89242015-07-15 12:23:48 -070033 return (int64_t) client.get();
34}
35
Ronghua Wu231c3d12015-03-11 15:10:32 -070036struct TestProcessInfo : public ProcessInfoInterface {
37 TestProcessInfo() {}
38 virtual ~TestProcessInfo() {}
39
40 virtual bool getPriority(int pid, int *priority) {
41 // For testing, use pid as priority.
42 // Lower the value higher the priority.
43 *priority = pid;
44 return true;
45 }
46
Ronghua Wud11c43a2016-01-27 16:26:12 -080047 virtual bool isValidPid(int /* pid */) {
48 return true;
49 }
50
Ronghua Wu231c3d12015-03-11 15:10:32 -070051private:
52 DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
53};
54
Chong Zhangdd726802019-08-21 17:24:13 -070055struct TestSystemCallback :
56 public ResourceManagerService::SystemCallbackInterface {
57 TestSystemCallback() :
58 mLastEvent({EventType::INVALID, 0}), mEventCount(0) {}
59
60 enum EventType {
61 INVALID = -1,
62 VIDEO_ON = 0,
63 VIDEO_OFF = 1,
64 VIDEO_RESET = 2,
65 CPUSET_ENABLE = 3,
66 CPUSET_DISABLE = 4,
67 };
68
69 struct EventEntry {
70 EventType type;
71 int arg;
72 };
73
74 virtual void noteStartVideo(int uid) override {
75 mLastEvent = {EventType::VIDEO_ON, uid};
76 mEventCount++;
77 }
78
79 virtual void noteStopVideo(int uid) override {
80 mLastEvent = {EventType::VIDEO_OFF, uid};
81 mEventCount++;
82 }
83
84 virtual void noteResetVideo() override {
85 mLastEvent = {EventType::VIDEO_RESET, 0};
86 mEventCount++;
87 }
88
89 virtual bool requestCpusetBoost(
90 bool enable, const sp<IInterface> &/*client*/) override {
91 mLastEvent = {enable ? EventType::CPUSET_ENABLE : EventType::CPUSET_DISABLE, 0};
92 mEventCount++;
93 return true;
94 }
95
96 size_t eventCount() { return mEventCount; }
97 EventType lastEventType() { return mLastEvent.type; }
98 EventEntry lastEvent() { return mLastEvent; }
99
100protected:
101 virtual ~TestSystemCallback() {}
102
103private:
104 EventEntry mLastEvent;
105 size_t mEventCount;
106
107 DISALLOW_EVIL_CONSTRUCTORS(TestSystemCallback);
108};
109
110
Ronghua Wu231c3d12015-03-11 15:10:32 -0700111struct TestClient : public BnResourceManagerClient {
Ronghua Wu37c89242015-07-15 12:23:48 -0700112 TestClient(int pid, sp<ResourceManagerService> service)
113 : mReclaimed(false), mPid(pid), mService(service) {}
Ronghua Wu231c3d12015-03-11 15:10:32 -0700114
115 virtual bool reclaimResource() {
116 sp<IResourceManagerClient> client(this);
Chong Zhangfb092d32019-08-12 09:45:44 -0700117 mService->removeClient(mPid, (int64_t) client.get());
Ronghua Wu231c3d12015-03-11 15:10:32 -0700118 mReclaimed = true;
119 return true;
120 }
121
Ronghua Wu8f9dd872015-04-23 15:24:25 -0700122 virtual String8 getName() {
123 return String8("test_client");
124 }
125
Ronghua Wu231c3d12015-03-11 15:10:32 -0700126 bool reclaimed() const {
127 return mReclaimed;
128 }
129
130 void reset() {
131 mReclaimed = false;
132 }
133
134protected:
135 virtual ~TestClient() {}
136
137private:
138 bool mReclaimed;
Ronghua Wu37c89242015-07-15 12:23:48 -0700139 int mPid;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700140 sp<ResourceManagerService> mService;
141 DISALLOW_EVIL_CONSTRUCTORS(TestClient);
142};
143
144static const int kTestPid1 = 30;
Chong Zhangee33d642019-08-08 14:26:43 -0700145static const int kTestUid1 = 1010;
146
Ronghua Wu231c3d12015-03-11 15:10:32 -0700147static const int kTestPid2 = 20;
Chong Zhangee33d642019-08-08 14:26:43 -0700148static const int kTestUid2 = 1011;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700149
Ronghua Wu05d89f12015-07-07 16:47:42 -0700150static const int kLowPriorityPid = 40;
151static const int kMidPriorityPid = 25;
152static const int kHighPriorityPid = 10;
153
Chong Zhangdd726802019-08-21 17:24:13 -0700154using EventType = TestSystemCallback::EventType;
155using EventEntry = TestSystemCallback::EventEntry;
156bool operator== (const EventEntry& lhs, const EventEntry& rhs) {
157 return lhs.type == rhs.type && lhs.arg == rhs.arg;
158}
159
Ronghua Wu231c3d12015-03-11 15:10:32 -0700160class ResourceManagerServiceTest : public ::testing::Test {
161public:
162 ResourceManagerServiceTest()
Chong Zhangdd726802019-08-21 17:24:13 -0700163 : mSystemCB(new TestSystemCallback()),
164 mService(new ResourceManagerService(new TestProcessInfo, mSystemCB)),
Ronghua Wu37c89242015-07-15 12:23:48 -0700165 mTestClient1(new TestClient(kTestPid1, mService)),
166 mTestClient2(new TestClient(kTestPid2, mService)),
167 mTestClient3(new TestClient(kTestPid2, mService)) {
Ronghua Wu231c3d12015-03-11 15:10:32 -0700168 }
169
170protected:
171 static bool isEqualResources(const Vector<MediaResource> &resources1,
Chong Zhangfb092d32019-08-12 09:45:44 -0700172 const ResourceList &resources2) {
173 // convert resource1 to ResourceList
174 ResourceList r1;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700175 for (size_t i = 0; i < resources1.size(); ++i) {
Robert Shih79673cf2019-09-20 21:45:01 -0700176 const auto &res = resources1[i];
177 const auto resType = std::tuple(res.mType, res.mSubType, res.mId);
178 r1[resType] = res;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700179 }
Chong Zhangfb092d32019-08-12 09:45:44 -0700180 return r1 == resources2;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700181 }
182
Chong Zhangee33d642019-08-08 14:26:43 -0700183 static void expectEqResourceInfo(const ResourceInfo &info,
184 int uid,
185 sp<IResourceManagerClient> client,
Ronghua Wu231c3d12015-03-11 15:10:32 -0700186 const Vector<MediaResource> &resources) {
Chong Zhangee33d642019-08-08 14:26:43 -0700187 EXPECT_EQ(uid, info.uid);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700188 EXPECT_EQ(client, info.client);
189 EXPECT_TRUE(isEqualResources(resources, info.resources));
190 }
191
192 void verifyClients(bool c1, bool c2, bool c3) {
193 TestClient *client1 = static_cast<TestClient*>(mTestClient1.get());
194 TestClient *client2 = static_cast<TestClient*>(mTestClient2.get());
195 TestClient *client3 = static_cast<TestClient*>(mTestClient3.get());
196
197 EXPECT_EQ(c1, client1->reclaimed());
198 EXPECT_EQ(c2, client2->reclaimed());
199 EXPECT_EQ(c3, client3->reclaimed());
200
201 client1->reset();
202 client2->reset();
203 client3->reset();
204 }
205
Ronghua Wu67e7f542015-03-13 10:47:08 -0700206 // test set up
207 // ---------------------------------------------------------------------------------
208 // pid priority client type number
209 // ---------------------------------------------------------------------------------
210 // kTestPid1(30) 30 mTestClient1 secure codec 1
211 // graphic memory 200
212 // graphic memory 200
213 // ---------------------------------------------------------------------------------
214 // kTestPid2(20) 20 mTestClient2 non-secure codec 1
215 // graphic memory 300
216 // -------------------------------------------
217 // mTestClient3 secure codec 1
218 // graphic memory 100
219 // ---------------------------------------------------------------------------------
Ronghua Wu231c3d12015-03-11 15:10:32 -0700220 void addResource() {
221 // kTestPid1 mTestClient1
222 Vector<MediaResource> resources1;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800223 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
Chong Zhangee33d642019-08-08 14:26:43 -0700224 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
Ronghua Wuea15fd22016-03-03 13:35:05 -0800225 resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700226 Vector<MediaResource> resources11;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800227 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
Chong Zhangee33d642019-08-08 14:26:43 -0700228 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700229
230 // kTestPid2 mTestClient2
231 Vector<MediaResource> resources2;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800232 resources2.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
233 resources2.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
Chong Zhangee33d642019-08-08 14:26:43 -0700234 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700235
236 // kTestPid2 mTestClient3
237 Vector<MediaResource> resources3;
Chong Zhangee33d642019-08-08 14:26:43 -0700238 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
Ronghua Wuea15fd22016-03-03 13:35:05 -0800239 resources3.push_back(MediaResource(MediaResource::kSecureCodec, 1));
240 resources3.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
Chong Zhangee33d642019-08-08 14:26:43 -0700241 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700242
243 const PidResourceInfosMap &map = mService->mMap;
244 EXPECT_EQ(2u, map.size());
245 ssize_t index1 = map.indexOfKey(kTestPid1);
246 ASSERT_GE(index1, 0);
247 const ResourceInfos &infos1 = map[index1];
248 EXPECT_EQ(1u, infos1.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700249 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, resources1);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700250
251 ssize_t index2 = map.indexOfKey(kTestPid2);
252 ASSERT_GE(index2, 0);
253 const ResourceInfos &infos2 = map[index2];
254 EXPECT_EQ(2u, infos2.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700255 expectEqResourceInfo(infos2.valueFor(getId(mTestClient2)), kTestUid2, mTestClient2, resources2);
256 expectEqResourceInfo(infos2.valueFor(getId(mTestClient3)), kTestUid2, mTestClient3, resources3);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700257 }
258
259 void testConfig() {
260 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
261 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
262
263 Vector<MediaResourcePolicy> policies1;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700264 policies1.push_back(
Ronghua Wu9ba21b92015-04-21 14:23:06 -0700265 MediaResourcePolicy(
266 String8(kPolicySupportsMultipleSecureCodecs),
267 String8("true")));
268 policies1.push_back(
269 MediaResourcePolicy(
270 String8(kPolicySupportsSecureWithNonSecureCodec),
271 String8("false")));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700272 mService->config(policies1);
273 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
274 EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
275
276 Vector<MediaResourcePolicy> policies2;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700277 policies2.push_back(
Ronghua Wu9ba21b92015-04-21 14:23:06 -0700278 MediaResourcePolicy(
279 String8(kPolicySupportsMultipleSecureCodecs),
280 String8("false")));
281 policies2.push_back(
282 MediaResourcePolicy(
283 String8(kPolicySupportsSecureWithNonSecureCodec),
284 String8("true")));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700285 mService->config(policies2);
286 EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
287 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
288 }
289
Chong Zhangfb092d32019-08-12 09:45:44 -0700290 void testCombineResource() {
291 // kTestPid1 mTestClient1
292 Vector<MediaResource> resources1;
293 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
294 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
295
296 Vector<MediaResource> resources11;
297 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
298 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
299
300 const PidResourceInfosMap &map = mService->mMap;
301 EXPECT_EQ(1u, map.size());
302 ssize_t index1 = map.indexOfKey(kTestPid1);
303 ASSERT_GE(index1, 0);
304 const ResourceInfos &infos1 = map[index1];
305 EXPECT_EQ(1u, infos1.size());
306
307 // test adding existing types to combine values
308 resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
309 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
310
311 Vector<MediaResource> expected;
312 expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
313 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
314 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
315
316 // test adding new types (including types that differs only in subType)
317 resources11.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
318 resources11.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
319 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
320
321 expected.clear();
322 expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
323 expected.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
324 expected.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
325 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 500));
326 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
327 }
328
Ronghua Wu231c3d12015-03-11 15:10:32 -0700329 void testRemoveResource() {
Chong Zhangfb092d32019-08-12 09:45:44 -0700330 // kTestPid1 mTestClient1
331 Vector<MediaResource> resources1;
332 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
333 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
334
335 Vector<MediaResource> resources11;
336 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
337 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
338
339 const PidResourceInfosMap &map = mService->mMap;
340 EXPECT_EQ(1u, map.size());
341 ssize_t index1 = map.indexOfKey(kTestPid1);
342 ASSERT_GE(index1, 0);
343 const ResourceInfos &infos1 = map[index1];
344 EXPECT_EQ(1u, infos1.size());
345
346 // test partial removal
347 resources11.editItemAt(0).mValue = 100;
348 mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
349
350 Vector<MediaResource> expected;
351 expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
352 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
353 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
354
355 // test complete removal with overshoot value
356 resources11.editItemAt(0).mValue = 1000;
357 mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
358
359 expected.clear();
360 expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
361 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
362 }
363
364 void testRemoveClient() {
Ronghua Wu231c3d12015-03-11 15:10:32 -0700365 addResource();
366
Chong Zhangfb092d32019-08-12 09:45:44 -0700367 mService->removeClient(kTestPid2, getId(mTestClient2));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700368
369 const PidResourceInfosMap &map = mService->mMap;
370 EXPECT_EQ(2u, map.size());
371 const ResourceInfos &infos1 = map.valueFor(kTestPid1);
372 const ResourceInfos &infos2 = map.valueFor(kTestPid2);
373 EXPECT_EQ(1u, infos1.size());
374 EXPECT_EQ(1u, infos2.size());
375 // mTestClient2 has been removed.
Chong Zhangfb092d32019-08-12 09:45:44 -0700376 // (OK to use infos2[0] as there is only 1 entry)
Ronghua Wu231c3d12015-03-11 15:10:32 -0700377 EXPECT_EQ(mTestClient3, infos2[0].client);
378 }
379
380 void testGetAllClients() {
381 addResource();
382
Ronghua Wuea15fd22016-03-03 13:35:05 -0800383 MediaResource::Type type = MediaResource::kSecureCodec;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700384 Vector<sp<IResourceManagerClient> > clients;
Ronghua Wu05d89f12015-07-07 16:47:42 -0700385 EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, &clients));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700386 // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
387 // will fail.
Ronghua Wu05d89f12015-07-07 16:47:42 -0700388 EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, &clients));
Ronghua Wu05d89f12015-07-07 16:47:42 -0700389 EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, &clients));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700390
391 EXPECT_EQ(2u, clients.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700392 // (OK to require ordering in clients[], as the pid map is sorted)
Ronghua Wu231c3d12015-03-11 15:10:32 -0700393 EXPECT_EQ(mTestClient3, clients[0]);
394 EXPECT_EQ(mTestClient1, clients[1]);
395 }
396
397 void testReclaimResourceSecure() {
398 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800399 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
400 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700401
402 // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
403 {
404 addResource();
405 mService->mSupportsMultipleSecureCodecs = false;
406 mService->mSupportsSecureWithNonSecureCodec = true;
407
408 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700409 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
410 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700411
412 // reclaim all secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700413 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
414 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700415
416 // call again should reclaim one largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700417 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
418 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700419
420 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700421 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700422 }
423
424 // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
425 {
426 addResource();
427 mService->mSupportsMultipleSecureCodecs = false;
428 mService->mSupportsSecureWithNonSecureCodec = false;
429
430 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700431 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
432 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700433
434 // reclaim all secure and non-secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700435 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
436 verifyClients(true /* c1 */, true /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700437
438 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700439 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700440 }
441
442
443 // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ###
444 {
445 addResource();
446 mService->mSupportsMultipleSecureCodecs = true;
447 mService->mSupportsSecureWithNonSecureCodec = false;
448
449 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700450 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
451 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700452
453 // reclaim all non-secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700454 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
455 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700456
457 // call again should reclaim one largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700458 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
459 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700460
461 // call again should reclaim another largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700462 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
463 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700464
465 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700466 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700467 }
468
469 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
470 {
471 addResource();
472 mService->mSupportsMultipleSecureCodecs = true;
473 mService->mSupportsSecureWithNonSecureCodec = true;
474
475 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700476 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700477
Ronghua Wu05d89f12015-07-07 16:47:42 -0700478 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700479 // one largest graphic memory from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700480 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700481
482 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700483 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
484 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700485
486 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700487 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
488 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700489
490 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700491 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700492 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700493
494 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
495 {
496 addResource();
497 mService->mSupportsMultipleSecureCodecs = true;
498 mService->mSupportsSecureWithNonSecureCodec = true;
499
500 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800501 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700502
Ronghua Wu05d89f12015-07-07 16:47:42 -0700503 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700504 // secure codec from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700505 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700506
507 // call again should reclaim another secure codec from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700508 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
509 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700510
Ronghua Wu05d89f12015-07-07 16:47:42 -0700511 // no more secure codec, non-secure codec will be reclaimed.
512 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
513 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700514 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700515 }
516
517 void testReclaimResourceNonSecure() {
518 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800519 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
520 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700521
522 // ### secure codec can't coexist with non-secure codec ###
523 {
524 addResource();
525 mService->mSupportsSecureWithNonSecureCodec = false;
526
527 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700528 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
529 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700530
531 // reclaim all secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700532 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
533 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700534
535 // call again should reclaim one graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700536 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
537 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700538
539 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700540 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700541 }
542
543
544 // ### secure codec can coexist with non-secure codec ###
545 {
546 addResource();
547 mService->mSupportsSecureWithNonSecureCodec = true;
548
549 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700550 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700551
Ronghua Wu05d89f12015-07-07 16:47:42 -0700552 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700553 // one largest graphic memory from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700554 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700555
556 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700557 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
558 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700559
560 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700561 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
562 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700563
564 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700565 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700566 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700567
568 // ### secure codec can coexist with non-secure codec ###
569 {
570 addResource();
571 mService->mSupportsSecureWithNonSecureCodec = true;
572
573 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800574 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700575
Ronghua Wu05d89f12015-07-07 16:47:42 -0700576 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700577 // one non secure codec from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700578 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700579
Ronghua Wu05d89f12015-07-07 16:47:42 -0700580 // no more non-secure codec, secure codec from lowest priority process will be reclaimed
581 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
582 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700583
Ronghua Wu05d89f12015-07-07 16:47:42 -0700584 // clean up client 3 which still left
Chong Zhangfb092d32019-08-12 09:45:44 -0700585 mService->removeClient(kTestPid2, getId(mTestClient3));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700586 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700587 }
588
589 void testGetLowestPriorityBiggestClient() {
Ronghua Wuea15fd22016-03-03 13:35:05 -0800590 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700591 sp<IResourceManagerClient> client;
Ronghua Wu05d89f12015-07-07 16:47:42 -0700592 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700593
594 addResource();
595
Ronghua Wu05d89f12015-07-07 16:47:42 -0700596 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, &client));
597 EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700598
Ronghua Wuea15fd22016-03-03 13:35:05 -0800599 // kTestPid1 is the lowest priority process with MediaResource::kGraphicMemory.
600 // mTestClient1 has the largest MediaResource::kGraphicMemory within kTestPid1.
Ronghua Wu231c3d12015-03-11 15:10:32 -0700601 EXPECT_EQ(mTestClient1, client);
602 }
603
604 void testGetLowestPriorityPid() {
605 int pid;
606 int priority;
607 TestProcessInfo processInfo;
608
Ronghua Wuea15fd22016-03-03 13:35:05 -0800609 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700610 EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority));
611
612 addResource();
613
614 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
615 EXPECT_EQ(kTestPid1, pid);
616 int priority1;
617 processInfo.getPriority(kTestPid1, &priority1);
618 EXPECT_EQ(priority1, priority);
619
Ronghua Wuea15fd22016-03-03 13:35:05 -0800620 type = MediaResource::kNonSecureCodec;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700621 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
622 EXPECT_EQ(kTestPid2, pid);
623 int priority2;
624 processInfo.getPriority(kTestPid2, &priority2);
625 EXPECT_EQ(priority2, priority);
626 }
627
628 void testGetBiggestClient() {
Ronghua Wuea15fd22016-03-03 13:35:05 -0800629 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700630 sp<IResourceManagerClient> client;
631 EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client));
632
633 addResource();
634
635 EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client));
636 EXPECT_EQ(mTestClient2, client);
637 }
638
639 void testIsCallingPriorityHigher() {
640 EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100));
641 EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100));
642 EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100));
643 }
644
Chong Zhangdd726802019-08-21 17:24:13 -0700645 void testBatteryStats() {
646 // reset should always be called when ResourceManagerService is created (restarted)
647 EXPECT_EQ(1u, mSystemCB->eventCount());
648 EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
649
650 // new client request should cause VIDEO_ON
651 Vector<MediaResource> resources1;
652 resources1.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1));
653 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
654 EXPECT_EQ(2u, mSystemCB->eventCount());
655 EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
656
657 // each client should only cause 1 VIDEO_ON
658 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
659 EXPECT_EQ(2u, mSystemCB->eventCount());
660
661 // new client request should cause VIDEO_ON
662 Vector<MediaResource> resources2;
663 resources2.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 2));
664 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
665 EXPECT_EQ(3u, mSystemCB->eventCount());
666 EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
667
668 // partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
669 mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
670 EXPECT_EQ(3u, mSystemCB->eventCount());
671
672 // remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
673 // (use resource2 to test removing more instances than previously requested)
674 mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
675 EXPECT_EQ(4u, mSystemCB->eventCount());
676 EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
677
678 // remove mTestClient2, should be VIDEO_OFF for kTestUid2
679 mService->removeClient(kTestPid2, getId(mTestClient2));
680 EXPECT_EQ(5u, mSystemCB->eventCount());
681 EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
682 }
683
684 void testCpusetBoost() {
685 // reset should always be called when ResourceManagerService is created (restarted)
686 EXPECT_EQ(1u, mSystemCB->eventCount());
687 EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
688
689 // new client request should cause CPUSET_ENABLE
690 Vector<MediaResource> resources1;
691 resources1.push_back(MediaResource(MediaResource::kCpuBoost, 1));
692 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
693 EXPECT_EQ(2u, mSystemCB->eventCount());
694 EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
695
696 // each client should only cause 1 CPUSET_ENABLE
697 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
698 EXPECT_EQ(2u, mSystemCB->eventCount());
699
700 // new client request should cause CPUSET_ENABLE
701 Vector<MediaResource> resources2;
702 resources2.push_back(MediaResource(MediaResource::kCpuBoost, 2));
703 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
704 EXPECT_EQ(3u, mSystemCB->eventCount());
705 EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
706
707 // remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
708 mService->removeClient(kTestPid2, getId(mTestClient2));
709 EXPECT_EQ(3u, mSystemCB->eventCount());
710
711 // remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
712 mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
713 EXPECT_EQ(3u, mSystemCB->eventCount());
714
715 // remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
716 // (use resource2 to test removing more than previously requested)
717 mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
718 EXPECT_EQ(4u, mSystemCB->eventCount());
719 EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
720 }
721
722 sp<TestSystemCallback> mSystemCB;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700723 sp<ResourceManagerService> mService;
724 sp<IResourceManagerClient> mTestClient1;
725 sp<IResourceManagerClient> mTestClient2;
726 sp<IResourceManagerClient> mTestClient3;
727};
728
729TEST_F(ResourceManagerServiceTest, config) {
730 testConfig();
731}
732
733TEST_F(ResourceManagerServiceTest, addResource) {
734 addResource();
735}
736
Chong Zhangfb092d32019-08-12 09:45:44 -0700737TEST_F(ResourceManagerServiceTest, combineResource) {
738 testCombineResource();
739}
740
Ronghua Wu231c3d12015-03-11 15:10:32 -0700741TEST_F(ResourceManagerServiceTest, removeResource) {
742 testRemoveResource();
743}
744
Chong Zhangfb092d32019-08-12 09:45:44 -0700745TEST_F(ResourceManagerServiceTest, removeClient) {
746 testRemoveClient();
747}
748
Ronghua Wu231c3d12015-03-11 15:10:32 -0700749TEST_F(ResourceManagerServiceTest, reclaimResource) {
750 testReclaimResourceSecure();
751 testReclaimResourceNonSecure();
752}
753
754TEST_F(ResourceManagerServiceTest, getAllClients_l) {
755 testGetAllClients();
756}
757
758TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) {
759 testGetLowestPriorityBiggestClient();
760}
761
762TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) {
763 testGetLowestPriorityPid();
764}
765
766TEST_F(ResourceManagerServiceTest, getBiggestClient_l) {
767 testGetBiggestClient();
768}
769
770TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) {
771 testIsCallingPriorityHigher();
772}
773
Chong Zhangdd726802019-08-21 17:24:13 -0700774TEST_F(ResourceManagerServiceTest, testBatteryStats) {
775 testBatteryStats();
776}
777
778TEST_F(ResourceManagerServiceTest, testCpusetBoost) {
779 testCpusetBoost();
780}
781
Ronghua Wu231c3d12015-03-11 15:10:32 -0700782} // namespace android