blob: bccc7fa0199ec9ea91df2a50a05b01b6785f168b [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
32struct TestProcessInfo : public ProcessInfoInterface {
33 TestProcessInfo() {}
34 virtual ~TestProcessInfo() {}
35
36 virtual bool getPriority(int pid, int *priority) {
37 // For testing, use pid as priority.
38 // Lower the value higher the priority.
39 *priority = pid;
40 return true;
41 }
42
43private:
44 DISALLOW_EVIL_CONSTRUCTORS(TestProcessInfo);
45};
46
47struct TestClient : public BnResourceManagerClient {
48 TestClient(sp<ResourceManagerService> service)
49 : mReclaimed(false), mService(service) {}
50
51 virtual bool reclaimResource() {
52 sp<IResourceManagerClient> client(this);
53 mService->removeResource((int64_t) client.get());
54 mReclaimed = true;
55 return true;
56 }
57
Ronghua Wu8f9dd872015-04-23 15:24:25 -070058 virtual String8 getName() {
59 return String8("test_client");
60 }
61
Ronghua Wu231c3d12015-03-11 15:10:32 -070062 bool reclaimed() const {
63 return mReclaimed;
64 }
65
66 void reset() {
67 mReclaimed = false;
68 }
69
70protected:
71 virtual ~TestClient() {}
72
73private:
74 bool mReclaimed;
75 sp<ResourceManagerService> mService;
76 DISALLOW_EVIL_CONSTRUCTORS(TestClient);
77};
78
79static const int kTestPid1 = 30;
80static const int kTestPid2 = 20;
81
82class ResourceManagerServiceTest : public ::testing::Test {
83public:
84 ResourceManagerServiceTest()
85 : mService(new ResourceManagerService(new TestProcessInfo)),
86 mTestClient1(new TestClient(mService)),
87 mTestClient2(new TestClient(mService)),
88 mTestClient3(new TestClient(mService)) {
89 }
90
91protected:
92 static bool isEqualResources(const Vector<MediaResource> &resources1,
93 const Vector<MediaResource> &resources2) {
94 if (resources1.size() != resources2.size()) {
95 return false;
96 }
97 for (size_t i = 0; i < resources1.size(); ++i) {
98 if (resources1[i] != resources2[i]) {
99 return false;
100 }
101 }
102 return true;
103 }
104
105 static void expectEqResourceInfo(const ResourceInfo &info, sp<IResourceManagerClient> client,
106 const Vector<MediaResource> &resources) {
107 EXPECT_EQ(client, info.client);
108 EXPECT_TRUE(isEqualResources(resources, info.resources));
109 }
110
111 void verifyClients(bool c1, bool c2, bool c3) {
112 TestClient *client1 = static_cast<TestClient*>(mTestClient1.get());
113 TestClient *client2 = static_cast<TestClient*>(mTestClient2.get());
114 TestClient *client3 = static_cast<TestClient*>(mTestClient3.get());
115
116 EXPECT_EQ(c1, client1->reclaimed());
117 EXPECT_EQ(c2, client2->reclaimed());
118 EXPECT_EQ(c3, client3->reclaimed());
119
120 client1->reset();
121 client2->reset();
122 client3->reset();
123 }
124
Ronghua Wu67e7f542015-03-13 10:47:08 -0700125 // test set up
126 // ---------------------------------------------------------------------------------
127 // pid priority client type number
128 // ---------------------------------------------------------------------------------
129 // kTestPid1(30) 30 mTestClient1 secure codec 1
130 // graphic memory 200
131 // graphic memory 200
132 // ---------------------------------------------------------------------------------
133 // kTestPid2(20) 20 mTestClient2 non-secure codec 1
134 // graphic memory 300
135 // -------------------------------------------
136 // mTestClient3 secure codec 1
137 // graphic memory 100
138 // ---------------------------------------------------------------------------------
Ronghua Wu231c3d12015-03-11 15:10:32 -0700139 void addResource() {
140 // kTestPid1 mTestClient1
141 Vector<MediaResource> resources1;
142 resources1.push_back(MediaResource(String8(kResourceSecureCodec), 1));
143 mService->addResource(kTestPid1, (int64_t) mTestClient1.get(), mTestClient1, resources1);
144 resources1.push_back(MediaResource(String8(kResourceGraphicMemory), 200));
145 Vector<MediaResource> resources11;
146 resources11.push_back(MediaResource(String8(kResourceGraphicMemory), 200));
147 mService->addResource(kTestPid1, (int64_t) mTestClient1.get(), mTestClient1, resources11);
148
149 // kTestPid2 mTestClient2
150 Vector<MediaResource> resources2;
151 resources2.push_back(MediaResource(String8(kResourceNonSecureCodec), 1));
152 resources2.push_back(MediaResource(String8(kResourceGraphicMemory), 300));
153 mService->addResource(kTestPid2, (int64_t) mTestClient2.get(), mTestClient2, resources2);
154
155 // kTestPid2 mTestClient3
156 Vector<MediaResource> resources3;
157 mService->addResource(kTestPid2, (int64_t) mTestClient3.get(), mTestClient3, resources3);
158 resources3.push_back(MediaResource(String8(kResourceSecureCodec), 1));
159 resources3.push_back(MediaResource(String8(kResourceGraphicMemory), 100));
160 mService->addResource(kTestPid2, (int64_t) mTestClient3.get(), mTestClient3, resources3);
161
162 const PidResourceInfosMap &map = mService->mMap;
163 EXPECT_EQ(2u, map.size());
164 ssize_t index1 = map.indexOfKey(kTestPid1);
165 ASSERT_GE(index1, 0);
166 const ResourceInfos &infos1 = map[index1];
167 EXPECT_EQ(1u, infos1.size());
168 expectEqResourceInfo(infos1[0], mTestClient1, resources1);
169
170 ssize_t index2 = map.indexOfKey(kTestPid2);
171 ASSERT_GE(index2, 0);
172 const ResourceInfos &infos2 = map[index2];
173 EXPECT_EQ(2u, infos2.size());
174 expectEqResourceInfo(infos2[0], mTestClient2, resources2);
175 expectEqResourceInfo(infos2[1], mTestClient3, resources3);
176 }
177
178 void testConfig() {
179 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
180 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
181
182 Vector<MediaResourcePolicy> policies1;
183 policies1.push_back(MediaResourcePolicy(String8(kPolicySupportsMultipleSecureCodecs), 1));
184 policies1.push_back(
185 MediaResourcePolicy(String8(kPolicySupportsSecureWithNonSecureCodec), 0));
186 mService->config(policies1);
187 EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
188 EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
189
190 Vector<MediaResourcePolicy> policies2;
191 policies2.push_back(MediaResourcePolicy(String8(kPolicySupportsMultipleSecureCodecs), 0));
192 policies2.push_back(
193 MediaResourcePolicy(String8(kPolicySupportsSecureWithNonSecureCodec), 1));
194 mService->config(policies2);
195 EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
196 EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
197 }
198
199 void testRemoveResource() {
200 addResource();
201
202 mService->removeResource((int64_t) mTestClient2.get());
203
204 const PidResourceInfosMap &map = mService->mMap;
205 EXPECT_EQ(2u, map.size());
206 const ResourceInfos &infos1 = map.valueFor(kTestPid1);
207 const ResourceInfos &infos2 = map.valueFor(kTestPid2);
208 EXPECT_EQ(1u, infos1.size());
209 EXPECT_EQ(1u, infos2.size());
210 // mTestClient2 has been removed.
211 EXPECT_EQ(mTestClient3, infos2[0].client);
212 }
213
214 void testGetAllClients() {
215 addResource();
216
217 String8 type = String8(kResourceSecureCodec);
218 String8 unknowType = String8("unknowType");
219 Vector<sp<IResourceManagerClient> > clients;
220 int lowPriorityPid = 100;
221 EXPECT_FALSE(mService->getAllClients_l(lowPriorityPid, type, &clients));
222 int midPriorityPid = 25;
Ronghua Wu67e7f542015-03-13 10:47:08 -0700223 // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
224 // will fail.
225 EXPECT_FALSE(mService->getAllClients_l(midPriorityPid, type, &clients));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700226 int highPriorityPid = 10;
Ronghua Wu67e7f542015-03-13 10:47:08 -0700227 EXPECT_TRUE(mService->getAllClients_l(highPriorityPid, unknowType, &clients));
228 EXPECT_TRUE(mService->getAllClients_l(highPriorityPid, type, &clients));
Ronghua Wu231c3d12015-03-11 15:10:32 -0700229
230 EXPECT_EQ(2u, clients.size());
231 EXPECT_EQ(mTestClient3, clients[0]);
232 EXPECT_EQ(mTestClient1, clients[1]);
233 }
234
235 void testReclaimResourceSecure() {
236 Vector<MediaResource> resources;
237 resources.push_back(MediaResource(String8(kResourceSecureCodec), 1));
238 resources.push_back(MediaResource(String8(kResourceGraphicMemory), 150));
239
240 // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
241 {
242 addResource();
243 mService->mSupportsMultipleSecureCodecs = false;
244 mService->mSupportsSecureWithNonSecureCodec = true;
245
246 // priority too low
247 EXPECT_FALSE(mService->reclaimResource(40, resources));
248 EXPECT_FALSE(mService->reclaimResource(25, resources));
249
250 // reclaim all secure codecs
251 EXPECT_TRUE(mService->reclaimResource(10, resources));
252 verifyClients(true, false, true);
253
254 // call again should reclaim one largest graphic memory from lowest process
255 EXPECT_TRUE(mService->reclaimResource(10, resources));
256 verifyClients(false, true, false);
257
258 // nothing left
259 EXPECT_FALSE(mService->reclaimResource(10, resources));
260 }
261
262 // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
263 {
264 addResource();
265 mService->mSupportsMultipleSecureCodecs = false;
266 mService->mSupportsSecureWithNonSecureCodec = false;
267
268 // priority too low
269 EXPECT_FALSE(mService->reclaimResource(40, resources));
270 EXPECT_FALSE(mService->reclaimResource(25, resources));
271
272 // reclaim all secure and non-secure codecs
273 EXPECT_TRUE(mService->reclaimResource(10, resources));
274 verifyClients(true, true, true);
275
276 // nothing left
277 EXPECT_FALSE(mService->reclaimResource(10, resources));
278 }
279
280
281 // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ###
282 {
283 addResource();
284 mService->mSupportsMultipleSecureCodecs = true;
285 mService->mSupportsSecureWithNonSecureCodec = false;
286
287 // priority too low
288 EXPECT_FALSE(mService->reclaimResource(40, resources));
289 EXPECT_FALSE(mService->reclaimResource(25, resources));
290
291 // reclaim all non-secure codecs
292 EXPECT_TRUE(mService->reclaimResource(10, resources));
293 verifyClients(false, true, false);
294
295 // call again should reclaim one largest graphic memory from lowest process
296 EXPECT_TRUE(mService->reclaimResource(10, resources));
297 verifyClients(true, false, false);
298
299 // call again should reclaim another largest graphic memory from lowest process
300 EXPECT_TRUE(mService->reclaimResource(10, resources));
301 verifyClients(false, false, true);
302
303 // nothing left
304 EXPECT_FALSE(mService->reclaimResource(10, resources));
305 }
306
307 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
308 {
309 addResource();
310 mService->mSupportsMultipleSecureCodecs = true;
311 mService->mSupportsSecureWithNonSecureCodec = true;
312
313 // priority too low
314 EXPECT_FALSE(mService->reclaimResource(40, resources));
315
316 EXPECT_TRUE(mService->reclaimResource(10, resources));
317 // one largest graphic memory from lowest process got reclaimed
318 verifyClients(true, false, false);
319
320 // call again should reclaim another graphic memory from lowest process
321 EXPECT_TRUE(mService->reclaimResource(10, resources));
322 verifyClients(false, true, false);
323
324 // call again should reclaim another graphic memory from lowest process
325 EXPECT_TRUE(mService->reclaimResource(10, resources));
326 verifyClients(false, false, true);
327
328 // nothing left
329 EXPECT_FALSE(mService->reclaimResource(10, resources));
330 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700331
332 // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
333 {
334 addResource();
335 mService->mSupportsMultipleSecureCodecs = true;
336 mService->mSupportsSecureWithNonSecureCodec = true;
337
338 Vector<MediaResource> resources;
339 resources.push_back(MediaResource(String8(kResourceSecureCodec), 1));
340
341 EXPECT_TRUE(mService->reclaimResource(10, resources));
342 // secure codec from lowest process got reclaimed
343 verifyClients(true, false, false);
344
345 // call again should reclaim another secure codec from lowest process
346 EXPECT_TRUE(mService->reclaimResource(10, resources));
347 verifyClients(false, false, true);
348
349 // nothing left
350 EXPECT_FALSE(mService->reclaimResource(10, resources));
351
352 // clean up client 2 which still has non secure codec left
353 mService->removeResource((int64_t) mTestClient2.get());
354 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700355 }
356
357 void testReclaimResourceNonSecure() {
358 Vector<MediaResource> resources;
359 resources.push_back(MediaResource(String8(kResourceNonSecureCodec), 1));
360 resources.push_back(MediaResource(String8(kResourceGraphicMemory), 150));
361
362 // ### secure codec can't coexist with non-secure codec ###
363 {
364 addResource();
365 mService->mSupportsSecureWithNonSecureCodec = false;
366
367 // priority too low
368 EXPECT_FALSE(mService->reclaimResource(40, resources));
369 EXPECT_FALSE(mService->reclaimResource(25, resources));
370
371 // reclaim all secure codecs
372 EXPECT_TRUE(mService->reclaimResource(10, resources));
373 verifyClients(true, false, true);
374
375 // call again should reclaim one graphic memory from lowest process
376 EXPECT_TRUE(mService->reclaimResource(10, resources));
377 verifyClients(false, true, false);
378
379 // nothing left
380 EXPECT_FALSE(mService->reclaimResource(10, resources));
381 }
382
383
384 // ### secure codec can coexist with non-secure codec ###
385 {
386 addResource();
387 mService->mSupportsSecureWithNonSecureCodec = true;
388
389 // priority too low
390 EXPECT_FALSE(mService->reclaimResource(40, resources));
391
392 EXPECT_TRUE(mService->reclaimResource(10, resources));
393 // one largest graphic memory from lowest process got reclaimed
394 verifyClients(true, false, false);
395
396 // call again should reclaim another graphic memory from lowest process
397 EXPECT_TRUE(mService->reclaimResource(10, resources));
398 verifyClients(false, true, false);
399
400 // call again should reclaim another graphic memory from lowest process
401 EXPECT_TRUE(mService->reclaimResource(10, resources));
402 verifyClients(false, false, true);
403
404 // nothing left
405 EXPECT_FALSE(mService->reclaimResource(10, resources));
406 }
Ronghua Wu67e7f542015-03-13 10:47:08 -0700407
408 // ### secure codec can coexist with non-secure codec ###
409 {
410 addResource();
411 mService->mSupportsSecureWithNonSecureCodec = true;
412
413 Vector<MediaResource> resources;
414 resources.push_back(MediaResource(String8(kResourceNonSecureCodec), 1));
415
416 EXPECT_TRUE(mService->reclaimResource(10, resources));
417 // one non secure codec from lowest process got reclaimed
418 verifyClients(false, true, false);
419
420 // nothing left
421 EXPECT_FALSE(mService->reclaimResource(10, resources));
422
423 // clean up client 1 and 3 which still have secure codec left
424 mService->removeResource((int64_t) mTestClient1.get());
425 mService->removeResource((int64_t) mTestClient3.get());
426 }
Ronghua Wu231c3d12015-03-11 15:10:32 -0700427 }
428
429 void testGetLowestPriorityBiggestClient() {
430 String8 type = String8(kResourceGraphicMemory);
431 sp<IResourceManagerClient> client;
432 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(10, type, &client));
433
434 addResource();
435
436 EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(100, type, &client));
437 EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(10, type, &client));
438
439 // kTestPid1 is the lowest priority process with kResourceGraphicMemory.
440 // mTestClient1 has the largest kResourceGraphicMemory within kTestPid1.
441 EXPECT_EQ(mTestClient1, client);
442 }
443
444 void testGetLowestPriorityPid() {
445 int pid;
446 int priority;
447 TestProcessInfo processInfo;
448
449 String8 type = String8(kResourceGraphicMemory);
450 EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority));
451
452 addResource();
453
454 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
455 EXPECT_EQ(kTestPid1, pid);
456 int priority1;
457 processInfo.getPriority(kTestPid1, &priority1);
458 EXPECT_EQ(priority1, priority);
459
460 type = String8(kResourceNonSecureCodec);
461 EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
462 EXPECT_EQ(kTestPid2, pid);
463 int priority2;
464 processInfo.getPriority(kTestPid2, &priority2);
465 EXPECT_EQ(priority2, priority);
466 }
467
468 void testGetBiggestClient() {
469 String8 type = String8(kResourceGraphicMemory);
470 sp<IResourceManagerClient> client;
471 EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client));
472
473 addResource();
474
475 EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client));
476 EXPECT_EQ(mTestClient2, client);
477 }
478
479 void testIsCallingPriorityHigher() {
480 EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100));
481 EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100));
482 EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100));
483 }
484
485 sp<ResourceManagerService> mService;
486 sp<IResourceManagerClient> mTestClient1;
487 sp<IResourceManagerClient> mTestClient2;
488 sp<IResourceManagerClient> mTestClient3;
489};
490
491TEST_F(ResourceManagerServiceTest, config) {
492 testConfig();
493}
494
495TEST_F(ResourceManagerServiceTest, addResource) {
496 addResource();
497}
498
499TEST_F(ResourceManagerServiceTest, removeResource) {
500 testRemoveResource();
501}
502
503TEST_F(ResourceManagerServiceTest, reclaimResource) {
504 testReclaimResourceSecure();
505 testReclaimResourceNonSecure();
506}
507
508TEST_F(ResourceManagerServiceTest, getAllClients_l) {
509 testGetAllClients();
510}
511
512TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) {
513 testGetLowestPriorityBiggestClient();
514}
515
516TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) {
517 testGetLowestPriorityPid();
518}
519
520TEST_F(ResourceManagerServiceTest, getBiggestClient_l) {
521 testGetBiggestClient();
522}
523
524TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) {
525 testIsCallingPriorityHigher();
526}
527
528} // namespace android