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 50using namespace android; 51// This extern "C" is mandatory to be managed by TPlugInManager 52extern "C" IDrmEngine* create() { 53 return new FwdLockEngine(); 54} 55 56// This extern "C" is mandatory to be managed by TPlugInManager 57extern "C" void destroy(IDrmEngine* plugIn) { 58 delete plugIn; 59} 60 61FwdLockEngine::FwdLockEngine() { 62 LOG_VERBOSE("FwdLockEngine Construction"); 63} 64 65FwdLockEngine::~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 83int 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 108DrmConstraints* 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 122DrmMetadata* 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 135android::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 148android::status_t 149FwdLockEngine::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 158android::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. 165const String8 FwdLockEngine::FileSuffixes[] = { 166 String8(".fl"), 167 String8(".dm"), 168}; 169 170// make sure that lower-case letters are used. 171const String8 FwdLockEngine::MimeTypes[] = { 172 String8("application/x-android-drm-fl"), 173 String8("application/vnd.oma.drm.message"), 174}; 175 176const String8 FwdLockEngine::Description("OMA V1 Forward Lock"); 177 178void 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 184void 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 190bool 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 201bool 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 212DrmSupportInfo* 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 227bool FwdLockEngine::onCanHandle(int /* uniqueId */, const String8& path) { 228 bool result = false; 229 230 String8 extString = path.getPathExtension(); 231 return IsFileSuffixSupported(extString); 232} 233 234DrmInfoStatus* 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 246status_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 256DrmInfo* 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 266int 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 296status_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 305bool 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 315String8 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 341int 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 362status_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 368status_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 375status_t FwdLockEngine::onSetPlaybackStatus(int /* uniqueId */, DecryptHandle* /* decryptHandle */, 376 int /* playbackStatus */, int64_t /* position */) { 377#else 378status_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 386status_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 404DrmConvertedStatus* 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 440DrmConvertedStatus* 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 472status_t FwdLockEngine::onOpenDecryptSession(int /* uniqueId */, 473 DecryptHandle* decryptHandle, 474 int fd, 475 off64_t offset, 476 off64_t /* length */) { 477#else 478status_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 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd"); 517 FwdLockFile_detach(fileDesc); 518 delete decodeSession; 519 } 520 } 521 522 if (DRM_NO_ERROR != result && -1 < fileDesc) { 523 ::close(fileDesc); 524 } 525 526 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result); 527 528 return result; 529} 530 531status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, 532 DecryptHandle* decryptHandle, 533 const char* uri) { 534 status_t result = DRM_ERROR_CANNOT_HANDLE; 535 const char fileTag [] = "file://"; 536 537 if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { 538 String8 uriTag = String8(uri); 539 uriTag.toLower(); 540 541 if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) { 542 const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/'); 543 if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) { 544 int fd = open(filePath, O_RDONLY); 545 546 if (-1 < fd) { 547 // offset is always 0 and length is not used. so any positive size. 548 result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1); 549 550 // fd is duplicated already if success. closing the file 551 close(fd); 552 } 553 } 554 } 555 } 556 557 return result; 558} 559 560status_t FwdLockEngine::onCloseDecryptSession(int /* uniqueId */, 561 DecryptHandle* decryptHandle) { 562 status_t result = DRM_ERROR_UNKNOWN; 563 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); 564 565 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 566 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 567 if (NULL != session && session->fileDesc > -1) { 568 FwdLockFile_detach(session->fileDesc); 569 ::close(session->fileDesc); 570 decodeSessionMap.removeValue(decryptHandle->decryptId); 571 result = DRM_NO_ERROR; 572 } 573 } 574 575 if (NULL != decryptHandle) { 576 if (NULL != decryptHandle->decryptInfo) { 577 delete decryptHandle->decryptInfo; 578 decryptHandle->decryptInfo = NULL; 579 } 580 581 decryptHandle->copyControlVector.clear(); 582 decryptHandle->extendedData.clear(); 583 584 delete decryptHandle; 585 decryptHandle = NULL; 586 } 587 588 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); 589 return result; 590} 591 592status_t FwdLockEngine::onInitializeDecryptUnit(int /* uniqueId */, 593 DecryptHandle* /* decryptHandle */, 594 int /* decryptUnitId */, 595 const DrmBuffer* /* headerInfo */) { 596 ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme"); 597 return DRM_ERROR_UNKNOWN; 598} 599 600status_t FwdLockEngine::onDecrypt( 601 int /* uniqueId */, 602 DecryptHandle* /* decryptHandle */, 603 int /* decryptUnitId */, 604 const DrmBuffer* /* encBuffer */, 605 DrmBuffer** /* decBuffer */, 606 DrmBuffer* /* IV */) { 607 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 608 return DRM_ERROR_UNKNOWN; 609} 610 611status_t FwdLockEngine::onDecrypt(int /* uniqueId */, 612 DecryptHandle* /* decryptHandle */, 613 int /* decryptUnitId */, 614 const DrmBuffer* /* encBuffer */, 615 DrmBuffer** /* decBuffer */) { 616 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); 617 return DRM_ERROR_UNKNOWN; 618} 619 620status_t FwdLockEngine::onFinalizeDecryptUnit(int /* uniqueId */, 621 DecryptHandle* /* decryptHandle */, 622 int /* decryptUnitId */) { 623 ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); 624 return DRM_ERROR_UNKNOWN; 625} 626 627ssize_t FwdLockEngine::onRead(int /* uniqueId */, 628 DecryptHandle* decryptHandle, 629 void* buffer, 630 int numBytes) { 631 ssize_t size = -1; 632 633 if (NULL != decryptHandle && 634 decodeSessionMap.isCreated(decryptHandle->decryptId) && 635 NULL != buffer && 636 numBytes > -1) { 637 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 638 if (NULL != session && session->fileDesc > -1) { 639 size = FwdLockFile_read(session->fileDesc, buffer, numBytes); 640 641 if (0 > size) { 642 session->offset = ((off_t)-1); 643 } else { 644 session->offset += size; 645 } 646 } 647 } 648 649 return size; 650} 651 652#ifdef USE_64BIT_DRM_API 653off64_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, 654 off64_t offset, int whence) { 655#else 656off_t FwdLockEngine::onLseek(int /* uniqueId */, DecryptHandle* decryptHandle, 657 off_t offset, int whence) { 658#endif 659 off_t offval = -1; 660 661 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { 662 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); 663 if (NULL != session && session->fileDesc > -1) { 664 offval = FwdLockFile_lseek(session->fileDesc, offset, whence); 665 session->offset = offval; 666 } 667 } 668 669 return offval; 670} 671 672#ifdef USE_64BIT_DRM_API 673ssize_t FwdLockEngine::onPread(int uniqueId, 674 DecryptHandle* decryptHandle, 675 void* buffer, 676 ssize_t numBytes, 677 off64_t offset) { 678#else 679ssize_t FwdLockEngine::onPread(int uniqueId, 680 DecryptHandle* decryptHandle, 681 void* buffer, 682 ssize_t numBytes, 683 off_t offset) { 684#endif 685 ssize_t bytesRead = -1; 686 687 DecodeSession* decoderSession = NULL; 688 689 if ((NULL != decryptHandle) && 690 (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && 691 (NULL != buffer) && 692 (numBytes > -1) && 693 (offset > -1)) { 694 if (offset != decoderSession->offset) { 695 decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET); 696 } 697 698 if (((off_t)-1) != decoderSession->offset) { 699 bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes); 700 if (bytesRead < 0) { 701 ALOGE("FwdLockEngine::onPread error reading"); 702 } 703 } 704 } else { 705 ALOGE("FwdLockEngine::onPread decryptId not found"); 706 } 707 708 return bytesRead; 709} 710