FwdLockEngine.cpp revision cfff1f2b0bac432fac49f0b21e09e08f0e913622
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 "FwdLockEngineConst.h"
39#include "MimeTypeUtil.h"
40
41#undef LOG_TAG
42#define LOG_TAG "FwdLockEngine"
43
44#ifdef DRM_OMA_FL_ENGINE_DEBUG
45#define LOG_NDEBUG 0
46#define LOG_VERBOSE(...) LOGV(__VA_ARGS__)
47#else
48#define LOG_VERBOSE(...)
49#endif
50
51using namespace android;
52// This extern "C" is mandatory to be managed by TPlugInManager
53extern "C" IDrmEngine* create() {
54    return new FwdLockEngine();
55}
56
57// This extern "C" is mandatory to be managed by TPlugInManager
58extern "C" void destroy(IDrmEngine* plugIn) {
59    delete plugIn;
60}
61
62FwdLockEngine::FwdLockEngine() {
63    LOG_VERBOSE("FwdLockEngine Construction");
64}
65
66FwdLockEngine::~FwdLockEngine() {
67    LOG_VERBOSE("FwdLockEngine Destruction");
68
69    int size = decodeSessionMap.getSize();
70
71    for (int i = 0; i < size; i++) {
72        DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i);
73        FwdLockFile_detach(session->fileDesc);
74        ::close(session->fileDesc);
75    }
76
77    size = convertSessionMap.getSize();
78    for (int i = 0; i < size; i++) {
79        ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i);
80        FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
81    }
82}
83
84int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) {
85    int retStatus = DrmConvertedStatus::STATUS_ERROR;
86
87    switch(status) {
88        case FwdLockConv_Status_OK:
89            retStatus = DrmConvertedStatus::STATUS_OK;
90            break;
91        case FwdLockConv_Status_SyntaxError:
92        case FwdLockConv_Status_InvalidArgument:
93        case FwdLockConv_Status_UnsupportedFileFormat:
94        case FwdLockConv_Status_UnsupportedContentTransferEncoding:
95            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
96                  "Returning STATUS_INPUTDATA_ERROR", status);
97            retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR;
98            break;
99        default:
100            LOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. "
101                  "Returning STATUS_ERROR", status);
102            retStatus = DrmConvertedStatus::STATUS_ERROR;
103            break;
104    }
105
106    return retStatus;
107}
108
109DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) {
110    DrmConstraints* drmConstraints = NULL;
111
112    LOG_VERBOSE("FwdLockEngine::onGetConstraints");
113
114    if (NULL != path &&
115        (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) {
116        // Return the empty constraints to show no error condition.
117        drmConstraints = new DrmConstraints();
118    }
119
120    return drmConstraints;
121}
122
123DrmMetadata* FwdLockEngine::onGetMetadata(int uniqueId, const String8* path) {
124    DrmMetadata* drmMetadata = NULL;
125
126    LOG_VERBOSE("FwdLockEngine::onGetMetadata");
127
128    if (NULL != path) {
129        // Returns empty metadata to show no error condition.
130        drmMetadata = new DrmMetadata();
131    }
132
133    return drmMetadata;
134}
135
136android::status_t FwdLockEngine::onInitialize(int uniqueId) {
137    LOG_VERBOSE("FwdLockEngine::onInitialize");
138
139    if (FwdLockGlue_InitializeKeyEncryption()) {
140        LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded");
141    } else {
142        LOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:"
143             "errno = %d", errno);
144    }
145
146    return DRM_NO_ERROR;
147}
148
149android::status_t
150FwdLockEngine::onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
151    // Not used
152    LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");
153
154    return DRM_NO_ERROR;
155}
156
157android::status_t FwdLockEngine::onTerminate(int uniqueId) {
158    LOG_VERBOSE("FwdLockEngine::onTerminate");
159
160    return DRM_NO_ERROR;
161}
162
163DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
164    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
165
166    LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");
167
168    // fill all Forward Lock mimetypes and extensions
169    if (NULL != pSupportInfo) {
170        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_FL));
171        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_FL));
172        pSupportInfo->addMimeType(String8(FWDLOCK_MIMETYPE_DM));
173        pSupportInfo->addFileSuffix(String8(FWDLOCK_DOTEXTENSION_DM));
174
175        pSupportInfo->setDescription(String8(FWDLOCK_DESCRIPTION));
176    }
177
178    return pSupportInfo;
179}
180
181bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
182    bool result = false;
183
184    String8 extString = path.getPathExtension();
185
186    extString.toLower();
187
188    if ((extString == String8(FWDLOCK_DOTEXTENSION_FL)) ||
189        (extString == String8(FWDLOCK_DOTEXTENSION_DM))) {
190        result = true;
191    }
192    return result;
193}
194
195DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
196    DrmInfoStatus *drmInfoStatus = NULL;
197
198    // Nothing to process
199
200    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
201
202    LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");
203
204    return drmInfoStatus;
205}
206
207status_t FwdLockEngine::onSaveRights(
208            int uniqueId,
209            const DrmRights& drmRights,
210            const String8& rightsPath,
211            const String8& contentPath) {
212    // No rights to save. Return
213    LOG_VERBOSE("FwdLockEngine::onSaveRights");
214    return DRM_ERROR_UNKNOWN;
215}
216
217DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
218    DrmInfo* drmInfo = NULL;
219
220    // Nothing to be done for Forward Lock file
221    LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");
222
223    return drmInfo;
224}
225
226int FwdLockEngine::onCheckRightsStatus(int uniqueId,
227                                       const String8& path,
228                                       int action) {
229    int result = RightsStatus::RIGHTS_INVALID;
230
231    LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");
232
233    // Only Transfer action is not allowed for forward Lock files.
234    if (onCanHandle(uniqueId, path)) {
235        switch(action) {
236            case Action::DEFAULT:
237            case Action::PLAY:
238            case Action::RINGTONE:
239            case Action::OUTPUT:
240            case Action::PREVIEW:
241            case Action::EXECUTE:
242            case Action::DISPLAY:
243                result = RightsStatus::RIGHTS_VALID;
244                break;
245
246            case Action::TRANSFER:
247            default:
248                result = RightsStatus::RIGHTS_INVALID;
249                break;
250        }
251    }
252
253    return result;
254}
255
256status_t FwdLockEngine::onConsumeRights(int uniqueId,
257                                        DecryptHandle* decryptHandle,
258                                        int action,
259                                        bool reserve) {
260    // No rights consumption
261    LOG_VERBOSE("FwdLockEngine::onConsumeRights");
262    return DRM_NO_ERROR;
263}
264
265bool FwdLockEngine::onValidateAction(int uniqueId,
266                                     const String8& path,
267                                     int action,
268                                     const ActionDescription& description) {
269    LOG_VERBOSE("FwdLockEngine::onValidateAction");
270
271    // For the forwardlock engine checkRights and ValidateAction are the same.
272    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
273}
274
275String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
276    LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
277    String8 mimeString = String8("");
278    int fileDesc = FwdLockFile_open(path.string());
279
280    if (-1 < fileDesc) {
281        const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
282
283        if (NULL != pMimeType) {
284            String8 contentType = String8(pMimeType);
285            contentType.toLower();
286            mimeString = MimeTypeUtil::convertMimeType(contentType);
287        }
288
289        FwdLockFile_close(fileDesc);
290    }
291
292    return mimeString;
293}
294
295int FwdLockEngine::onGetDrmObjectType(int uniqueId,
296                                      const String8& path,
297                                      const String8& mimeType) {
298    String8 mimeStr = String8(mimeType);
299
300    LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
301
302    mimeStr.toLower();
303
304    /* Checks whether
305    * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
306    * 2. if one of them is empty string and if other is known then its a DRM Content Object.
307    * 3. if both of them are available, then both may be of known type
308    *    (regardless of the relation between them to make it compatible with other DRM Engines)
309    */
310    if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
311        ((0 == mimeType.length()) || ((mimeStr == String8(FWDLOCK_MIMETYPE_FL)) ||
312        (mimeStr == String8(FWDLOCK_MIMETYPE_DM)))) && (mimeType != path) ) {
313            return DrmObjectType::CONTENT;
314    }
315
316    return DrmObjectType::UNKNOWN;
317}
318
319status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
320    // No Rights to remove
321    LOG_VERBOSE("FwdLockEngine::onRemoveRights");
322    return DRM_NO_ERROR;
323}
324
325status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
326    // No rights to remove
327    LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
328    return DRM_NO_ERROR;
329}
330
331#ifdef USE_64BIT_DRM_API
332status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
333                                            int playbackStatus, int64_t position) {
334#else
335status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
336                                            int playbackStatus, int position) {
337#endif
338    // Not used
339    LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
340    return DRM_NO_ERROR;
341}
342
343status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
344                                         int convertId) {
345    status_t result = DRM_ERROR_UNKNOWN;
346    LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
347    if (!convertSessionMap.isCreated(convertId)) {
348        ConvertSession *newSession = new ConvertSession();
349        if (FwdLockConv_Status_OK ==
350            FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
351            convertSessionMap.addValue(convertId, newSession);
352            result = DRM_NO_ERROR;
353        } else {
354            LOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
355            delete newSession;
356        }
357    }
358    return result;
359}
360
361DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
362                                                 int convertId,
363                                                 const DrmBuffer* inputData) {
364    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
365    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
366    int offset = -1;
367
368    if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
369        ConvertSession *convSession = convertSessionMap.getValue(convertId);
370
371        if (NULL != convSession) {
372            retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
373                                                inputData->data,
374                                                inputData->length,
375                                                &(convSession->output));
376
377            if (FwdLockConv_Status_OK == retStatus) {
378                // return bytes from conversion if available
379                if (convSession->output.fromConvertData.numBytes > 0) {
380                    convResult->data = new char[convSession->output.fromConvertData.numBytes];
381
382                    if (NULL != convResult->data) {
383                        convResult->length = convSession->output.fromConvertData.numBytes;
384                        memcpy(convResult->data,
385                               (char *)convSession->output.fromConvertData.pBuffer,
386                               convResult->length);
387                    }
388                }
389            } else {
390                offset = convSession->output.fromConvertData.errorPos;
391            }
392        }
393    }
394    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
395}
396
397DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
398                                                         int convertId) {
399    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
400    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
401    int offset = -1;
402
403    LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");
404
405    if (convertSessionMap.isCreated(convertId)) {
406        ConvertSession *convSession = convertSessionMap.getValue(convertId);
407
408        if (NULL != convSession) {
409            retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
410
411            if (FwdLockConv_Status_OK == retStatus) {
412                offset = convSession->output.fromCloseSession.fileOffset;
413                convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
414
415                if (NULL != convResult->data) {
416                      convResult->length = FWD_LOCK_SIGNATURES_SIZE;
417                      memcpy(convResult->data,
418                             (char *)convSession->output.fromCloseSession.signatures,
419                             convResult->length);
420                }
421            }
422        }
423        convertSessionMap.removeValue(convertId);
424    }
425    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
426}
427
428#ifdef USE_64BIT_DRM_API
429status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
430                                             DecryptHandle* decryptHandle,
431                                             int fd,
432                                             off64_t offset,
433                                             off64_t length) {
434#else
435status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
436                                             DecryptHandle* decryptHandle,
437                                             int fd,
438                                             int offset,
439                                             int length) {
440#endif
441    status_t result = DRM_ERROR_CANNOT_HANDLE;
442    int fileDesc = -1;
443
444    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");
445
446    if ((-1 < fd) &&
447        (NULL != decryptHandle) &&
448        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
449        fileDesc = dup(fd);
450    } else {
451        LOGE("FwdLockEngine::onOpenDecryptSession parameter error");
452        return result;
453    }
454
455    if (-1 < fileDesc &&
456        -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
457        -1 < FwdLockFile_attach(fileDesc)) {
458        // check for file integrity. This must be done to protect the content mangling.
459        int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
460        DecodeSession* decodeSession = new DecodeSession(fileDesc);
461
462        if (retVal && NULL != decodeSession) {
463            decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
464            const char *pmime= FwdLockFile_GetContentType(fileDesc);
465            String8 contentType = String8(pmime == NULL ? "" : pmime);
466            contentType.toLower();
467            decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
468            decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
469            decryptHandle->status = RightsStatus::RIGHTS_VALID;
470            decryptHandle->decryptInfo = NULL;
471            result = DRM_NO_ERROR;
472        } else {
473            LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
474            FwdLockFile_detach(fileDesc);
475            delete decodeSession;
476        }
477    }
478
479    if (DRM_NO_ERROR != result && -1 < fileDesc) {
480        ::close(fileDesc);
481    }
482
483    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
484
485    return result;
486}
487
488status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
489                                             DecryptHandle* decryptHandle,
490                                             const char* uri) {
491    status_t result = DRM_ERROR_CANNOT_HANDLE;
492    const char fileTag [] = "file://";
493
494    if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
495        String8 uriTag = String8(uri);
496        uriTag.toLower();
497
498        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
499            const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
500            if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
501                int fd = open(filePath, O_RDONLY);
502
503                if (-1 < fd) {
504                    // offset is always 0 and length is not used. so any positive size.
505                    result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
506
507                    // fd is duplicated already if success. closing the file
508                    close(fd);
509                }
510            }
511        }
512    }
513
514    return result;
515}
516
517status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
518                                              DecryptHandle* decryptHandle) {
519    status_t result = DRM_ERROR_UNKNOWN;
520    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
521
522    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
523        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
524        if (NULL != session && session->fileDesc > -1) {
525            FwdLockFile_detach(session->fileDesc);
526            ::close(session->fileDesc);
527            decodeSessionMap.removeValue(decryptHandle->decryptId);
528            result = DRM_NO_ERROR;
529        }
530    }
531
532    if (NULL != decryptHandle) {
533        if (NULL != decryptHandle->decryptInfo) {
534            delete decryptHandle->decryptInfo;
535            decryptHandle->decryptInfo = NULL;
536        }
537
538        decryptHandle->copyControlVector.clear();
539        decryptHandle->extendedData.clear();
540
541        delete decryptHandle;
542        decryptHandle = NULL;
543    }
544
545    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
546    return result;
547}
548
549status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
550                                                DecryptHandle* decryptHandle,
551                                                int decryptUnitId,
552                                                const DrmBuffer* headerInfo) {
553    LOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
554    return DRM_ERROR_UNKNOWN;
555}
556
557status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
558            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
559    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
560    return DRM_ERROR_UNKNOWN;
561}
562
563status_t FwdLockEngine::onDecrypt(int uniqueId,
564                                  DecryptHandle* decryptHandle,
565                                  int decryptUnitId,
566                                  const DrmBuffer* encBuffer,
567                                  DrmBuffer** decBuffer) {
568    LOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
569    return DRM_ERROR_UNKNOWN;
570}
571
572status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
573                                              DecryptHandle* decryptHandle,
574                                              int decryptUnitId) {
575    LOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
576    return DRM_ERROR_UNKNOWN;
577}
578
579ssize_t FwdLockEngine::onRead(int uniqueId,
580                              DecryptHandle* decryptHandle,
581                              void* buffer,
582                              int numBytes) {
583    ssize_t size = -1;
584
585    if (NULL != decryptHandle &&
586       decodeSessionMap.isCreated(decryptHandle->decryptId) &&
587        NULL != buffer &&
588        numBytes > -1) {
589        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
590        if (NULL != session && session->fileDesc > -1) {
591            size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
592
593            if (0 > size) {
594                session->offset = ((off_t)-1);
595            } else {
596                session->offset += size;
597            }
598        }
599    }
600
601    return size;
602}
603
604#ifdef USE_64BIT_DRM_API
605off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
606                               off64_t offset, int whence) {
607#else
608off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
609                             off_t offset, int whence) {
610#endif
611    off_t offval = -1;
612
613    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
614        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
615        if (NULL != session && session->fileDesc > -1) {
616            offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
617            session->offset = offval;
618        }
619    }
620
621    return offval;
622}
623
624#ifdef USE_64BIT_DRM_API
625ssize_t FwdLockEngine::onPread(int uniqueId,
626                               DecryptHandle* decryptHandle,
627                               void* buffer,
628                               ssize_t numBytes,
629                               off64_t offset) {
630#else
631ssize_t FwdLockEngine::onPread(int uniqueId,
632                               DecryptHandle* decryptHandle,
633                               void* buffer,
634                               ssize_t numBytes,
635                               off_t offset) {
636#endif
637    ssize_t bytesRead = -1;
638
639    DecodeSession* decoderSession = NULL;
640
641    if ((NULL != decryptHandle) &&
642        (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
643        (NULL != buffer) &&
644        (numBytes > -1) &&
645        (offset > -1)) {
646        if (offset != decoderSession->offset) {
647            decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
648        }
649
650        if (((off_t)-1) != decoderSession->offset) {
651            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
652            if (bytesRead < 0) {
653                LOGE("FwdLockEngine::onPread error reading");
654            }
655        }
656    } else {
657        LOGE("FwdLockEngine::onPread decryptId not found");
658    }
659
660    return bytesRead;
661}
662