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