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