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