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