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