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, int fd) { 313 LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType"); 314 String8 mimeString = String8(""); 315 int fileDesc = dup(fd); 316 317 if (-1 < fileDesc) { 318 if (FwdLockFile_attach(fileDesc) < 0) { 319 close(fileDesc); 320 return mimeString; 321 } 322 const char* pMimeType = FwdLockFile_GetContentType(fileDesc); 323 324 if (NULL != pMimeType) { 325 String8 contentType = String8(pMimeType); 326 contentType.toLower(); 327 mimeString = MimeTypeUtil::convertMimeType(contentType); 328 } 329 330 FwdLockFile_close(fileDesc); 331 } 332 333 return mimeString; 334 } 335 336 int FwdLockEngine::onGetDrmObjectType(int uniqueId, 337 const String8& path, 338 const String8& mimeType) { 339 String8 mimeStr = String8(mimeType); 340 341 LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType"); 342 343 /* Checks whether 344 * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown 345 * 2. if one of them is empty string and if other is known then its a DRM Content Object. 346 * 3. if both of them are available, then both may be of known type 347 * (regardless of the relation between them to make it compatible with other DRM Engines) 348 */ 349 if (((0 == path.length()) || onCanHandle(uniqueId, path)) && 350 ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) { 351 return DrmObjectType::CONTENT; 352 } 353 354 return DrmObjectType::UNKNOWN; 355 } 356 357 status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) { 358 // No Rights to remove 359 LOG_VERBOSE("FwdLockEngine::onRemoveRights"); 360 return DRM_NO_ERROR; 361 } 362 363 status_t FwdLockEngine::onRemoveAllRights(int uniqueId) { 364 // No rights to remove 365 LOG_VERBOSE("FwdLockEngine::onRemoveAllRights"); 366 return DRM_NO_ERROR; 367 } 368 369 #ifdef USE_64BIT_DRM_API 370 status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, 371 int playbackStatus, int64_t position) { 372 #else 373 status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle, 374 int playbackStatus, int position) { 375 #endif 376 // Not used 377 LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus"); 378 return DRM_NO_ERROR; 379 } 380 381 status_t FwdLockEngine::onOpenConvertSession(int uniqueId, 382 int convertId) { 383 status_t result = DRM_ERROR_UNKNOWN; 384 LOG_VERBOSE("FwdLockEngine::onOpenConvertSession"); 385 if (!convertSessionMap.isCreated(convertId)) { 386 ConvertSession *newSession = new ConvertSession(); 387 if (FwdLockConv_Status_OK == 388 FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) { 389 convertSessionMap.addValue(convertId, newSession); 390 result = DRM_NO_ERROR; 391 } else { 392 ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed."); 393 delete newSession; 394 } 395 } 396 return result; 397 } 398 399 DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId, 400 int convertId, 401 const DrmBuffer* inputData) { 402 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; 403 DrmBuffer *convResult = new DrmBuffer(NULL, 0); 404 int offset = -1; 405 406 if (NULL != inputData && convertSessionMap.isCreated(convertId)) { 407 ConvertSession *convSession = convertSessionMap.getValue(convertId); 408 409 if (NULL != convSession) { 410 retStatus = FwdLockConv_ConvertData(convSession->uniqueId, 411 inputData->data, 412 inputData->length, 413 &(convSession->output)); 414 415 if (FwdLockConv_Status_OK == retStatus) { 416 // return bytes from conversion if available 417 if (convSession->output.fromConvertData.numBytes > 0) { 418 convResult->data = new char[convSession->output.fromConvertData.numBytes]; 419 420 if (NULL != convResult->data) { 421 convResult->length = convSession->output.fromConvertData.numBytes; 422 memcpy(convResult->data, 423 (char *)convSession->output.fromConvertData.pBuffer, 424 convResult->length); 425 } 426 } 427 } else { 428 offset = convSession->output.fromConvertData.errorPos; 429 } 430 } 431 } 432 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); 433 } 434 435 DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId, 436 int convertId) { 437 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; 438 DrmBuffer *convResult = new DrmBuffer(NULL, 0); 439 int offset = -1; 440 441 LOG_VERBOSE("FwdLockEngine::onCloseConvertSession"); 442 443 if (convertSessionMap.isCreated(convertId)) { 444 ConvertSession *convSession = convertSessionMap.getValue(convertId); 445 446 if (NULL != convSession) { 447 retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); 448 449 if (FwdLockConv_Status_OK == retStatus) { 450 offset = convSession->output.fromCloseSession.fileOffset; 451 convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE]; 452 453 if (NULL != convResult->data) { 454 convResult->length = FWD_LOCK_SIGNATURES_SIZE; 455 memcpy(convResult->data, 456 (char *)convSession->output.fromCloseSession.signatures, 457 convResult->length); 458 } 459 } 460 } 461 convertSessionMap.removeValue(convertId); 462 } 463 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); 464 } 465 466 #ifdef USE_64BIT_DRM_API 467 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, 468 DecryptHandle* decryptHandle, 469 int fd, 470 off64_t offset, 471 off64_t length) { 472 #else 473 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, 474 DecryptHandle* decryptHandle, 475 int fd, 476 int offset, 477 int length) { 478 #endif 479 status_t result = DRM_ERROR_CANNOT_HANDLE; 480 int fileDesc = -1; 481 482 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession"); 483 484 if ((-1 < fd) && 485 (NULL != decryptHandle) && 486 (!decodeSessionMap.isCreated(decryptHandle->decryptId))) { 487 fileDesc = dup(fd); 488 } else { 489 ALOGE("FwdLockEngine::onOpenDecryptSession parameter error"); 490 return result; 491 } 492 493 if (-1 < fileDesc && 494 -1 < ::lseek(fileDesc, offset, SEEK_SET) && 495 -1 < FwdLockFile_attach(fileDesc)) { 496 // check for file integrity. This must be done to protect the content mangling. 497 int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc); 498 DecodeSession* decodeSession = new DecodeSession(fileDesc); 499 500 if (retVal && NULL != decodeSession) { 501 decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession); 502 const char *pmime= FwdLockFile_GetContentType(fileDesc); 503 String8 contentType = String8(pmime == NULL ? "" : pmime); 504 contentType.toLower(); 505 decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType); 506 decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED; 507 decryptHandle->status = RightsStatus::RIGHTS_VALID; 508 decryptHandle->decryptInfo = NULL; 509 result = DRM_NO_ERROR; 510 } else { 511 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd"); 512 FwdLockFile_detach(fileDesc); 513 delete decodeSession; 514 } 515 } 516 517 if (DRM_NO_ERROR != result && -1 < fileDesc) { 518 ::close(fileDesc); 519 } 520 521 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result); 522 523 return result; 524 } 525 526 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, 527 DecryptHandle* decryptHandle, 528 const char* uri) { 529 status_t result = DRM_ERROR_CANNOT_HANDLE; 530 const char fileTag [] = "file://"; 531 532 if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { 533 String8 uriTag = String8(uri); 534 uriTag.toLower(); 535 536 if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) { 537 const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/'); 538 if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) { 539 int fd = open(filePath, O_RDONLY); 540 541 if (-1 < fd) { 542 // offset is always 0 and length is not used. so any positive size. 543 result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1); 544 545 // fd is duplicated already if success. closing the file 546 close(fd); 547 } 548 } 549 } 550 } 551 552 return result; 553 } 554 555 status_t FwdLockEngine::onCloseDecryptSession(int uniqueId, 556 DecryptHandle* decryptHandle) { 557 status_t result = DRM_ERROR_UNKNOWN; 558 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); 559 560 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 561 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 562 if (NULL != session && session->fileDesc > -1) { 563 FwdLockFile_detach(session->fileDesc); 564 ::close(session->fileDesc); 565 decodeSessionMap.removeValue(decryptHandle->decryptId); 566 result = DRM_NO_ERROR; 567 } 568 } 569 570 if (NULL != decryptHandle) { 571 if (NULL != decryptHandle->decryptInfo) { 572 delete decryptHandle->decryptInfo; 573 decryptHandle->decryptInfo = NULL; 574 } 575 576 decryptHandle->copyControlVector.clear(); 577 decryptHandle->extendedData.clear(); 578 579 delete decryptHandle; 580 decryptHandle = NULL; 581 } 582 583 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); 584 return result; 585 } 586 587 status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId, 588 DecryptHandle* decryptHandle, 589 int decryptUnitId, 590 const DrmBuffer* headerInfo) { 591 ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme"); 592 return DRM_ERROR_UNKNOWN; 593 } 594 595 status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId, 596 const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) { 597 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 598 return DRM_ERROR_UNKNOWN; 599 } 600 601 status_t FwdLockEngine::onDecrypt(int uniqueId, 602 DecryptHandle* decryptHandle, 603 int decryptUnitId, 604 const DrmBuffer* encBuffer, 605 DrmBuffer** decBuffer) { 606 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 607 return DRM_ERROR_UNKNOWN; 608 } 609 610 status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId, 611 DecryptHandle* decryptHandle, 612 int decryptUnitId) { 613 ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); 614 return DRM_ERROR_UNKNOWN; 615 } 616 617 ssize_t FwdLockEngine::onRead(int uniqueId, 618 DecryptHandle* decryptHandle, 619 void* buffer, 620 int numBytes) { 621 ssize_t size = -1; 622 623 if (NULL != decryptHandle && 624 decodeSessionMap.isCreated(decryptHandle->decryptId) && 625 NULL != buffer && 626 numBytes > -1) { 627 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 628 if (NULL != session && session->fileDesc > -1) { 629 size = FwdLockFile_read(session->fileDesc, buffer, numBytes); 630 631 if (0 > size) { 632 session->offset = ((off_t)-1); 633 } else { 634 session->offset += size; 635 } 636 } 637 } 638 639 return size; 640 } 641 642 #ifdef USE_64BIT_DRM_API 643 off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle, 644 off64_t offset, int whence) { 645 #else 646 off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle, 647 off_t offset, int whence) { 648 #endif 649 off_t offval = -1; 650 651 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 652 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 653 if (NULL != session && session->fileDesc > -1) { 654 offval = FwdLockFile_lseek(session->fileDesc, offset, whence); 655 session->offset = offval; 656 } 657 } 658 659 return offval; 660 } 661 662 #ifdef USE_64BIT_DRM_API 663 ssize_t FwdLockEngine::onPread(int uniqueId, 664 DecryptHandle* decryptHandle, 665 void* buffer, 666 ssize_t numBytes, 667 off64_t offset) { 668 #else 669 ssize_t FwdLockEngine::onPread(int uniqueId, 670 DecryptHandle* decryptHandle, 671 void* buffer, 672 ssize_t numBytes, 673 off_t offset) { 674 #endif 675 ssize_t bytesRead = -1; 676 677 DecodeSession* decoderSession = NULL; 678 679 if ((NULL != decryptHandle) && 680 (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && 681 (NULL != buffer) && 682 (numBytes > -1) && 683 (offset > -1)) { 684 if (offset != decoderSession->offset) { 685 decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET); 686 } 687 688 if (((off_t)-1) != decoderSession->offset) { 689 bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes); 690 if (bytesRead < 0) { 691 ALOGE("FwdLockEngine::onPread error reading"); 692 } 693 } 694 } else { 695 ALOGE("FwdLockEngine::onPread decryptId not found"); 696 } 697 698 return bytesRead; 699 } 700