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