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