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
162// make sure that lower-case letters are used.
163const String8 FwdLockEngine::FileSuffixes[] = {
164    String8(".fl"),
165    String8(".dm"),
166};
167
168// make sure that lower-case letters are used.
169const String8 FwdLockEngine::MimeTypes[] = {
170    String8("application/x-android-drm-fl"),
171    String8("application/vnd.oma.drm.message"),
172};
173
174const String8 FwdLockEngine::Description("OMA V1 Forward Lock");
175
176void 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
182void 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
188bool 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
199bool 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
210DrmSupportInfo* 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
225bool FwdLockEngine::onCanHandle(int uniqueId, const String8& path) {
226    bool result = false;
227
228    String8 extString = path.getPathExtension();
229    return IsFileSuffixSupported(extString);
230}
231
232DrmInfoStatus* 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
244status_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
254DrmInfo* 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
263int 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
293status_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
302bool 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
312String8 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
336int 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
357status_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
363status_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
370status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
371                                            int playbackStatus, int64_t position) {
372#else
373status_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
381status_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
399DrmConvertedStatus* 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
435DrmConvertedStatus* 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
467status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
468                                             DecryptHandle* decryptHandle,
469                                             int fd,
470                                             off64_t offset,
471                                             off64_t length) {
472#else
473status_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
526status_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
555status_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
587status_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
595status_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
601status_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
610status_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
617ssize_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
643off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
644                               off64_t offset, int whence) {
645#else
646off_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
663ssize_t FwdLockEngine::onPread(int uniqueId,
664                               DecryptHandle* decryptHandle,
665                               void* buffer,
666                               ssize_t numBytes,
667                               off64_t offset) {
668#else
669ssize_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