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