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