• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
19 #include <utils/Log.h>
20 
21 #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>
26 #include <cutils/properties.h>
27 #include <mediadrm/DrmUtils.h>
28 #include <mediadrm/DrmSessionManager.h>
29 #include <unistd.h>
30 #include <utils/String8.h>
31 
32 #include <vector>
33 
34 namespace android {
35 
36 using aidl::android::media::MediaResourceParcel;
37 
38 namespace {
ResourceManagerServiceDied(void * cookie)39 void ResourceManagerServiceDied(void* cookie) {
40     auto thiz = static_cast<DrmSessionManager*>(cookie);
41     thiz->binderDied();
42 }
43 }
44 
45 using ::ndk::ScopedAStatus;
46 
GetSessionIdString(const Vector<uint8_t> & sessionId)47 static 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 
55 template <typename Byte = uint8_t>
toStdVec(const Vector<uint8_t> & vector)56 static 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());
59     return vec;
60 }
61 
toResourceVec(const Vector<uint8_t> & sessionId,int64_t value)62 static std::vector<MediaResourceParcel> toResourceVec(
63         const Vector<uint8_t> &sessionId, int64_t value) {
64     using Type = aidl::android::media::MediaResourceType;
65     using SubType = aidl::android::media::MediaResourceSubType;
66     std::vector<MediaResourceParcel> resources;
67     MediaResourceParcel resource{
68             Type::kDrmSession, SubType::kUnspecifiedSubType,
69             toStdVec<>(sessionId), value};
70     resources.push_back(resource);
71     return resources;
72 }
73 
getResourceManagerService()74 static std::shared_ptr<IResourceManagerService> getResourceManagerService() {
75     ::ndk::SpAIBinder binder(AServiceManager_getService("media.resource_manager"));
76     return IResourceManagerService::fromBinder(binder);
77 }
78 
isEqualSessionId(const Vector<uint8_t> & sessionId1,const Vector<uint8_t> & sessionId2)79 bool 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 
Instance()91 sp<DrmSessionManager> DrmSessionManager::Instance() {
92     static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
93     drmSessionManager->init();
94     return drmSessionManager;
95 }
96 
DrmSessionManager()97 DrmSessionManager::DrmSessionManager()
98     : DrmSessionManager(getResourceManagerService()) {
99 }
100 
DrmSessionManager(const std::shared_ptr<IResourceManagerService> & service)101 DrmSessionManager::DrmSessionManager(const std::shared_ptr<IResourceManagerService> &service)
102     : mService(service),
103       mInitialized(false),
104       mDeathRecipient(AIBinder_DeathRecipient_new(ResourceManagerServiceDied)) {
105     if (mService == NULL) {
106         ALOGE("Failed to init ResourceManagerService");
107     }
108 }
109 
~DrmSessionManager()110 DrmSessionManager::~DrmSessionManager() {
111     if (mService != NULL) {
112         AIBinder_unlinkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
113     }
114 }
115 
init()116 void DrmSessionManager::init() {
117     Mutex::Autolock lock(mLock);
118     if (mInitialized) {
119         return;
120     }
121     mInitialized = true;
122     if (mService != NULL) {
123         AIBinder_linkToDeath(mService->asBinder().get(), mDeathRecipient.get(), this);
124     }
125 }
126 
addSession(int pid,const std::shared_ptr<IResourceManagerClient> & drm,const Vector<uint8_t> & sessionId)127 void DrmSessionManager::addSession(int pid,
128         const std::shared_ptr<IResourceManagerClient>& drm, const Vector<uint8_t> &sessionId) {
129     uid_t uid = AIBinder_getCallingUid();
130     ALOGV("addSession(pid %d, uid %d, drm %p, sessionId %s)", pid, uid, drm.get(),
131             GetSessionIdString(sessionId).string());
132 
133     Mutex::Autolock lock(mLock);
134     if (mService == NULL) {
135         return;
136     }
137 
138     static int64_t clientId = 0;
139     mSessionMap[toStdVec(sessionId)] = (SessionInfo){pid, uid, clientId};
140     mService->addResource(pid, uid, clientId++, drm, toResourceVec(sessionId, INT64_MAX));
141 }
142 
useSession(const Vector<uint8_t> & sessionId)143 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
144     ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
145 
146     Mutex::Autolock lock(mLock);
147     auto it = mSessionMap.find(toStdVec(sessionId));
148     if (mService == NULL || it == mSessionMap.end()) {
149         return;
150     }
151 
152     auto info = it->second;
153     mService->addResource(info.pid, info.uid, info.clientId, NULL, toResourceVec(sessionId, -1));
154 }
155 
removeSession(const Vector<uint8_t> & sessionId)156 void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
157     ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
158 
159     Mutex::Autolock lock(mLock);
160     auto it = mSessionMap.find(toStdVec(sessionId));
161     if (mService == NULL || it == mSessionMap.end()) {
162         return;
163     }
164 
165     auto info = it->second;
166     // removeClient instead of removeSession because each client has only one session
167     mService->removeClient(info.pid, info.clientId);
168     mSessionMap.erase(it);
169 }
170 
reclaimSession(int callingPid)171 bool DrmSessionManager::reclaimSession(int callingPid) {
172     ALOGV("reclaimSession(%d)", callingPid);
173 
174     // unlock early because reclaimResource might callback into removeSession
175     mLock.lock();
176     std::shared_ptr<IResourceManagerService> service(mService);
177     mLock.unlock();
178 
179     if (service == NULL) {
180         return false;
181     }
182 
183     // cannot update mSessionMap because we do not know which sessionId is reclaimed;
184     // we rely on IResourceManagerClient to removeSession in reclaimResource
185     Vector<uint8_t> dummy;
186     bool success;
187     ScopedAStatus status = service->reclaimResource(callingPid, toResourceVec(dummy, INT64_MAX), &success);
188     return status.isOk() && success;
189 }
190 
getSessionCount() const191 size_t DrmSessionManager::getSessionCount() const {
192     Mutex::Autolock lock(mLock);
193     return mSessionMap.size();
194 }
195 
containsSession(const Vector<uint8_t> & sessionId) const196 bool DrmSessionManager::containsSession(const Vector<uint8_t>& sessionId) const {
197     Mutex::Autolock lock(mLock);
198     return mSessionMap.count(toStdVec(sessionId));
199 }
200 
binderDied()201 void DrmSessionManager::binderDied() {
202     ALOGW("ResourceManagerService died.");
203     Mutex::Autolock lock(mLock);
204     mService.reset();
205 }
206 
207 }  // namespace android
208