• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
create()52 extern "C" IDrmEngine* create() {
53     return new FwdLockEngine();
54 }
55 
56 // This extern "C" is mandatory to be managed by TPlugInManager
destroy(IDrmEngine * plugIn)57 extern "C" void destroy(IDrmEngine* plugIn) {
58     delete plugIn;
59 }
60 
FwdLockEngine()61 FwdLockEngine::FwdLockEngine() {
62     LOG_VERBOSE("FwdLockEngine Construction");
63 }
64 
~FwdLockEngine()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 
getConvertedStatus(FwdLockConv_Status_t status)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 
onGetConstraints(int uniqueId,const String8 * path,int action)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 
onGetMetadata(int uniqueId,const String8 * path)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 
onInitialize(int uniqueId)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
onSetOnInfoListener(int uniqueId,const IDrmEngine::OnInfoListener * infoListener)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 
onTerminate(int uniqueId)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 
AddSupportedMimeTypes(DrmSupportInfo * info)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 
AddSupportedFileSuffixes(DrmSupportInfo * info)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 
IsMimeTypeSupported(const String8 & mime)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 
IsFileSuffixSupported(const String8 & suffix)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 
onGetSupportInfo(int uniqueId)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 
onCanHandle(int uniqueId,const String8 & path)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 
onProcessDrmInfo(int uniqueId,const DrmInfo * drmInfo)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 
onSaveRights(int uniqueId,const DrmRights & drmRights,const String8 & rightsPath,const String8 & contentPath)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 
onAcquireDrmInfo(int uniqueId,const DrmInfoRequest * drmInfoRequest)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 
onCheckRightsStatus(int uniqueId,const String8 & path,int action)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 
onConsumeRights(int uniqueId,DecryptHandle * decryptHandle,int action,bool reserve)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 
onValidateAction(int uniqueId,const String8 & path,int action,const ActionDescription & description)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 
onGetOriginalMimeType(int uniqueId,const String8 & path,int fd)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 
onGetDrmObjectType(int uniqueId,const String8 & path,const String8 & mimeType)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 
onRemoveRights(int uniqueId,const String8 & path)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 
onRemoveAllRights(int uniqueId)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
onSetPlaybackStatus(int uniqueId,DecryptHandle * decryptHandle,int playbackStatus,int64_t position)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