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