blob: 375644ce87dbffd8d22ffab66b2055a8bb008616 [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
Ronghua Wu10305cc2015-02-22 07:55:32 -080021#include <binder/IPCThreadState.h>
Ronghua Wu5c3da202015-02-22 08:45:28 -080022#include <binder/IProcessInfoService.h>
23#include <binder/IServiceManager.h>
Ronghua Wu14bcaca2015-03-16 11:24:30 -070024#include <media/stagefright/ProcessInfo.h>
Jeff Tinker7d2c6e82018-02-16 16:14:59 -080025#include <mediadrm/DrmSessionClientInterface.h>
26#include <mediadrm/DrmSessionManager.h>
Ronghua Wu10305cc2015-02-22 07:55:32 -080027#include <unistd.h>
28#include <utils/String8.h>
29
30namespace android {
31
32static 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
Ronghua Wu10305cc2015-02-22 07:55:32 -080040bool 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
Ronghua Wu5c3da202015-02-22 08:45:28 -080052sp<DrmSessionManager> DrmSessionManager::Instance() {
53 static sp<DrmSessionManager> drmSessionManager = new DrmSessionManager();
54 return drmSessionManager;
55}
56
Ronghua Wu10305cc2015-02-22 07:55:32 -080057DrmSessionManager::DrmSessionManager()
58 : mProcessInfo(new ProcessInfo()),
59 mTime(0) {}
60
61DrmSessionManager::DrmSessionManager(sp<ProcessInfoInterface> processInfo)
62 : mProcessInfo(processInfo),
63 mTime(0) {}
64
65DrmSessionManager::~DrmSessionManager() {}
66
67void DrmSessionManager::addSession(
Chih-Hung Hsieh8c0164c2016-08-09 14:20:59 -070068 int pid, const sp<DrmSessionClientInterface>& drm, const Vector<uint8_t> &sessionId) {
Ronghua Wu10305cc2015-02-22 07:55:32 -080069 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
88void 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
104void 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
Chih-Hung Hsieh8c0164c2016-08-09 14:20:59 -0700119void DrmSessionManager::removeDrm(const sp<DrmSessionClientInterface>& drm) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800120 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
141bool DrmSessionManager::reclaimSession(int callingPid) {
142 ALOGV("reclaimSession(%d)", callingPid);
143
144 sp<DrmSessionClientInterface> drm;
145 Vector<uint8_t> sessionId;
Ronghua Wu5c3da202015-02-22 08:45:28 -0800146 int lowestPriorityPid;
147 int lowestPriority;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800148 {
149 Mutex::Autolock lock(mLock);
Ronghua Wu5c3da202015-02-22 08:45:28 -0800150 int callingPriority;
151 if (!mProcessInfo->getPriority(callingPid, &callingPriority)) {
152 return false;
153 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800154 if (!getLowestPriority_l(&lowestPriorityPid, &lowestPriority)) {
155 return false;
156 }
Ronghua Wu5c3da202015-02-22 08:45:28 -0800157 if (lowestPriority <= callingPriority) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800158 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
Ronghua Wu5c3da202015-02-22 08:45:28 -0800170 ALOGV("reclaim session(%s) opened by pid %d",
171 GetSessionIdString(sessionId).string(), lowestPriorityPid);
172
Ronghua Wu10305cc2015-02-22 07:55:32 -0800173 return drm->reclaimSession(sessionId);
174}
175
176int64_t DrmSessionManager::getTime_l() {
177 return mTime++;
178}
179
180bool DrmSessionManager::getLowestPriority_l(int* lowestPriorityPid, int* lowestPriority) {
181 int pid = -1;
Ronghua Wu5c3da202015-02-22 08:45:28 -0800182 int priority = -1;
Ronghua Wu10305cc2015-02-22 07:55:32 -0800183 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);
Ronghua Wu5c3da202015-02-22 08:45:28 -0800189 int tempPriority;
190 if (!mProcessInfo->getPriority(tempPid, &tempPriority)) {
191 // shouldn't happen.
192 return false;
193 }
Ronghua Wu10305cc2015-02-22 07:55:32 -0800194 if (pid == -1) {
195 pid = tempPid;
196 priority = tempPriority;
197 } else {
Ronghua Wu5c3da202015-02-22 08:45:28 -0800198 if (tempPriority > priority) {
Ronghua Wu10305cc2015-02-22 07:55:32 -0800199 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
211bool 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