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