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
overrideProcessInfoandroid::FakeProcessInfo68 virtual bool overrideProcessInfo(
69 int /* pid */, int /* procState */, int /* oomScore */) {
70 return true;
71 }
72
removeProcessInfoOverrideandroid::FakeProcessInfo73 virtual void removeProcessInfoOverride(int /* pid */) {
74 }
75
76 private:
77 DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
78 };
79
80 struct FakeDrm : public BnResourceManagerClient {
FakeDrmandroid::FakeDrm81 FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
82 : mSessionId(toAndroidVector(sessionId)),
83 mReclaimed(false),
84 mDrmSessionManager(manager) {}
85
reclaimResourceandroid::FakeDrm86 Status reclaimResource(bool* _aidl_return) {
87 mReclaimed = true;
88 mDrmSessionManager->removeSession(mSessionId);
89 *_aidl_return = true;
90 return Status::ok();
91 }
92
getNameandroid::FakeDrm93 Status getName(::std::string* _aidl_return) {
94 String8 name("FakeDrm[");
95 for (size_t i = 0; i < mSessionId.size(); ++i) {
96 name.appendFormat("%02x", mSessionId[i]);
97 }
98 name.append("]");
99 *_aidl_return = name;
100 return Status::ok();
101 }
102
isReclaimedandroid::FakeDrm103 bool isReclaimed() const {
104 return mReclaimed;
105 }
106
107 const Vector<uint8_t> mSessionId;
108
109 private:
110 bool mReclaimed;
111 const sp<DrmSessionManager> mDrmSessionManager;
112
113 DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
114 };
115
116 struct FakeSystemCallback :
117 public ResourceManagerService::SystemCallbackInterface {
FakeSystemCallbackandroid::FakeSystemCallback118 FakeSystemCallback() {}
119
noteStartVideoandroid::FakeSystemCallback120 virtual void noteStartVideo(int /*uid*/) override {}
121
noteStopVideoandroid::FakeSystemCallback122 virtual void noteStopVideo(int /*uid*/) override {}
123
noteResetVideoandroid::FakeSystemCallback124 virtual void noteResetVideo() override {}
125
requestCpusetBoostandroid::FakeSystemCallback126 virtual bool requestCpusetBoost(bool /*enable*/) override {
127 return true;
128 }
129
130 protected:
~FakeSystemCallbackandroid::FakeSystemCallback131 virtual ~FakeSystemCallback() {}
132
133 private:
134
135 DISALLOW_EVIL_CONSTRUCTORS(FakeSystemCallback);
136 };
137
138 static const int kTestPid1 = 30;
139 static const int kTestPid2 = 20;
140 static const std::vector<uint8_t> kTestSessionId1{1, 2, 3};
141 static const std::vector<uint8_t> kTestSessionId2{4, 5, 6, 7, 8};
142 static const std::vector<uint8_t> kTestSessionId3{9, 0};
143
144 class DrmSessionManagerTest : public ::testing::Test {
145 public:
DrmSessionManagerTest()146 DrmSessionManagerTest()
147 : mService(::ndk::SharedRefBase::make<ResourceManagerService>
148 (new FakeProcessInfo(), new FakeSystemCallback())),
149 mDrmSessionManager(new DrmSessionManager(mService)),
150 mTestDrm1(::ndk::SharedRefBase::make<FakeDrm>(
151 kTestSessionId1, mDrmSessionManager)),
152 mTestDrm2(::ndk::SharedRefBase::make<FakeDrm>(
153 kTestSessionId2, mDrmSessionManager)),
154 mTestDrm3(::ndk::SharedRefBase::make<FakeDrm>(
155 kTestSessionId3, mDrmSessionManager)) {
156 }
157
158 protected:
addSession()159 void addSession() {
160 mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mTestDrm1->mSessionId);
161 mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
162 mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
163 }
164
165 std::shared_ptr<ResourceManagerService> mService;
166 sp<DrmSessionManager> mDrmSessionManager;
167 std::shared_ptr<FakeDrm> mTestDrm1;
168 std::shared_ptr<FakeDrm> mTestDrm2;
169 std::shared_ptr<FakeDrm> mTestDrm3;
170 };
171
TEST_F(DrmSessionManagerTest,addSession)172 TEST_F(DrmSessionManagerTest, addSession) {
173 addSession();
174
175 EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
176 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
177 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
178 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
179 }
180
TEST_F(DrmSessionManagerTest,useSession)181 TEST_F(DrmSessionManagerTest, useSession) {
182 addSession();
183
184 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
185 mDrmSessionManager->useSession(mTestDrm3->mSessionId);
186
187 EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
188 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
189 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
190 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
191 }
192
TEST_F(DrmSessionManagerTest,removeSession)193 TEST_F(DrmSessionManagerTest, removeSession) {
194 addSession();
195
196 mDrmSessionManager->removeSession(mTestDrm2->mSessionId);
197
198 EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
199 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
200 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
201 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
202 }
203
TEST_F(DrmSessionManagerTest,reclaimSession)204 TEST_F(DrmSessionManagerTest, reclaimSession) {
205 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
206 addSession();
207
208 // calling pid priority is too low
209 EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
210
211 EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
212 EXPECT_TRUE(mTestDrm1->isReclaimed());
213
214 // add a session from a higher priority process.
215 const std::vector<uint8_t> sid{1, 3, 5};
216 std::shared_ptr<FakeDrm> drm =
217 ::ndk::SharedRefBase::make<FakeDrm>(sid, mDrmSessionManager);
218 mDrmSessionManager->addSession(15, drm, drm->mSessionId);
219
220 // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
221 mDrmSessionManager->useSession(mTestDrm3->mSessionId);
222 EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
223 EXPECT_TRUE(mTestDrm2->isReclaimed());
224
225 EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
226 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
227 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
228 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
229 EXPECT_TRUE(mDrmSessionManager->containsSession(drm->mSessionId));
230 }
231
TEST_F(DrmSessionManagerTest,reclaimAfterUse)232 TEST_F(DrmSessionManagerTest, reclaimAfterUse) {
233 // nothing to reclaim yet
234 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
235 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
236
237 // add sessions from same pid
238 mDrmSessionManager->addSession(kTestPid2, mTestDrm1, mTestDrm1->mSessionId);
239 mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mTestDrm2->mSessionId);
240 mDrmSessionManager->addSession(kTestPid2, mTestDrm3, mTestDrm3->mSessionId);
241
242 // use some but not all sessions
243 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
244 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
245 mDrmSessionManager->useSession(mTestDrm2->mSessionId);
246
247 // calling pid priority is too low
248 int lowPriorityPid = kTestPid2 + 1;
249 EXPECT_FALSE(mDrmSessionManager->reclaimSession(lowPriorityPid));
250
251 // unused session is reclaimed first
252 int highPriorityPid = kTestPid2 - 1;
253 EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
254 EXPECT_FALSE(mTestDrm1->isReclaimed());
255 EXPECT_FALSE(mTestDrm2->isReclaimed());
256 EXPECT_TRUE(mTestDrm3->isReclaimed());
257 mDrmSessionManager->removeSession(mTestDrm3->mSessionId);
258
259 // less-used session is reclaimed next
260 EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
261 EXPECT_FALSE(mTestDrm1->isReclaimed());
262 EXPECT_TRUE(mTestDrm2->isReclaimed());
263 EXPECT_TRUE(mTestDrm3->isReclaimed());
264
265 // most-used session still open
266 EXPECT_EQ(1u, mDrmSessionManager->getSessionCount());
267 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
268 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
269 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
270 }
271
272 } // namespace android
273