1 /*
2  * Copyright 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "ResourceManagerService_test"
19 
20 #include <utils/Log.h>
21 
22 #include "ResourceManagerServiceTestUtils.h"
23 #include "ResourceManagerService.h"
24 
25 namespace android {
26 
27 class ResourceManagerServiceTest : public ResourceManagerServiceTestBase {
28 public:
ResourceManagerServiceTest()29     ResourceManagerServiceTest() : ResourceManagerServiceTestBase() {}
30 
verifyClients(bool c1,bool c2,bool c3)31     void verifyClients(bool c1, bool c2, bool c3) {
32         TestClient *client1 = static_cast<TestClient*>(mTestClient1.get());
33         TestClient *client2 = static_cast<TestClient*>(mTestClient2.get());
34         TestClient *client3 = static_cast<TestClient*>(mTestClient3.get());
35 
36         EXPECT_EQ(c1, client1->reclaimed());
37         EXPECT_EQ(c2, client2->reclaimed());
38         EXPECT_EQ(c3, client3->reclaimed());
39 
40         client1->reset();
41         client2->reset();
42         client3->reset();
43     }
44 
45     // test set up
46     // ---------------------------------------------------------------------------------
47     //   pid                priority         client           type               number
48     // ---------------------------------------------------------------------------------
49     //   kTestPid1(30)      30               mTestClient1     secure codec       1
50     //                                                        graphic memory     200
51     //                                                        graphic memory     200
52     // ---------------------------------------------------------------------------------
53     //   kTestPid2(20)      20               mTestClient2     non-secure codec   1
54     //                                                        graphic memory     300
55     //                                       -------------------------------------------
56     //                                       mTestClient3     secure codec       1
57     //                                                        graphic memory     100
58     // ---------------------------------------------------------------------------------
addResource()59     void addResource() {
60         // kTestPid1 mTestClient1
61         std::vector<MediaResourceParcel> resources1;
62         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
63         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
64         resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
65         std::vector<MediaResourceParcel> resources11;
66         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
67         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
68 
69         // kTestPid2 mTestClient2
70         std::vector<MediaResourceParcel> resources2;
71         resources2.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
72         resources2.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
73         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
74 
75         // kTestPid2 mTestClient3
76         std::vector<MediaResourceParcel> resources3;
77         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
78         resources3.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
79         resources3.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
80         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient3), mTestClient3, resources3);
81 
82         const PidResourceInfosMap &map = mService->mMap;
83         EXPECT_EQ(2u, map.size());
84         ssize_t index1 = map.indexOfKey(kTestPid1);
85         ASSERT_GE(index1, 0);
86         const ResourceInfos &infos1 = map[index1];
87         EXPECT_EQ(1u, infos1.size());
88         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, resources1);
89 
90         ssize_t index2 = map.indexOfKey(kTestPid2);
91         ASSERT_GE(index2, 0);
92         const ResourceInfos &infos2 = map[index2];
93         EXPECT_EQ(2u, infos2.size());
94         expectEqResourceInfo(infos2.valueFor(getId(mTestClient2)), kTestUid2, mTestClient2, resources2);
95         expectEqResourceInfo(infos2.valueFor(getId(mTestClient3)), kTestUid2, mTestClient3, resources3);
96     }
97 
testCombineResourceWithNegativeValues()98     void testCombineResourceWithNegativeValues() {
99         // kTestPid1 mTestClient1
100         std::vector<MediaResourceParcel> resources1;
101         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -100));
102         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -100));
103         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
104 
105         // Expected result:
106         // 1) the client should have been added;
107         // 2) both resource entries should have been rejected, resource list should be empty.
108         const PidResourceInfosMap &map = mService->mMap;
109         EXPECT_EQ(1u, map.size());
110         ssize_t index1 = map.indexOfKey(kTestPid1);
111         ASSERT_GE(index1, 0);
112         const ResourceInfos &infos1 = map[index1];
113         EXPECT_EQ(1u, infos1.size());
114         std::vector<MediaResourceParcel> expected;
115         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
116 
117         resources1.clear();
118         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
119         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
120         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
121         resources1.clear();
122         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, 10));
123         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 10));
124         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
125 
126         // Expected result:
127         // Both values should saturate to INT64_MAX
128         expected.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX));
129         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
130         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
131 
132         resources1.clear();
133         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, -10));
134         resources1.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, -10));
135         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
136 
137         // Expected result:
138         // 1) DrmSession resource should allow negative value addition, and value should drop accordingly
139         // 2) Non-drm session resource should ignore negative value addition.
140         expected.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MAX - 10));
141         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
142         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
143 
144         resources1.clear();
145         resources1.push_back(MediaResource(MediaResource::Type::kDrmSession, INT64_MIN));
146         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MIN));
147         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
148 
149         // Expected result:
150         // 1) DrmSession resource value should drop to 0, but the entry shouldn't be removed.
151         // 2) Non-drm session resource should ignore negative value addition.
152         expected.clear();
153         expected.push_back(MediaResource(MediaResource::Type::kDrmSession, 0));
154         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, INT64_MAX));
155         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
156     }
157 
testConfig()158     void testConfig() {
159         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
160         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
161 
162         std::vector<MediaResourcePolicyParcel> policies1;
163         policies1.push_back(
164                 MediaResourcePolicy(
165                         IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
166                         "true"));
167         policies1.push_back(
168                 MediaResourcePolicy(
169                         IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
170                         "false"));
171         mService->config(policies1);
172         EXPECT_TRUE(mService->mSupportsMultipleSecureCodecs);
173         EXPECT_FALSE(mService->mSupportsSecureWithNonSecureCodec);
174 
175         std::vector<MediaResourcePolicyParcel> policies2;
176         policies2.push_back(
177                 MediaResourcePolicy(
178                         IResourceManagerService::kPolicySupportsMultipleSecureCodecs,
179                         "false"));
180         policies2.push_back(
181                 MediaResourcePolicy(
182                         IResourceManagerService::kPolicySupportsSecureWithNonSecureCodec,
183                         "true"));
184         mService->config(policies2);
185         EXPECT_FALSE(mService->mSupportsMultipleSecureCodecs);
186         EXPECT_TRUE(mService->mSupportsSecureWithNonSecureCodec);
187     }
188 
testCombineResource()189     void testCombineResource() {
190         // kTestPid1 mTestClient1
191         std::vector<MediaResourceParcel> resources1;
192         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
193         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
194 
195         std::vector<MediaResourceParcel> resources11;
196         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
197         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
198 
199         const PidResourceInfosMap &map = mService->mMap;
200         EXPECT_EQ(1u, map.size());
201         ssize_t index1 = map.indexOfKey(kTestPid1);
202         ASSERT_GE(index1, 0);
203         const ResourceInfos &infos1 = map[index1];
204         EXPECT_EQ(1u, infos1.size());
205 
206         // test adding existing types to combine values
207         resources1.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
208         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
209 
210         std::vector<MediaResourceParcel> expected;
211         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
212         expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 300));
213         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
214 
215         // test adding new types (including types that differs only in subType)
216         resources11.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
217         resources11.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
218         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
219 
220         expected.clear();
221         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 2));
222         expected.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
223         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, MediaResource::SubType::kVideoCodec, 1));
224         expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 500));
225         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
226     }
227 
testRemoveResource()228     void testRemoveResource() {
229         // kTestPid1 mTestClient1
230         std::vector<MediaResourceParcel> resources1;
231         resources1.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
232         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
233 
234         std::vector<MediaResourceParcel> resources11;
235         resources11.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 200));
236         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources11);
237 
238         const PidResourceInfosMap &map = mService->mMap;
239         EXPECT_EQ(1u, map.size());
240         ssize_t index1 = map.indexOfKey(kTestPid1);
241         ASSERT_GE(index1, 0);
242         const ResourceInfos &infos1 = map[index1];
243         EXPECT_EQ(1u, infos1.size());
244 
245         // test partial removal
246         resources11[0].value = 100;
247         mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
248 
249         std::vector<MediaResourceParcel> expected;
250         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
251         expected.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 100));
252         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
253 
254         // test removal request with negative value, should be ignored
255         resources11[0].value = -10000;
256         mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
257 
258         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
259 
260         // test complete removal with overshoot value
261         resources11[0].value = 1000;
262         mService->removeResource(kTestPid1, getId(mTestClient1), resources11);
263 
264         expected.clear();
265         expected.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
266         expectEqResourceInfo(infos1.valueFor(getId(mTestClient1)), kTestUid1, mTestClient1, expected);
267     }
268 
testOverridePid()269     void testOverridePid() {
270 
271         bool result;
272         std::vector<MediaResourceParcel> resources;
273         resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
274         resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
275 
276         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
277         {
278             addResource();
279             mService->mSupportsMultipleSecureCodecs = false;
280             mService->mSupportsSecureWithNonSecureCodec = true;
281 
282             // priority too low to reclaim resource
283             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
284 
285             // override Low Priority Pid with High Priority Pid
286             mService->overridePid(kLowPriorityPid, kHighPriorityPid);
287             CHECK_STATUS_TRUE(mService->reclaimResource(kLowPriorityPid, resources, &result));
288 
289             // restore Low Priority Pid
290             mService->overridePid(kLowPriorityPid, -1);
291             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
292         }
293     }
294 
testMarkClientForPendingRemoval()295     void testMarkClientForPendingRemoval() {
296         bool result;
297 
298         {
299             addResource();
300             mService->mSupportsSecureWithNonSecureCodec = true;
301 
302             std::vector<MediaResourceParcel> resources;
303             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
304 
305             // Remove low priority clients
306             mService->removeClient(kTestPid1, getId(mTestClient1));
307 
308             // no lower priority client
309             CHECK_STATUS_FALSE(mService->reclaimResource(kTestPid2, resources, &result));
310             verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
311 
312             mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
313 
314             // client marked for pending removal from the same process got reclaimed
315             CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
316             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
317 
318             // clean up client 3 which still left
319             mService->removeClient(kTestPid2, getId(mTestClient3));
320         }
321 
322         {
323             addResource();
324             mService->mSupportsSecureWithNonSecureCodec = true;
325 
326             std::vector<MediaResourceParcel> resources;
327             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
328 
329             mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
330 
331             // client marked for pending removal from the same process got reclaimed
332             // first, even though there are lower priority process
333             CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
334             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
335 
336             // lower priority client got reclaimed
337             CHECK_STATUS_TRUE(mService->reclaimResource(kTestPid2, resources, &result));
338             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
339 
340             // clean up client 3 which still left
341             mService->removeClient(kTestPid2, getId(mTestClient3));
342         }
343 
344         {
345             addResource();
346             mService->mSupportsSecureWithNonSecureCodec = true;
347 
348             mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient2));
349 
350             // client marked for pending removal got reclaimed
351             EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
352             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
353 
354             // No more clients marked for removal
355             EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
356             verifyClients(false /* c1 */, false /* c2 */, false /* c3 */);
357 
358             mService->markClientForPendingRemoval(kTestPid2, getId(mTestClient3));
359 
360             // client marked for pending removal got reclaimed
361             EXPECT_TRUE(mService->reclaimResourcesFromClientsPendingRemoval(kTestPid2).isOk());
362             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
363 
364             // clean up client 1 which still left
365             mService->removeClient(kTestPid1, getId(mTestClient1));
366         }
367     }
368 
testRemoveClient()369     void testRemoveClient() {
370         addResource();
371 
372         mService->removeClient(kTestPid2, getId(mTestClient2));
373 
374         const PidResourceInfosMap &map = mService->mMap;
375         EXPECT_EQ(2u, map.size());
376         const ResourceInfos &infos1 = map.valueFor(kTestPid1);
377         const ResourceInfos &infos2 = map.valueFor(kTestPid2);
378         EXPECT_EQ(1u, infos1.size());
379         EXPECT_EQ(1u, infos2.size());
380         // mTestClient2 has been removed.
381         // (OK to use infos2[0] as there is only 1 entry)
382         EXPECT_EQ(mTestClient3, infos2[0].client);
383     }
384 
testGetAllClients()385     void testGetAllClients() {
386         addResource();
387 
388         MediaResource::Type type = MediaResource::Type::kSecureCodec;
389         Vector<std::shared_ptr<IResourceManagerClient> > clients;
390         EXPECT_FALSE(mService->getAllClients_l(kLowPriorityPid, type, &clients));
391         // some higher priority process (e.g. kTestPid2) owns the resource, so getAllClients_l
392         // will fail.
393         EXPECT_FALSE(mService->getAllClients_l(kMidPriorityPid, type, &clients));
394         EXPECT_TRUE(mService->getAllClients_l(kHighPriorityPid, type, &clients));
395 
396         EXPECT_EQ(2u, clients.size());
397         // (OK to require ordering in clients[], as the pid map is sorted)
398         EXPECT_EQ(mTestClient3, clients[0]);
399         EXPECT_EQ(mTestClient1, clients[1]);
400     }
401 
testReclaimResourceSecure()402     void testReclaimResourceSecure() {
403         bool result;
404         std::vector<MediaResourceParcel> resources;
405         resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
406         resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
407 
408         // ### secure codec can't coexist and secure codec can coexist with non-secure codec ###
409         {
410             addResource();
411             mService->mSupportsMultipleSecureCodecs = false;
412             mService->mSupportsSecureWithNonSecureCodec = true;
413 
414             // priority too low
415             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
416             CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
417 
418             // reclaim all secure codecs
419             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
420             verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
421 
422             // call again should reclaim one largest graphic memory from lowest process
423             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
424             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
425 
426             // nothing left
427             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
428         }
429 
430         // ### secure codecs can't coexist and secure codec can't coexist with non-secure codec ###
431         {
432             addResource();
433             mService->mSupportsMultipleSecureCodecs = false;
434             mService->mSupportsSecureWithNonSecureCodec = false;
435 
436             // priority too low
437             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
438             CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
439 
440             // reclaim all secure and non-secure codecs
441             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
442             verifyClients(true /* c1 */, true /* c2 */, true /* c3 */);
443 
444             // nothing left
445             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
446         }
447 
448 
449         // ### secure codecs can coexist but secure codec can't coexist with non-secure codec ###
450         {
451             addResource();
452             mService->mSupportsMultipleSecureCodecs = true;
453             mService->mSupportsSecureWithNonSecureCodec = false;
454 
455             // priority too low
456             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
457             CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
458 
459             // reclaim all non-secure codecs
460             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
461             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
462 
463             // call again should reclaim one largest graphic memory from lowest process
464             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
465             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
466 
467             // call again should reclaim another largest graphic memory from lowest process
468             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
469             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
470 
471             // nothing left
472             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
473         }
474 
475         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
476         {
477             addResource();
478             mService->mSupportsMultipleSecureCodecs = true;
479             mService->mSupportsSecureWithNonSecureCodec = true;
480 
481             // priority too low
482             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
483 
484             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
485             // one largest graphic memory from lowest process got reclaimed
486             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
487 
488             // call again should reclaim another graphic memory from lowest process
489             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
490             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
491 
492             // call again should reclaim another graphic memory from lowest process
493             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
494             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
495 
496             // nothing left
497             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
498         }
499 
500         // ### secure codecs can coexist and secure codec can coexist with non-secure codec ###
501         {
502             addResource();
503             mService->mSupportsMultipleSecureCodecs = true;
504             mService->mSupportsSecureWithNonSecureCodec = true;
505 
506             std::vector<MediaResourceParcel> resources;
507             resources.push_back(MediaResource(MediaResource::Type::kSecureCodec, 1));
508 
509             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
510             // secure codec from lowest process got reclaimed
511             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
512 
513             // call again should reclaim another secure codec from lowest process
514             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
515             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
516 
517             // no more secure codec, non-secure codec will be reclaimed.
518             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
519             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
520         }
521     }
522 
testReclaimResourceNonSecure()523     void testReclaimResourceNonSecure() {
524         bool result;
525         std::vector<MediaResourceParcel> resources;
526         resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
527         resources.push_back(MediaResource(MediaResource::Type::kGraphicMemory, 150));
528 
529         // ### secure codec can't coexist with non-secure codec ###
530         {
531             addResource();
532             mService->mSupportsSecureWithNonSecureCodec = false;
533 
534             // priority too low
535             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
536             CHECK_STATUS_FALSE(mService->reclaimResource(kMidPriorityPid, resources, &result));
537 
538             // reclaim all secure codecs
539             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
540             verifyClients(true /* c1 */, false /* c2 */, true /* c3 */);
541 
542             // call again should reclaim one graphic memory from lowest process
543             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
544             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
545 
546             // nothing left
547             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
548         }
549 
550 
551         // ### secure codec can coexist with non-secure codec ###
552         {
553             addResource();
554             mService->mSupportsSecureWithNonSecureCodec = true;
555 
556             // priority too low
557             CHECK_STATUS_FALSE(mService->reclaimResource(kLowPriorityPid, resources, &result));
558 
559             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
560             // one largest graphic memory from lowest process got reclaimed
561             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
562 
563             // call again should reclaim another graphic memory from lowest process
564             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
565             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
566 
567             // call again should reclaim another graphic memory from lowest process
568             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
569             verifyClients(false /* c1 */, false /* c2 */, true /* c3 */);
570 
571             // nothing left
572             CHECK_STATUS_FALSE(mService->reclaimResource(kHighPriorityPid, resources, &result));
573         }
574 
575         // ### secure codec can coexist with non-secure codec ###
576         {
577             addResource();
578             mService->mSupportsSecureWithNonSecureCodec = true;
579 
580             std::vector<MediaResourceParcel> resources;
581             resources.push_back(MediaResource(MediaResource::Type::kNonSecureCodec, 1));
582 
583             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
584             // one non secure codec from lowest process got reclaimed
585             verifyClients(false /* c1 */, true /* c2 */, false /* c3 */);
586 
587             // no more non-secure codec, secure codec from lowest priority process will be reclaimed
588             CHECK_STATUS_TRUE(mService->reclaimResource(kHighPriorityPid, resources, &result));
589             verifyClients(true /* c1 */, false /* c2 */, false /* c3 */);
590 
591             // clean up client 3 which still left
592             mService->removeClient(kTestPid2, getId(mTestClient3));
593         }
594     }
595 
testGetLowestPriorityBiggestClient()596     void testGetLowestPriorityBiggestClient() {
597         MediaResource::Type type = MediaResource::Type::kGraphicMemory;
598         std::shared_ptr<IResourceManagerClient> client;
599         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
600 
601         addResource();
602 
603         EXPECT_FALSE(mService->getLowestPriorityBiggestClient_l(kLowPriorityPid, type, &client));
604         EXPECT_TRUE(mService->getLowestPriorityBiggestClient_l(kHighPriorityPid, type, &client));
605 
606         // kTestPid1 is the lowest priority process with MediaResource::Type::kGraphicMemory.
607         // mTestClient1 has the largest MediaResource::Type::kGraphicMemory within kTestPid1.
608         EXPECT_EQ(mTestClient1, client);
609     }
610 
testGetLowestPriorityPid()611     void testGetLowestPriorityPid() {
612         int pid;
613         int priority;
614         TestProcessInfo processInfo;
615 
616         MediaResource::Type type = MediaResource::Type::kGraphicMemory;
617         EXPECT_FALSE(mService->getLowestPriorityPid_l(type, &pid, &priority));
618 
619         addResource();
620 
621         EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
622         EXPECT_EQ(kTestPid1, pid);
623         int priority1;
624         processInfo.getPriority(kTestPid1, &priority1);
625         EXPECT_EQ(priority1, priority);
626 
627         type = MediaResource::Type::kNonSecureCodec;
628         EXPECT_TRUE(mService->getLowestPriorityPid_l(type, &pid, &priority));
629         EXPECT_EQ(kTestPid2, pid);
630         int priority2;
631         processInfo.getPriority(kTestPid2, &priority2);
632         EXPECT_EQ(priority2, priority);
633     }
634 
testGetBiggestClient()635     void testGetBiggestClient() {
636         MediaResource::Type type = MediaResource::Type::kGraphicMemory;
637         std::shared_ptr<IResourceManagerClient> client;
638         EXPECT_FALSE(mService->getBiggestClient_l(kTestPid2, type, &client));
639 
640         addResource();
641 
642         EXPECT_TRUE(mService->getBiggestClient_l(kTestPid2, type, &client));
643         EXPECT_EQ(mTestClient2, client);
644     }
645 
testIsCallingPriorityHigher()646     void testIsCallingPriorityHigher() {
647         EXPECT_FALSE(mService->isCallingPriorityHigher_l(101, 100));
648         EXPECT_FALSE(mService->isCallingPriorityHigher_l(100, 100));
649         EXPECT_TRUE(mService->isCallingPriorityHigher_l(99, 100));
650     }
651 
testBatteryStats()652     void testBatteryStats() {
653         // reset should always be called when ResourceManagerService is created (restarted)
654         EXPECT_EQ(1u, mSystemCB->eventCount());
655         EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
656 
657         // new client request should cause VIDEO_ON
658         std::vector<MediaResourceParcel> resources1;
659         resources1.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 1));
660         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
661         EXPECT_EQ(2u, mSystemCB->eventCount());
662         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid1}), mSystemCB->lastEvent());
663 
664         // each client should only cause 1 VIDEO_ON
665         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
666         EXPECT_EQ(2u, mSystemCB->eventCount());
667 
668         // new client request should cause VIDEO_ON
669         std::vector<MediaResourceParcel> resources2;
670         resources2.push_back(MediaResource(MediaResource::Type::kBattery, MediaResource::SubType::kVideoCodec, 2));
671         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
672         EXPECT_EQ(3u, mSystemCB->eventCount());
673         EXPECT_EQ(EventEntry({EventType::VIDEO_ON, kTestUid2}), mSystemCB->lastEvent());
674 
675         // partially remove mTestClient1's request, shouldn't be any VIDEO_OFF
676         mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
677         EXPECT_EQ(3u, mSystemCB->eventCount());
678 
679         // remove mTestClient1's request, should be VIDEO_OFF for kTestUid1
680         // (use resource2 to test removing more instances than previously requested)
681         mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
682         EXPECT_EQ(4u, mSystemCB->eventCount());
683         EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid1}), mSystemCB->lastEvent());
684 
685         // remove mTestClient2, should be VIDEO_OFF for kTestUid2
686         mService->removeClient(kTestPid2, getId(mTestClient2));
687         EXPECT_EQ(5u, mSystemCB->eventCount());
688         EXPECT_EQ(EventEntry({EventType::VIDEO_OFF, kTestUid2}), mSystemCB->lastEvent());
689     }
690 
testCpusetBoost()691     void testCpusetBoost() {
692         // reset should always be called when ResourceManagerService is created (restarted)
693         EXPECT_EQ(1u, mSystemCB->eventCount());
694         EXPECT_EQ(EventType::VIDEO_RESET, mSystemCB->lastEventType());
695 
696         // new client request should cause CPUSET_ENABLE
697         std::vector<MediaResourceParcel> resources1;
698         resources1.push_back(MediaResource(MediaResource::Type::kCpuBoost, 1));
699         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
700         EXPECT_EQ(2u, mSystemCB->eventCount());
701         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
702 
703         // each client should only cause 1 CPUSET_ENABLE
704         mService->addResource(kTestPid1, kTestUid1, getId(mTestClient1), mTestClient1, resources1);
705         EXPECT_EQ(2u, mSystemCB->eventCount());
706 
707         // new client request should cause CPUSET_ENABLE
708         std::vector<MediaResourceParcel> resources2;
709         resources2.push_back(MediaResource(MediaResource::Type::kCpuBoost, 2));
710         mService->addResource(kTestPid2, kTestUid2, getId(mTestClient2), mTestClient2, resources2);
711         EXPECT_EQ(3u, mSystemCB->eventCount());
712         EXPECT_EQ(EventType::CPUSET_ENABLE, mSystemCB->lastEventType());
713 
714         // remove mTestClient2 should not cause CPUSET_DISABLE, mTestClient1 still active
715         mService->removeClient(kTestPid2, getId(mTestClient2));
716         EXPECT_EQ(3u, mSystemCB->eventCount());
717 
718         // remove 1 cpuboost from mTestClient1, should not be CPUSET_DISABLE (still 1 left)
719         mService->removeResource(kTestPid1, getId(mTestClient1), resources1);
720         EXPECT_EQ(3u, mSystemCB->eventCount());
721 
722         // remove 2 cpuboost from mTestClient1, should be CPUSET_DISABLE
723         // (use resource2 to test removing more than previously requested)
724         mService->removeResource(kTestPid1, getId(mTestClient1), resources2);
725         EXPECT_EQ(4u, mSystemCB->eventCount());
726         EXPECT_EQ(EventType::CPUSET_DISABLE, mSystemCB->lastEventType());
727     }
728 };
729 
TEST_F(ResourceManagerServiceTest,config)730 TEST_F(ResourceManagerServiceTest, config) {
731     testConfig();
732 }
733 
TEST_F(ResourceManagerServiceTest,addResource)734 TEST_F(ResourceManagerServiceTest, addResource) {
735     addResource();
736 }
737 
TEST_F(ResourceManagerServiceTest,combineResource)738 TEST_F(ResourceManagerServiceTest, combineResource) {
739     testCombineResource();
740 }
741 
TEST_F(ResourceManagerServiceTest,combineResourceNegative)742 TEST_F(ResourceManagerServiceTest, combineResourceNegative) {
743     testCombineResourceWithNegativeValues();
744 }
745 
TEST_F(ResourceManagerServiceTest,removeResource)746 TEST_F(ResourceManagerServiceTest, removeResource) {
747     testRemoveResource();
748 }
749 
TEST_F(ResourceManagerServiceTest,removeClient)750 TEST_F(ResourceManagerServiceTest, removeClient) {
751     testRemoveClient();
752 }
753 
TEST_F(ResourceManagerServiceTest,reclaimResource)754 TEST_F(ResourceManagerServiceTest, reclaimResource) {
755     testReclaimResourceSecure();
756     testReclaimResourceNonSecure();
757 }
758 
TEST_F(ResourceManagerServiceTest,getAllClients_l)759 TEST_F(ResourceManagerServiceTest, getAllClients_l) {
760     testGetAllClients();
761 }
762 
TEST_F(ResourceManagerServiceTest,getLowestPriorityBiggestClient_l)763 TEST_F(ResourceManagerServiceTest, getLowestPriorityBiggestClient_l) {
764     testGetLowestPriorityBiggestClient();
765 }
766 
TEST_F(ResourceManagerServiceTest,getLowestPriorityPid_l)767 TEST_F(ResourceManagerServiceTest, getLowestPriorityPid_l) {
768     testGetLowestPriorityPid();
769 }
770 
TEST_F(ResourceManagerServiceTest,getBiggestClient_l)771 TEST_F(ResourceManagerServiceTest, getBiggestClient_l) {
772     testGetBiggestClient();
773 }
774 
TEST_F(ResourceManagerServiceTest,isCallingPriorityHigher_l)775 TEST_F(ResourceManagerServiceTest, isCallingPriorityHigher_l) {
776     testIsCallingPriorityHigher();
777 }
778 
TEST_F(ResourceManagerServiceTest,testBatteryStats)779 TEST_F(ResourceManagerServiceTest, testBatteryStats) {
780     testBatteryStats();
781 }
782 
TEST_F(ResourceManagerServiceTest,testCpusetBoost)783 TEST_F(ResourceManagerServiceTest, testCpusetBoost) {
784     testCpusetBoost();
785 }
786 
TEST_F(ResourceManagerServiceTest,overridePid)787 TEST_F(ResourceManagerServiceTest, overridePid) {
788     testOverridePid();
789 }
790 
TEST_F(ResourceManagerServiceTest,markClientForPendingRemoval)791 TEST_F(ResourceManagerServiceTest, markClientForPendingRemoval) {
792     testMarkClientForPendingRemoval();
793 }
794 
795 } // namespace android
796