blob: 301538f4419503a2b8e6ec53cbb72835a9493dc4 [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"
19#include <utils/Log.h>
20
Robert Shih0f3a8a02019-11-14 15:43:39 -080021#include <aidl/android/media/IResourceManagerClient.h>
22#include <aidl/android/media/IResourceManagerService.h>
23#include <aidl/android/media/MediaResourceParcel.h>
24#include <android/binder_ibinder.h>
25#include <android/binder_manager.h>
Robert Shihc3af31b2019-09-20 21:45:01 -070026#include <cutils/properties.h>
Robert Shih28c2ed32019-10-27 22:55:12 -070027#include <mediadrm/DrmUtils.h>
Jeff Tinker7d2c6e82018-02-16 16:14:59 -080028#include <mediadrm/DrmSessionManager.h>
Ronghua Wu10305cc2015-02-22 07:55:32 -080029#include <unistd.h>
30#include <utils/String8.h>
31
Robert Shihc3af31b2019-09-20 21:45:01 -070032#include <vector>
33
Ronghua Wu10305cc2015-02-22 07:55:32 -080034namespace android {
Robert Shih0f3a8a02019-11-14 15:43:39 -080035
36using aidl::android::media::MediaResourceParcel;
Girish9128e242022-11-23 20:52:29 +000037using aidl::android::media::ClientInfoParcel;
Robert Shih0f3a8a02019-11-14 15:43:39 -080038
39namespace {
40void ResourceManagerServiceDied(void* cookie) {
41 auto thiz = static_cast<DrmSessionManager*>(cookie);
42 thiz->binderDied();
43}
44}
45
46using ::ndk::ScopedAStatus;
Ronghua Wu10305cc2015-02-22 07:55:32 -080047
48static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
49 String8 sessionIdStr;
50 for (size_t i = 0; i < sessionId.size(); ++i) {
51 sessionIdStr.appendFormat("%u ", sessionId[i]);
52 }
53 return sessionIdStr;
54}
55
Robert Shih0f3a8a02019-11-14 15:43:39 -080056template <typename Byte = uint8_t>
57static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
58 auto v = reinterpret_cast<const Byte *>(vector.array());
59 std::vector<Byte> vec(v, v + vector.size());
Robert Shihc3af31b2019-09-20 21:45:01 -070060 return vec;
61}
62
Chong Zhang181e6952019-10-09 13:23:39 -070063static std::vector<MediaResourceParcel> toResourceVec(
64 const Vector<uint8_t> &sessionId, int64_t value) {
Robert Shih0f3a8a02019-11-14 15:43:39 -080065 using Type = aidl::android::media::MediaResourceType;
66 using SubType = aidl::android::media::MediaResourceSubType;
Chong Zhang181e6952019-10-09 13:23:39 -070067 std::vector<MediaResourceParcel> resources;
Robert Shih0f3a8a02019-11-14 15:43:39 -080068 MediaResourceParcel resource{
69 Type::kDrmSession, SubType::kUnspecifiedSubType,
Jooyung Han3d564ff2020-02-22 00:46:06 +090070 toStdVec<>(sessionId), value};
Robert Shih0f3a8a02019-11-14 15:43:39 -080071 resources.push_back(resource);
Robert Shihc3af31b2019-09-20 21:45:01 -070072 return resources;
73}
74
Robert Shih0f3a8a02019-11-14 15:43:39 -080075static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
76 ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
77 return IResourceManagerService::fromBinder(binder);
Robert Shihc3af31b2019-09-20 21:45:01 -070078}
79
Ronghua Wu10305cc2015-02-22 07:55:32 -080080bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
81 if (sessionId1.size() != sessionId2.size()) {
82 return false;
83 }
84 for (size_t i = 0; i < sessionId1.size(); ++i) {
85 if (sessionId1[i] != sessionId2[i]) {
86 return false;
87 }
88 }
89 return true;
90}
91
Ronghua Wu5c3da202015-02-22 08:45:28 -080092sp<DrmSessionManager> DrmSessionManager::Instance() {
Robert Shihfc62baf2020-03-13 21:49:06 -070093 static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
Robert Shihc3af31b2019-09-20 21:45:01 -070094 drmSessionManager->init();
Ronghua Wu5c3da202015-02-22 08:45:28 -080095 return drmSessionManager;
96}
97
Ronghua Wu10305cc2015-02-22 07:55:32 -080098DrmSessionManager::DrmSessionManager()
Robert Shihc3af31b2019-09-20 21:45:01 -070099 : DrmSessionManager(getResourceManagerService()) {
100}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800101
Robert Shih0f3a8a02019-11-14 15:43:39 -0800102DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
Robert Shihc3af31b2019-09-20 21:45:01 -0700103 : mService(service),
Robert Shih0f3a8a02019-11-14 15:43:39 -0800104 mInitialized(false),
105 mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
Robert Shihc3af31b2019-09-20 21:45:01 -0700106 if (mService == NULL) {
107 ALOGE("Failed to init ResourceManagerService");
108 }
109}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800110
Robert Shihc3af31b2019-09-20 21:45:01 -0700111DrmSessionManager::~DrmSessionManager() {
112 if (mService != NULL) {
Robert Shih0f3a8a02019-11-14 15:43:39 -0800113 AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
Robert Shihc3af31b2019-09-20 21:45:01 -0700114 }
115}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800116
Robert Shihc3af31b2019-09-20 21:45:01 -0700117void DrmSessionManager::init() {
118 Mutex::Autolock lock(mLock);
119 if (mInitialized) {
120 return;
121 }
122 mInitialized = true;
123 if (mService != NULL) {
Robert Shih0f3a8a02019-11-14 15:43:39 -0800124 AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
Robert Shihc3af31b2019-09-20 21:45:01 -0700125 }
126}
127
128void DrmSessionManager::addSession(int pid,
Robert Shih0f3a8a02019-11-14 15:43:39 -0800129 const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
130 uid_t uid = AIBinder_getCallingUid();
Robert Shihc3af31b2019-09-20 21:45:01 -0700131 ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
Ronghua Wu10305cc2015-02-22 07:55:32 -0800132 GetSessionIdString(sessionId).string());
133
134 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700135 if (mService == NULL) {
136 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800137 }
Robert Shihc3af31b2019-09-20 21:45:01 -0700138
Robert Shih0f3a8a02019-11-14 15:43:39 -0800139 static int64_t clientId = 0;
Robert Shihc3af31b2019-09-20 21:45:01 -0700140 mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
Girish9128e242022-11-23 20:52:29 +0000141 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(pid),
142 .uid = static_cast<int32_t>(uid),
143 .id = clientId++};
144 mService->addResource(clientInfo, drm, toResourceVec(sessionId, INT64_MAX));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800145}
146
147void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
148 ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
149
150 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700151 auto it = mSessionMap.find(toStdVec(sessionId));
152 if (mService == NULL || it == mSessionMap.end()) {
153 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800154 }
Robert Shihc3af31b2019-09-20 21:45:01 -0700155
156 auto info = it->second;
Girish9128e242022-11-23 20:52:29 +0000157 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
158 .uid = static_cast<int32_t>(info.uid),
159 .id = info.clientId};
160 mService->addResource(clientInfo, NULL, toResourceVec(sessionId, -1));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800161}
162
163void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
164 ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
165
166 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700167 auto it = mSessionMap.find(toStdVec(sessionId));
168 if (mService == NULL || it == mSessionMap.end()) {
169 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800170 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800171
Robert Shihc3af31b2019-09-20 21:45:01 -0700172 auto info = it->second;
Robert Shihfc62baf2020-03-13 21:49:06 -0700173 // removeClient instead of removeSession because each client has only one session
Girish9128e242022-11-23 20:52:29 +0000174 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(info.pid),
175 .uid = static_cast<int32_t>(info.uid),
176 .id = info.clientId};
177 mService->removeClient(clientInfo);
Robert Shihc3af31b2019-09-20 21:45:01 -0700178 mSessionMap.erase(it);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800179}
180
181bool DrmSessionManager::reclaimSession(int callingPid) {
182 ALOGV("reclaimSession(%d)", callingPid);
183
Robert Shihc3af31b2019-09-20 21:45:01 -0700184 // unlock early because reclaimResource might callback into removeSession
185 mLock.lock();
Robert Shih0f3a8a02019-11-14 15:43:39 -0800186 std::shared_ptr<IResourceManagerService> service(mService);
Robert Shihc3af31b2019-09-20 21:45:01 -0700187 mLock.unlock();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800188
Robert Shihc3af31b2019-09-20 21:45:01 -0700189 if (service == NULL) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800190 return false;
191 }
192
Robert Shihc3af31b2019-09-20 21:45:01 -0700193 // cannot update mSessionMap because we do not know which sessionId is reclaimed;
194 // we rely on IResourceManagerClient to removeSession in reclaimResource
Girish9128e242022-11-23 20:52:29 +0000195 Vector<uint8_t> placeHolder;
Chong Zhang181e6952019-10-09 13:23:39 -0700196 bool success;
Girish9128e242022-11-23 20:52:29 +0000197 uid_t uid = AIBinder_getCallingUid();
198 ClientInfoParcel clientInfo{.pid = static_cast<int32_t>(callingPid),
199 .uid = static_cast<int32_t>(uid)};
200 ScopedAStatus status = service->reclaimResource(
201 clientInfo, toResourceVec(placeHolder, INT64_MAX), &success);
Chong Zhang181e6952019-10-09 13:23:39 -0700202 return status.isOk() && success;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800203}
204
Robert Shihc3af31b2019-09-20 21:45:01 -0700205size_t DrmSessionManager::getSessionCount() const {
206 Mutex::Autolock lock(mLock);
207 return mSessionMap.size();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800208}
209
Robert Shihc3af31b2019-09-20 21:45:01 -0700210bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const {
211 Mutex::Autolock lock(mLock);
212 return mSessionMap.count(toStdVec(sessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800213}
214
Robert Shih0f3a8a02019-11-14 15:43:39 -0800215void DrmSessionManager::binderDied() {
Robert Shihc3af31b2019-09-20 21:45:01 -0700216 ALOGW("ResourceManagerService died.");
217 Mutex::Autolock lock(mLock);
Robert Shih0f3a8a02019-11-14 15:43:39 -0800218 mService.reset();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800219}
220
221} // namespace android