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