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