FwdLockEngine.cpp revision bd2f13ddbe7a9e7550205f6b53880329e09b9457
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(int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
150    // Not used
151    LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener");
152
153    return DRM_NO_ERROR;
154}
155
156android::status_t FwdLockEngine::onTerminate(int uniqueId) {
157    LOG_VERBOSE("FwdLockEngine::onTerminate");
158
159    return DRM_NO_ERROR;
160}
161
162const String8 FwdLockEngine::FileSuffixes[] = {
163    String8(".fl"),
164    String8(".dm"),
165};
166
167const String8 FwdLockEngine::MimeTypes[] = {
168    String8("application/x-android-drm-fl"),
169    String8("application/vnd.oma.drm.message"),
170};
171
172const String8 FwdLockEngine::Description("OMA V1 Forward Lock");
173
174void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) {
175    for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
176        info->addMimeType(MimeTypes[i]);
177    }
178}
179
180void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) {
181    for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
182        info->addFileSuffix(FileSuffixes[i]);
183    }
184}
185
186bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) {
187    for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) {
188        if (mime == MimeTypes[i]) {
189            return true;
190        }
191    }
192    return false;
193}
194
195bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) {
196    for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) {
197        if (suffix == FileSuffixes[i]) {
198            return true;
199        }
200    }
201    return false;
202}
203
204DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int uniqueId) {
205    DrmSupportInfo* pSupportInfo = new DrmSupportInfo();
206
207    LOG_VERBOSE("FwdLockEngine::onGetSupportInfo");
208
209    // fill all Forward Lock mimetypes and extensions
210    if (NULL != pSupportInfo) {
211        AddSupportedMimeTypes(pSupportInfo);
212        AddSupportedFileSuffixes(pSupportInfo);
213        pSupportInfo->setDescription(Description);
214    }
215
216    return pSupportInfo;
217}
218
219bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
220    bool result = false;
221
222    String8 extString = path.getPathExtension();
223    extString.toLower();
224    return IsFileSuffixSupported(extString);
225}
226
227DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) {
228    DrmInfoStatus *drmInfoStatus = NULL;
229
230    // Nothing to process
231
232    drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8(""));
233
234    LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo");
235
236    return drmInfoStatus;
237}
238
239status_t FwdLockEngine::onSaveRights(
240            int uniqueId,
241            const DrmRights& drmRights,
242            const String8& rightsPath,
243            const String8& contentPath) {
244    // No rights to save. Return
245    LOG_VERBOSE("FwdLockEngine::onSaveRights");
246    return DRM_ERROR_UNKNOWN;
247}
248
249DrmInfo* FwdLockEngine::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) {
250    DrmInfo* drmInfo = NULL;
251
252    // Nothing to be done for Forward Lock file
253    LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo");
254
255    return drmInfo;
256}
257
258int FwdLockEngine::onCheckRightsStatus(int uniqueId,
259                                       const String8& path,
260                                       int action) {
261    int result = RightsStatus::RIGHTS_INVALID;
262
263    LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus");
264
265    // Only Transfer action is not allowed for forward Lock files.
266    if (onCanHandle(uniqueId, path)) {
267        switch(action) {
268            case Action::DEFAULT:
269            case Action::PLAY:
270            case Action::RINGTONE:
271            case Action::OUTPUT:
272            case Action::PREVIEW:
273            case Action::EXECUTE:
274            case Action::DISPLAY:
275                result = RightsStatus::RIGHTS_VALID;
276                break;
277
278            case Action::TRANSFER:
279            default:
280                result = RightsStatus::RIGHTS_INVALID;
281                break;
282        }
283    }
284
285    return result;
286}
287
288status_t FwdLockEngine::onConsumeRights(int uniqueId,
289                                        DecryptHandle* decryptHandle,
290                                        int action,
291                                        bool reserve) {
292    // No rights consumption
293    LOG_VERBOSE("FwdLockEngine::onConsumeRights");
294    return DRM_NO_ERROR;
295}
296
297bool FwdLockEngine::onValidateAction(int uniqueId,
298                                     const String8& path,
299                                     int action,
300                                     const ActionDescription& description) {
301    LOG_VERBOSE("FwdLockEngine::onValidateAction");
302
303    // For the forwardlock engine checkRights and ValidateAction are the same.
304    return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID);
305}
306
307String8 FwdLockEngine::onGetOriginalMimeType(int uniqueId, const String8& path) {
308    LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType");
309    String8 mimeString = String8("");
310    int fileDesc = FwdLockFile_open(path.string());
311
312    if (-1 < fileDesc) {
313        const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
314
315        if (NULL != pMimeType) {
316            String8 contentType = String8(pMimeType);
317            contentType.toLower();
318            mimeString = MimeTypeUtil::convertMimeType(contentType);
319        }
320
321        FwdLockFile_close(fileDesc);
322    }
323
324    return mimeString;
325}
326
327int FwdLockEngine::onGetDrmObjectType(int uniqueId,
328                                      const String8& path,
329                                      const String8& mimeType) {
330    String8 mimeStr = String8(mimeType);
331
332    LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
333
334    mimeStr.toLower();
335
336    /* Checks whether
337    * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
338    * 2. if one of them is empty string and if other is known then its a DRM Content Object.
339    * 3. if both of them are available, then both may be of known type
340    *    (regardless of the relation between them to make it compatible with other DRM Engines)
341    */
342    if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
343        ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) {
344            return DrmObjectType::CONTENT;
345    }
346
347    return DrmObjectType::UNKNOWN;
348}
349
350status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
351    // No Rights to remove
352    LOG_VERBOSE("FwdLockEngine::onRemoveRights");
353    return DRM_NO_ERROR;
354}
355
356status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
357    // No rights to remove
358    LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
359    return DRM_NO_ERROR;
360}
361
362#ifdef USE_64BIT_DRM_API
363status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
364                                            int playbackStatus, int64_t position) {
365#else
366status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
367                                            int playbackStatus, int position) {
368#endif
369    // Not used
370    LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
371    return DRM_NO_ERROR;
372}
373
374status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
375                                         int convertId) {
376    status_t result = DRM_ERROR_UNKNOWN;
377    LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
378    if (!convertSessionMap.isCreated(convertId)) {
379        ConvertSession *newSession = new ConvertSession();
380        if (FwdLockConv_Status_OK ==
381            FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
382            convertSessionMap.addValue(convertId, newSession);
383            result = DRM_NO_ERROR;
384        } else {
385            ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
386            delete newSession;
387        }
388    }
389    return result;
390}
391
392DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
393                                                 int convertId,
394                                                 const DrmBuffer* inputData) {
395    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
396    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
397    int offset = -1;
398
399    if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
400        ConvertSession *convSession = convertSessionMap.getValue(convertId);
401
402        if (NULL != convSession) {
403            retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
404                                                inputData->data,
405                                                inputData->length,
406                                                &(convSession->output));
407
408            if (FwdLockConv_Status_OK == retStatus) {
409                // return bytes from conversion if available
410                if (convSession->output.fromConvertData.numBytes > 0) {
411                    convResult->data = new char[convSession->output.fromConvertData.numBytes];
412
413                    if (NULL != convResult->data) {
414                        convResult->length = convSession->output.fromConvertData.numBytes;
415                        memcpy(convResult->data,
416                               (char *)convSession->output.fromConvertData.pBuffer,
417                               convResult->length);
418                    }
419                }
420            } else {
421                offset = convSession->output.fromConvertData.errorPos;
422            }
423        }
424    }
425    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
426}
427
428DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
429                                                         int convertId) {
430    FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
431    DrmBuffer *convResult = new DrmBuffer(NULL, 0);
432    int offset = -1;
433
434    LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");
435
436    if (convertSessionMap.isCreated(convertId)) {
437        ConvertSession *convSession = convertSessionMap.getValue(convertId);
438
439        if (NULL != convSession) {
440            retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
441
442            if (FwdLockConv_Status_OK == retStatus) {
443                offset = convSession->output.fromCloseSession.fileOffset;
444                convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
445
446                if (NULL != convResult->data) {
447                      convResult->length = FWD_LOCK_SIGNATURES_SIZE;
448                      memcpy(convResult->data,
449                             (char *)convSession->output.fromCloseSession.signatures,
450                             convResult->length);
451                }
452            }
453        }
454        convertSessionMap.removeValue(convertId);
455    }
456    return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
457}
458
459#ifdef USE_64BIT_DRM_API
460status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
461                                             DecryptHandle* decryptHandle,
462                                             int fd,
463                                             off64_t offset,
464                                             off64_t length) {
465#else
466status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
467                                             DecryptHandle* decryptHandle,
468                                             int fd,
469                                             int offset,
470                                             int length) {
471#endif
472    status_t result = DRM_ERROR_CANNOT_HANDLE;
473    int fileDesc = -1;
474
475    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");
476
477    if ((-1 < fd) &&
478        (NULL != decryptHandle) &&
479        (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
480        fileDesc = dup(fd);
481    } else {
482        ALOGE("FwdLockEngine::onOpenDecryptSession parameter error");
483        return result;
484    }
485
486    if (-1 < fileDesc &&
487        -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
488        -1 < FwdLockFile_attach(fileDesc)) {
489        // check for file integrity. This must be done to protect the content mangling.
490        int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
491        DecodeSession* decodeSession = new DecodeSession(fileDesc);
492
493        if (retVal && NULL != decodeSession) {
494            decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
495            const char *pmime= FwdLockFile_GetContentType(fileDesc);
496            String8 contentType = String8(pmime == NULL ? "" : pmime);
497            contentType.toLower();
498            decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
499            decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
500            decryptHandle->status = RightsStatus::RIGHTS_VALID;
501            decryptHandle->decryptInfo = NULL;
502            result = DRM_NO_ERROR;
503        } else {
504            LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
505            FwdLockFile_detach(fileDesc);
506            delete decodeSession;
507        }
508    }
509
510    if (DRM_NO_ERROR != result && -1 < fileDesc) {
511        ::close(fileDesc);
512    }
513
514    LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
515
516    return result;
517}
518
519status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
520                                             DecryptHandle* decryptHandle,
521                                             const char* uri) {
522    status_t result = DRM_ERROR_CANNOT_HANDLE;
523    const char fileTag [] = "file://";
524
525    if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
526        String8 uriTag = String8(uri);
527        uriTag.toLower();
528
529        if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
530            const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
531            if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
532                int fd = open(filePath, O_RDONLY);
533
534                if (-1 < fd) {
535                    // offset is always 0 and length is not used. so any positive size.
536                    result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
537
538                    // fd is duplicated already if success. closing the file
539                    close(fd);
540                }
541            }
542        }
543    }
544
545    return result;
546}
547
548status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
549                                              DecryptHandle* decryptHandle) {
550    status_t result = DRM_ERROR_UNKNOWN;
551    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
552
553    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
554        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
555        if (NULL != session && session->fileDesc > -1) {
556            FwdLockFile_detach(session->fileDesc);
557            ::close(session->fileDesc);
558            decodeSessionMap.removeValue(decryptHandle->decryptId);
559            result = DRM_NO_ERROR;
560        }
561    }
562
563    if (NULL != decryptHandle) {
564        if (NULL != decryptHandle->decryptInfo) {
565            delete decryptHandle->decryptInfo;
566            decryptHandle->decryptInfo = NULL;
567        }
568
569        decryptHandle->copyControlVector.clear();
570        decryptHandle->extendedData.clear();
571
572        delete decryptHandle;
573        decryptHandle = NULL;
574    }
575
576    LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
577    return result;
578}
579
580status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
581                                                DecryptHandle* decryptHandle,
582                                                int decryptUnitId,
583                                                const DrmBuffer* headerInfo) {
584    ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
585    return DRM_ERROR_UNKNOWN;
586}
587
588status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
589            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
590    ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
591    return DRM_ERROR_UNKNOWN;
592}
593
594status_t FwdLockEngine::onDecrypt(int uniqueId,
595                                  DecryptHandle* decryptHandle,
596                                  int decryptUnitId,
597                                  const DrmBuffer* encBuffer,
598                                  DrmBuffer** decBuffer) {
599    ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
600    return DRM_ERROR_UNKNOWN;
601}
602
603status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
604                                              DecryptHandle* decryptHandle,
605                                              int decryptUnitId) {
606    ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
607    return DRM_ERROR_UNKNOWN;
608}
609
610ssize_t FwdLockEngine::onRead(int uniqueId,
611                              DecryptHandle* decryptHandle,
612                              void* buffer,
613                              int numBytes) {
614    ssize_t size = -1;
615
616    if (NULL != decryptHandle &&
617       decodeSessionMap.isCreated(decryptHandle->decryptId) &&
618        NULL != buffer &&
619        numBytes > -1) {
620        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
621        if (NULL != session && session->fileDesc > -1) {
622            size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
623
624            if (0 > size) {
625                session->offset = ((off_t)-1);
626            } else {
627                session->offset += size;
628            }
629        }
630    }
631
632    return size;
633}
634
635#ifdef USE_64BIT_DRM_API
636off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
637                               off64_t offset, int whence) {
638#else
639off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
640                             off_t offset, int whence) {
641#endif
642    off_t offval = -1;
643
644    if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
645        DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
646        if (NULL != session && session->fileDesc > -1) {
647            offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
648            session->offset = offval;
649        }
650    }
651
652    return offval;
653}
654
655#ifdef USE_64BIT_DRM_API
656ssize_t FwdLockEngine::onPread(int uniqueId,
657                               DecryptHandle* decryptHandle,
658                               void* buffer,
659                               ssize_t numBytes,
660                               off64_t offset) {
661#else
662ssize_t FwdLockEngine::onPread(int uniqueId,
663                               DecryptHandle* decryptHandle,
664                               void* buffer,
665                               ssize_t numBytes,
666                               off_t offset) {
667#endif
668    ssize_t bytesRead = -1;
669
670    DecodeSession* decoderSession = NULL;
671
672    if ((NULL != decryptHandle) &&
673        (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
674        (NULL != buffer) &&
675        (numBytes > -1) &&
676        (offset > -1)) {
677        if (offset != decoderSession->offset) {
678            decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
679        }
680
681        if (((off_t)-1) != decoderSession->offset) {
682            bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
683            if (bytesRead < 0) {
684                ALOGE("FwdLockEngine::onPread error reading");
685            }
686        }
687    } else {
688        ALOGE("FwdLockEngine::onPread decryptId not found");
689    }
690
691    return bytesRead;
692}
693