DrmManager.cpp revision 3473846f64f5b28e1cbeb70ef5867073fc93159e
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#include "utils/Log.h" 20 21#include <utils/String8.h> 22#include <drm/DrmInfo.h> 23#include <drm/DrmInfoEvent.h> 24#include <drm/DrmRights.h> 25#include <drm/DrmConstraints.h> 26#include <drm/DrmMetadata.h> 27#include <drm/DrmInfoStatus.h> 28#include <drm/DrmInfoRequest.h> 29#include <drm/DrmSupportInfo.h> 30#include <drm/DrmConvertedStatus.h> 31#include <IDrmEngine.h> 32 33#include "DrmManager.h" 34#include "ReadWriteUtils.h" 35 36#define DECRYPT_FILE_ERROR -1 37 38using namespace android; 39 40Vector<int> DrmManager::mUniqueIdVector; 41const String8 DrmManager::EMPTY_STRING(""); 42 43DrmManager::DrmManager() : 44 mDecryptSessionId(0), 45 mConvertId(0) { 46 47} 48 49DrmManager::~DrmManager() { 50 51} 52 53int DrmManager::addUniqueId(int uniqueId) { 54 if (0 == uniqueId) { 55 int temp = 0; 56 bool foundUniqueId = false; 57 srand(time(NULL)); 58 59 while (!foundUniqueId) { 60 const int size = mUniqueIdVector.size(); 61 temp = rand() % 100; 62 63 int index = 0; 64 for (; index < size; ++index) { 65 if (mUniqueIdVector.itemAt(index) == temp) { 66 foundUniqueId = false; 67 break; 68 } 69 } 70 if (index == size) { 71 foundUniqueId = true; 72 } 73 } 74 uniqueId = temp; 75 } 76 mUniqueIdVector.push(uniqueId); 77 return uniqueId; 78} 79 80void DrmManager::removeUniqueId(int uniqueId) { 81 for (unsigned int i = 0; i < mUniqueIdVector.size(); i++) { 82 if (uniqueId == mUniqueIdVector.itemAt(i)) { 83 mUniqueIdVector.removeAt(i); 84 break; 85 } 86 } 87} 88 89status_t DrmManager::loadPlugIns() { 90 String8 pluginDirPath("/system/lib/drm/plugins/native"); 91 return loadPlugIns(pluginDirPath); 92} 93 94status_t DrmManager::loadPlugIns(const String8& plugInDirPath) { 95 if (mSupportInfoToPlugInIdMap.isEmpty()) { 96 mPlugInManager.loadPlugIns(plugInDirPath); 97 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); 98 for (unsigned int i = 0; i < plugInPathList.size(); ++i) { 99 String8 plugInPath = plugInPathList[i]; 100 DrmSupportInfo* info = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); 101 if (NULL != info) { 102 mSupportInfoToPlugInIdMap.add(*info, plugInPath); 103 } 104 } 105 } 106 return DRM_NO_ERROR; 107} 108 109status_t DrmManager::unloadPlugIns() { 110 mConvertSessionMap.clear(); 111 mDecryptSessionMap.clear(); 112 mPlugInManager.unloadPlugIns(); 113 mSupportInfoToPlugInIdMap.clear(); 114 return DRM_NO_ERROR; 115} 116 117status_t DrmManager::setDrmServiceListener( 118 int uniqueId, const sp<IDrmServiceListener>& drmServiceListener) { 119 Mutex::Autolock _l(mLock); 120 mServiceListeners.add(uniqueId, drmServiceListener); 121 return DRM_NO_ERROR; 122} 123 124void DrmManager::addClient(int uniqueId) { 125 if (!mSupportInfoToPlugInIdMap.isEmpty()) { 126 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); 127 for (unsigned int index = 0; index < plugInIdList.size(); index++) { 128 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); 129 rDrmEngine.initialize(uniqueId); 130 rDrmEngine.setOnInfoListener(uniqueId, this); 131 } 132 } 133} 134 135void DrmManager::removeClient(int uniqueId) { 136 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); 137 for (unsigned int index = 0; index < plugInIdList.size(); index++) { 138 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); 139 rDrmEngine.terminate(uniqueId); 140 } 141} 142 143DrmConstraints* DrmManager::getConstraints(int uniqueId, const String8* path, const int action) { 144 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); 145 if (EMPTY_STRING != plugInId) { 146 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 147 return rDrmEngine.getConstraints(uniqueId, path, action); 148 } 149 return NULL; 150} 151 152DrmMetadata* DrmManager::getMetadata(int uniqueId, const String8* path) { 153 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, *path); 154 if (EMPTY_STRING != plugInId) { 155 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 156 return rDrmEngine.getMetadata(uniqueId, path); 157 } 158 return NULL; 159} 160 161status_t DrmManager::installDrmEngine(int uniqueId, const String8& absolutePath) { 162 mPlugInManager.loadPlugIn(absolutePath); 163 164 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(absolutePath); 165 rDrmEngine.initialize(uniqueId); 166 rDrmEngine.setOnInfoListener(uniqueId, this); 167 168 DrmSupportInfo* info = rDrmEngine.getSupportInfo(0); 169 mSupportInfoToPlugInIdMap.add(*info, absolutePath); 170 171 return DRM_NO_ERROR; 172} 173 174bool DrmManager::canHandle(int uniqueId, const String8& path, const String8& mimeType) { 175 const String8 plugInId = getSupportedPlugInId(mimeType); 176 bool result = (EMPTY_STRING != plugInId) ? true : false; 177 178 if (0 < path.length()) { 179 if (result) { 180 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 181 result = rDrmEngine.canHandle(uniqueId, path); 182 } else { 183 result = canHandle(uniqueId, path); 184 } 185 } 186 return result; 187} 188 189DrmInfoStatus* DrmManager::processDrmInfo(int uniqueId, const DrmInfo* drmInfo) { 190 const String8 plugInId = getSupportedPlugInId(drmInfo->getMimeType()); 191 if (EMPTY_STRING != plugInId) { 192 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 193 return rDrmEngine.processDrmInfo(uniqueId, drmInfo); 194 } 195 return NULL; 196} 197 198bool DrmManager::canHandle(int uniqueId, const String8& path) { 199 bool result = false; 200 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); 201 202 for (unsigned int i = 0; i < plugInPathList.size(); ++i) { 203 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInPathList[i]); 204 result = rDrmEngine.canHandle(uniqueId, path); 205 206 if (result) { 207 break; 208 } 209 } 210 return result; 211} 212 213DrmInfo* DrmManager::acquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { 214 const String8 plugInId = getSupportedPlugInId(drmInfoRequest->getMimeType()); 215 if (EMPTY_STRING != plugInId) { 216 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 217 return rDrmEngine.acquireDrmInfo(uniqueId, drmInfoRequest); 218 } 219 return NULL; 220} 221 222status_t DrmManager::saveRights(int uniqueId, const DrmRights& drmRights, 223 const String8& rightsPath, const String8& contentPath) { 224 const String8 plugInId = getSupportedPlugInId(drmRights.getMimeType()); 225 status_t result = DRM_ERROR_UNKNOWN; 226 if (EMPTY_STRING != plugInId) { 227 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 228 result = rDrmEngine.saveRights(uniqueId, drmRights, rightsPath, contentPath); 229 } 230 return result; 231} 232 233String8 DrmManager::getOriginalMimeType(int uniqueId, const String8& path) { 234 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); 235 if (EMPTY_STRING != plugInId) { 236 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 237 return rDrmEngine.getOriginalMimeType(uniqueId, path); 238 } 239 return EMPTY_STRING; 240} 241 242int DrmManager::getDrmObjectType(int uniqueId, const String8& path, const String8& mimeType) { 243 const String8 plugInId = getSupportedPlugInId(uniqueId, path, mimeType); 244 if (EMPTY_STRING != plugInId) { 245 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 246 return rDrmEngine.getDrmObjectType(uniqueId, path, mimeType); 247 } 248 return DrmObjectType::UNKNOWN; 249} 250 251int DrmManager::checkRightsStatus(int uniqueId, const String8& path, int action) { 252 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); 253 if (EMPTY_STRING != plugInId) { 254 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 255 return rDrmEngine.checkRightsStatus(uniqueId, path, action); 256 } 257 return RightsStatus::RIGHTS_INVALID; 258} 259 260status_t DrmManager::consumeRights( 261 int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) { 262 status_t result = DRM_ERROR_UNKNOWN; 263 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 264 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 265 result = drmEngine->consumeRights(uniqueId, decryptHandle, action, reserve); 266 } 267 return result; 268} 269 270status_t DrmManager::setPlaybackStatus( 271 int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int position) { 272 status_t result = DRM_ERROR_UNKNOWN; 273 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 274 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 275 result = drmEngine->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position); 276 } 277 return result; 278} 279 280bool DrmManager::validateAction( 281 int uniqueId, const String8& path, int action, const ActionDescription& description) { 282 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); 283 if (EMPTY_STRING != plugInId) { 284 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 285 return rDrmEngine.validateAction(uniqueId, path, action, description); 286 } 287 return false; 288} 289 290status_t DrmManager::removeRights(int uniqueId, const String8& path) { 291 const String8 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); 292 status_t result = DRM_ERROR_UNKNOWN; 293 if (EMPTY_STRING != plugInId) { 294 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 295 result = rDrmEngine.removeRights(uniqueId, path); 296 } 297 return result; 298} 299 300status_t DrmManager::removeAllRights(int uniqueId) { 301 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); 302 status_t result = DRM_ERROR_UNKNOWN; 303 for (unsigned int index = 0; index < plugInIdList.size(); index++) { 304 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInIdList.itemAt(index)); 305 result = rDrmEngine.removeAllRights(uniqueId); 306 if (DRM_NO_ERROR != result) { 307 break; 308 } 309 } 310 return result; 311} 312 313int DrmManager::openConvertSession(int uniqueId, const String8& mimeType) { 314 int convertId = -1; 315 316 const String8 plugInId = getSupportedPlugInId(mimeType); 317 if (EMPTY_STRING != plugInId) { 318 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 319 320 if (DRM_NO_ERROR == rDrmEngine.openConvertSession(uniqueId, mConvertId + 1)) { 321 Mutex::Autolock _l(mConvertLock); 322 ++mConvertId; 323 convertId = mConvertId; 324 mConvertSessionMap.add(convertId, &rDrmEngine); 325 } 326 } 327 return convertId; 328} 329 330DrmConvertedStatus* DrmManager::convertData( 331 int uniqueId, int convertId, const DrmBuffer* inputData) { 332 DrmConvertedStatus *drmConvertedStatus = NULL; 333 334 if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { 335 IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId); 336 drmConvertedStatus = drmEngine->convertData(uniqueId, convertId, inputData); 337 } 338 return drmConvertedStatus; 339} 340 341DrmConvertedStatus* DrmManager::closeConvertSession(int uniqueId, int convertId) { 342 DrmConvertedStatus *drmConvertedStatus = NULL; 343 344 if (mConvertSessionMap.indexOfKey(convertId) != NAME_NOT_FOUND) { 345 IDrmEngine* drmEngine = mConvertSessionMap.valueFor(convertId); 346 drmConvertedStatus = drmEngine->closeConvertSession(uniqueId, convertId); 347 mConvertSessionMap.removeItem(convertId); 348 } 349 return drmConvertedStatus; 350} 351 352status_t DrmManager::getAllSupportInfo( 353 int uniqueId, int* length, DrmSupportInfo** drmSupportInfoArray) { 354 Vector<String8> plugInPathList = mPlugInManager.getPlugInIdList(); 355 int size = plugInPathList.size(); 356 int validPlugins = 0; 357 358 if (0 < size) { 359 Vector<DrmSupportInfo> drmSupportInfoList; 360 361 for (int i = 0; i < size; ++i) { 362 String8 plugInPath = plugInPathList[i]; 363 DrmSupportInfo* drmSupportInfo 364 = mPlugInManager.getPlugIn(plugInPath).getSupportInfo(0); 365 if (NULL != drmSupportInfo) { 366 drmSupportInfoList.add(*drmSupportInfo); 367 delete drmSupportInfo; drmSupportInfo = NULL; 368 } 369 } 370 371 validPlugins = drmSupportInfoList.size(); 372 if (0 < validPlugins) { 373 *drmSupportInfoArray = new DrmSupportInfo[validPlugins]; 374 for (int i = 0; i < validPlugins; ++i) { 375 (*drmSupportInfoArray)[i] = drmSupportInfoList[i]; 376 } 377 } 378 } 379 *length = validPlugins; 380 return DRM_NO_ERROR; 381} 382 383DecryptHandle* DrmManager::openDecryptSession(int uniqueId, int fd, int offset, int length) { 384 Mutex::Autolock _l(mDecryptLock); 385 status_t result = DRM_ERROR_CANNOT_HANDLE; 386 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); 387 388 DecryptHandle* handle = new DecryptHandle(); 389 if (NULL != handle) { 390 handle->decryptId = mDecryptSessionId + 1; 391 392 for (unsigned int index = 0; index < plugInIdList.size(); index++) { 393 String8 plugInId = plugInIdList.itemAt(index); 394 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 395 result = rDrmEngine.openDecryptSession(uniqueId, handle, fd, offset, length); 396 397 if (DRM_NO_ERROR == result) { 398 ++mDecryptSessionId; 399 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); 400 break; 401 } 402 } 403 } 404 if (DRM_NO_ERROR != result) { 405 delete handle; handle = NULL; 406 LOGE("DrmManager::openDecryptSession: no capable plug-in found"); 407 } 408 return handle; 409} 410 411DecryptHandle* DrmManager::openDecryptSession(int uniqueId, const char* uri) { 412 Mutex::Autolock _l(mDecryptLock); 413 status_t result = DRM_ERROR_CANNOT_HANDLE; 414 Vector<String8> plugInIdList = mPlugInManager.getPlugInIdList(); 415 416 DecryptHandle* handle = new DecryptHandle(); 417 if (NULL != handle) { 418 handle->decryptId = mDecryptSessionId + 1; 419 420 for (unsigned int index = 0; index < plugInIdList.size(); index++) { 421 String8 plugInId = plugInIdList.itemAt(index); 422 IDrmEngine& rDrmEngine = mPlugInManager.getPlugIn(plugInId); 423 result = rDrmEngine.openDecryptSession(uniqueId, handle, uri); 424 425 if (DRM_NO_ERROR == result) { 426 ++mDecryptSessionId; 427 mDecryptSessionMap.add(mDecryptSessionId, &rDrmEngine); 428 break; 429 } 430 } 431 } 432 if (DRM_NO_ERROR != result) { 433 delete handle; handle = NULL; 434 LOGE("DrmManager::openDecryptSession: no capable plug-in found"); 435 } 436 return handle; 437} 438 439status_t DrmManager::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { 440 Mutex::Autolock _l(mDecryptLock); 441 status_t result = DRM_ERROR_UNKNOWN; 442 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 443 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 444 result = drmEngine->closeDecryptSession(uniqueId, decryptHandle); 445 if (DRM_NO_ERROR == result) { 446 mDecryptSessionMap.removeItem(decryptHandle->decryptId); 447 } 448 } 449 return result; 450} 451 452status_t DrmManager::initializeDecryptUnit( 453 int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, const DrmBuffer* headerInfo) { 454 status_t result = DRM_ERROR_UNKNOWN; 455 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 456 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 457 result = drmEngine->initializeDecryptUnit(uniqueId, decryptHandle, decryptUnitId, headerInfo); 458 } 459 return result; 460} 461 462status_t DrmManager::decrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, 463 const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { 464 status_t result = DRM_ERROR_UNKNOWN; 465 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 466 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 467 result = drmEngine->decrypt( 468 uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV); 469 } 470 return result; 471} 472 473status_t DrmManager::finalizeDecryptUnit( 474 int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) { 475 status_t result = DRM_ERROR_UNKNOWN; 476 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 477 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 478 result = drmEngine->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId); 479 } 480 return result; 481} 482 483ssize_t DrmManager::pread(int uniqueId, DecryptHandle* decryptHandle, 484 void* buffer, ssize_t numBytes, off_t offset) { 485 ssize_t result = DECRYPT_FILE_ERROR; 486 487 if (mDecryptSessionMap.indexOfKey(decryptHandle->decryptId) != NAME_NOT_FOUND) { 488 IDrmEngine* drmEngine = mDecryptSessionMap.valueFor(decryptHandle->decryptId); 489 result = drmEngine->pread(uniqueId, decryptHandle, buffer, numBytes, offset); 490 } 491 return result; 492} 493 494String8 DrmManager::getSupportedPlugInId( 495 int uniqueId, const String8& path, const String8& mimeType) { 496 String8 plugInId(""); 497 498 if (EMPTY_STRING != mimeType) { 499 plugInId = getSupportedPlugInId(mimeType); 500 } else { 501 plugInId = getSupportedPlugInIdFromPath(uniqueId, path); 502 } 503 return plugInId; 504} 505 506String8 DrmManager::getSupportedPlugInId(const String8& mimeType) { 507 String8 plugInId(""); 508 509 if (EMPTY_STRING != mimeType) { 510 for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { 511 const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); 512 513 if (drmSupportInfo.isSupportedMimeType(mimeType)) { 514 plugInId = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo); 515 break; 516 } 517 } 518 } 519 return plugInId; 520} 521 522String8 DrmManager::getSupportedPlugInIdFromPath(int uniqueId, const String8& path) { 523 String8 plugInId(""); 524 const String8 fileSuffix = path.getPathExtension(); 525 526 for (unsigned int index = 0; index < mSupportInfoToPlugInIdMap.size(); index++) { 527 const DrmSupportInfo& drmSupportInfo = mSupportInfoToPlugInIdMap.keyAt(index); 528 529 if (drmSupportInfo.isSupportedFileSuffix(fileSuffix)) { 530 String8 key = mSupportInfoToPlugInIdMap.valueFor(drmSupportInfo); 531 IDrmEngine& drmEngine = mPlugInManager.getPlugIn(key); 532 533 if (drmEngine.canHandle(uniqueId, path)) { 534 plugInId = key; 535 break; 536 } 537 } 538 } 539 return plugInId; 540} 541 542void DrmManager::onInfo(const DrmInfoEvent& event) { 543 Mutex::Autolock _l(mLock); 544 for (unsigned int index = 0; index < mServiceListeners.size(); index++) { 545 int uniqueId = mServiceListeners.keyAt(index); 546 547 if (uniqueId == event.getUniqueId()) { 548 sp<IDrmServiceListener> serviceListener = mServiceListeners.valueFor(uniqueId); 549 serviceListener->notify(event); 550 } 551 } 552} 553 554