• 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 <binder/IPCThreadState.h>
22 #include <binder/IProcessInfoService.h>
23 #include <binder/IServiceManager.h>
24 #include <media/stagefright/ProcessInfo.h>
25 #include <mediadrm/DrmSessionClientInterface.h>
26 #include <mediadrm/DrmSessionManager.h>
27 #include <unistd.h>
28 #include <utils/String8.h>
29 
30 namespace android {
31 
GetSessionIdString(const Vector<uint8_t> & sessionId)32 static String8 GetSessionIdString(const Vector<uint8_t> &sessionId) {
33     String8 sessionIdStr;
34     for (size_t i = 0; i < sessionId.size(); ++i) {
35         sessionIdStr.appendFormat("%u ", sessionId[i]);
36     }
37     return sessionIdStr;
38 }
39 
isEqualSessionId(const Vector<uint8_t> & sessionId1,const Vector<uint8_t> & sessionId2)40 bool isEqualSessionId(const Vector<uint8_t> &sessionId1, const Vector<uint8_t> &sessionId2) {
41     if (sessionId1.size() != sessionId2.size()) {
42         return false;
43     }
44     for (size_t i = 0; i < sessionId1.size(); ++i) {
45         if (sessionId1[i] != sessionId2[i]) {
46             return false;
47         }
48     }
49     return true;
50 }
51 
Instance()52 sp<DrmSessionManager> DrmSessionManager::Instance() {
53     static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
54     return drmSessionManager;
55 }
56 
DrmSessionManager()57 DrmSessionManager::DrmSessionManager()
58     : mProcessInfo(new ProcessInfo()),
59       mTime(0) {}
60 
DrmSessionManager(sp<ProcessInfoInterface> processInfo)61 DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
62     : mProcessInfo(processInfo),
63       mTime(0) {}
64 
~DrmSessionManager()65 DrmSessionManager::~DrmSessionManager() {}
66 
addSession(int pid,const sp<DrmSessionClientInterface> & drm,const Vector<uint8_t> & sessionId)67 void DrmSessionManager::addSession(
68         int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) {
69     ALOGV("addSession(pid %d, drm %p, sessionId %s)", pid, drm.get(),
70             GetSessionIdString(sessionId).string());
71 
72     Mutex::Autolock lock(mLock);
73     SessionInfo info;
74     info.drm = drm;
75     info.sessionId = sessionId;
76     info.timeStamp = getTime_l();
77     ssize_t index = mSessionMap.indexOfKey(pid);
78     if (index < 0) {
79         // new pid
80         SessionInfos infosForPid;
81         infosForPid.push_back(info);
82         mSessionMap.add(pid, infosForPid);
83     } else {
84         mSessionMap.editValueAt(index).push_back(info);
85     }
86 }
87 
useSession(const Vector<uint8_t> & sessionId)88 void DrmSessionManager::useSession(const Vector<uint8_t> &sessionId) {
89     ALOGV("useSession(%s)", GetSessionIdString(sessionId).string());
90 
91     Mutex::Autolock lock(mLock);
92     for (size_t i = 0; i < mSessionMap.size(); ++i) {
93         SessionInfos& infos = mSessionMap.editValueAt(i);
94         for (size_t j = 0; j < infos.size(); ++j) {
95             SessionInfo& info = infos.editItemAt(j);
96             if (isEqualSessionId(sessionId, info.sessionId)) {
97                 info.timeStamp = getTime_l();
98                 return;
99             }
100         }
101     }
102 }
103 
removeSession(const Vector<uint8_t> & sessionId)104 void DrmSessionManager::removeSession(const Vector<uint8_t> &sessionId) {
105     ALOGV("removeSession(%s)", GetSessionIdString(sessionId).string());
106 
107     Mutex::Autolock lock(mLock);
108     for (size_t i = 0; i < mSessionMap.size(); ++i) {
109         SessionInfos& infos = mSessionMap.editValueAt(i);
110         for (size_t j = 0; j < infos.size(); ++j) {
111             if (isEqualSessionId(sessionId, infos[j].sessionId)) {
112                 infos.removeAt(j);
113                 return;
114             }
115         }
116     }
117 }
118 
removeDrm(const sp<DrmSessionClientInterface> & drm)119 void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) {
120     ALOGV("removeDrm(%p)", drm.get());
121 
122     Mutex::Autolock lock(mLock);
123     bool found = false;
124     for (size_t i = 0; i < mSessionMap.size(); ++i) {
125         SessionInfos& infos = mSessionMap.editValueAt(i);
126         for (size_t j = 0; j < infos.size();) {
127             if (infos[j].drm == drm) {
128                 ALOGV("removed session (%s)", GetSessionIdString(infos[j].sessionId).string());
129                 j = infos.removeAt(j);
130                 found = true;
131             } else {
132                 ++j;
133             }
134         }
135         if (found) {
136             break;
137         }
138     }
139 }
140 
reclaimSession(int callingPid)141 bool DrmSessionManager::reclaimSession(int callingPid) {
142     ALOGV("reclaimSession(%d)", callingPid);
143 
144     sp<DrmSessionClientInterface> drm;
145     Vector<uint8_t> sessionId;
146     int lowestPriorityPid;
147     int lowestPriority;
148     {
149         Mutex::Autolock lock(mLock);
150         int callingPriority;
151         if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
152             return false;
153         }
154         if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
155             return false;
156         }
157         if (lowestPriority <= callingPriority) {
158             return false;
159         }
160 
161         if (!getLeastUsedSession_l(lowestPriorityPid, &drm, &sessionId)) {
162             return false;
163         }
164     }
165 
166     if (drm == NULL) {
167         return false;
168     }
169 
170     ALOGV("reclaim session(%s) opened by pid %d",
171             GetSessionIdString(sessionId).string(), lowestPriorityPid);
172 
173     return drm->reclaimSession(sessionId);
174 }
175 
getTime_l()176 int64_t DrmSessionManager::getTime_l() {
177     return mTime++;
178 }
179 
getLowestPriority_l(int * lowestPriorityPid,int * lowestPriority)180 bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
181     int pid = -1;
182     int priority = -1;
183     for (size_t i = 0; i < mSessionMap.size(); ++i) {
184         if (mSessionMap.valueAt(i).size() == 0) {
185             // no opened session by this process.
186             continue;
187         }
188         int tempPid = mSessionMap.keyAt(i);
189         int tempPriority;
190         if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
191             // shouldn't happen.
192             return false;
193         }
194         if (pid == -1) {
195             pid = tempPid;
196             priority = tempPriority;
197         } else {
198             if (tempPriority > priority) {
199                 pid = tempPid;
200                 priority = tempPriority;
201             }
202         }
203     }
204     if (pid != -1) {
205         *lowestPriorityPid = pid;
206         *lowestPriority = priority;
207     }
208     return (pid != -1);
209 }
210 
getLeastUsedSession_l(int pid,sp<DrmSessionClientInterface> * drm,Vector<uint8_t> * sessionId)211 bool DrmSessionManager::getLeastUsedSession_l(
212         int pid, sp<DrmSessionClientInterface>* drm, Vector<uint8_t>* sessionId) {
213     ssize_t index = mSessionMap.indexOfKey(pid);
214     if (index < 0) {
215         return false;
216     }
217 
218     int leastUsedIndex = -1;
219     int64_t minTs = LLONG_MAX;
220     const SessionInfos& infos = mSessionMap.valueAt(index);
221     for (size_t j = 0; j < infos.size(); ++j) {
222         if (leastUsedIndex == -1) {
223             leastUsedIndex = j;
224             minTs = infos[j].timeStamp;
225         } else {
226             if (infos[j].timeStamp < minTs) {
227                 leastUsedIndex = j;
228                 minTs = infos[j].timeStamp;
229             }
230         }
231     }
232     if (leastUsedIndex != -1) {
233         *drm = infos[leastUsedIndex].drm;
234         *sessionId = infos[leastUsedIndex].sessionId;
235     }
236     return (leastUsedIndex != -1);
237 }
238 
239 }  // namespace android
240