/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "DrmSessionManager_test" #include <utils/Log.h> #include <gtest/gtest.h> #include <media/Drm.h> #include <media/DrmSessionClientInterface.h> #include <media/DrmSessionManager.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/ProcessInfoInterface.h> namespace android { struct FakeProcessInfo : public ProcessInfoInterface { FakeProcessInfo() {} virtual ~FakeProcessInfo() {} virtual bool getPriority(int pid, int* priority) { // For testing, use pid as priority. // Lower the value higher the priority. *priority = pid; return true; } virtual bool isValidPid(int /* pid */) { return true; } private: DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo); }; struct FakeDrm : public DrmSessionClientInterface { FakeDrm() {} virtual ~FakeDrm() {} virtual bool reclaimSession(const Vector<uint8_t>& sessionId) { mReclaimedSessions.push_back(sessionId); return true; } const Vector<Vector<uint8_t> >& reclaimedSessions() const { return mReclaimedSessions; } private: Vector<Vector<uint8_t> > mReclaimedSessions; DISALLOW_EVIL_CONSTRUCTORS(FakeDrm); }; static const int kTestPid1 = 30; static const int kTestPid2 = 20; static const uint8_t kTestSessionId1[] = {1, 2, 3}; static const uint8_t kTestSessionId2[] = {4, 5, 6, 7, 8}; static const uint8_t kTestSessionId3[] = {9, 0}; class DrmSessionManagerTest : public ::testing::Test { public: DrmSessionManagerTest() : mDrmSessionManager(new DrmSessionManager(new FakeProcessInfo())), mTestDrm1(new FakeDrm()), mTestDrm2(new FakeDrm()) { GetSessionId(kTestSessionId1, ARRAY_SIZE(kTestSessionId1), &mSessionId1); GetSessionId(kTestSessionId2, ARRAY_SIZE(kTestSessionId2), &mSessionId2); GetSessionId(kTestSessionId3, ARRAY_SIZE(kTestSessionId3), &mSessionId3); } protected: static void GetSessionId(const uint8_t* ids, size_t num, Vector<uint8_t>* sessionId) { for (size_t i = 0; i < num; ++i) { sessionId->push_back(ids[i]); } } static void ExpectEqSessionInfo(const SessionInfo& info, sp<DrmSessionClientInterface> drm, const Vector<uint8_t>& sessionId, int64_t timeStamp) { EXPECT_EQ(drm, info.drm); EXPECT_TRUE(isEqualSessionId(sessionId, info.sessionId)); EXPECT_EQ(timeStamp, info.timeStamp); } void addSession() { mDrmSessionManager->addSession(kTestPid1, mTestDrm1, mSessionId1); mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId2); mDrmSessionManager->addSession(kTestPid2, mTestDrm2, mSessionId3); const PidSessionInfosMap& map = sessionMap(); EXPECT_EQ(2u, map.size()); ssize_t index1 = map.indexOfKey(kTestPid1); ASSERT_GE(index1, 0); const SessionInfos& infos1 = map[index1]; EXPECT_EQ(1u, infos1.size()); ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 0); ssize_t index2 = map.indexOfKey(kTestPid2); ASSERT_GE(index2, 0); const SessionInfos& infos2 = map[index2]; EXPECT_EQ(2u, infos2.size()); ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId2, 1); ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 2); } const PidSessionInfosMap& sessionMap() { return mDrmSessionManager->mSessionMap; } void testGetLowestPriority() { int pid; int priority; EXPECT_FALSE(mDrmSessionManager->getLowestPriority_l(&pid, &priority)); addSession(); EXPECT_TRUE(mDrmSessionManager->getLowestPriority_l(&pid, &priority)); EXPECT_EQ(kTestPid1, pid); FakeProcessInfo processInfo; int priority1; processInfo.getPriority(kTestPid1, &priority1); EXPECT_EQ(priority1, priority); } void testGetLeastUsedSession() { sp<DrmSessionClientInterface> drm; Vector<uint8_t> sessionId; EXPECT_FALSE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId)); addSession(); EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid1, &drm, &sessionId)); EXPECT_EQ(mTestDrm1, drm); EXPECT_TRUE(isEqualSessionId(mSessionId1, sessionId)); EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId)); EXPECT_EQ(mTestDrm2, drm); EXPECT_TRUE(isEqualSessionId(mSessionId2, sessionId)); // mSessionId2 is no longer the least used session. mDrmSessionManager->useSession(mSessionId2); EXPECT_TRUE(mDrmSessionManager->getLeastUsedSession_l(kTestPid2, &drm, &sessionId)); EXPECT_EQ(mTestDrm2, drm); EXPECT_TRUE(isEqualSessionId(mSessionId3, sessionId)); } sp<DrmSessionManager> mDrmSessionManager; sp<FakeDrm> mTestDrm1; sp<FakeDrm> mTestDrm2; Vector<uint8_t> mSessionId1; Vector<uint8_t> mSessionId2; Vector<uint8_t> mSessionId3; }; TEST_F(DrmSessionManagerTest, addSession) { addSession(); } TEST_F(DrmSessionManagerTest, useSession) { addSession(); mDrmSessionManager->useSession(mSessionId1); mDrmSessionManager->useSession(mSessionId3); const PidSessionInfosMap& map = sessionMap(); const SessionInfos& infos1 = map.valueFor(kTestPid1); const SessionInfos& infos2 = map.valueFor(kTestPid2); ExpectEqSessionInfo(infos1[0], mTestDrm1, mSessionId1, 3); ExpectEqSessionInfo(infos2[1], mTestDrm2, mSessionId3, 4); } TEST_F(DrmSessionManagerTest, removeSession) { addSession(); mDrmSessionManager->removeSession(mSessionId2); const PidSessionInfosMap& map = sessionMap(); EXPECT_EQ(2u, map.size()); const SessionInfos& infos1 = map.valueFor(kTestPid1); const SessionInfos& infos2 = map.valueFor(kTestPid2); EXPECT_EQ(1u, infos1.size()); EXPECT_EQ(1u, infos2.size()); // mSessionId2 has been removed. ExpectEqSessionInfo(infos2[0], mTestDrm2, mSessionId3, 2); } TEST_F(DrmSessionManagerTest, removeDrm) { addSession(); sp<FakeDrm> drm = new FakeDrm; const uint8_t ids[] = {123}; Vector<uint8_t> sessionId; GetSessionId(ids, ARRAY_SIZE(ids), &sessionId); mDrmSessionManager->addSession(kTestPid2, drm, sessionId); mDrmSessionManager->removeDrm(mTestDrm2); const PidSessionInfosMap& map = sessionMap(); const SessionInfos& infos2 = map.valueFor(kTestPid2); EXPECT_EQ(1u, infos2.size()); // mTestDrm2 has been removed. ExpectEqSessionInfo(infos2[0], drm, sessionId, 3); } TEST_F(DrmSessionManagerTest, reclaimSession) { EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1)); addSession(); // calling pid priority is too low EXPECT_FALSE(mDrmSessionManager->reclaimSession(50)); EXPECT_TRUE(mDrmSessionManager->reclaimSession(10)); EXPECT_EQ(1u, mTestDrm1->reclaimedSessions().size()); EXPECT_TRUE(isEqualSessionId(mSessionId1, mTestDrm1->reclaimedSessions()[0])); mDrmSessionManager->removeSession(mSessionId1); // add a session from a higher priority process. sp<FakeDrm> drm = new FakeDrm; const uint8_t ids[] = {1, 3, 5}; Vector<uint8_t> sessionId; GetSessionId(ids, ARRAY_SIZE(ids), &sessionId); mDrmSessionManager->addSession(15, drm, sessionId); EXPECT_TRUE(mDrmSessionManager->reclaimSession(18)); EXPECT_EQ(1u, mTestDrm2->reclaimedSessions().size()); // mSessionId2 is reclaimed. EXPECT_TRUE(isEqualSessionId(mSessionId2, mTestDrm2->reclaimedSessions()[0])); } TEST_F(DrmSessionManagerTest, getLowestPriority) { testGetLowestPriority(); } TEST_F(DrmSessionManagerTest, getLeastUsedSession_l) { testGetLeastUsedSession(); } } // namespace android