1 /*
2 * Copyright (C) 2010 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 "DrmManager(Native)"
19
20 #include <cutils/properties.h>
21 #include <utils/String8.h>
22 #include <utils/Log.h>
23
24 #include <binder/IPCThreadState.h>
25 #include <drm/DrmInfo.h>
26
27 #include <drm/DrmInfoEvent.h>
28 #include <drm/DrmRights.h>
29 #include <drm/DrmConstraints.h>
30 #include <drm/DrmMetadata.h>
31 #include <drm/DrmInfoStatus.h>
32 #include <drm/DrmInfoRequest.h>
33 #include <drm/DrmSupportInfo.h>
34 #include <drm/DrmConvertedStatus.h>
35 #include <media/MediaMetricsItem.h>
36 #include <IDrmEngine.h>
37
38 #include "DrmManager.h"
39 #include "ReadWriteUtils.h"
40
41 #include <algorithm>
42
43 #define DECRYPT_FILE_ERROR (-1)
44
45 using namespace android;
46
47 const String8 DrmManager::EMPTY_STRING("");
48
49 const std::map<const char*, size_t> DrmManager::kMethodIdMap {
50 {"getConstraints" , DrmManagerMethodId::GET_CONSTRAINTS },
51 {"getMetadata" , DrmManagerMethodId::GET_METADATA },
52 {"canHandle" , DrmManagerMethodId::CAN_HANDLE },
53 {"processDrmInfo" , DrmManagerMethodId::PROCESS_DRM_INFO },
54 {"acquireDrmInfo" , DrmManagerMethodId::ACQUIRE_DRM_INFO },
55 {"saveRights" , DrmManagerMethodId::SAVE_RIGHTS },
56 {"getOriginalMimeType", DrmManagerMethodId::GET_ORIGINAL_MIME_TYPE},
57 {"getDrmObjectType" , DrmManagerMethodId::GET_DRM_OBJECT_TYPE },
58 {"checkRightsStatus" , DrmManagerMethodId::CHECK_RIGHTS_STATUS },
59 {"removeRights" , DrmManagerMethodId::REMOVE_RIGHTS },
60 {"removeAllRights" , DrmManagerMethodId::REMOVE_ALL_RIGHTS },
61 {"openConvertSession" , DrmManagerMethodId::OPEN_CONVERT_SESSION },
62 {"openDecryptSession" , DrmManagerMethodId::OPEN_DECRYPT_SESSION }
63 };
64
DrmManager()65 DrmManager::DrmManager() :
66 mDecryptSessionId(0),
67 mConvertId(0) {
68 srand(time(NULL));
69 memset(mUniqueIdArray, 0, sizeof(bool) * kMaxNumUniqueIds);
70 }
71
~DrmManager()72 DrmManager::~DrmManager() {
73 if (mMetricsLooper != NULL) {
74 mMetricsLooper->stop();
75 }
76 flushEngineMetrics();
77 }
78
initMetricsLooper()79 void DrmManager::initMetricsLooper() {
80 if (mMetricsLooper != NULL) {
81 return;
82 }
83 mMetricsLooper = new ALooper;
84 mMetricsLooper->setName("DrmManagerMetricsLooper");
85 mMetricsLooper->start();
86 mMetricsLooper->registerHandler(this);
87
88 sp<AMessage> msg = new AMessage(kWhatFlushMetrics, this);
89 msg->post(getMetricsFlushPeriodUs());
90 }
91
onMessageReceived(const sp<AMessage> & msg)92 void DrmManager::onMessageReceived(const sp<AMessage> &msg) {
93 switch (msg->what()) {
94 case kWhatFlushMetrics:
95 {
96 flushEngineMetrics();
97 msg->post(getMetricsFlushPeriodUs());
98 break;
99 }
100 default:
101 {
102 ALOGW("Unrecognized message type: %zd", msg->what());
103 }
104 }
105 }
106
getMetricsFlushPeriodUs()107 int64_t DrmManager::getMetricsFlushPeriodUs() {
108 return 1000 * 1000 * std::max(1ll, property_get_int64("drmmanager.metrics.period", 86400));
109 }
110
recordEngineMetrics(const char func[],const String8 & plugInId8,const String8 & mimeType)111 void DrmManager::recordEngineMetrics(
112 const char func[], const String8& plugInId8, const String8& mimeType) {
113 IDrmEngine& engine = mPlugInManager.getPlugIn(plugInId8);
114 std::unique_ptr<DrmSupportInfo> info(engine.getSupportInfo(0));
115
116 uid_t callingUid = IPCThreadState::self()->getCallingUid();
117 std::string plugInId(plugInId8.getPathLeaf().getBasePath().c_str());
118 ALOGV("%d calling %s %s", callingUid, plugInId.c_str(), func);
119
120 Mutex::Autolock _l(mMetricsLock);
121 auto& metrics = mPluginMetrics[std::make_pair(callingUid, plugInId)];
122 if (metrics.mPluginId.empty()) {
123 metrics.mPluginId = plugInId;
124 metrics.mCallingUid = callingUid;
125 if (NULL != info) {
126 metrics.mDescription = info->getDescription().c_str();
127 }
128 }
129
130 if (!mimeType.isEmpty()) {
131 metrics.mMimeTypes.insert(mimeType.c_str());
132 } else if (NULL != info) {
133 DrmSupportInfo::MimeTypeIterator mimeIter = info->getMimeTypeIterator();
134 while (mimeIter.hasNext()) {
135 metrics.mMimeTypes.insert(mimeIter.next().c_str());
136 }
137 }
138
139 size_t methodId = kMethodIdMap.at(func);
140 if (methodId < metrics.mMethodCounts.size()) {
141 metrics.mMethodCounts[methodId]++;
142 }
143 }
144
flushEngineMetrics()145 void DrmManager::flushEngineMetrics() {
146 using namespace std::string_literals;
147 Mutex::Autolock _l(mMetricsLock);
148 for (auto kv : mPluginMetrics) {
149 DrmManagerMetrics& metrics = kv.second;
150 std::unique_ptr<mediametrics::Item> item(mediametrics::Item::create("drmmanager"));
151 item->setUid(metrics.mCallingUid);
152 item->setCString("plugin_id", metrics.mPluginId.c_str());
153 item->setCString("description", metrics.mDescription.c_str());
154
155 std::vector<std::string> mimeTypes(metrics.mMimeTypes.begin(), metrics.mMimeTypes.end());
156 std::string mimeTypesStr(mimeTypes.empty() ? "" : mimeTypes[0]);
157 for (size_t i = 1; i < mimeTypes.size() ; i++) {
158 mimeTypesStr.append(",").append(mimeTypes[i]);
159 }
160 item->setCString("mime_types", mimeTypesStr.c_str());
161
162 for (size_t i = 0; i < metrics.mMethodCounts.size() ; i++) {
163 item->setInt64(("method"s + std::to_string(i)).c_str(), metrics.mMethodCounts[i]);
164 }
165
166 if (!item->selfrecord()) {
167 ALOGE("Failed to record metrics");
168 }
169 }
170 mPluginMetrics.clear();
171 }
172
addUniqueId(bool isNative)173 int DrmManager::addUniqueId(bool isNative) {
174 Mutex::Autolock _l(mLock);
175
176 int uniqueId = -1;
177 int random = rand();
178
179 for (size_t index = 0; index < kMaxNumUniqueIds; ++index) {
180 int temp = (random + index) % kMaxNumUniqueIds;
181 if (!mUniqueIdArray[temp]) {
182 uniqueId = temp;
183 mUniqueIdArray[uniqueId] = true;
184
185 if (isNative) {
186 // set a flag to differentiate DrmManagerClient
187 // created from native side and java side
188 uniqueId |= 0x1000;
189 }
190 break;
191 }
192 }
193
194 // -1 indicates that no unique id can be allocated.
195 return uniqueId;
196 }
197
removeUniqueId(int uniqueId)198 void DrmManager::removeUniqueId(int uniqueId) {
199 Mutex::Autolock _l(mLock);
200 if (uniqueId & 0x1000) {
201 // clear the flag for the native side.
202 uniqueId &= ~(0x1000);
203 }
204
205 if (uniqueId >= 0 && uniqueId < kMaxNumUniqueIds) {
206 mUniqueIdArray[uniqueId] = false;
207 }
208 }
209
loadPlugIns()210 status_t DrmManager::loadPlugIns() {
211 String8 pluginDirPath("/system/lib/drm");
212 loadPlugIns(pluginDirPath);
213 return DRM_NO_ERROR;
214 }
215
loadPlugIns(const String8 & plugInDirPath)216 status_t DrmManager::loadPlugIns(const String8& plugInDirPath) {
217 mPlugInManager.loadPlugIns(plugInDirPath);
218 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
219 for (size_t i = 0; i < plugInPathList.size(); ++i) {
220 String8 plugInPath = plugInPathList[i];
221 DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
222 if (NULL != info) {
223 if (mSupportInfoToPlugInIdMap.indexOfKey(*info) < 0) {
224 mSupportInfoToPlugInIdMap.add(*info, plugInPath);
225 }
226 delete info;
227 }
228 }
229 return DRM_NO_ERROR;
230 }
231
unloadPlugIns()232 status_t DrmManager::unloadPlugIns() {
233 Mutex::Autolock _l(mLock);
234 mConvertSessionMap.clear();
235 mDecryptSessionMap.clear();
236 mPlugInManager.unloadPlugIns();
237 mSupportInfoToPlugInIdMap.clear();
238 return DRM_NO_ERROR;
239 }
240
setDrmServiceListener(int uniqueId,const sp<IDrmServiceListener> & drmServiceListener)241 status_t DrmManager::setDrmServiceListener(
242 int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) {
243 Mutex::Autolock _l(mListenerLock);
244 if (NULL != drmServiceListener.get()) {
245 mServiceListeners.add(uniqueId, drmServiceListener);
246 } else {
247 mServiceListeners.removeItem(uniqueId);
248 }
249 return DRM_NO_ERROR;
250 }
251
addClient(int uniqueId)252 void DrmManager::addClient(int uniqueId) {
253 Mutex::Autolock _l(mLock);
254 if (!mSupportInfoToPlugInIdMap.isEmpty()) {
255 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
256 for (size_t index = 0; index < plugInIdList.size(); index++) {
257 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
258 rDrmEngine.initialize(uniqueId);
259 rDrmEngine.setOnInfoListener(uniqueId, this);
260 }
261 }
262 }
263
removeClient(int uniqueId)264 void DrmManager::removeClient(int uniqueId) {
265 Mutex::Autolock _l(mLock);
266 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
267 for (size_t index = 0; index < plugInIdList.size(); index++) {
268 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
269 rDrmEngine.terminate(uniqueId);
270 }
271 }
272
getConstraints(int uniqueId,const String8 * path,const int action)273 DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) {
274 Mutex::Autolock _l(mLock);
275 DrmConstraints *constraints = NULL;
276 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
277 if (EMPTY_STRING != plugInId) {
278 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
279 constraints = rDrmEngine.getConstraints(uniqueId, path, action);
280 }
281 if (NULL != constraints) {
282 recordEngineMetrics(__func__, plugInId);
283 }
284 return constraints;
285 }
286
getMetadata(int uniqueId,const String8 * path)287 DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) {
288 Mutex::Autolock _l(mLock);
289 DrmMetadata *meta = NULL;
290 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path);
291 if (EMPTY_STRING != plugInId) {
292 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
293 meta = rDrmEngine.getMetadata(uniqueId, path);
294 }
295 if (NULL != meta) {
296 recordEngineMetrics(__func__, plugInId);
297 }
298 return meta;
299 }
300
canHandle(int uniqueId,const String8 & path,const String8 & mimeType)301 bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) {
302 Mutex::Autolock _l(mLock);
303 const String8 plugInId = getSupportedPlugInId(mimeType);
304 bool result = (EMPTY_STRING != plugInId) ? true : false;
305
306 if (result) {
307 recordEngineMetrics(__func__, plugInId, mimeType);
308 }
309
310 if (0 < path.length()) {
311 if (result) {
312 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
313 result = rDrmEngine.canHandle(uniqueId, path);
314 } else {
315 String8 extension = path.getPathExtension();
316 if (String8("") != extension) {
317 result = canHandle(uniqueId, path);
318 }
319 }
320 }
321 return result;
322 }
323
processDrmInfo(int uniqueId,const DrmInfo * drmInfo)324 DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
325 Mutex::Autolock _l(mLock);
326 DrmInfoStatus *infoStatus = NULL;
327 const String8 mimeType = drmInfo->getMimeType();
328 const String8 plugInId = getSupportedPlugInId(mimeType);
329 if (EMPTY_STRING != plugInId) {
330 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
331 infoStatus = rDrmEngine.processDrmInfo(uniqueId, drmInfo);
332 }
333 if (NULL != infoStatus) {
334 recordEngineMetrics(__func__, plugInId, mimeType);
335 }
336 return infoStatus;
337 }
338
canHandle(int uniqueId,const String8 & path)339 bool DrmManager::canHandle(int uniqueId, const String8& path) {
340 bool result = false;
341 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
342
343 for (size_t i = 0; i < plugInPathList.size(); ++i) {
344 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]);
345 result = rDrmEngine.canHandle(uniqueId, path);
346
347 if (result) {
348 recordEngineMetrics(__func__, plugInPathList[i]);
349 break;
350 }
351 }
352 return result;
353 }
354
acquireDrmInfo(int uniqueId,const DrmInfoRequest * drmInfoRequest)355 DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
356 Mutex::Autolock _l(mLock);
357 DrmInfo *info = NULL;
358 const String8 mimeType = drmInfoRequest->getMimeType();
359 const String8 plugInId = getSupportedPlugInId(mimeType);
360 if (EMPTY_STRING != plugInId) {
361 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
362 info = rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest);
363 }
364 if (NULL != info) {
365 recordEngineMetrics(__func__, plugInId, mimeType);
366 }
367 return info;
368 }
369
saveRights(int uniqueId,const DrmRights & drmRights,const String8 & rightsPath,const String8 & contentPath)370 status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights,
371 const String8& rightsPath, const String8& contentPath) {
372 Mutex::Autolock _l(mLock);
373 const String8 mimeType = drmRights.getMimeType();
374 const String8 plugInId = getSupportedPlugInId(mimeType);
375 status_t result = DRM_ERROR_UNKNOWN;
376 if (EMPTY_STRING != plugInId) {
377 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
378 result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath);
379 }
380 if (DRM_NO_ERROR == result) {
381 recordEngineMetrics(__func__, plugInId, mimeType);
382 }
383 return result;
384 }
385
getOriginalMimeType(int uniqueId,const String8 & path,int fd)386 String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path, int fd) {
387 Mutex::Autolock _l(mLock);
388 String8 mimeType(EMPTY_STRING);
389 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
390 if (EMPTY_STRING != plugInId) {
391 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
392 mimeType = rDrmEngine.getOriginalMimeType(uniqueId, path, fd);
393 }
394 if (!mimeType.isEmpty()) {
395 recordEngineMetrics(__func__, plugInId, mimeType);
396 }
397 return mimeType;
398 }
399
getDrmObjectType(int uniqueId,const String8 & path,const String8 & mimeType)400 int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) {
401 Mutex::Autolock _l(mLock);
402 int type = DrmObjectType::UNKNOWN;
403 const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType);
404 if (EMPTY_STRING != plugInId) {
405 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
406 type = rDrmEngine.getDrmObjectType(uniqueId, path, mimeType);
407 }
408 if (DrmObjectType::UNKNOWN != type) {
409 recordEngineMetrics(__func__, plugInId, mimeType);
410 }
411 return type;
412 }
413
checkRightsStatus(int uniqueId,const String8 & path,int action)414 int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) {
415 Mutex::Autolock _l(mLock);
416 int rightsStatus = RightsStatus::RIGHTS_INVALID;
417 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
418 if (EMPTY_STRING != plugInId) {
419 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
420 rightsStatus = rDrmEngine.checkRightsStatus(uniqueId, path, action);
421 }
422 if (RightsStatus::RIGHTS_INVALID != rightsStatus) {
423 recordEngineMetrics(__func__, plugInId);
424 }
425 return rightsStatus;
426 }
427
consumeRights(int uniqueId,sp<DecryptHandle> & decryptHandle,int action,bool reserve)428 status_t DrmManager::consumeRights(
429 int uniqueId, sp<DecryptHandle>& decryptHandle, int action, bool reserve) {
430 status_t result = DRM_ERROR_UNKNOWN;
431 Mutex::Autolock _l(mDecryptLock);
432 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
433 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
434 result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve);
435 }
436 return result;
437 }
438
setPlaybackStatus(int uniqueId,sp<DecryptHandle> & decryptHandle,int playbackStatus,int64_t position)439 status_t DrmManager::setPlaybackStatus(
440 int uniqueId, sp<DecryptHandle>& decryptHandle, int playbackStatus, int64_t position) {
441 status_t result = DRM_ERROR_UNKNOWN;
442 Mutex::Autolock _l(mDecryptLock);
443 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
444 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
445 result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
446 }
447 return result;
448 }
449
validateAction(int uniqueId,const String8 & path,int action,const ActionDescription & description)450 bool DrmManager::validateAction(
451 int uniqueId, const String8& path, int action, const ActionDescription& description) {
452 Mutex::Autolock _l(mLock);
453 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
454 if (EMPTY_STRING != plugInId) {
455 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
456 return rDrmEngine.validateAction(uniqueId, path, action, description);
457 }
458 return false;
459 }
460
removeRights(int uniqueId,const String8 & path)461 status_t DrmManager::removeRights(int uniqueId, const String8& path) {
462 Mutex::Autolock _l(mLock);
463 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
464 status_t result = DRM_ERROR_UNKNOWN;
465 if (EMPTY_STRING != plugInId) {
466 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
467 result = rDrmEngine.removeRights(uniqueId, path);
468 }
469 if (DRM_NO_ERROR == result) {
470 recordEngineMetrics(__func__, plugInId);
471 }
472 return result;
473 }
474
removeAllRights(int uniqueId)475 status_t DrmManager::removeAllRights(int uniqueId) {
476 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
477 status_t result = DRM_ERROR_UNKNOWN;
478 for (size_t index = 0; index < plugInIdList.size(); index++) {
479 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index));
480 result = rDrmEngine.removeAllRights(uniqueId);
481 if (DRM_NO_ERROR != result) {
482 break;
483 }
484 recordEngineMetrics(__func__, plugInIdList[index]);
485 }
486 return result;
487 }
488
openConvertSession(int uniqueId,const String8 & mimeType)489 int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) {
490 Mutex::Autolock _l(mConvertLock);
491 int convertId = -1;
492
493 const String8 plugInId = getSupportedPlugInId(mimeType);
494 if (EMPTY_STRING != plugInId) {
495 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
496
497 if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) {
498 ++mConvertId;
499 convertId = mConvertId;
500 mConvertSessionMap.add(convertId, &rDrmEngine);
501 recordEngineMetrics(__func__, plugInId, mimeType);
502 }
503 }
504 return convertId;
505 }
506
convertData(int uniqueId,int convertId,const DrmBuffer * inputData)507 DrmConvertedStatus* DrmManager::convertData(
508 int uniqueId, int convertId, const DrmBuffer* inputData) {
509 DrmConvertedStatus *drmConvertedStatus = NULL;
510
511 Mutex::Autolock _l(mConvertLock);
512 if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
513 IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
514 drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData);
515 }
516 return drmConvertedStatus;
517 }
518
closeConvertSession(int uniqueId,int convertId)519 DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) {
520 Mutex::Autolock _l(mConvertLock);
521 DrmConvertedStatus *drmConvertedStatus = NULL;
522
523 if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) {
524 IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId);
525 drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId);
526 mConvertSessionMap.removeItem(convertId);
527 }
528 return drmConvertedStatus;
529 }
530
getAllSupportInfo(int,int * length,DrmSupportInfo ** drmSupportInfoArray)531 status_t DrmManager::getAllSupportInfo(
532 int /* uniqueId */, int* length, DrmSupportInfo** drmSupportInfoArray) {
533 Mutex::Autolock _l(mLock);
534 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList();
535 int size = plugInPathList.size();
536 int validPlugins = 0;
537
538 if (0 < size) {
539 Vector<DrmSupportInfo> drmSupportInfoList;
540
541 for (int i = 0; i < size; ++i) {
542 String8 plugInPath = plugInPathList[i];
543 DrmSupportInfo* drmSupportInfo
544 = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0);
545 if (NULL != drmSupportInfo) {
546 drmSupportInfoList.add(*drmSupportInfo);
547 delete drmSupportInfo; drmSupportInfo = NULL;
548 }
549 }
550
551 validPlugins = drmSupportInfoList.size();
552 if (0 < validPlugins) {
553 *drmSupportInfoArray = new DrmSupportInfo[validPlugins];
554 for (int i = 0; i < validPlugins; ++i) {
555 (*drmSupportInfoArray)[i] = drmSupportInfoList[i];
556 }
557 }
558 }
559 *length = validPlugins;
560 return DRM_NO_ERROR;
561 }
562
openDecryptSession(int uniqueId,int fd,off64_t offset,off64_t length,const char * mime)563 sp<DecryptHandle> DrmManager::openDecryptSession(
564 int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
565
566 Mutex::Autolock _l(mDecryptLock);
567 status_t result = DRM_ERROR_CANNOT_HANDLE;
568 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
569
570 sp<DecryptHandle> handle = new DecryptHandle();
571 if (NULL != handle.get()) {
572 handle->decryptId = mDecryptSessionId + 1;
573
574 for (size_t index = 0; index < plugInIdList.size(); index++) {
575 const String8& plugInId = plugInIdList.itemAt(index);
576 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
577 result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length, mime);
578
579 if (DRM_NO_ERROR == result) {
580 ++mDecryptSessionId;
581 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
582 recordEngineMetrics(__func__, plugInId, String8(mime));
583 break;
584 }
585 }
586 }
587 if (DRM_NO_ERROR != result) {
588 handle.clear();
589 }
590 return handle;
591 }
592
openDecryptSession(int uniqueId,const char * uri,const char * mime)593 sp<DecryptHandle> DrmManager::openDecryptSession(
594 int uniqueId, const char* uri, const char* mime) {
595 Mutex::Autolock _l(mDecryptLock);
596 status_t result = DRM_ERROR_CANNOT_HANDLE;
597 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
598
599 sp<DecryptHandle> handle = new DecryptHandle();
600 if (NULL != handle.get()) {
601 handle->decryptId = mDecryptSessionId + 1;
602
603 for (size_t index = 0; index < plugInIdList.size(); index++) {
604 const String8& plugInId = plugInIdList.itemAt(index);
605 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
606 result = rDrmEngine.openDecryptSession(uniqueId, handle, uri, mime);
607
608 if (DRM_NO_ERROR == result) {
609 ++mDecryptSessionId;
610 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
611 recordEngineMetrics(__func__, plugInId, String8(mime));
612 break;
613 }
614 }
615 }
616 if (DRM_NO_ERROR != result) {
617 handle.clear();
618 ALOGV("DrmManager::openDecryptSession: no capable plug-in found");
619 }
620 return handle;
621 }
622
openDecryptSession(int uniqueId,const DrmBuffer & buf,const String8 & mimeType)623 sp<DecryptHandle> DrmManager::openDecryptSession(
624 int uniqueId, const DrmBuffer& buf, const String8& mimeType) {
625 Mutex::Autolock _l(mDecryptLock);
626 status_t result = DRM_ERROR_CANNOT_HANDLE;
627 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList();
628
629 sp<DecryptHandle> handle = new DecryptHandle();
630 if (NULL != handle.get()) {
631 handle->decryptId = mDecryptSessionId + 1;
632
633 for (size_t index = 0; index < plugInIdList.size(); index++) {
634 const String8& plugInId = plugInIdList.itemAt(index);
635 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId);
636 result = rDrmEngine.openDecryptSession(uniqueId, handle, buf, mimeType);
637
638 if (DRM_NO_ERROR == result) {
639 ++mDecryptSessionId;
640 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine);
641 recordEngineMetrics(__func__, plugInId, mimeType);
642 break;
643 }
644 }
645 }
646 if (DRM_NO_ERROR != result) {
647 handle.clear();
648 ALOGV("DrmManager::openDecryptSession: no capable plug-in found");
649 }
650 return handle;
651 }
652
closeDecryptSession(int uniqueId,sp<DecryptHandle> & decryptHandle)653 status_t DrmManager::closeDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) {
654 Mutex::Autolock _l(mDecryptLock);
655 status_t result = DRM_ERROR_UNKNOWN;
656 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
657 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
658 result = drmEngine->closeDecryptSession(uniqueId, decryptHandle);
659 if (DRM_NO_ERROR == result && NULL != decryptHandle.get()) {
660 mDecryptSessionMap.removeItem(decryptHandle->decryptId);
661 }
662 }
663 return result;
664 }
665
initializeDecryptUnit(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId,const DrmBuffer * headerInfo)666 status_t DrmManager::initializeDecryptUnit(
667 int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId,
668 const DrmBuffer* headerInfo) {
669 status_t result = DRM_ERROR_UNKNOWN;
670 Mutex::Autolock _l(mDecryptLock);
671 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
672 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
673 result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo);
674 }
675 return result;
676 }
677
decrypt(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId,const DrmBuffer * encBuffer,DrmBuffer ** decBuffer,DrmBuffer * IV)678 status_t DrmManager::decrypt(int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId,
679 const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
680 status_t result = DRM_ERROR_UNKNOWN;
681
682 Mutex::Autolock _l(mDecryptLock);
683 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
684 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
685 result = drmEngine->decrypt(
686 uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
687 }
688 return result;
689 }
690
finalizeDecryptUnit(int uniqueId,sp<DecryptHandle> & decryptHandle,int decryptUnitId)691 status_t DrmManager::finalizeDecryptUnit(
692 int uniqueId, sp<DecryptHandle>& decryptHandle, int decryptUnitId) {
693 status_t result = DRM_ERROR_UNKNOWN;
694 Mutex::Autolock _l(mDecryptLock);
695 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
696 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
697 result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
698 }
699 return result;
700 }
701
pread(int uniqueId,sp<DecryptHandle> & decryptHandle,void * buffer,ssize_t numBytes,off64_t offset)702 ssize_t DrmManager::pread(int uniqueId, sp<DecryptHandle>& decryptHandle,
703 void* buffer, ssize_t numBytes, off64_t offset) {
704 ssize_t result = DECRYPT_FILE_ERROR;
705
706 Mutex::Autolock _l(mDecryptLock);
707 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) {
708 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId);
709 result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
710 }
711 return result;
712 }
713
getSupportedPlugInId(int uniqueId,const String8 & path,const String8 & mimeType)714 String8 DrmManager::getSupportedPlugInId(
715 int uniqueId, const String8& path, const String8& mimeType) {
716 String8 plugInId("");
717
718 if (EMPTY_STRING != mimeType) {
719 plugInId = getSupportedPlugInId(mimeType);
720 } else {
721 plugInId = getSupportedPlugInIdFromPath(uniqueId, path);
722 }
723 return plugInId;
724 }
725
getSupportedPlugInId(const String8 & mimeType)726 String8 DrmManager::getSupportedPlugInId(const String8& mimeType) {
727 String8 plugInId("");
728
729 if (EMPTY_STRING != mimeType) {
730 for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
731 const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
732
733 if (drmSupportInfo.isSupportedMimeType(mimeType)) {
734 plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
735 break;
736 }
737 }
738 }
739 return plugInId;
740 }
741
getSupportedPlugInIdFromPath(int uniqueId,const String8 & path)742 String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) {
743 String8 plugInId("");
744 const String8 fileSuffix = path.getPathExtension();
745
746 for (size_t index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) {
747 const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index);
748
749 if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) {
750 String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo);
751 IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key);
752
753 if (drmEngine.canHandle(uniqueId, path)) {
754 plugInId = key;
755 break;
756 }
757 }
758 }
759 return plugInId;
760 }
761
onInfo(const DrmInfoEvent & event)762 void DrmManager::onInfo(const DrmInfoEvent& event) {
763 Mutex::Autolock _l(mListenerLock);
764 for (size_t index = 0; index < mServiceListeners.size(); index++) {
765 int uniqueId = mServiceListeners.keyAt(index);
766
767 if (uniqueId == event.getUniqueId()) {
768 sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId);
769 serviceListener->notify(event);
770 }
771 }
772 }
773
774