| /* |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "SessionMap.h" |
| #include "FwdLockEngine.h" |
| #include <utils/Log.h> |
| #include <errno.h> |
| #include <stdio.h> |
| #include <unistd.h> |
| #include "drm_framework_common.h" |
| #include <fcntl.h> |
| #include <limits.h> |
| #include <DrmRights.h> |
| #include <DrmConstraints.h> |
| #include <DrmMetadata.h> |
| #include <DrmInfo.h> |
| #include <DrmInfoStatus.h> |
| #include <DrmInfoRequest.h> |
| #include <DrmSupportInfo.h> |
| #include <DrmConvertedStatus.h> |
| #include <utils/String8.h> |
| #include "FwdLockConv.h" |
| #include "FwdLockFile.h" |
| #include "FwdLockGlue.h" |
| #include "MimeTypeUtil.h" |
| |
| #undef LOG_TAG |
| #define LOG_TAG "FwdLockEngine" |
| |
| #ifdef DRM_OMA_FL_ENGINE_DEBUG |
| #define LOG_NDEBUG 0 |
| #define LOG_VERBOSE(...) ALOGV(__VA_ARGS__) |
| #else |
| #define LOG_VERBOSE(...) |
| #endif |
| |
| using namespace android; |
| // This extern "C" is mandatory to be managed by TPlugInManager |
| extern "C" IDrmEngine* create() { |
| return new FwdLockEngine(); |
| } |
| |
| // This extern "C" is mandatory to be managed by TPlugInManager |
| extern "C" void destroy(IDrmEngine* plugIn) { |
| delete plugIn; |
| } |
| |
| FwdLockEngine::FwdLockEngine() { |
| LOG_VERBOSE("FwdLockEngine Construction"); |
| } |
| |
| FwdLockEngine::~FwdLockEngine() { |
| LOG_VERBOSE("FwdLockEngine Destruction"); |
| |
| int size = decodeSessionMap.getSize(); |
| |
| for (int i = 0; i < size; i++) { |
| DecodeSession *session = (DecodeSession*) decodeSessionMap.getValueAt(i); |
| FwdLockFile_detach(session->fileDesc); |
| ::close(session->fileDesc); |
| } |
| |
| size = convertSessionMap.getSize(); |
| for (int i = 0; i < size; i++) { |
| ConvertSession *convSession = (ConvertSession*) convertSessionMap.getValueAt(i); |
| FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); |
| } |
| } |
| |
| int FwdLockEngine::getConvertedStatus(FwdLockConv_Status_t status) { |
| int retStatus = DrmConvertedStatus::STATUS_ERROR; |
| |
| switch(status) { |
| case FwdLockConv_Status_OK: |
| retStatus = DrmConvertedStatus::STATUS_OK; |
| break; |
| case FwdLockConv_Status_SyntaxError: |
| case FwdLockConv_Status_InvalidArgument: |
| case FwdLockConv_Status_UnsupportedFileFormat: |
| case FwdLockConv_Status_UnsupportedContentTransferEncoding: |
| ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " |
| "Returning STATUS_INPUTDATA_ERROR", status); |
| retStatus = DrmConvertedStatus::STATUS_INPUTDATA_ERROR; |
| break; |
| default: |
| ALOGE("FwdLockEngine getConvertedStatus: file conversion Error %d. " |
| "Returning STATUS_ERROR", status); |
| retStatus = DrmConvertedStatus::STATUS_ERROR; |
| break; |
| } |
| |
| return retStatus; |
| } |
| |
| DrmConstraints* FwdLockEngine::onGetConstraints(int uniqueId, const String8* path, int action) { |
| DrmConstraints* drmConstraints = NULL; |
| |
| LOG_VERBOSE("FwdLockEngine::onGetConstraints"); |
| |
| if (NULL != path && |
| (RightsStatus::RIGHTS_VALID == onCheckRightsStatus(uniqueId, *path, action))) { |
| // Return the empty constraints to show no error condition. |
| drmConstraints = new DrmConstraints(); |
| } |
| |
| return drmConstraints; |
| } |
| |
| DrmMetadata* FwdLockEngine::onGetMetadata(int /*uniqueId*/, const String8* path) { |
| DrmMetadata* drmMetadata = NULL; |
| |
| LOG_VERBOSE("FwdLockEngine::onGetMetadata"); |
| |
| if (NULL != path) { |
| // Returns empty metadata to show no error condition. |
| drmMetadata = new DrmMetadata(); |
| } |
| |
| return drmMetadata; |
| } |
| |
| android::status_t FwdLockEngine::onInitialize(int /*uniqueId*/) { |
| LOG_VERBOSE("FwdLockEngine::onInitialize"); |
| |
| if (FwdLockGlue_InitializeKeyEncryption()) { |
| LOG_VERBOSE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption succeeded"); |
| } else { |
| ALOGE("FwdLockEngine::onInitialize -- FwdLockGlue_InitializeKeyEncryption failed:" |
| "errno = %d", errno); |
| } |
| |
| return DRM_NO_ERROR; |
| } |
| |
| android::status_t |
| FwdLockEngine::onSetOnInfoListener(int /*uniqueId*/, const IDrmEngine::OnInfoListener* /*infoListener*/) { |
| // Not used |
| LOG_VERBOSE("FwdLockEngine::onSetOnInfoListener"); |
| |
| return DRM_NO_ERROR; |
| } |
| |
| android::status_t FwdLockEngine::onTerminate(int /*uniqueId*/) { |
| LOG_VERBOSE("FwdLockEngine::onTerminate"); |
| |
| return DRM_NO_ERROR; |
| } |
| |
| // make sure that lower-case letters are used. |
| const String8 FwdLockEngine::FileSuffixes[] = { |
| String8(".fl"), |
| String8(".dm"), |
| }; |
| |
| // make sure that lower-case letters are used. |
| const String8 FwdLockEngine::MimeTypes[] = { |
| String8("application/x-android-drm-fl"), |
| String8("application/vnd.oma.drm.message"), |
| }; |
| |
| const String8 FwdLockEngine::Description("OMA V1 Forward Lock"); |
| |
| void FwdLockEngine::AddSupportedMimeTypes(DrmSupportInfo *info) { |
| for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { |
| info->addMimeType(MimeTypes[i]); |
| } |
| } |
| |
| void FwdLockEngine::AddSupportedFileSuffixes(DrmSupportInfo *info) { |
| for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { |
| info->addFileSuffix(FileSuffixes[i]); |
| } |
| } |
| |
| bool FwdLockEngine::IsMimeTypeSupported(const String8& mime) { |
| String8 tmp(mime); |
| tmp.toLower(); |
| for (size_t i = 0, n = sizeof(MimeTypes)/sizeof(MimeTypes[0]); i < n; ++i) { |
| if (tmp == MimeTypes[i]) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool FwdLockEngine::IsFileSuffixSupported(const String8& suffix) { |
| String8 tmp(suffix); |
| tmp.toLower(); |
| for (size_t i = 0, n = sizeof(FileSuffixes)/sizeof(FileSuffixes[0]); i < n; ++i) { |
| if (tmp == FileSuffixes[i]) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| DrmSupportInfo* FwdLockEngine::onGetSupportInfo(int /*uniqueId*/) { |
| DrmSupportInfo* pSupportInfo = new DrmSupportInfo(); |
| |
| LOG_VERBOSE("FwdLockEngine::onGetSupportInfo"); |
| |
| // fill all Forward Lock mimetypes and extensions |
| if (NULL != pSupportInfo) { |
| AddSupportedMimeTypes(pSupportInfo); |
| AddSupportedFileSuffixes(pSupportInfo); |
| pSupportInfo->setDescription(Description); |
| } |
| |
| return pSupportInfo; |
| } |
| |
| bool FwdLockEngine::onCanHandle(int /*uniqueId*/, const String8& path) { |
| bool result = false; |
| |
| String8 extString = path.getPathExtension(); |
| return IsFileSuffixSupported(extString); |
| } |
| |
| DrmInfoStatus* FwdLockEngine::onProcessDrmInfo(int /*uniqueId*/, const DrmInfo* /*drmInfo*/) { |
| DrmInfoStatus *drmInfoStatus = NULL; |
| |
| // Nothing to process |
| |
| drmInfoStatus = new DrmInfoStatus((int)DrmInfoStatus::STATUS_OK, 0, NULL, String8("")); |
| |
| LOG_VERBOSE("FwdLockEngine::onProcessDrmInfo"); |
| |
| return drmInfoStatus; |
| } |
| |
| status_t FwdLockEngine::onSaveRights( |
| int /*uniqueId*/, |
| const DrmRights& /*drmRights*/, |
| const String8& /*rightsPath*/, |
| const String8& /*contentPath*/) { |
| // No rights to save. Return |
| LOG_VERBOSE("FwdLockEngine::onSaveRights"); |
| return DRM_ERROR_UNKNOWN; |
| } |
| |
| DrmInfo* FwdLockEngine::onAcquireDrmInfo(int /*uniqueId*/, const DrmInfoRequest* /*drmInfoRequest*/) { |
| DrmInfo* drmInfo = NULL; |
| |
| // Nothing to be done for Forward Lock file |
| LOG_VERBOSE("FwdLockEngine::onAcquireDrmInfo"); |
| |
| return drmInfo; |
| } |
| |
| int FwdLockEngine::onCheckRightsStatus(int uniqueId, |
| const String8& path, |
| int action) { |
| int result = RightsStatus::RIGHTS_INVALID; |
| |
| LOG_VERBOSE("FwdLockEngine::onCheckRightsStatus"); |
| |
| // Only Transfer action is not allowed for forward Lock files. |
| if (onCanHandle(uniqueId, path)) { |
| switch(action) { |
| case Action::DEFAULT: |
| case Action::PLAY: |
| case Action::RINGTONE: |
| case Action::OUTPUT: |
| case Action::PREVIEW: |
| case Action::EXECUTE: |
| case Action::DISPLAY: |
| result = RightsStatus::RIGHTS_VALID; |
| break; |
| |
| case Action::TRANSFER: |
| default: |
| result = RightsStatus::RIGHTS_INVALID; |
| break; |
| } |
| } |
| |
| return result; |
| } |
| |
| status_t FwdLockEngine::onConsumeRights(int /*uniqueId*/, |
| DecryptHandle* /*decryptHandle*/, |
| int /*action*/, |
| bool /*reserve*/) { |
| // No rights consumption |
| LOG_VERBOSE("FwdLockEngine::onConsumeRights"); |
| return DRM_NO_ERROR; |
| } |
| |
| bool FwdLockEngine::onValidateAction(int uniqueId, |
| const String8& path, |
| int action, |
| const ActionDescription& /*description*/) { |
| LOG_VERBOSE("FwdLockEngine::onValidateAction"); |
| |
| // For the forwardlock engine checkRights and ValidateAction are the same. |
| return (onCheckRightsStatus(uniqueId, path, action) == RightsStatus::RIGHTS_VALID); |
| } |
| |
| String8 FwdLockEngine::onGetOriginalMimeType(int /*uniqueId*/, const String8& /*path*/, int fd) { |
| LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType"); |
| String8 mimeString = String8(""); |
| int fileDesc = dup(fd); |
| |
| if (-1 < fileDesc) { |
| if (FwdLockFile_attach(fileDesc) < 0) { |
| close(fileDesc); |
| return mimeString; |
| } |
| const char* pMimeType = FwdLockFile_GetContentType(fileDesc); |
| |
| if (NULL != pMimeType) { |
| String8 contentType = String8(pMimeType); |
| contentType.toLower(); |
| mimeString = MimeTypeUtil::convertMimeType(contentType); |
| } |
| |
| FwdLockFile_close(fileDesc); |
| } |
| |
| return mimeString; |
| } |
| |
| int FwdLockEngine::onGetDrmObjectType(int uniqueId, |
| const String8& path, |
| const String8& mimeType) { |
| String8 mimeStr = String8(mimeType); |
| |
| LOG_VERBOSE("FwdLockEngine::onGetDrmObjectType"); |
| |
| /* Checks whether |
| * 1. path and mime type both are not empty strings (meaning unavailable) else content is unknown |
| * 2. if one of them is empty string and if other is known then its a DRM Content Object. |
| * 3. if both of them are available, then both may be of known type |
| * (regardless of the relation between them to make it compatible with other DRM Engines) |
| */ |
| if (((0 == path.length()) || onCanHandle(uniqueId, path)) && |
| ((0 == mimeType.length()) || IsMimeTypeSupported(mimeType)) && (mimeType != path) ) { |
| return DrmObjectType::CONTENT; |
| } |
| |
| return DrmObjectType::UNKNOWN; |
| } |
| |
| status_t FwdLockEngine::onRemoveRights(int /*uniqueId*/, const String8& /*path*/) { |
| // No Rights to remove |
| LOG_VERBOSE("FwdLockEngine::onRemoveRights"); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t FwdLockEngine::onRemoveAllRights(int /*uniqueId*/) { |
| // No rights to remove |
| LOG_VERBOSE("FwdLockEngine::onRemoveAllRights"); |
| return DRM_NO_ERROR; |
| } |
| |
| #ifdef USE_64BIT_DRM_API |
| status_t FwdLockEngine::onSetPlaybackStatus(int /*uniqueId*/, DecryptHandle* /*decryptHandle*/, |
| int /*playbackStatus*/, int64_t /*position*/) { |
| #else |
| status_t FwdLockEngine::onSetPlaybackStatus(int /*uniqueId*/, DecryptHandle* /*decryptHandle*/, |
| int /*playbackStatus*/, int /*position*/) { |
| #endif |
| // Not used |
| LOG_VERBOSE("FwdLockEngine::onSetPlaybackStatus"); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t FwdLockEngine::onOpenConvertSession(int /*uniqueId*/, |
| int convertId) { |
| status_t result = DRM_ERROR_UNKNOWN; |
| LOG_VERBOSE("FwdLockEngine::onOpenConvertSession"); |
| if (!convertSessionMap.isCreated(convertId)) { |
| ConvertSession *newSession = new ConvertSession(); |
| if (FwdLockConv_Status_OK == |
| FwdLockConv_OpenSession(&(newSession->uniqueId), &(newSession->output))) { |
| convertSessionMap.addValue(convertId, newSession); |
| result = DRM_NO_ERROR; |
| } else { |
| ALOGE("FwdLockEngine::onOpenConvertSession -- FwdLockConv_OpenSession failed."); |
| delete newSession; |
| } |
| } |
| return result; |
| } |
| |
| DrmConvertedStatus* FwdLockEngine::onConvertData(int /*uniqueId*/, |
| int convertId, |
| const DrmBuffer* inputData) { |
| FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; |
| DrmBuffer *convResult = new DrmBuffer(NULL, 0); |
| int offset = -1; |
| |
| if (NULL != inputData && convertSessionMap.isCreated(convertId)) { |
| ConvertSession *convSession = convertSessionMap.getValue(convertId); |
| |
| if (NULL != convSession) { |
| retStatus = FwdLockConv_ConvertData(convSession->uniqueId, |
| inputData->data, |
| inputData->length, |
| &(convSession->output)); |
| |
| if (FwdLockConv_Status_OK == retStatus) { |
| // return bytes from conversion if available |
| if (convSession->output.fromConvertData.numBytes > 0) { |
| convResult->data = new char[convSession->output.fromConvertData.numBytes]; |
| |
| if (NULL != convResult->data) { |
| convResult->length = convSession->output.fromConvertData.numBytes; |
| memcpy(convResult->data, |
| (char *)convSession->output.fromConvertData.pBuffer, |
| convResult->length); |
| } |
| } |
| } else { |
| offset = convSession->output.fromConvertData.errorPos; |
| } |
| } |
| } |
| return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); |
| } |
| |
| DrmConvertedStatus* FwdLockEngine::onCloseConvertSession(int /*uniqueId*/, |
| int convertId) { |
| FwdLockConv_Status_t retStatus = FwdLockConv_Status_InvalidArgument; |
| DrmBuffer *convResult = new DrmBuffer(NULL, 0); |
| int offset = -1; |
| |
| LOG_VERBOSE("FwdLockEngine::onCloseConvertSession"); |
| |
| if (convertSessionMap.isCreated(convertId)) { |
| ConvertSession *convSession = convertSessionMap.getValue(convertId); |
| |
| if (NULL != convSession) { |
| retStatus = FwdLockConv_CloseSession(convSession->uniqueId, &(convSession->output)); |
| |
| if (FwdLockConv_Status_OK == retStatus) { |
| offset = convSession->output.fromCloseSession.fileOffset; |
| convResult->data = new char[FWD_LOCK_SIGNATURES_SIZE]; |
| |
| if (NULL != convResult->data) { |
| convResult->length = FWD_LOCK_SIGNATURES_SIZE; |
| memcpy(convResult->data, |
| (char *)convSession->output.fromCloseSession.signatures, |
| convResult->length); |
| } |
| } |
| } |
| convertSessionMap.removeValue(convertId); |
| } |
| return new DrmConvertedStatus(getConvertedStatus(retStatus), convResult, offset); |
| } |
| |
| #ifdef USE_64BIT_DRM_API |
| status_t FwdLockEngine::onOpenDecryptSession(int /*uniqueId*/, |
| DecryptHandle* decryptHandle, |
| int fd, |
| off64_t offset, |
| off64_t /*length*/) { |
| #else |
| status_t FwdLockEngine::onOpenDecryptSession(int /*uniqueId*/, |
| DecryptHandle* decryptHandle, |
| int fd, |
| int offset, |
| int /*length*/) { |
| #endif |
| status_t result = DRM_ERROR_CANNOT_HANDLE; |
| int fileDesc = -1; |
| |
| LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession"); |
| |
| if ((-1 < fd) && |
| (NULL != decryptHandle) && |
| (!decodeSessionMap.isCreated(decryptHandle->decryptId))) { |
| fileDesc = dup(fd); |
| } else { |
| ALOGE("FwdLockEngine::onOpenDecryptSession parameter error"); |
| return result; |
| } |
| |
| if (-1 < fileDesc && |
| -1 < ::lseek(fileDesc, offset, SEEK_SET) && |
| -1 < FwdLockFile_attach(fileDesc)) { |
| // check for file integrity. This must be done to protect the content mangling. |
| int retVal = FwdLockFile_CheckHeaderIntegrity(fileDesc); |
| DecodeSession* decodeSession = new DecodeSession(fileDesc); |
| |
| if (retVal && NULL != decodeSession) { |
| decodeSessionMap.addValue(decryptHandle->decryptId, decodeSession); |
| const char *pmime= FwdLockFile_GetContentType(fileDesc); |
| String8 contentType = String8(pmime == NULL ? "" : pmime); |
| contentType.toLower(); |
| decryptHandle->mimeType = MimeTypeUtil::convertMimeType(contentType); |
| decryptHandle->decryptApiType = DecryptApiType::CONTAINER_BASED; |
| decryptHandle->status = RightsStatus::RIGHTS_VALID; |
| decryptHandle->decryptInfo = NULL; |
| result = DRM_NO_ERROR; |
| } else { |
| LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Integrity Check failed for the fd"); |
| FwdLockFile_detach(fileDesc); |
| delete decodeSession; |
| } |
| } |
| |
| if (DRM_NO_ERROR != result && -1 < fileDesc) { |
| ::close(fileDesc); |
| } |
| |
| LOG_VERBOSE("FwdLockEngine::onOpenDecryptSession Exit. result = %d", result); |
| |
| return result; |
| } |
| |
| status_t FwdLockEngine::onOpenDecryptSession(int uniqueId, |
| DecryptHandle* decryptHandle, |
| const char* uri) { |
| status_t result = DRM_ERROR_CANNOT_HANDLE; |
| const char fileTag [] = "file://"; |
| |
| if (NULL != decryptHandle && NULL != uri && strlen(uri) > sizeof(fileTag)) { |
| String8 uriTag = String8(uri); |
| uriTag.toLower(); |
| |
| if (0 == strncmp(uriTag.string(), fileTag, sizeof(fileTag) - 1)) { |
| const char *filePath = strchr(uri + sizeof(fileTag) - 1, '/'); |
| if (NULL != filePath && onCanHandle(uniqueId, String8(filePath))) { |
| int fd = open(filePath, O_RDONLY); |
| |
| if (-1 < fd) { |
| // offset is always 0 and length is not used. so any positive size. |
| result = onOpenDecryptSession(uniqueId, decryptHandle, fd, 0, 1); |
| |
| // fd is duplicated already if success. closing the file |
| close(fd); |
| } |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| status_t FwdLockEngine::onCloseDecryptSession(int /*uniqueId*/, |
| DecryptHandle* decryptHandle) { |
| status_t result = DRM_ERROR_UNKNOWN; |
| LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession"); |
| |
| if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { |
| DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); |
| if (NULL != session && session->fileDesc > -1) { |
| FwdLockFile_detach(session->fileDesc); |
| ::close(session->fileDesc); |
| decodeSessionMap.removeValue(decryptHandle->decryptId); |
| result = DRM_NO_ERROR; |
| } |
| } |
| |
| if (NULL != decryptHandle) { |
| if (NULL != decryptHandle->decryptInfo) { |
| delete decryptHandle->decryptInfo; |
| decryptHandle->decryptInfo = NULL; |
| } |
| |
| decryptHandle->copyControlVector.clear(); |
| decryptHandle->extendedData.clear(); |
| |
| delete decryptHandle; |
| decryptHandle = NULL; |
| } |
| |
| LOG_VERBOSE("FwdLockEngine::onCloseDecryptSession Exit"); |
| return result; |
| } |
| |
| status_t FwdLockEngine::onInitializeDecryptUnit(int /*uniqueId*/, |
| DecryptHandle* /*decryptHandle*/, |
| int /*decryptUnitId*/, |
| const DrmBuffer* /*headerInfo*/) { |
| ALOGE("FwdLockEngine::onInitializeDecryptUnit is not supported for this DRM scheme"); |
| return DRM_ERROR_UNKNOWN; |
| } |
| |
| status_t FwdLockEngine::onDecrypt(int /*uniqueId*/, |
| DecryptHandle* /*decryptHandle*/, int /*decryptUnitId*/, |
| const DrmBuffer* /*encBuffer*/, DrmBuffer** /*decBuffer*/, |
| DrmBuffer* /*IV*/) { |
| ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); |
| return DRM_ERROR_UNKNOWN; |
| } |
| |
| status_t FwdLockEngine::onDecrypt(int /*uniqueId*/, |
| DecryptHandle* /*decryptHandle*/, |
| int /*decryptUnitId*/, |
| const DrmBuffer* /*encBuffer*/, |
| DrmBuffer** /*decBuffer*/) { |
| ALOGE("FwdLockEngine::onDecrypt is not supported for this DRM scheme"); |
| return DRM_ERROR_UNKNOWN; |
| } |
| |
| status_t FwdLockEngine::onFinalizeDecryptUnit(int /*uniqueId*/, |
| DecryptHandle* /*decryptHandle*/, |
| int /*decryptUnitId*/) { |
| ALOGE("FwdLockEngine::onFinalizeDecryptUnit is not supported for this DRM scheme"); |
| return DRM_ERROR_UNKNOWN; |
| } |
| |
| ssize_t FwdLockEngine::onRead(int /*uniqueId*/, |
| DecryptHandle* decryptHandle, |
| void* buffer, |
| int numBytes) { |
| ssize_t size = -1; |
| |
| if (NULL != decryptHandle && |
| decodeSessionMap.isCreated(decryptHandle->decryptId) && |
| NULL != buffer && |
| numBytes > -1) { |
| DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); |
| if (NULL != session && session->fileDesc > -1) { |
| size = FwdLockFile_read(session->fileDesc, buffer, numBytes); |
| |
| if (0 > size) { |
| session->offset = ((off_t)-1); |
| } else { |
| session->offset += size; |
| } |
| } |
| } |
| |
| return size; |
| } |
| |
| #ifdef USE_64BIT_DRM_API |
| off64_t FwdLockEngine::onLseek(int /*uniqueId*/, DecryptHandle* decryptHandle, |
| off64_t offset, int whence) { |
| #else |
| off_t FwdLockEngine::onLseek(int /*uniqueId*/, DecryptHandle* decryptHandle, |
| off_t offset, int whence) { |
| #endif |
| off_t offval = -1; |
| |
| if (NULL != decryptHandle && decodeSessionMap.isCreated(decryptHandle->decryptId)) { |
| DecodeSession* session = decodeSessionMap.getValue(decryptHandle->decryptId); |
| if (NULL != session && session->fileDesc > -1) { |
| offval = FwdLockFile_lseek(session->fileDesc, offset, whence); |
| session->offset = offval; |
| } |
| } |
| |
| return offval; |
| } |
| |
| #ifdef USE_64BIT_DRM_API |
| ssize_t FwdLockEngine::onPread(int uniqueId, |
| DecryptHandle* decryptHandle, |
| void* buffer, |
| ssize_t numBytes, |
| off64_t offset) { |
| #else |
| ssize_t FwdLockEngine::onPread(int uniqueId, |
| DecryptHandle* decryptHandle, |
| void* buffer, |
| ssize_t numBytes, |
| off_t offset) { |
| #endif |
| ssize_t bytesRead = -1; |
| |
| DecodeSession* decoderSession = NULL; |
| |
| if ((NULL != decryptHandle) && |
| (NULL != (decoderSession = decodeSessionMap.getValue(decryptHandle->decryptId))) && |
| (NULL != buffer) && |
| (numBytes > -1) && |
| (offset > -1)) { |
| if (offset != decoderSession->offset) { |
| decoderSession->offset = onLseek(uniqueId, decryptHandle, offset, SEEK_SET); |
| } |
| |
| if (((off_t)-1) != decoderSession->offset) { |
| bytesRead = onRead(uniqueId, decryptHandle, buffer, numBytes); |
| if (bytesRead < 0) { |
| ALOGE("FwdLockEngine::onPread error reading"); |
| } |
| } |
| } else { |
| ALOGE("FwdLockEngine::onPread decryptId not found"); |
| } |
| |
| return bytesRead; |
| } |