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