blob: 7a4e1aee90fa871fe41ddf93e373bf0a786d3cd3 [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;
37
38namespace {
39void ResourceManagerServiceDied(void* cookie) {
40 auto thiz = static_cast<DrmSessionManager*>(cookie);
41 thiz->binderDied();
42}
43}
44
45using ::ndk::ScopedAStatus;
Ronghua Wu10305cc2015-02-22 07:55:32 -080046
47static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
48 String8 sessionIdStr;
49 for (size_t i = 0; i < sessionId.size(); ++i) {
50 sessionIdStr.appendFormat("%u ", sessionId[i]);
51 }
52 return sessionIdStr;
53}
54
Robert Shih0f3a8a02019-11-14 15:43:39 -080055template <typename Byte = uint8_t>
56static std::vector<Byte> toStdVec(const Vector<uint8_t> &vector) {
57 auto v = reinterpret_cast<const Byte *>(vector.array());
58 std::vector<Byte> vec(v, v + vector.size());
Robert Shihc3af31b2019-09-20 21:45:01 -070059 return vec;
60}
61
Chong Zhang181e6952019-10-09 13:23:39 -070062static std::vector<MediaResourceParcel> toResourceVec(
63 const Vector<uint8_t> &sessionId, int64_t value) {
Robert Shih0f3a8a02019-11-14 15:43:39 -080064 using Type = aidl::android::media::MediaResourceType;
65 using SubType = aidl::android::media::MediaResourceSubType;
Chong Zhang181e6952019-10-09 13:23:39 -070066 std::vector<MediaResourceParcel> resources;
Robert Shih0f3a8a02019-11-14 15:43:39 -080067 MediaResourceParcel resource{
68 Type::kDrmSession, SubType::kUnspecifiedSubType,
69 toStdVec<int8_t>(sessionId), value};
70 resources.push_back(resource);
Robert Shihc3af31b2019-09-20 21:45:01 -070071 return resources;
72}
73
Robert Shih0f3a8a02019-11-14 15:43:39 -080074static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
75 ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
76 return IResourceManagerService::fromBinder(binder);
Robert Shihc3af31b2019-09-20 21:45:01 -070077}
78
Ronghua Wu10305cc2015-02-22 07:55:32 -080079bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
80 if (sessionId1.size() != sessionId2.size()) {
81 return false;
82 }
83 for (size_t i = 0; i < sessionId1.size(); ++i) {
84 if (sessionId1[i] != sessionId2[i]) {
85 return false;
86 }
87 }
88 return true;
89}
90
Ronghua Wu5c3da202015-02-22 08:45:28 -080091sp<DrmSessionManager> DrmSessionManager::Instance() {
Robert Shih0f3a8a02019-11-14 15:43:39 -080092 auto drmSessionManager = new DrmSessionManager();
Robert Shihc3af31b2019-09-20 21:45:01 -070093 drmSessionManager->init();
Ronghua Wu5c3da202015-02-22 08:45:28 -080094 return drmSessionManager;
95}
96
Ronghua Wu10305cc2015-02-22 07:55:32 -080097DrmSessionManager::DrmSessionManager()
Robert Shihc3af31b2019-09-20 21:45:01 -070098 : DrmSessionManager(getResourceManagerService()) {
99}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800100
Robert Shih0f3a8a02019-11-14 15:43:39 -0800101DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
Robert Shihc3af31b2019-09-20 21:45:01 -0700102 : mService(service),
Robert Shih0f3a8a02019-11-14 15:43:39 -0800103 mInitialized(false),
104 mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
Robert Shihc3af31b2019-09-20 21:45:01 -0700105 if (mService == NULL) {
106 ALOGE("Failed to init ResourceManagerService");
107 }
108}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800109
Robert Shihc3af31b2019-09-20 21:45:01 -0700110DrmSessionManager::~DrmSessionManager() {
111 if (mService != NULL) {
Robert Shih0f3a8a02019-11-14 15:43:39 -0800112 AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
Robert Shihc3af31b2019-09-20 21:45:01 -0700113 }
114}
Ronghua Wu10305cc2015-02-22 07:55:32 -0800115
Robert Shihc3af31b2019-09-20 21:45:01 -0700116void DrmSessionManager::init() {
117 Mutex::Autolock lock(mLock);
118 if (mInitialized) {
119 return;
120 }
121 mInitialized = true;
122 if (mService != NULL) {
Robert Shih0f3a8a02019-11-14 15:43:39 -0800123 AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
Robert Shihc3af31b2019-09-20 21:45:01 -0700124 }
125}
126
127void DrmSessionManager::addSession(int pid,
Robert Shih0f3a8a02019-11-14 15:43:39 -0800128 const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
129 uid_t uid = AIBinder_getCallingUid();
Robert Shihc3af31b2019-09-20 21:45:01 -0700130 ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
Ronghua Wu10305cc2015-02-22 07:55:32 -0800131 GetSessionIdString(sessionId).string());
132
133 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700134 if (mService == NULL) {
135 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800136 }
Robert Shihc3af31b2019-09-20 21:45:01 -0700137
Robert Shih0f3a8a02019-11-14 15:43:39 -0800138 static int64_t clientId = 0;
Robert Shihc3af31b2019-09-20 21:45:01 -0700139 mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
Robert Shih0f3a8a02019-11-14 15:43:39 -0800140 mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800141}
142
143void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
144 ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
145
146 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700147 auto it = mSessionMap.find(toStdVec(sessionId));
148 if (mService == NULL || it == mSessionMap.end()) {
149 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800150 }
Robert Shihc3af31b2019-09-20 21:45:01 -0700151
152 auto info = it->second;
Chong Zhang181e6952019-10-09 13:23:39 -0700153 mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800154}
155
156void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
157 ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
158
159 Mutex::Autolock lock(mLock);
Robert Shihc3af31b2019-09-20 21:45:01 -0700160 auto it = mSessionMap.find(toStdVec(sessionId));
161 if (mService == NULL || it == mSessionMap.end()) {
162 return;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800163 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800164
Robert Shihc3af31b2019-09-20 21:45:01 -0700165 auto info = it->second;
Chong Zhang181e6952019-10-09 13:23:39 -0700166 mService->removeResource(info.pid, info.clientId, toResourceVec(sessionId, INT64_MAX));
Robert Shihc3af31b2019-09-20 21:45:01 -0700167 mSessionMap.erase(it);
Ronghua Wu10305cc2015-02-22 07:55:32 -0800168}
169
170bool DrmSessionManager::reclaimSession(int callingPid) {
171 ALOGV("reclaimSession(%d)", callingPid);
172
Robert Shihc3af31b2019-09-20 21:45:01 -0700173 // unlock early because reclaimResource might callback into removeSession
174 mLock.lock();
Robert Shih0f3a8a02019-11-14 15:43:39 -0800175 std::shared_ptr<IResourceManagerService> service(mService);
Robert Shihc3af31b2019-09-20 21:45:01 -0700176 mLock.unlock();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800177
Robert Shihc3af31b2019-09-20 21:45:01 -0700178 if (service == NULL) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800179 return false;
180 }
181
Robert Shihc3af31b2019-09-20 21:45:01 -0700182 // cannot update mSessionMap because we do not know which sessionId is reclaimed;
183 // we rely on IResourceManagerClient to removeSession in reclaimResource
184 Vector<uint8_t> dummy;
Chong Zhang181e6952019-10-09 13:23:39 -0700185 bool success;
Robert Shih0f3a8a02019-11-14 15:43:39 -0800186 ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
Chong Zhang181e6952019-10-09 13:23:39 -0700187 return status.isOk() && success;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800188}
189
Robert Shihc3af31b2019-09-20 21:45:01 -0700190size_t DrmSessionManager::getSessionCount() const {
191 Mutex::Autolock lock(mLock);
192 return mSessionMap.size();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800193}
194
Robert Shihc3af31b2019-09-20 21:45:01 -0700195bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const {
196 Mutex::Autolock lock(mLock);
197 return mSessionMap.count(toStdVec(sessionId));
Ronghua Wu10305cc2015-02-22 07:55:32 -0800198}
199
Robert Shih0f3a8a02019-11-14 15:43:39 -0800200void DrmSessionManager::binderDied() {
Robert Shihc3af31b2019-09-20 21:45:01 -0700201 ALOGW("ResourceManagerService died.");
202 Mutex::Autolock lock(mLock);
Robert Shih0f3a8a02019-11-14 15:43:39 -0800203 mService.reset();
Ronghua Wu10305cc2015-02-22 07:55:32 -0800204}
205
206} // namespace android