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