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 return mimeString;
320 }
321 const char* pMimeType = FwdLockFile_GetContentType(fileDesc);
322
323 if (NULL != pMimeType) {
324 String8 contentType = String8(pMimeType);
325 contentType.toLower();
326 mimeString = MimeTypeUtil::convertMimeType(contentType);
327 }
328
329 FwdLockFile_close(fileDesc);
330 }
331
332 return mimeString;
333 }
334
onGetDrmObjectType(int uniqueId,const String8 & path,const String8 & mimeType)335 int FwdLockEngine::onGetDrmObjectType(int uniqueId,
336 const String8& path,
337 const String8& mimeType) {
338 String8 mimeStr = String8(mimeType);
339
340 LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType");
341
342 /* Checks whether
343 * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown
344 * 2. if one of them is empty string and if other is known then its a DRM Content Object.
345 * 3. if both of them are available, then both may be of known type
346 * (regardless of the relation between them to make it compatible with other DRM Engines)
347 */
348 if (((0 == path.length()) || onCanHandle(uniqueId, path)) &&
349 ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) {
350 return DrmObjectType::CONTENT;
351 }
352
353 return DrmObjectType::UNKNOWN;
354 }
355
onRemoveRights(int uniqueId,const String8 & path)356 status_t FwdLockEngine::onRemoveRights(int uniqueId, const String8& path) {
357 // No Rights to remove
358 LOG_VERBOSE("FwdLockEngine::onRemoveRights");
359 return DRM_NO_ERROR;
360 }
361
onRemoveAllRights(int uniqueId)362 status_t FwdLockEngine::onRemoveAllRights(int uniqueId) {
363 // No rights to remove
364 LOG_VERBOSE("FwdLockEngine::onRemoveAllRights");
365 return DRM_NO_ERROR;
366 }
367
368 #ifdef USE_64BIT_DRM_API
onSetPlaybackStatus(int uniqueId,DecryptHandle * decryptHandle,int playbackStatus,int64_t position)369 status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
370 int playbackStatus, int64_t position) {
371 #else
372 status_t FwdLockEngine::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
373 int playbackStatus, int position) {
374 #endif
375 // Not used
376 LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus");
377 return DRM_NO_ERROR;
378 }
379
380 status_t FwdLockEngine::onOpenConvertSession(int uniqueId,
381 int convertId) {
382 status_t result = DRM_ERROR_UNKNOWN;
383 LOG_VERBOSE("FwdLockEngine::onOpenConvertSession");
384 if (!convertSessionMap.isCreated(convertId)) {
385 ConvertSession *newSession = new ConvertSession();
386 if (FwdLockConv_Status_OK ==
387 FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) {
388 convertSessionMap.addValue(convertId, newSession);
389 result = DRM_NO_ERROR;
390 } else {
391 ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed.");
392 delete newSession;
393 }
394 }
395 return result;
396 }
397
398 DrmConvertedStatus* FwdLockEngine::onConvertData(int uniqueId,
399 int convertId,
400 const DrmBuffer* inputData) {
401 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
402 DrmBuffer *convResult = new DrmBuffer(NULL, 0);
403 int offset = -1;
404
405 if (NULL != inputData && convertSessionMap.isCreated(convertId)) {
406 ConvertSession *convSession = convertSessionMap.getValue(convertId);
407
408 if (NULL != convSession) {
409 retStatus = FwdLockConv_ConvertData(convSession->uniqueId,
410 inputData->data,
411 inputData->length,
412 &(convSession->output));
413
414 if (FwdLockConv_Status_OK == retStatus) {
415 // return bytes from conversion if available
416 if (convSession->output.fromConvertData.numBytes > 0) {
417 convResult->data = new char[convSession->output.fromConvertData.numBytes];
418
419 if (NULL != convResult->data) {
420 convResult->length = convSession->output.fromConvertData.numBytes;
421 memcpy(convResult->data,
422 (char *)convSession->output.fromConvertData.pBuffer,
423 convResult->length);
424 }
425 }
426 } else {
427 offset = convSession->output.fromConvertData.errorPos;
428 }
429 }
430 }
431 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
432 }
433
434 DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int uniqueId,
435 int convertId) {
436 FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument;
437 DrmBuffer *convResult = new DrmBuffer(NULL, 0);
438 int offset = -1;
439
440 LOG_VERBOSE("FwdLockEngine::onCloseConvertSession");
441
442 if (convertSessionMap.isCreated(convertId)) {
443 ConvertSession *convSession = convertSessionMap.getValue(convertId);
444
445 if (NULL != convSession) {
446 retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output));
447
448 if (FwdLockConv_Status_OK == retStatus) {
449 offset = convSession->output.fromCloseSession.fileOffset;
450 convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE];
451
452 if (NULL != convResult->data) {
453 convResult->length = FWD_LOCK_SIGNATURES_SIZE;
454 memcpy(convResult->data,
455 (char *)convSession->output.fromCloseSession.signatures,
456 convResult->length);
457 }
458 }
459 }
460 convertSessionMap.removeValue(convertId);
461 }
462 return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset);
463 }
464
465 #ifdef USE_64BIT_DRM_API
466 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
467 DecryptHandle* decryptHandle,
468 int fd,
469 off64_t offset,
470 off64_t length) {
471 #else
472 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
473 DecryptHandle* decryptHandle,
474 int fd,
475 int offset,
476 int length) {
477 #endif
478 status_t result = DRM_ERROR_CANNOT_HANDLE;
479 int fileDesc = -1;
480
481 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession");
482
483 if ((-1 < fd) &&
484 (NULL != decryptHandle) &&
485 (!decodeSessionMap.isCreated(decryptHandle->decryptId))) {
486 fileDesc = dup(fd);
487 } else {
488 ALOGE("FwdLockEngine::onOpenDecryptSession parameter error");
489 return result;
490 }
491
492 if (-1 < fileDesc &&
493 -1 < ::lseek(fileDesc, offset, SEEK_SET) &&
494 -1 < FwdLockFile_attach(fileDesc)) {
495 // check for file integrity. This must be done to protect the content mangling.
496 int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc);
497 DecodeSession* decodeSession = new DecodeSession(fileDesc);
498
499 if (retVal && NULL != decodeSession) {
500 decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession);
501 const char *pmime= FwdLockFile_GetContentType(fileDesc);
502 String8 contentType = String8(pmime == NULL ? "" : pmime);
503 contentType.toLower();
504 decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType);
505 decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED;
506 decryptHandle->status = RightsStatus::RIGHTS_VALID;
507 decryptHandle->decryptInfo = NULL;
508 result = DRM_NO_ERROR;
509 } else {
510 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd");
511 FwdLockFile_detach(fileDesc);
512 delete decodeSession;
513 }
514 }
515
516 if (DRM_NO_ERROR != result && -1 < fileDesc) {
517 ::close(fileDesc);
518 }
519
520 LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result);
521
522 return result;
523 }
524
525 status_t FwdLockEngine::onOpenDecryptSession(int uniqueId,
526 DecryptHandle* decryptHandle,
527 const char* uri) {
528 status_t result = DRM_ERROR_CANNOT_HANDLE;
529 const char fileTag [] = "file://";
530
531 if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) {
532 String8 uriTag = String8(uri);
533 uriTag.toLower();
534
535 if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) {
536 const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/');
537 if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) {
538 int fd = open(filePath, O_RDONLY);
539
540 if (-1 < fd) {
541 // offset is always 0 and length is not used. so any positive size.
542 result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1);
543
544 // fd is duplicated already if success. closing the file
545 close(fd);
546 }
547 }
548 }
549 }
550
551 return result;
552 }
553
554 status_t FwdLockEngine::onCloseDecryptSession(int uniqueId,
555 DecryptHandle* decryptHandle) {
556 status_t result = DRM_ERROR_UNKNOWN;
557 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession");
558
559 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
560 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
561 if (NULL != session && session->fileDesc > -1) {
562 FwdLockFile_detach(session->fileDesc);
563 ::close(session->fileDesc);
564 decodeSessionMap.removeValue(decryptHandle->decryptId);
565 result = DRM_NO_ERROR;
566 }
567 }
568
569 if (NULL != decryptHandle) {
570 if (NULL != decryptHandle->decryptInfo) {
571 delete decryptHandle->decryptInfo;
572 decryptHandle->decryptInfo = NULL;
573 }
574
575 decryptHandle->copyControlVector.clear();
576 decryptHandle->extendedData.clear();
577
578 delete decryptHandle;
579 decryptHandle = NULL;
580 }
581
582 LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit");
583 return result;
584 }
585
586 status_t FwdLockEngine::onInitializeDecryptUnit(int uniqueId,
587 DecryptHandle* decryptHandle,
588 int decryptUnitId,
589 const DrmBuffer* headerInfo) {
590 ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme");
591 return DRM_ERROR_UNKNOWN;
592 }
593
594 status_t FwdLockEngine::onDecrypt(int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
595 const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
596 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
597 return DRM_ERROR_UNKNOWN;
598 }
599
600 status_t FwdLockEngine::onDecrypt(int uniqueId,
601 DecryptHandle* decryptHandle,
602 int decryptUnitId,
603 const DrmBuffer* encBuffer,
604 DrmBuffer** decBuffer) {
605 ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme");
606 return DRM_ERROR_UNKNOWN;
607 }
608
609 status_t FwdLockEngine::onFinalizeDecryptUnit(int uniqueId,
610 DecryptHandle* decryptHandle,
611 int decryptUnitId) {
612 ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme");
613 return DRM_ERROR_UNKNOWN;
614 }
615
616 ssize_t FwdLockEngine::onRead(int uniqueId,
617 DecryptHandle* decryptHandle,
618 void* buffer,
619 int numBytes) {
620 ssize_t size = -1;
621
622 if (NULL != decryptHandle &&
623 decodeSessionMap.isCreated(decryptHandle->decryptId) &&
624 NULL != buffer &&
625 numBytes > -1) {
626 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
627 if (NULL != session && session->fileDesc > -1) {
628 size = FwdLockFile_read(session->fileDesc, buffer, numBytes);
629
630 if (0 > size) {
631 session->offset = ((off_t)-1);
632 } else {
633 session->offset += size;
634 }
635 }
636 }
637
638 return size;
639 }
640
641 #ifdef USE_64BIT_DRM_API
642 off64_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
643 off64_t offset, int whence) {
644 #else
645 off_t FwdLockEngine::onLseek(int uniqueId, DecryptHandle* decryptHandle,
646 off_t offset, int whence) {
647 #endif
648 off_t offval = -1;
649
650 if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) {
651 DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId);
652 if (NULL != session && session->fileDesc > -1) {
653 offval = FwdLockFile_lseek(session->fileDesc, offset, whence);
654 session->offset = offval;
655 }
656 }
657
658 return offval;
659 }
660
661 #ifdef USE_64BIT_DRM_API
662 ssize_t FwdLockEngine::onPread(int uniqueId,
663 DecryptHandle* decryptHandle,
664 void* buffer,
665 ssize_t numBytes,
666 off64_t offset) {
667 #else
668 ssize_t FwdLockEngine::onPread(int uniqueId,
669 DecryptHandle* decryptHandle,
670 void* buffer,
671 ssize_t numBytes,
672 off_t offset) {
673 #endif
674 ssize_t bytesRead = -1;
675
676 DecodeSession* decoderSession = NULL;
677
678 if ((NULL != decryptHandle) &&
679 (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) &&
680 (NULL != buffer) &&
681 (numBytes > -1) &&
682 (offset > -1)) {
683 if (offset != decoderSession->offset) {
684 decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET);
685 }
686
687 if (((off_t)-1) != decoderSession->offset) {
688 bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes);
689 if (bytesRead < 0) {
690 ALOGE("FwdLockEngine::onPread error reading");
691 }
692 }
693 } else {
694 ALOGE("FwdLockEngine::onPread decryptId not found");
695 }
696
697 return bytesRead;
698 }
699