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_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