blob: ae97ec83247f80be53cca02333657bb2bc7a1f65 [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) {
Chong Zhangfb092d32019-08-12 09:45:44 -0700176 const auto resType = std::make_pair(resources1[i].mType, resources1[i].mSubType);
177 r1[resType] = resources1[i];
Ronghua Wu231c3d12015-03-11 15:10:32 -0700178 }
Chong Zhangfb092d32019-08-12 09:45:44 -0700179 return r1 == resources2;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700180 }
181
Chong Zhangee33d642019-08-08 14:26:43 -0700182 static void expectEqResourceInfo(const ResourceInfo &info,
183 int uid,
184 sp<IResourceManagerClient> client,
Ronghua Wu231c3d12015-03-11 15:10:32 -0700185 const Vector<MediaResource> &resources) {
Chong Zhangee33d642019-08-08 14:26:43 -0700186 EXPECT_EQ(uid, info.uid);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700187 EXPECT_EQ(client, info.client);
188 EXPECT_TRUE(isEqualResources(resources, info.resources));
189 }
190
191 void verifyClients(bool c1, bool c2, bool c3) {
192 TestClient *client1 = static_cast<TestClient*>(mTestClient1.get());
193 TestClient *client2 = static_cast<TestClient*>(mTestClient2.get());
194 TestClient *client3 = static_cast<TestClient*>(mTestClient3.get());
195
196 EXPECT_EQ(c1, client1->reclaimed());
197 EXPECT_EQ(c2, client2->reclaimed());
198 EXPECT_EQ(c3, client3->reclaimed());
199
200 client1->reset();
201 client2->reset();
202 client3->reset();
203 }
204
Ronghua Wu67e7f542015-03-13 10:47:08 -0700205 // test set up
206 // ---------------------------------------------------------------------------------
207 // pid priority client type number
208 // ---------------------------------------------------------------------------------
209 // kTestPid1(30) 30 mTestClient1 secure codec 1
210 // graphic memory 200
211 // graphic memory 200
212 // ---------------------------------------------------------------------------------
213 // kTestPid2(20) 20 mTestClient2 non-secure codec 1
214 // graphic memory 300
215 // -------------------------------------------
216 // mTestClient3 secure codec 1
217 // graphic memory 100
218 // ---------------------------------------------------------------------------------
Ronghua Wu231c3d12015-03-11 15:10:32 -0700219 void addResource() {
220 // kTestPid1 mTestClient1
221 Vector<MediaResource> resources1;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800222 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
Chong Zhangee33d642019-08-08 14:26:43 -0700223 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
Ronghua Wuea15fd22016-03-03 13:35:05 -0800224 resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700225 Vector<MediaResource> resources11;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800226 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
Chong Zhangee33d642019-08-08 14:26:43 -0700227 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700228
229 // kTestPid2 mTestClient2
230 Vector<MediaResource> resources2;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800231 resources2.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
232 resources2.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
Chong Zhangee33d642019-08-08 14:26:43 -0700233 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700234
235 // kTestPid2 mTestClient3
236 Vector<MediaResource> resources3;
Chong Zhangee33d642019-08-08 14:26:43 -0700237 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
Ronghua Wuea15fd22016-03-03 13:35:05 -0800238 resources3.push_back(MediaResource(MediaResource::kSecureCodec, 1));
239 resources3.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
Chong Zhangee33d642019-08-08 14:26:43 -0700240 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700241
242 const PidResourceInfosMap &map = mService->mMap;
243 EXPECT_EQ(2u, map.size());
244 ssize_t index1 = map.indexOfKey(kTestPid1);
245 ASSERT_GE(index1, 0);
246 const ResourceInfos &infos1 = map[index1];
247 EXPECT_EQ(1u, infos1.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700248 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, resources1);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700249
250 ssize_t index2 = map.indexOfKey(kTestPid2);
251 ASSERT_GE(index2, 0);
252 const ResourceInfos &infos2 = map[index2];
253 EXPECT_EQ(2u, infos2.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700254 expectEqResourceInfo(infos2.valueFor(getId(mTestClient2)), kTestUid2, mTestClient2, resources2);
255 expectEqResourceInfo(infos2.valueFor(getId(mTestClient3)), kTestUid2, mTestClient3, resources3);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700256 }
257
258 void testConfig() {
259 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
260 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
261
262 Vector<MediaResourcePolicy> policies1;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700263 policies1.push_back(
Ronghua Wu9ba21b92015-04-21 14:23:06 -0700264 MediaResourcePolicy(
265 String8(kPolicySupportsMultipleSecureCodecs),
266 String8("true")));
267 policies1.push_back(
268 MediaResourcePolicy(
269 String8(kPolicySupportsSecureWithNonSecureCodec),
270 String8("false")));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700271 mService->config(policies1);
272 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
273 EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
274
275 Vector<MediaResourcePolicy> policies2;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700276 policies2.push_back(
Ronghua Wu9ba21b92015-04-21 14:23:06 -0700277 MediaResourcePolicy(
278 String8(kPolicySupportsMultipleSecureCodecs),
279 String8("false")));
280 policies2.push_back(
281 MediaResourcePolicy(
282 String8(kPolicySupportsSecureWithNonSecureCodec),
283 String8("true")));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700284 mService->config(policies2);
285 EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
286 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
287 }
288
Chong Zhangfb092d32019-08-12 09:45:44 -0700289 void testCombineResource() {
290 // kTestPid1 mTestClient1
291 Vector<MediaResource> resources1;
292 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
293 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
294
295 Vector<MediaResource> resources11;
296 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
297 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
298
299 const PidResourceInfosMap &map = mService->mMap;
300 EXPECT_EQ(1u, map.size());
301 ssize_t index1 = map.indexOfKey(kTestPid1);
302 ASSERT_GE(index1, 0);
303 const ResourceInfos &infos1 = map[index1];
304 EXPECT_EQ(1u, infos1.size());
305
306 // test adding existing types to combine values
307 resources1.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
308 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
309
310 Vector<MediaResource> expected;
311 expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
312 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 300));
313 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
314
315 // test adding new types (including types that differs only in subType)
316 resources11.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
317 resources11.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
318 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
319
320 expected.clear();
321 expected.push_back(MediaResource(MediaResource::kSecureCodec, 2));
322 expected.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
323 expected.push_back(MediaResource(MediaResource::kSecureCodec, MediaResource::kVideoCodec, 1));
324 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 500));
325 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
326 }
327
Ronghua Wu231c3d12015-03-11 15:10:32 -0700328 void testRemoveResource() {
Chong Zhangfb092d32019-08-12 09:45:44 -0700329 // kTestPid1 mTestClient1
330 Vector<MediaResource> resources1;
331 resources1.push_back(MediaResource(MediaResource::kSecureCodec, 1));
332 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
333
334 Vector<MediaResource> resources11;
335 resources11.push_back(MediaResource(MediaResource::kGraphicMemory, 200));
336 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
337
338 const PidResourceInfosMap &map = mService->mMap;
339 EXPECT_EQ(1u, map.size());
340 ssize_t index1 = map.indexOfKey(kTestPid1);
341 ASSERT_GE(index1, 0);
342 const ResourceInfos &infos1 = map[index1];
343 EXPECT_EQ(1u, infos1.size());
344
345 // test partial removal
346 resources11.editItemAt(0).mValue = 100;
347 mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
348
349 Vector<MediaResource> expected;
350 expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
351 expected.push_back(MediaResource(MediaResource::kGraphicMemory, 100));
352 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
353
354 // test complete removal with overshoot value
355 resources11.editItemAt(0).mValue = 1000;
356 mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
357
358 expected.clear();
359 expected.push_back(MediaResource(MediaResource::kSecureCodec, 1));
360 expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
361 }
362
363 void testRemoveClient() {
Ronghua Wu231c3d12015-03-11 15:10:32 -0700364 addResource();
365
Chong Zhangfb092d32019-08-12 09:45:44 -0700366 mService->removeClient(kTestPid2, getId(mTestClient2));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700367
368 const PidResourceInfosMap &map = mService->mMap;
369 EXPECT_EQ(2u, map.size());
370 const ResourceInfos &infos1 = map.valueFor(kTestPid1);
371 const ResourceInfos &infos2 = map.valueFor(kTestPid2);
372 EXPECT_EQ(1u, infos1.size());
373 EXPECT_EQ(1u, infos2.size());
374 // mTestClient2 has been removed.
Chong Zhangfb092d32019-08-12 09:45:44 -0700375 // (OK to use infos2[0] as there is only 1 entry)
Ronghua Wu231c3d12015-03-11 15:10:32 -0700376 EXPECT_EQ(mTestClient3, infos2[0].client);
377 }
378
379 void testGetAllClients() {
380 addResource();
381
Ronghua Wuea15fd22016-03-03 13:35:05 -0800382 MediaResource::Type type = MediaResource::kSecureCodec;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700383 Vector<sp<IResourceManagerClient> > clients;
Ronghua Wu05d89f12015-07-07 16:47:42 -0700384 EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, &clients));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700385 // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
386 // will fail.
Ronghua Wu05d89f12015-07-07 16:47:42 -0700387 EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, &clients));
Ronghua Wu05d89f12015-07-07 16:47:42 -0700388 EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, &clients));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700389
390 EXPECT_EQ(2u, clients.size());
Chong Zhangfb092d32019-08-12 09:45:44 -0700391 // (OK to require ordering in clients[], as the pid map is sorted)
Ronghua Wu231c3d12015-03-11 15:10:32 -0700392 EXPECT_EQ(mTestClient3, clients[0]);
393 EXPECT_EQ(mTestClient1, clients[1]);
394 }
395
396 void testReclaimResourceSecure() {
397 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800398 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
399 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700400
401 // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
402 {
403 addResource();
404 mService->mSupportsMultipleSecureCodecs = false;
405 mService->mSupportsSecureWithNonSecureCodec = true;
406
407 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700408 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
409 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700410
411 // reclaim all secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700412 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
413 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700414
415 // call again should reclaim one largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700416 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
417 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700418
419 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700420 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700421 }
422
423 // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
424 {
425 addResource();
426 mService->mSupportsMultipleSecureCodecs = false;
427 mService->mSupportsSecureWithNonSecureCodec = false;
428
429 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700430 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
431 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700432
433 // reclaim all secure and non-secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700434 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
435 verifyClients(true /* c1 */, true /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700436
437 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700438 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700439 }
440
441
442 // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ###
443 {
444 addResource();
445 mService->mSupportsMultipleSecureCodecs = true;
446 mService->mSupportsSecureWithNonSecureCodec = false;
447
448 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700449 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
450 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700451
452 // reclaim all non-secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700453 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
454 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700455
456 // call again should reclaim one largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700457 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
458 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700459
460 // call again should reclaim another largest graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700461 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
462 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700463
464 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700465 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700466 }
467
468 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
469 {
470 addResource();
471 mService->mSupportsMultipleSecureCodecs = true;
472 mService->mSupportsSecureWithNonSecureCodec = true;
473
474 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700475 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700476
Ronghua Wu05d89f12015-07-07 16:47:42 -0700477 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700478 // one largest graphic memory from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700479 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700480
481 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700482 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
483 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700484
485 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700486 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
487 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700488
489 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700490 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700491 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700492
493 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
494 {
495 addResource();
496 mService->mSupportsMultipleSecureCodecs = true;
497 mService->mSupportsSecureWithNonSecureCodec = true;
498
499 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800500 resources.push_back(MediaResource(MediaResource::kSecureCodec, 1));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700501
Ronghua Wu05d89f12015-07-07 16:47:42 -0700502 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700503 // secure codec from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700504 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700505
506 // call again should reclaim another secure codec from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700507 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
508 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700509
Ronghua Wu05d89f12015-07-07 16:47:42 -0700510 // no more secure codec, non-secure codec will be reclaimed.
511 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
512 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700513 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700514 }
515
516 void testReclaimResourceNonSecure() {
517 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800518 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
519 resources.push_back(MediaResource(MediaResource::kGraphicMemory, 150));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700520
521 // ### secure codec can't coexist with non-secure codec ###
522 {
523 addResource();
524 mService->mSupportsSecureWithNonSecureCodec = false;
525
526 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700527 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
528 EXPECT_FALSE(mService->reclaimResource(kMidPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700529
530 // reclaim all secure codecs
Ronghua Wu05d89f12015-07-07 16:47:42 -0700531 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
532 verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700533
534 // call again should reclaim one graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700535 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
536 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700537
538 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700539 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700540 }
541
542
543 // ### secure codec can coexist with non-secure codec ###
544 {
545 addResource();
546 mService->mSupportsSecureWithNonSecureCodec = true;
547
548 // priority too low
Ronghua Wu05d89f12015-07-07 16:47:42 -0700549 EXPECT_FALSE(mService->reclaimResource(kLowPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700550
Ronghua Wu05d89f12015-07-07 16:47:42 -0700551 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700552 // one largest graphic memory from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700553 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700554
555 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700556 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
557 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700558
559 // call again should reclaim another graphic memory from lowest process
Ronghua Wu05d89f12015-07-07 16:47:42 -0700560 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
561 verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
Ronghua Wu231c3d12015-03-11 15:10:32 -0700562
563 // nothing left
Ronghua Wu05d89f12015-07-07 16:47:42 -0700564 EXPECT_FALSE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700565 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700566
567 // ### secure codec can coexist with non-secure codec ###
568 {
569 addResource();
570 mService->mSupportsSecureWithNonSecureCodec = true;
571
572 Vector<MediaResource> resources;
Ronghua Wuea15fd22016-03-03 13:35:05 -0800573 resources.push_back(MediaResource(MediaResource::kNonSecureCodec, 1));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700574
Ronghua Wu05d89f12015-07-07 16:47:42 -0700575 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700576 // one non secure codec from lowest process got reclaimed
Ronghua Wu05d89f12015-07-07 16:47:42 -0700577 verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700578
Ronghua Wu05d89f12015-07-07 16:47:42 -0700579 // no more non-secure codec, secure codec from lowest priority process will be reclaimed
580 EXPECT_TRUE(mService->reclaimResource(kHighPriorityPid, resources));
581 verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
Ronghua Wu67e7f542015-03-13 10:47:08 -0700582
Ronghua Wu05d89f12015-07-07 16:47:42 -0700583 // clean up client 3 which still left
Chong Zhangfb092d32019-08-12 09:45:44 -0700584 mService->removeClient(kTestPid2, getId(mTestClient3));
Ronghua Wu67e7f542015-03-13 10:47:08 -0700585 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700586 }
587
588 void testGetLowestPriorityBiggestClient() {
Ronghua Wuea15fd22016-03-03 13:35:05 -0800589 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700590 sp<IResourceManagerClient> client;
Ronghua Wu05d89f12015-07-07 16:47:42 -0700591 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700592
593 addResource();
594
Ronghua Wu05d89f12015-07-07 16:47:42 -0700595 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, &client));
596 EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700597
Ronghua Wuea15fd22016-03-03 13:35:05 -0800598 // kTestPid1 is the lowest priority process with MediaResource::kGraphicMemory.
599 // mTestClient1 has the largest MediaResource::kGraphicMemory within kTestPid1.
Ronghua Wu231c3d12015-03-11 15:10:32 -0700600 EXPECT_EQ(mTestClient1, client);
601 }
602
603 void testGetLowestPriorityPid() {
604 int pid;
605 int priority;
606 TestProcessInfo processInfo;
607
Ronghua Wuea15fd22016-03-03 13:35:05 -0800608 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700609 EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority));
610
611 addResource();
612
613 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
614 EXPECT_EQ(kTestPid1, pid);
615 int priority1;
616 processInfo.getPriority(kTestPid1, &priority1);
617 EXPECT_EQ(priority1, priority);
618
Ronghua Wuea15fd22016-03-03 13:35:05 -0800619 type = MediaResource::kNonSecureCodec;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700620 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
621 EXPECT_EQ(kTestPid2, pid);
622 int priority2;
623 processInfo.getPriority(kTestPid2, &priority2);
624 EXPECT_EQ(priority2, priority);
625 }
626
627 void testGetBiggestClient() {
Ronghua Wuea15fd22016-03-03 13:35:05 -0800628 MediaResource::Type type = MediaResource::kGraphicMemory;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700629 sp<IResourceManagerClient> client;
630 EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client));
631
632 addResource();
633
634 EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client));
635 EXPECT_EQ(mTestClient2, client);
636 }
637
638 void testIsCallingPriorityHigher() {
639 EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100));
640 EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100));
641 EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100));
642 }
643
Chong Zhangdd726802019-08-21 17:24:13 -0700644 void testBatteryStats() {
645 // reset should always be called when ResourceManagerService is created (restarted)
646 EXPECT_EQ(1u, mSystemCB->eventCount());
647 EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
648
649 // new client request should cause VIDEO_ON
650 Vector<MediaResource> resources1;
651 resources1.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 1));
652 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
653 EXPECT_EQ(2u, mSystemCB->eventCount());
654 EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
655
656 // each client should only cause 1 VIDEO_ON
657 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
658 EXPECT_EQ(2u, mSystemCB->eventCount());
659
660 // new client request should cause VIDEO_ON
661 Vector<MediaResource> resources2;
662 resources2.push_back(MediaResource(MediaResource::kBattery, MediaResource::kVideoCodec, 2));
663 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
664 EXPECT_EQ(3u, mSystemCB->eventCount());
665 EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
666
667 // partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
668 mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
669 EXPECT_EQ(3u, mSystemCB->eventCount());
670
671 // remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
672 // (use resource2 to test removing more instances than previously requested)
673 mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
674 EXPECT_EQ(4u, mSystemCB->eventCount());
675 EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
676
677 // remove mTestClient2, should be VIDEO_OFF for kTestUid2
678 mService->removeClient(kTestPid2, getId(mTestClient2));
679 EXPECT_EQ(5u, mSystemCB->eventCount());
680 EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
681 }
682
683 void testCpusetBoost() {
684 // reset should always be called when ResourceManagerService is created (restarted)
685 EXPECT_EQ(1u, mSystemCB->eventCount());
686 EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
687
688 // new client request should cause CPUSET_ENABLE
689 Vector<MediaResource> resources1;
690 resources1.push_back(MediaResource(MediaResource::kCpuBoost, 1));
691 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
692 EXPECT_EQ(2u, mSystemCB->eventCount());
693 EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
694
695 // each client should only cause 1 CPUSET_ENABLE
696 mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
697 EXPECT_EQ(2u, mSystemCB->eventCount());
698
699 // new client request should cause CPUSET_ENABLE
700 Vector<MediaResource> resources2;
701 resources2.push_back(MediaResource(MediaResource::kCpuBoost, 2));
702 mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
703 EXPECT_EQ(3u, mSystemCB->eventCount());
704 EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
705
706 // remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
707 mService->removeClient(kTestPid2, getId(mTestClient2));
708 EXPECT_EQ(3u, mSystemCB->eventCount());
709
710 // remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
711 mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
712 EXPECT_EQ(3u, mSystemCB->eventCount());
713
714 // remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
715 // (use resource2 to test removing more than previously requested)
716 mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
717 EXPECT_EQ(4u, mSystemCB->eventCount());
718 EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
719 }
720
721 sp<TestSystemCallback> mSystemCB;
Ronghua Wu231c3d12015-03-11 15:10:32 -0700722 sp<ResourceManagerService> mService;
723 sp<IResourceManagerClient> mTestClient1;
724 sp<IResourceManagerClient> mTestClient2;
725 sp<IResourceManagerClient> mTestClient3;
726};
727
728TEST_F(ResourceManagerServiceTest, config) {
729 testConfig();
730}
731
732TEST_F(ResourceManagerServiceTest, addResource) {
733 addResource();
734}
735
Chong Zhangfb092d32019-08-12 09:45:44 -0700736TEST_F(ResourceManagerServiceTest, combineResource) {
737 testCombineResource();
738}
739
Ronghua Wu231c3d12015-03-11 15:10:32 -0700740TEST_F(ResourceManagerServiceTest, removeResource) {
741 testRemoveResource();
742}
743
Chong Zhangfb092d32019-08-12 09:45:44 -0700744TEST_F(ResourceManagerServiceTest, removeClient) {
745 testRemoveClient();
746}
747
Ronghua Wu231c3d12015-03-11 15:10:32 -0700748TEST_F(ResourceManagerServiceTest, reclaimResource) {
749 testReclaimResourceSecure();
750 testReclaimResourceNonSecure();
751}
752
753TEST_F(ResourceManagerServiceTest, getAllClients_l) {
754 testGetAllClients();
755}
756
757TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) {
758 testGetLowestPriorityBiggestClient();
759}
760
761TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) {
762 testGetLowestPriorityPid();
763}
764
765TEST_F(ResourceManagerServiceTest, getBiggestClient_l) {
766 testGetBiggestClient();
767}
768
769TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) {
770 testIsCallingPriorityHigher();
771}
772
Chong Zhangdd726802019-08-21 17:24:13 -0700773TEST_F(ResourceManagerServiceTest, testBatteryStats) {
774 testBatteryStats();
775}
776
777TEST_F(ResourceManagerServiceTest, testCpusetBoost) {
778 testCpusetBoost();
779}
780
Ronghua Wu231c3d12015-03-11 15:10:32 -0700781} // namespace android