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 #include "SessionMap.h" 18 #include "FwdLockEngine.h" 19 #include <utils/Log.h> 20 #include <errno.h> 21 #include <stdio.h> 22 #include <unistd.h> 23 #include <drm/drm_framework_common.h> 24 #include <fcntl.h> 25 #include <limits.h> 26 #include <drm/DrmRights.h> 27 #include <drm/DrmConstraints.h> 28 #include <drm/DrmMetadata.h> 29 #include <drm/DrmInfo.h> 30 #include <drm/DrmInfoStatus.h> 31 #include <drm/DrmInfoRequest.h> 32 #include <drm/DrmSupportInfo.h> 33 #include <drm/DrmConvertedStatus.h> 34 #include <utils/String8.h> 35 #include "FwdLockConv.h" 36 #include "FwdLockFile.h" 37 #include "FwdLockGlue.h" 38 #include "MimeTypeUtil.h" 39 40 #undef LOG_TAG 41 #define LOG_TAG "FwdLockEngine" 42 43 #ifdef DRM_OMA_FL_ENGINE_DEBUG 44 #define LOG_NDEBUG 0 45 #define LOG_VERBOSE(...) ALOGV(__VA_ARGS__) 46 #else 47 #define LOG_VERBOSE(...) 48 #endif 49 50 using namespace android; 51 // This extern "C" is mandatory to be managed by TPlugInManager 52 extern "C" IDrmEngine* create() { 53 return new FwdLockEngine(); 54 } 55 56 // This extern "C" is mandatory to be managed by TPlugInManager 57 extern "C" void destroy(IDrmEngine* plugIn) { 58 delete plugIn; 59 } 60 61 FwdLockEngine::FwdLockEngine() { 62 LOG_VERBOSE("FwdLockEngine Construction"); 63 } 64 65 FwdLockEngine::~FwdLockEngine() { 66 LOG_VERBOSE("FwdLockEngine Destruction"); 67 68 int size = decodeSessionMap.getSize(); 69 70 for (int i = 0; i < size; i++) { 71 DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i); 72 FwdLockFile_detach(session->fileDesc); 73 ::close(session->fileDesc); 74 } 75 76 size = convertSessionMap.getSize(); 77 for (int i = 0; i < size; i++) { 78 ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i); 79 FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); 80 } 81 } 82 83 int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) { 84 int retStatus = DrmConvertedStatus::STATUS_ERROR; 85 86 switch(status) { 87 case FwdLockConv_Status_OK: 88 retStatus = DrmConvertedStatus::STATUS_OK; 89 break; 90 case FwdLockConv_Status_SyntaxError: 91 case FwdLockConv_Status_InvalidArgument: 92 case FwdLockConv_Status_UnsupportedFileFormat: 93 case FwdLockConv_Status_UnsupportedContentTransferEncoding: 94 ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " 95 "Returning STATUS_INPUTDATA_ERROR", status); 96 retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR; 97 break; 98 default: 99 ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " 100 "Returning STATUS_ERROR", status); 101 retStatus = DrmConvertedStatus::STATUS_ERROR; 102 break; 103 } 104 105 return retStatus; 106 } 107 108 DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) { 109 DrmConstraints* drmConstraints = NULL; 110 111 LOG_VERBOSE("FwdLockEngine::onGetConstraints"); 112 113 if (NULL != path && 114 (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) { 115 // Return the empty constraints to show no error condition. 116 drmConstraints = new DrmConstraints(); 117 } 118 119 return drmConstraints; 120 } 121 122 DrmMetadata* FwdLockEngine::onGetMetadata(int /* uniqueId */, const String8* path) { 123 DrmMetadata* drmMetadata = NULL; 124 125 LOG_VERBOSE("FwdLockEngine::onGetMetadata"); 126 127 if (NULL != path) { 128 // Returns empty metadata to show no error condition. 129 drmMetadata = new DrmMetadata(); 130 } 131 132 return drmMetadata; 133 } 134 135 android::status_t FwdLockEngine::onInitialize(int /* uniqueId */) { 136 LOG_VERBOSE("FwdLockEngine::onInitialize"); 137 138 if (FwdLockGlue_InitializeKeyEncryption()) { 139 LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded"); 140 } else { 141 ALOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:" 142 "errno = %d", errno); 143 } 144 145 return DRM_NO_ERROR; 146 } 147 148 android::status_t 149 FwdLockEngine::onSetOnInfoListener( 150 int /* uniqueId */, 151 const IDrmEngine::OnInfoListener* /* infoListener */) { 152 // Not used 153 LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener"); 154 155 return DRM_NO_ERROR; 156 } 157 158 android::status_t FwdLockEngine::onTerminate(int /* uniqueId */) { 159 LOG_VERBOSE("FwdLockEngine::onTerminate"); 160 161 return DRM_NO_ERROR; 162 } 163 164 // make sure that lower-case letters are used. 165 const String8 FwdLockEngine::FileSuffixes[] = { 166 String8(".fl"), 167 String8(".dm"), 168 }; 169 170 // make sure that lower-case letters are used. 171 const String8 FwdLockEngine::MimeTypes[] = { 172 String8("application/x-android-drm-fl"), 173 String8("application/vnd.oma.drm.message"), 174 }; 175 176 const String8 FwdLockEngine::Description("OMA V1 Forward Lock"); 177 178 void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) { 179 for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { 180 info->addMimeType(MimeTypes[i]); 181 } 182 } 183 184 void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) { 185 for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { 186 info->addFileSuffix(FileSuffixes[i]); 187 } 188 } 189 190 bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) { 191 String8 tmp(mime); 192 tmp.toLower(); 193 for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { 194 if (tmp == MimeTypes[i]) { 195 return true; 196 } 197 } 198 return false; 199 } 200 201 bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) { 202 String8 tmp(suffix); 203 tmp.toLower(); 204 for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { 205 if (tmp == FileSuffixes[i]) { 206 return true; 207 } 208 } 209 return false; 210 } 211 212 DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int /* uniqueId */) { 213 DrmSupportInfo* pSupportInfo = new DrmSupportInfo(); 214 215 LOG_VERBOSE("FwdLockEngine::onGetSupportInfo"); 216 217 // fill all Forward Lock mimetypes and extensions 218 if (NULL != pSupportInfo) { 219 AddSupportedMimeTypes(pSupportInfo); 220 AddSupportedFileSuffixes(pSupportInfo); 221 pSupportInfo->setDescription(Description); 222 } 223 224 return pSupportInfo; 225 } 226 227 bool FwdLockEngine::onCanHandle(int /* uniqueId */, const String8& path) { 228 bool result = false; 229 230 String8 extString = path.getPathExtension(); 231 return IsFileSuffixSupported(extString); 232 } 233 234 DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int /* uniqueId */, const DrmInfo* /* drmInfo */) { 235 DrmInfoStatus *drmInfoStatus = NULL; 236 237 // Nothing to process 238 239 drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8("")); 240 241 LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo"); 242 243 return drmInfoStatus; 244 } 245 246 status_t FwdLockEngine::onSaveRights( 247 int /* uniqueId */, 248 const DrmRights& /* drmRights */, 249 const String8& /* rightsPath */, 250 const String8& /* contentPath */) { 251 // No rights to save. Return 252 LOG_VERBOSE("FwdLockEngine::onSaveRights"); 253 return DRM_ERROR_UNKNOWN; 254 } 255 256 DrmInfo* FwdLockEngine::onAcquireDrmInfo( 257 int /* uniqueId */, const DrmInfoRequest* /* drmInfoRequest */) { 258 DrmInfo* drmInfo = NULL; 259 260 // Nothing to be done for Forward Lock file 261 LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo"); 262 263 return drmInfo; 264 } 265 266 int FwdLockEngine::onCheckRightsStatus(int uniqueId, 267 const String8& path, 268 int action) { 269 int result = RightsStatus::RIGHTS_INVALID; 270 271 LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus"); 272 273 // Only Transfer action is not allowed for forward Lock files. 274 if (onCanHandle(uniqueId, path)) { 275 switch(action) { 276 case Action::DEFAULT: 277 case Action::PLAY: 278 case Action::RINGTONE: 279 case Action::OUTPUT: 280 case Action::PREVIEW: 281 case Action::EXECUTE: 282 case Action::DISPLAY: 283 result = RightsStatus::RIGHTS_VALID; 284 break; 285 286 case Action::TRANSFER: 287 default: 288 result = RightsStatus::RIGHTS_INVALID; 289 break; 290 } 291 } 292 293 return result; 294 } 295 296 status_t FwdLockEngine::onConsumeRights(int /* uniqueId */, 297 DecryptHandle* /* decryptHandle */, 298 int /* action */, 299 bool /* reserve */) { 300 // No rights consumption 301 LOG_VERBOSE("FwdLockEngine::onConsumeRights"); 302 return DRM_NO_ERROR; 303 } 304 305 bool FwdLockEngine::onValidateAction(int uniqueId, 306 const String8& path, 307 int action, 308 const ActionDescription& /* description */) { 309 LOG_VERBOSE("FwdLockEngine::onValidateAction"); 310 311 // For the forwardlock engine checkRights and ValidateAction are the same. 312 return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID); 313 } 314 315 String8 FwdLockEngine::onGetOriginalMimeType(int /* uniqueId */, 316 const String8& /* path */, 317 int fd) { 318 LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType"); 319 String8 mimeString = String8(""); 320 int fileDesc = dup(fd); 321 322 if (-1 < fileDesc) { 323 if (FwdLockFile_attach(fileDesc) < 0) { 324 close(fileDesc); 325 return mimeString; 326 } 327 const char* pMimeType = FwdLockFile_GetContentType(fileDesc); 328 329 if (NULL != pMimeType) { 330 String8 contentType = String8(pMimeType); 331 contentType.toLower(); 332 mimeString = MimeTypeUtil::convertMimeType(contentType); 333 } 334 335 FwdLockFile_close(fileDesc); 336 } 337 338 return mimeString; 339 } 340 341 int FwdLockEngine::onGetDrmObjectType(int uniqueId, 342 const String8& path, 343 const String8& mimeType) { 344 String8 mimeStr = String8(mimeType); 345 346 LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType"); 347 348 /* Checks whether 349 * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown 350 * 2. if one of them is empty string and if other is known then its a DRM Content Object. 351 * 3. if both of them are available, then both may be of known type 352 * (regardless of the relation between them to make it compatible with other DRM Engines) 353 */ 354 if (((0 == path.length()) || onCanHandle(uniqueId, path)) && 355 ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) { 356 return DrmObjectType::CONTENT; 357 } 358 359 return DrmObjectType::UNKNOWN; 360 } 361 362 status_t FwdLockEngine::onRemoveRights(int /* uniqueId */, const String8& /* path */) { 363 // No Rights to remove 364 LOG_VERBOSE("FwdLockEngine::onRemoveRights"); 365 return DRM_NO_ERROR; 366 } 367 368 status_t FwdLockEngine::onRemoveAllRights(int /* uniqueId */) { 369 // No rights to remove 370 LOG_VERBOSE("FwdLockEngine::onRemoveAllRights"); 371 return DRM_NO_ERROR; 372 } 373 374 #ifdef USE_64BIT_DRM_API 375 status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */, 376 int /* playbackStatus */, int64_t /* position */) { 377 #else 378 status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */, 379 int /* playbackStatus */, int /* position */) { 380 #endif 381 // Not used 382 LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus"); 383 return DRM_NO_ERROR; 384 } 385 386 status_t FwdLockEngine::onOpenConvertSession( 387 int /* uniqueId */, int convertId) { 388 status_t result = DRM_ERROR_UNKNOWN; 389 LOG_VERBOSE("FwdLockEngine::onOpenConvertSession"); 390 if (!convertSessionMap.isCreated(convertId)) { 391 ConvertSession *newSession = new ConvertSession(); 392 if (FwdLockConv_Status_OK == 393 FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) { 394 convertSessionMap.addValue(convertId, newSession); 395 result = DRM_NO_ERROR; 396 } else { 397 ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed."); 398 delete newSession; 399 } 400 } 401 return result; 402 } 403 404 DrmConvertedStatus* FwdLockEngine::onConvertData(int /* uniqueId */, 405 int convertId, 406 const DrmBuffer* inputData) { 407 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; 408 DrmBuffer *convResult = new DrmBuffer(NULL, 0); 409 int offset = -1; 410 411 if (NULL != inputData && convertSessionMap.isCreated(convertId)) { 412 ConvertSession *convSession = convertSessionMap.getValue(convertId); 413 414 if (NULL != convSession) { 415 retStatus = FwdLockConv_ConvertData(convSession->uniqueId, 416 inputData->data, 417 inputData->length, 418 &(convSession->output)); 419 420 if (FwdLockConv_Status_OK == retStatus) { 421 // return bytes from conversion if available 422 if (convSession->output.fromConvertData.numBytes > 0) { 423 convResult->data = new char[convSession->output.fromConvertData.numBytes]; 424 425 if (NULL != convResult->data) { 426 convResult->length = convSession->output.fromConvertData.numBytes; 427 memcpy(convResult->data, 428 (char *)convSession->output.fromConvertData.pBuffer, 429 convResult->length); 430 } 431 } 432 } else { 433 offset = convSession->output.fromConvertData.errorPos; 434 } 435 } 436 } 437 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); 438 } 439 440 DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int /* uniqueId */, 441 int convertId) { 442 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; 443 DrmBuffer *convResult = new DrmBuffer(NULL, 0); 444 int offset = -1; 445 446 LOG_VERBOSE("FwdLockEngine::onCloseConvertSession"); 447 448 if (convertSessionMap.isCreated(convertId)) { 449 ConvertSession *convSession = convertSessionMap.getValue(convertId); 450 451 if (NULL != convSession) { 452 retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); 453 454 if (FwdLockConv_Status_OK == retStatus) { 455 offset = convSession->output.fromCloseSession.fileOffset; 456 convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE]; 457 458 if (NULL != convResult->data) { 459 convResult->length = FWD_LOCK_SIGNATURES_SIZE; 460 memcpy(convResult->data, 461 (char *)convSession->output.fromCloseSession.signatures, 462 convResult->length); 463 } 464 } 465 } 466 convertSessionMap.removeValue(convertId); 467 } 468 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); 469 } 470 471 #ifdef USE_64BIT_DRM_API 472 status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, 473 DecryptHandle* decryptHandle, 474 int fd, 475 off64_t offset, 476 off64_t /* length */) { 477 #else 478 status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, 479 DecryptHandle* decryptHandle, 480 int fd, 481 int offset, 482 int /* length */) { 483 #endif 484 status_t result = DRM_ERROR_CANNOT_HANDLE; 485 int fileDesc = -1; 486 487 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession"); 488 489 if ((-1 < fd) && 490 (NULL != decryptHandle) && 491 (!decodeSessionMap.isCreated(decryptHandle->decryptId))) { 492 fileDesc = dup(fd); 493 } else { 494 ALOGE("FwdLockEngine::onOpenDecryptSession parameter error"); 495 return result; 496 } 497 498 if (-1 < fileDesc && 499 -1 < ::lseek(fileDesc, offset, SEEK_SET) && 500 -1 < FwdLockFile_attach(fileDesc)) { 501 // check for file integrity. This must be done to protect the content mangling. 502 int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc); 503 DecodeSession* decodeSession = new DecodeSession(fileDesc); 504 505 if (retVal && NULL != decodeSession && 506 decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession)) { 507 const char *pmime= FwdLockFile_GetContentType(fileDesc); 508 String8 contentType = String8(pmime == NULL ? "" : pmime); 509 contentType.toLower(); 510 decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType); 511 decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED; 512 decryptHandle->status = RightsStatus::RIGHTS_VALID; 513 decryptHandle->decryptInfo = NULL; 514 result = DRM_NO_ERROR; 515 } else { 516 if (retVal && NULL != decodeSession) { 517 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd"); 518 } else { 519 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession DecodeSesssion insertion failed"); 520 } 521 FwdLockFile_detach(fileDesc); 522 delete decodeSession; 523 } 524 } 525 526 if (DRM_NO_ERROR != result && -1 < fileDesc) { 527 ::close(fileDesc); 528 } 529 530 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result); 531 532 return result; 533 } 534 535 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, 536 DecryptHandle* decryptHandle, 537 const char* uri) { 538 status_t result = DRM_ERROR_CANNOT_HANDLE; 539 const char fileTag [] = "file://"; 540 541 if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { 542 String8 uriTag = String8(uri); 543 uriTag.toLower(); 544 545 if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) { 546 const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/'); 547 if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) { 548 int fd = open(filePath, O_RDONLY); 549 550 if (-1 < fd) { 551 // offset is always 0 and length is not used. so any positive size. 552 result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1); 553 554 // fd is duplicated already if success. closing the file 555 close(fd); 556 } 557 } 558 } 559 } 560 561 return result; 562 } 563 564 status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, 565 DecryptHandle* decryptHandle) { 566 status_t result = DRM_ERROR_UNKNOWN; 567 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); 568 569 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 570 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 571 if (NULL != session && session->fileDesc > -1) { 572 FwdLockFile_detach(session->fileDesc); 573 ::close(session->fileDesc); 574 decodeSessionMap.removeValue(decryptHandle->decryptId); 575 result = DRM_NO_ERROR; 576 } 577 } 578 579 if (NULL != decryptHandle) { 580 if (NULL != decryptHandle->decryptInfo) { 581 delete decryptHandle->decryptInfo; 582 decryptHandle->decryptInfo = NULL; 583 } 584 585 decryptHandle->copyControlVector.clear(); 586 decryptHandle->extendedData.clear(); 587 588 delete decryptHandle; 589 decryptHandle = NULL; 590 } 591 592 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); 593 return result; 594 } 595 596 status_t FwdLockEngine::onInitializeDecryptUnit(int /* uniqueId */, 597 DecryptHandle* /* decryptHandle */, 598 int /* decryptUnitId */, 599 const DrmBuffer* /* headerInfo */) { 600 ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme"); 601 return DRM_ERROR_UNKNOWN; 602 } 603 604 status_t FwdLockEngine::onDecrypt( 605 int /* uniqueId */, 606 DecryptHandle* /* decryptHandle */, 607 int /* decryptUnitId */, 608 const DrmBuffer* /* encBuffer */, 609 DrmBuffer** /* decBuffer */, 610 DrmBuffer* /* IV */) { 611 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 612 return DRM_ERROR_UNKNOWN; 613 } 614 615 status_t FwdLockEngine::onDecrypt(int /* uniqueId */, 616 DecryptHandle* /* decryptHandle */, 617 int /* decryptUnitId */, 618 const DrmBuffer* /* encBuffer */, 619 DrmBuffer** /* decBuffer */) { 620 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 621 return DRM_ERROR_UNKNOWN; 622 } 623 624 status_t FwdLockEngine::onFinalizeDecryptUnit(int /* uniqueId */, 625 DecryptHandle* /* decryptHandle */, 626 int /* decryptUnitId */) { 627 ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); 628 return DRM_ERROR_UNKNOWN; 629 } 630 631 ssize_t FwdLockEngine::onRead(int /* uniqueId */, 632 DecryptHandle* decryptHandle, 633 void* buffer, 634 int numBytes) { 635 ssize_t size = -1; 636 637 if (NULL != decryptHandle && 638 decodeSessionMap.isCreated(decryptHandle->decryptId) && 639 NULL != buffer && 640 numBytes > -1) { 641 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 642 if (NULL != session && session->fileDesc > -1) { 643 size = FwdLockFile_read(session->fileDesc, buffer, numBytes); 644 645 if (0 > size) { 646 session->offset = ((off_t)-1); 647 } else { 648 session->offset += size; 649 } 650 } 651 } 652 653 return size; 654 } 655 656 #ifdef USE_64BIT_DRM_API 657 off64_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, 658 off64_t offset, int whence) { 659 #else 660 off_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, 661 off_t offset, int whence) { 662 #endif 663 off_t offval = -1; 664 665 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 666 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 667 if (NULL != session && session->fileDesc > -1) { 668 offval = FwdLockFile_lseek(session->fileDesc, offset, whence); 669 session->offset = offval; 670 } 671 } 672 673 return offval; 674 } 675 676 #ifdef USE_64BIT_DRM_API 677 ssize_t FwdLockEngine::onPread(int uniqueId, 678 DecryptHandle* decryptHandle, 679 void* buffer, 680 ssize_t numBytes, 681 off64_t offset) { 682 #else 683 ssize_t FwdLockEngine::onPread(int uniqueId, 684 DecryptHandle* decryptHandle, 685 void* buffer, 686 ssize_t numBytes, 687 off_t offset) { 688 #endif 689 ssize_t bytesRead = -1; 690 691 DecodeSession* decoderSession = NULL; 692 693 if ((NULL != decryptHandle) && 694 (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && 695 (NULL != buffer) && 696 (numBytes > -1) && 697 (offset > -1)) { 698 if (offset != decoderSession->offset) { 699 decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET); 700 } 701 702 if (((off_t)-1) != decoderSession->offset) { 703 bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes); 704 if (bytesRead < 0) { 705 ALOGE("FwdLockEngine::onPread error reading"); 706 } 707 } 708 } else { 709 ALOGE("FwdLockEngine::onPread decryptId not found"); 710 } 711 712 return bytesRead; 713 } 714