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