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