• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 "DrmSessionManager_test"
19 #include <android/binder_auto_utils.h>
20 #include <utils/Log.h>
21 
22 #include <gtest/gtest.h>
23 
24 #include <aidl/android/media/BnResourceManagerClient.h>
25 #include <aidl/android/media/BnResourceManagerService.h>
26 
27 #include <media/stagefright/foundation/ADebug.h>
28 #include <media/stagefright/ProcessInfoInterface.h>
29 #include <mediadrm/DrmSessionManager.h>
30 
31 #include <algorithm>
32 #include <iostream>
33 #include <vector>
34 
35 #include "ResourceManagerService.h"
36 
37 namespace android {
38 
39 using Status = ::ndk::ScopedAStatus;
40 using ::aidl::android::media::BnResourceManagerClient;
41 using ::aidl::android::media::BnResourceManagerService;
42 using ::aidl::android::media::MediaResourceParcel;
43 using ::aidl::android::media::IResourceManagerClient;
44 
toAndroidVector(const std::vector<uint8_t> & vec)45 static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
46     Vector<uint8_t> aVec;
47     for (auto b : vec) {
48         aVec.push_back(b);
49     }
50     return aVec;
51 }
52 
53 struct FakeProcessInfo : public ProcessInfoInterface {
FakeProcessInfoandroid::FakeProcessInfo54     FakeProcessInfo() {}
~FakeProcessInfoandroid::FakeProcessInfo55     virtual ~FakeProcessInfo() {}
56 
getPriorityandroid::FakeProcessInfo57     virtual bool getPriority(int pid, int* priority) {
58         // For testing, use pid as priority.
59         // Lower the value higher the priority.
60         *priority = pid;
61         return true;
62     }
63 
isValidPidandroid::FakeProcessInfo64     virtual bool isValidPid(int /* pid */) {
65         return true;
66     }
67 
68 private:
69     DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
70 };
71 
72 struct FakeDrm : public BnResourceManagerClient {
FakeDrmandroid::FakeDrm73     FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
74         : mSessionId(toAndroidVector(sessionId)),
75           mReclaimed(false),
76           mDrmSessionManager(manager) {}
77 
reclaimResourceandroid::FakeDrm78     Status reclaimResource(bool* _aidl_return) {
79         mReclaimed = true;
80         mDrmSessionManager->removeSession(mSessionId);
81         *_aidl_return = true;
82         return Status::ok();
83     }
84 
getNameandroid::FakeDrm85     Status getName(::std::string* _aidl_return) {
86         String8 name("FakeDrm[");
87         for (size_t i = 0; i < mSessionId.size(); ++i) {
88             name.appendFormat("%02x", mSessionId[i]);
89         }
90         name.append("]");
91         *_aidl_return = name;
92         return Status::ok();
93     }
94 
isReclaimedandroid::FakeDrm95     bool isReclaimed() const {
96         return mReclaimed;
97     }
98 
99     const Vector<uint8_t> mSessionId;
100 
101 private:
102     bool mReclaimed;
103     const sp<DrmSessionManager> mDrmSessionManager;
104 
105     DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
106 };
107 
108 struct FakeSystemCallback :
109         public ResourceManagerService::SystemCallbackInterface {
FakeSystemCallbackandroid::FakeSystemCallback110     FakeSystemCallback() {}
111 
noteStartVideoandroid::FakeSystemCallback112     virtual void noteStartVideo(int /*uid*/) override {}
113 
noteStopVideoandroid::FakeSystemCallback114     virtual void noteStopVideo(int /*uid*/) override {}
115 
noteResetVideoandroid::FakeSystemCallback116     virtual void noteResetVideo() override {}
117 
requestCpusetBoostandroid::FakeSystemCallback118     virtual bool requestCpusetBoost(bool /*enable*/) override {
119         return true;
120     }
121 
122 protected:
~FakeSystemCallbackandroid::FakeSystemCallback123     virtual ~FakeSystemCallback() {}
124 
125 private:
126 
127     DISALLOW_EVIL_CONSTRUCTORS(FakeSystemCallback);
128 };
129 
130 static const int kTestPid1 = 30;
131 static const int kTestPid2 = 20;
132 static const std::vector<uint8_t> kTestSessionId1{1, 2, 3};
133 static const std::vector<uint8_t> kTestSessionId2{4, 5, 6, 7, 8};
134 static const std::vector<uint8_t> kTestSessionId3{9, 0};
135 
136 class DrmSessionManagerTest : public ::testing::Test {
137 public:
DrmSessionManagerTest()138     DrmSessionManagerTest()
139         : mService(::ndk::SharedRefBase::make<ResourceManagerService>
140             (new FakeProcessInfo(), new FakeSystemCallback())),
141           mDrmSessionManager(new DrmSessionManager(mService)),
142           mTestDrm1(::ndk::SharedRefBase::make<FakeDrm>(
143                   kTestSessionId1, mDrmSessionManager)),
144           mTestDrm2(::ndk::SharedRefBase::make<FakeDrm>(
145                   kTestSessionId2, mDrmSessionManager)),
146           mTestDrm3(::ndk::SharedRefBase::make<FakeDrm>(
147                   kTestSessionId3, mDrmSessionManager)) {
148     }
149 
150 protected:
addSession()151     void addSession() {
152         mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
153         mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
154         mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
155     }
156 
157     std::shared_ptr<ResourceManagerService> mService;
158     sp<DrmSessionManager> mDrmSessionManager;
159     std::shared_ptr<FakeDrm> mTestDrm1;
160     std::shared_ptr<FakeDrm> mTestDrm2;
161     std::shared_ptr<FakeDrm> mTestDrm3;
162 };
163 
TEST_F(DrmSessionManagerTest,addSession)164 TEST_F(DrmSessionManagerTest, addSession) {
165     addSession();
166 
167     EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
168     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
169     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
170     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
171 }
172 
TEST_F(DrmSessionManagerTest,useSession)173 TEST_F(DrmSessionManagerTest, useSession) {
174     addSession();
175 
176     mDrmSessionManager->useSession(mTestDrm1->mSessionId);
177     mDrmSessionManager->useSession(mTestDrm3->mSessionId);
178 
179     EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
180     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
181     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
182     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
183 }
184 
TEST_F(DrmSessionManagerTest,removeSession)185 TEST_F(DrmSessionManagerTest, removeSession) {
186     addSession();
187 
188     mDrmSessionManager->removeSession(mTestDrm2->mSessionId);
189 
190     EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
191     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
192     EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
193     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
194 }
195 
TEST_F(DrmSessionManagerTest,reclaimSession)196 TEST_F(DrmSessionManagerTest, reclaimSession) {
197     EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
198     addSession();
199 
200     // calling pid priority is too low
201     EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
202 
203     EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
204     EXPECT_TRUE(mTestDrm1->isReclaimed());
205 
206     // add a session from a higher priority process.
207     const std::vector<uint8_t> sid{1, 3, 5};
208     std::shared_ptr<FakeDrm> drm =
209             ::ndk::SharedRefBase::make<FakeDrm>(sid, mDrmSessionManager);
210     mDrmSessionManager->addSession(15, drm, drm->mSessionId);
211 
212     // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
213     mDrmSessionManager->useSession(mTestDrm3->mSessionId);
214     EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
215     EXPECT_TRUE(mTestDrm2->isReclaimed());
216 
217     EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
218     EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
219     EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
220     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
221     EXPECT_TRUE(mDrmSessionManager->containsSession(drm->mSessionId));
222 }
223 
TEST_F(DrmSessionManagerTest,reclaimAfterUse)224 TEST_F(DrmSessionManagerTest, reclaimAfterUse) {
225     // nothing to reclaim yet
226     EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
227     EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
228 
229     // add sessions from same pid
230     mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
231     mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
232     mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
233 
234     // use some but not all sessions
235     mDrmSessionManager->useSession(mTestDrm1->mSessionId);
236     mDrmSessionManager->useSession(mTestDrm1->mSessionId);
237     mDrmSessionManager->useSession(mTestDrm2->mSessionId);
238 
239     // calling pid priority is too low
240     int lowPriorityPid = kTestPid2 + 1;
241     EXPECT_FALSE(mDrmSessionManager->reclaimSession(lowPriorityPid));
242 
243     // unused session is reclaimed first
244     int highPriorityPid = kTestPid2 - 1;
245     EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
246     EXPECT_FALSE(mTestDrm1->isReclaimed());
247     EXPECT_FALSE(mTestDrm2->isReclaimed());
248     EXPECT_TRUE(mTestDrm3->isReclaimed());
249     mDrmSessionManager->removeSession(mTestDrm3->mSessionId);
250 
251     // less-used session is reclaimed next
252     EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
253     EXPECT_FALSE(mTestDrm1->isReclaimed());
254     EXPECT_TRUE(mTestDrm2->isReclaimed());
255     EXPECT_TRUE(mTestDrm3->isReclaimed());
256 
257     // most-used session still open
258     EXPECT_EQ(1u, mDrmSessionManager->getSessionCount());
259     EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
260     EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
261     EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
262 }
263 
264 } // namespace android
265