Home | History | Annotate | Download | only in src
      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