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