blob: 641f88173734aff2b803e49cebff5dfd272bae5d [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
21#include "DrmSessionManager.h"
22
23#include "DrmSessionClientInterface.h"
Ronghua Wu10305cc2015-02-22 07:55:32 -080024#include <binder/IPCThreadState.h>
Ronghua Wu5c3da202015-02-22 08:45:28 -080025#include <binder/IProcessInfoService.h>
26#include <binder/IServiceManager.h>
Ronghua Wu14bcaca2015-03-16 11:24:30 -070027#include <media/stagefright/ProcessInfo.h>
Ronghua Wu10305cc2015-02-22 07:55:32 -080028#include <unistd.h>
29#include <utils/String8.h>
30
31namespace android {
32
33static 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
Ronghua Wu10305cc2015-02-22 07:55:32 -080041bool 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
Ronghua Wu5c3da202015-02-22 08:45:28 -080053sp<DrmSessionManager> DrmSessionManager::Instance() {
54 static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
55 return drmSessionManager;
56}
57
Ronghua Wu10305cc2015-02-22 07:55:32 -080058DrmSessionManager::DrmSessionManager()
59 : mProcessInfo(new ProcessInfo()),
60 mTime(0) {}
61
62DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
63 : mProcessInfo(processInfo),
64 mTime(0) {}
65
66DrmSessionManager::~DrmSessionManager() {}
67
68void 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
89void 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
105void 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
120void 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
142bool DrmSessionManager::reclaimSession(int callingPid) {
143 ALOGV("reclaimSession(%d)", callingPid);
144
145 sp<DrmSessionClientInterface> drm;
146 Vector<uint8_t> sessionId;
Ronghua Wu5c3da202015-02-22 08:45:28 -0800147 int lowestPriorityPid;
148 int lowestPriority;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800149 {
150 Mutex::Autolock lock(mLock);
Ronghua Wu5c3da202015-02-22 08:45:28 -0800151 int callingPriority;
152 if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
153 return false;
154 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800155 if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
156 return false;
157 }
Ronghua Wu5c3da202015-02-22 08:45:28 -0800158 if (lowestPriority <= callingPriority) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800159 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
Ronghua Wu5c3da202015-02-22 08:45:28 -0800171 ALOGV("reclaim session(%s) opened by pid %d",
172 GetSessionIdString(sessionId).string(), lowestPriorityPid);
173
Ronghua Wu10305cc2015-02-22 07:55:32 -0800174 return drm->reclaimSession(sessionId);
175}
176
177int64_t DrmSessionManager::getTime_l() {
178 return mTime++;
179}
180
181bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
182 int pid = -1;
Ronghua Wu5c3da202015-02-22 08:45:28 -0800183 int priority = -1;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800184 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);
Ronghua Wu5c3da202015-02-22 08:45:28 -0800190 int tempPriority;
191 if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
192 // shouldn't happen.
193 return false;
194 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800195 if (pid == -1) {
196 pid = tempPid;
197 priority = tempPriority;
198 } else {
Ronghua Wu5c3da202015-02-22 08:45:28 -0800199 if (tempPriority > priority) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800200 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
212bool 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