blob: 9a8ed8dbdb5562e33e60a62225ddc3d82d915bda [file] [log] [blame]
Ronghua Wu10305cc2015-02-22 07:55:32 -08001/*
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"
Robert Shiha90aee32019-11-14 15:43:39 -080019#include <android/binder_auto_utils.h>
Ronghua Wu10305cc2015-02-22 07:55:32 -080020#include <utils/Log.h>
21
22#include <gtest/gtest.h>
23
Robert Shiha90aee32019-11-14 15:43:39 -080024#include <aidl/android/media/BnResourceManagerClient.h>
25#include <aidl/android/media/BnResourceManagerService.h>
Chong Zhang181e6952019-10-09 13:23:39 -070026#include <android/media/BnResourceManagerClient.h>
Robert Shiha90aee32019-11-14 15:43:39 -080027
Ronghua Wu10305cc2015-02-22 07:55:32 -080028#include <media/stagefright/foundation/ADebug.h>
Ronghua Wu14bcaca2015-03-16 11:24:30 -070029#include <media/stagefright/ProcessInfoInterface.h>
Jeff Tinker7d2c6e82018-02-16 16:14:59 -080030#include <mediadrm/DrmSessionManager.h>
Ronghua Wu10305cc2015-02-22 07:55:32 -080031
Robert Shihc3af31b2019-09-20 21:45:01 -070032#include <algorithm>
Robert Shiha90aee32019-11-14 15:43:39 -080033#include <iostream>
Robert Shihc3af31b2019-09-20 21:45:01 -070034#include <vector>
35
36#include "ResourceManagerService.h"
37
Ronghua Wu10305cc2015-02-22 07:55:32 -080038namespace android {
39
Chong Zhang181e6952019-10-09 13:23:39 -070040using ::android::binder::Status;
Chong Zhang181e6952019-10-09 13:23:39 -070041using ::android::media::ResourceManagerService;
Robert Shiha90aee32019-11-14 15:43:39 -080042using ::ndk::ScopedAStatus;
43
44using NdkBnResourceManagerClient = ::aidl::android::media::BnResourceManagerClient;
45using NdkBnResourceManagerService = ::aidl::android::media::BnResourceManagerService;
46using NdkMediaResource = ::aidl::android::media::MediaResourceParcel;
47using NdkResourceManagerClient = ::aidl::android::media::IResourceManagerClient;
48
49using FwkBnResourceManagerClient = ::android::media::BnResourceManagerClient;
50using FwkMediaResource = ::android::media::MediaResourceParcel;
51
52namespace {
53
54struct FwkResourceManagerClientImpl : public FwkBnResourceManagerClient {
55 FwkResourceManagerClientImpl(const std::shared_ptr<NdkResourceManagerClient> &client)
56 : mClient(client) {
57 }
58
59 Status reclaimResource(bool* _aidl_return) override {
60 mClient->reclaimResource(_aidl_return);
61 return Status::ok();
62 }
63
64 Status getName(std::string* _aidl_return) override {
65 mClient->getName(_aidl_return);
66 return Status::ok();
67 }
68
69private:
70 std::shared_ptr<NdkResourceManagerClient> mClient;
71};
72
73FwkMediaResource NdkToFwkMediaResource(const NdkMediaResource &in) {
74 FwkMediaResource out{};
75 out.type = static_cast<decltype(out.type)>(in.type);
76 out.subType = static_cast<decltype(out.subType)>(in.subType);
77 auto v(reinterpret_cast<const uint8_t *>(in.id.data()));
78 out.id.assign(v, v + in.id.size());
79 out.value = in.value;
80 return out;
81}
82
83std::vector<FwkMediaResource> NdkToFwkMediaResourceVec(const std::vector<NdkMediaResource> &in) {
84 std::vector<FwkMediaResource> out;
85 for (auto e : in) {
86 out.push_back(NdkToFwkMediaResource(e));
87 }
88 return out;
89}
90
91ScopedAStatus FwkToNdkStatus(Status err) {
92 return ScopedAStatus(AStatus_fromExceptionCode(err.serviceSpecificErrorCode()));
93}
94
95struct NdkResourceManagerServiceImpl : public NdkBnResourceManagerService {
96 using NdkMediaResourcePolicy = ::aidl::android::media::MediaResourcePolicyParcel;
97
98 NdkResourceManagerServiceImpl(const sp<ResourceManagerService> &service)
99 : mService(service) {}
100
101 ScopedAStatus config(const std::vector<NdkMediaResourcePolicy>& in_policies) override {
102 (void)in_policies;
103 return ScopedAStatus::ok();
104 }
105
106 ScopedAStatus addResource(int32_t in_pid, int32_t in_uid, int64_t in_clientId,
107 const std::shared_ptr<NdkResourceManagerClient>& in_client,
108 const std::vector<NdkMediaResource>& in_resources) override {
109 sp<FwkBnResourceManagerClient> client(new FwkResourceManagerClientImpl(in_client));
110 std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
111 auto err = mService->addResource(in_pid, in_uid, in_clientId, client, resources);
112 return FwkToNdkStatus(err);
113 }
114
115 ScopedAStatus removeResource(int32_t in_pid, int64_t in_clientId,
116 const std::vector<NdkMediaResource>& in_resources) override {
117 std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
118 auto err = mService->removeResource(in_pid, in_clientId, resources);
119 return FwkToNdkStatus(err);
120 }
121
122 ScopedAStatus removeClient(int32_t in_pid, int64_t in_clientId) override{
123 auto err = mService->removeClient(in_pid, in_clientId);
124 return FwkToNdkStatus(err);
125 }
126
127 ScopedAStatus reclaimResource(int32_t in_callingPid,
128 const std::vector<NdkMediaResource>& in_resources, bool* _aidl_return) override {
129 std::vector<FwkMediaResource> resources(NdkToFwkMediaResourceVec(in_resources));
130 auto err = mService->reclaimResource(in_callingPid, resources, _aidl_return);
131 return FwkToNdkStatus(err);
132 }
133
134private:
135 sp<ResourceManagerService> mService;
136};
137
138template <typename Impl>
139std::shared_ptr<NdkResourceManagerClient> NdkImplToIface(const Impl &impl) {
140 return std::static_pointer_cast<NdkResourceManagerClient>(impl);
141}
142
143}
Chong Zhang181e6952019-10-09 13:23:39 -0700144
Robert Shihc3af31b2019-09-20 21:45:01 -0700145static Vector<uint8_t> toAndroidVector(const std::vector<uint8_t> &vec) {
146 Vector<uint8_t> aVec;
147 for (auto b : vec) {
148 aVec.push_back(b);
149 }
150 return aVec;
151}
152
Ronghua Wu10305cc2015-02-22 07:55:32 -0800153struct FakeProcessInfo : public ProcessInfoInterface {
154 FakeProcessInfo() {}
155 virtual ~FakeProcessInfo() {}
156
Ronghua Wu5c3da202015-02-22 08:45:28 -0800157 virtual bool getPriority(int pid, int* priority) {
158 // For testing, use pid as priority.
159 // Lower the value higher the priority.
160 *priority = pid;
161 return true;
162 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800163
Ronghua Wud11c43a2016-01-27 16:26:12 -0800164 virtual bool isValidPid(int /* pid */) {
165 return true;
166 }
167
Ronghua Wu10305cc2015-02-22 07:55:32 -0800168private:
169 DISALLOW_EVIL_CONSTRUCTORS(FakeProcessInfo);
170};
171
Robert Shiha90aee32019-11-14 15:43:39 -0800172struct FakeDrm : public NdkBnResourceManagerClient {
Robert Shihc3af31b2019-09-20 21:45:01 -0700173 FakeDrm(const std::vector<uint8_t>& sessionId, const sp<DrmSessionManager>& manager)
174 : mSessionId(toAndroidVector(sessionId)),
175 mReclaimed(false),
176 mDrmSessionManager(manager) {}
177
Robert Shiha90aee32019-11-14 15:43:39 -0800178 ScopedAStatus reclaimResource(bool* _aidl_return) {
Robert Shihc3af31b2019-09-20 21:45:01 -0700179 mReclaimed = true;
180 mDrmSessionManager->removeSession(mSessionId);
Chong Zhang181e6952019-10-09 13:23:39 -0700181 *_aidl_return = true;
Robert Shiha90aee32019-11-14 15:43:39 -0800182 return ScopedAStatus::ok();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800183 }
184
Robert Shiha90aee32019-11-14 15:43:39 -0800185 ScopedAStatus getName(::std::string* _aidl_return) {
Robert Shihc3af31b2019-09-20 21:45:01 -0700186 String8 name("FakeDrm[");
187 for (size_t i = 0; i < mSessionId.size(); ++i) {
188 name.appendFormat("%02x", mSessionId[i]);
189 }
190 name.append("]");
Chong Zhang181e6952019-10-09 13:23:39 -0700191 *_aidl_return = name;
Robert Shiha90aee32019-11-14 15:43:39 -0800192 return ScopedAStatus::ok();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800193 }
194
Robert Shihc3af31b2019-09-20 21:45:01 -0700195 bool isReclaimed() const {
196 return mReclaimed;
197 }
198
199 const Vector<uint8_t> mSessionId;
200
Ronghua Wu10305cc2015-02-22 07:55:32 -0800201private:
Robert Shihc3af31b2019-09-20 21:45:01 -0700202 bool mReclaimed;
203 const sp<DrmSessionManager> mDrmSessionManager;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800204
205 DISALLOW_EVIL_CONSTRUCTORS(FakeDrm);
206};
207
Robert Shihc3af31b2019-09-20 21:45:01 -0700208struct FakeSystemCallback :
209 public ResourceManagerService::SystemCallbackInterface {
210 FakeSystemCallback() {}
211
212 virtual void noteStartVideo(int /*uid*/) override {}
213
214 virtual void noteStopVideo(int /*uid*/) override {}
215
216 virtual void noteResetVideo() override {}
217
218 virtual bool requestCpusetBoost(
219 bool /*enable*/, const sp<IInterface> &/*client*/) override {
220 return true;
221 }
222
223protected:
224 virtual ~FakeSystemCallback() {}
225
226private:
227
228 DISALLOW_EVIL_CONSTRUCTORS(FakeSystemCallback);
229};
230
Ronghua Wu5c3da202015-02-22 08:45:28 -0800231static const int kTestPid1 = 30;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800232static const int kTestPid2 = 20;
Robert Shihc3af31b2019-09-20 21:45:01 -0700233static const std::vector<uint8_t> kTestSessionId1{1, 2, 3};
234static const std::vector<uint8_t> kTestSessionId2{4, 5, 6, 7, 8};
235static const std::vector<uint8_t> kTestSessionId3{9, 0};
Ronghua Wu10305cc2015-02-22 07:55:32 -0800236
237class DrmSessionManagerTest : public ::testing::Test {
238public:
239 DrmSessionManagerTest()
Robert Shihc3af31b2019-09-20 21:45:01 -0700240 : mService(new ResourceManagerService(new FakeProcessInfo(), new FakeSystemCallback())),
Robert Shiha90aee32019-11-14 15:43:39 -0800241 mDrmSessionManager(new DrmSessionManager(std::shared_ptr<NdkBnResourceManagerService>(new NdkResourceManagerServiceImpl(mService)))),
Robert Shihc3af31b2019-09-20 21:45:01 -0700242 mTestDrm1(new FakeDrm(kTestSessionId1, mDrmSessionManager)),
243 mTestDrm2(new FakeDrm(kTestSessionId2, mDrmSessionManager)),
244 mTestDrm3(new FakeDrm(kTestSessionId3, mDrmSessionManager)) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800245 }
246
247protected:
Ronghua Wu10305cc2015-02-22 07:55:32 -0800248 void addSession() {
Robert Shiha90aee32019-11-14 15:43:39 -0800249 mDrmSessionManager->addSession(kTestPid1, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
250 mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
251 mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800252 }
253
Robert Shiha90aee32019-11-14 15:43:39 -0800254 sp<ResourceManagerService> mService;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800255 sp<DrmSessionManager> mDrmSessionManager;
Robert Shiha90aee32019-11-14 15:43:39 -0800256 std::shared_ptr<FakeDrm> mTestDrm1;
257 std::shared_ptr<FakeDrm> mTestDrm2;
258 std::shared_ptr<FakeDrm> mTestDrm3;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800259};
260
261TEST_F(DrmSessionManagerTest, addSession) {
262 addSession();
Robert Shihc3af31b2019-09-20 21:45:01 -0700263
264 EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
265 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
266 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
267 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800268}
269
270TEST_F(DrmSessionManagerTest, useSession) {
271 addSession();
272
Robert Shihc3af31b2019-09-20 21:45:01 -0700273 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
274 mDrmSessionManager->useSession(mTestDrm3->mSessionId);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800275
Robert Shihc3af31b2019-09-20 21:45:01 -0700276 EXPECT_EQ(3u, mDrmSessionManager->getSessionCount());
277 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
278 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
279 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800280}
281
282TEST_F(DrmSessionManagerTest, removeSession) {
283 addSession();
284
Robert Shihc3af31b2019-09-20 21:45:01 -0700285 mDrmSessionManager->removeSession(mTestDrm2->mSessionId);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800286
Robert Shihc3af31b2019-09-20 21:45:01 -0700287 EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
288 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
289 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
290 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800291}
292
293TEST_F(DrmSessionManagerTest, reclaimSession) {
294 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
295 addSession();
296
297 // calling pid priority is too low
Ronghua Wu5c3da202015-02-22 08:45:28 -0800298 EXPECT_FALSE(mDrmSessionManager->reclaimSession(50));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800299
Ronghua Wu5c3da202015-02-22 08:45:28 -0800300 EXPECT_TRUE(mDrmSessionManager->reclaimSession(10));
Robert Shihc3af31b2019-09-20 21:45:01 -0700301 EXPECT_TRUE(mTestDrm1->isReclaimed());
Ronghua Wu10305cc2015-02-22 07:55:32 -0800302
303 // add a session from a higher priority process.
Robert Shihc3af31b2019-09-20 21:45:01 -0700304 const std::vector<uint8_t> sid{1, 3, 5};
Robert Shiha90aee32019-11-14 15:43:39 -0800305 std::shared_ptr<FakeDrm> drm(new FakeDrm(sid, mDrmSessionManager));
306 mDrmSessionManager->addSession(15, NdkImplToIface(drm), drm->mSessionId);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800307
Robert Shihc3af31b2019-09-20 21:45:01 -0700308 // make sure mTestDrm2 is reclaimed next instead of mTestDrm3
309 mDrmSessionManager->useSession(mTestDrm3->mSessionId);
Ronghua Wu5c3da202015-02-22 08:45:28 -0800310 EXPECT_TRUE(mDrmSessionManager->reclaimSession(18));
Robert Shihc3af31b2019-09-20 21:45:01 -0700311 EXPECT_TRUE(mTestDrm2->isReclaimed());
312
313 EXPECT_EQ(2u, mDrmSessionManager->getSessionCount());
314 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
315 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
316 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
317 EXPECT_TRUE(mDrmSessionManager->containsSession(drm->mSessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800318}
319
Robert Shihc3af31b2019-09-20 21:45:01 -0700320TEST_F(DrmSessionManagerTest, reclaimAfterUse) {
321 // nothing to reclaim yet
322 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid1));
323 EXPECT_FALSE(mDrmSessionManager->reclaimSession(kTestPid2));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800324
Robert Shihc3af31b2019-09-20 21:45:01 -0700325 // add sessions from same pid
Robert Shiha90aee32019-11-14 15:43:39 -0800326 mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm1), mTestDrm1->mSessionId);
327 mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm2), mTestDrm2->mSessionId);
328 mDrmSessionManager->addSession(kTestPid2, NdkImplToIface(mTestDrm3), mTestDrm3->mSessionId);
Robert Shihc3af31b2019-09-20 21:45:01 -0700329
330 // use some but not all sessions
331 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
332 mDrmSessionManager->useSession(mTestDrm1->mSessionId);
333 mDrmSessionManager->useSession(mTestDrm2->mSessionId);
334
335 // calling pid priority is too low
336 int lowPriorityPid = kTestPid2 + 1;
337 EXPECT_FALSE(mDrmSessionManager->reclaimSession(lowPriorityPid));
338
339 // unused session is reclaimed first
340 int highPriorityPid = kTestPid2 - 1;
341 EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
342 EXPECT_FALSE(mTestDrm1->isReclaimed());
343 EXPECT_FALSE(mTestDrm2->isReclaimed());
344 EXPECT_TRUE(mTestDrm3->isReclaimed());
345 mDrmSessionManager->removeSession(mTestDrm3->mSessionId);
346
347 // less-used session is reclaimed next
348 EXPECT_TRUE(mDrmSessionManager->reclaimSession(highPriorityPid));
349 EXPECT_FALSE(mTestDrm1->isReclaimed());
350 EXPECT_TRUE(mTestDrm2->isReclaimed());
351 EXPECT_TRUE(mTestDrm3->isReclaimed());
352
353 // most-used session still open
354 EXPECT_EQ(1u, mDrmSessionManager->getSessionCount());
355 EXPECT_TRUE(mDrmSessionManager->containsSession(mTestDrm1->mSessionId));
356 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm2->mSessionId));
357 EXPECT_FALSE(mDrmSessionManager->containsSession(mTestDrm3->mSessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800358}
359
360} // namespace android