diff options
author | Anatol Pomozov <anatol.pomozov@gmail.com> | 2012-03-28 09:12:55 -0700 |
---|---|---|
committer | Anatol Pomozov <anatol.pomozov@gmail.com> | 2012-03-28 12:02:47 -0700 |
commit | b0b2b4d890cf3bfb274797a759642b4e733343d7 (patch) | |
tree | 12ad21cbad346f02d542aa4d672ffd76407d58a9 /drm/libdrmframework/plugins/forward-lock/FwdLockEngine | |
parent | 51f8eec23a2bcc2cc190373cdd1195972d9b8804 (diff) | |
parent | 5a5491c17d74bd2c80cf451c6ddbba22d5d5f08a (diff) | |
download | frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.zip frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.gz frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.bz2 |
Merge media files with history from frameworks/base.git
Diffstat (limited to 'drm/libdrmframework/plugins/forward-lock/FwdLockEngine')
3 files changed, 1332 insertions, 0 deletions
diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk new file mode 100644 index 0000000..e359dbd --- /dev/null +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/Android.mk @@ -0,0 +1,70 @@ +# +# 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. +# +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +# The flag below turns on local debug printouts +#LOCAL_CFLAGS += -DDRM_OMA_FL_ENGINE_DEBUG + +base := frameworks/base + +# Determine whether the DRM framework uses 64-bit data types for file offsets and do the same. +ifneq ($(shell grep -c 'off64_t offset' $(base)/drm/libdrmframework/plugins/common/include/IDrmEngine.h), 0) +LOCAL_CFLAGS += -DUSE_64BIT_DRM_API +endif + +LOCAL_SRC_FILES:= \ + src/FwdLockEngine.cpp + +LOCAL_MODULE := libfwdlockengine + +LOCAL_SHARED_LIBRARIES := \ + libicui18n \ + libicuuc \ + libutils \ + libdl \ + libandroid_runtime \ + libnativehelper \ + libcrypto \ + libssl \ + libdrmframework + +LOCAL_STATIC_LIBRARIES := \ + libdrmutility \ + libdrmframeworkcommon \ + libfwdlock-common \ + libfwdlock-converter \ + libfwdlock-decoder + + + +LOCAL_C_INCLUDES += \ + $(JNI_H_INCLUDE) \ + $(base)/include/drm \ + $(base)/drm/libdrmframework/plugins/common/include \ + $(base)/drm/libdrmframework/plugins/common/util/include \ + $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/common \ + $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/converter \ + $(base)/drm/libdrmframework/plugins/forward-lock/internal-format/decoder \ + $(LOCAL_PATH)/include \ + external/openssl/include + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/drm + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h new file mode 100644 index 0000000..c0e408e --- /dev/null +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/include/FwdLockEngine.h @@ -0,0 +1,567 @@ +/* + * 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. + */ + +#ifndef __FWDLOCKENGINE_H__ +#define __FWDLOCKENGINE_H__ + +#include <DrmEngineBase.h> +#include <DrmConstraints.h> +#include <DrmRights.h> +#include <DrmInfo.h> +#include <DrmInfoStatus.h> +#include <DrmConvertedStatus.h> +#include <DrmInfoRequest.h> +#include <DrmSupportInfo.h> +#include <DrmInfoEvent.h> + +#include "SessionMap.h" +#include "FwdLockConv.h" + +namespace android { + +/** + * Forward Lock Engine class. + */ +class FwdLockEngine : public android::DrmEngineBase { + +public: + FwdLockEngine(); + virtual ~FwdLockEngine(); + +protected: +/** + * Get constraint information associated with input content. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @param action Actions defined such as, + * Action::DEFAULT, Action::PLAY, etc + * @return DrmConstraints + * key-value pairs of constraint are embedded in it + * @note + * In case of error, return NULL + */ +DrmConstraints* onGetConstraints(int uniqueId, const String8* path, int action); + +/** + * Get metadata information associated with input content. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @return DrmMetadata + * For Forward Lock engine, it returns an empty object + * @note + * In case of error, returns NULL + */ +DrmMetadata* onGetMetadata(int uniqueId, const String8* path); + +/** + * Initialize plug-in. + * + * @param uniqueId Unique identifier for a session + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onInitialize(int uniqueId); + +/** + * Register a callback to be invoked when the caller required to + * receive necessary information. + * + * @param uniqueId Unique identifier for a session + * @param infoListener Listener + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onSetOnInfoListener(int uniqueId, const IDrmEngine::OnInfoListener* infoListener); + +/** + * Terminate the plug-in and release resources bound to it. + * + * @param uniqueId Unique identifier for a session + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onTerminate(int uniqueId); + +/** + * Get whether the given content can be handled by this plugin or not. + * + * @param uniqueId Unique identifier for a session + * @param path Path to the protected object + * @return bool + * Returns true if this plugin can handle , false in case of not able to handle + */ +bool onCanHandle(int uniqueId, const String8& path); + +/** + * Processes the given DRM information as appropriate for its type. + * Not used for Forward Lock Engine. + * + * @param uniqueId Unique identifier for a session + * @param drmInfo Information that needs to be processed + * @return DrmInfoStatus + * instance as a result of processing given input + */ +DrmInfoStatus* onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo); + +/** + * Save DRM rights to specified rights path + * and make association with content path. + * + * @param uniqueId Unique identifier for a session + * @param drmRights DrmRights to be saved + * @param rightsPath File path where rights to be saved + * @param contentPath File path where content was saved + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onSaveRights(int uniqueId, + const DrmRights& drmRights, + const String8& rightsPath, + const String8& contentPath); + +/** + * Retrieves necessary information for registration, unregistration or rights + * acquisition information. + * + * @param uniqueId Unique identifier for a session + * @param drmInfoRequest Request information to retrieve drmInfo + * @return DrmInfo + * instance as a result of processing given input + */ +DrmInfo* onAcquireDrmInfo(int uniqueId, + const DrmInfoRequest* drmInfoRequest); + +/** + * Retrieves the mime type embedded inside the original content. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @return String8 + * Returns mime-type of the original content, such as "video/mpeg" + */ +String8 onGetOriginalMimeType(int uniqueId, const String8& path); + +/** + * Retrieves the type of the protected object (content, rights, etc..) + * using specified path or mimetype. At least one parameter should be non null + * to retrieve DRM object type. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the content or null. + * @param mimeType Mime type of the content or null. + * @return type of the DRM content, + * such as DrmObjectType::CONTENT, DrmObjectType::RIGHTS_OBJECT + */ +int onGetDrmObjectType(int uniqueId, + const String8& path, + const String8& mimeType); + +/** + * Check whether the given content has valid rights or not. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @param action Action to perform (Action::DEFAULT, Action::PLAY, etc) + * @return the status of the rights for the protected content, + * such as RightsStatus::RIGHTS_VALID, RightsStatus::RIGHTS_EXPIRED, etc. + */ +int onCheckRightsStatus(int uniqueId, + const String8& path, + int action); + +/** + * Consumes the rights for a content. + * If the reserve parameter is true the rights are reserved until the same + * application calls this api again with the reserve parameter set to false. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param action Action to perform. (Action::DEFAULT, Action::PLAY, etc) + * @param reserve True if the rights should be reserved. + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onConsumeRights(int uniqueId, + DecryptHandle* decryptHandle, + int action, + bool reserve); + +/** + * Informs the DRM Engine about the playback actions performed on the DRM files. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param playbackStatus Playback action (Playback::START, Playback::STOP, Playback::PAUSE) + * @param position Position in the file (in milliseconds) where the start occurs. + * Only valid together with Playback::START. + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +#ifdef USE_64BIT_DRM_API +status_t onSetPlaybackStatus(int uniqueId, + DecryptHandle* decryptHandle, + int playbackStatus, + int64_t position); +#else +status_t onSetPlaybackStatus(int uniqueId, + DecryptHandle* decryptHandle, + int playbackStatus, + int position); +#endif + +/** + * Validates whether an action on the DRM content is allowed or not. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @param action Action to validate (Action::PLAY, Action::TRANSFER, etc) + * @param description Detailed description of the action + * @return true if the action is allowed. + */ +bool onValidateAction(int uniqueId, + const String8& path, + int action, + const ActionDescription& description); + +/** + * Removes the rights associated with the given protected content. + * Not used for Forward Lock Engine. + * + * @param uniqueId Unique identifier for a session + * @param path Path of the protected content + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onRemoveRights(int uniqueId, const String8& path); + +/** + * Removes all the rights information of each plug-in associated with + * DRM framework. Will be used in master reset but does nothing for + * Forward Lock Engine. + * + * @param uniqueId Unique identifier for a session + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onRemoveAllRights(int uniqueId); + +/** + * Starts the Forward Lock file conversion session. + * Each time the application tries to download a new DRM file + * which needs to be converted, then the application has to + * begin with calling this API. The convertId is used as the conversion session key + * and must not be the same for different convert sessions. + * + * @param uniqueId Unique identifier for a session + * @param convertId Handle for the convert session + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onOpenConvertSession(int uniqueId, int convertId); + +/** + * Accepts and converts the input data which is part of DRM file. + * The resultant converted data and the status is returned in the DrmConvertedInfo + * object. This method will be called each time there is a new block + * of data received by the application. + * + * @param uniqueId Unique identifier for a session + * @param convertId Handle for the convert session + * @param inputData Input Data which need to be converted + * @return Return object contains the status of the data conversion, + * the output converted data and offset. In this case the + * application will ignore the offset information. + */ +DrmConvertedStatus* onConvertData(int uniqueId, + int convertId, + const DrmBuffer* inputData); + +/** + * Closes the convert session in case of data supply completed or error occurred. + * Upon successful conversion of the complete data, it returns signature calculated over + * the entire data used over a conversion session. This signature must be copied to the offset + * mentioned in the DrmConvertedStatus. Signature is used for data integrity protection. + * + * @param uniqueId Unique identifier for a session + * @param convertId Handle for the convert session + * @return Return object contains the status of the data conversion, + * the header and body signature data. It also informs + * the application about the file offset at which this + * signature data should be written. + */ +DrmConvertedStatus* onCloseConvertSession(int uniqueId, int convertId); + +/** + * Returns the information about the Drm Engine capabilities which includes + * supported MimeTypes and file suffixes. + * + * @param uniqueId Unique identifier for a session + * @return DrmSupportInfo + * instance which holds the capabilities of a plug-in + */ +DrmSupportInfo* onGetSupportInfo(int uniqueId); + +/** + * Open the decrypt session to decrypt the given protected content. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the current decryption session + * @param fd File descriptor of the protected content to be decrypted + * @param offset Start position of the content + * @param length The length of the protected content + * @return + * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success + */ +#ifdef USE_64BIT_DRM_API +status_t onOpenDecryptSession(int uniqueId, + DecryptHandle* decryptHandle, + int fd, off64_t offset, off64_t length); +#else +status_t onOpenDecryptSession(int uniqueId, + DecryptHandle* decryptHandle, + int fd, int offset, int length); +#endif + +/** + * Open the decrypt session to decrypt the given protected content. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the current decryption session + * @param uri Path of the protected content to be decrypted + * @return + * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success + */ +status_t onOpenDecryptSession(int uniqueId, + DecryptHandle* decryptHandle, + const char* uri); + +/** + * Close the decrypt session for the given handle. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @return status_t + * Returns DRM_NO_ERROR for success, DRM_ERROR_UNKNOWN for failure + */ +status_t onCloseDecryptSession(int uniqueId, + DecryptHandle* decryptHandle); + +/** + * Initialize decryption for the given unit of the protected content. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param decryptUnitId ID which specifies decryption unit, such as track ID + * @param headerInfo Information for initializing decryption of this decrypUnit + * @return + * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success + */ +status_t onInitializeDecryptUnit(int uniqueId, + DecryptHandle* decryptHandle, + int decryptUnitId, + const DrmBuffer* headerInfo); + +/** + * Decrypt the protected content buffers for the given unit. + * This method will be called any number of times, based on number of + * encrypted streams received from application. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param decryptUnitId ID which specifies decryption unit, such as track ID + * @param encBuffer Encrypted data block + * @param decBuffer Decrypted data block + * @return status_t + * Returns the error code for this API + * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED + * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, + * DRM_ERROR_DECRYPT for failure. + */ +status_t onDecrypt(int uniqueId, + DecryptHandle* decryptHandle, + int decryptUnitId, + const DrmBuffer* encBuffer, + DrmBuffer** decBuffer); + +/** + * Decrypt the protected content buffers for the given unit. + * This method will be called any number of times, based on number of + * encrypted streams received from application. + * + * @param uniqueId Unique identifier for a session + * @param decryptId Handle for the decryption session + * @param decryptUnitId ID Specifies decryption unit, such as track ID + * @param encBuffer Encrypted data block + * @param decBuffer Decrypted data block + * @param IV Optional buffer + * @return status_t + * Returns the error code for this API + * DRM_NO_ERROR for success, and one of DRM_ERROR_UNKNOWN, DRM_ERROR_LICENSE_EXPIRED + * DRM_ERROR_SESSION_NOT_OPENED, DRM_ERROR_DECRYPT_UNIT_NOT_INITIALIZED, + * DRM_ERROR_DECRYPT for failure. + */ +status_t onDecrypt(int uniqueId, DecryptHandle* decryptHandle, + int decryptUnitId, const DrmBuffer* encBuffer, + DrmBuffer** decBuffer, DrmBuffer* IV); + +/** + * Finalize decryption for the given unit of the protected content. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param decryptUnitId ID Specifies decryption unit, such as track ID + * @return + * DRM_ERROR_CANNOT_HANDLE for failure and DRM_NO_ERROR for success + */ +status_t onFinalizeDecryptUnit(int uniqueId, + DecryptHandle* decryptHandle, + int decryptUnitId); + +/** + * Reads the specified number of bytes from an open DRM file. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param buffer Reference to the buffer that should receive the read data. + * @param numBytes Number of bytes to read. + * + * @return Number of bytes read. + * @retval -1 Failure. + */ +ssize_t onRead(int uniqueId, + DecryptHandle* decryptHandle, + void* pBuffer, + int numBytes); + +/** + * Updates the file position within an open DRM file. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param offset Offset with which to update the file position. + * @param whence One of SEEK_SET, SEEK_CUR, and SEEK_END. + * These constants are defined in unistd.h. + * + * @return New file position. + * @retval ((off_t)-1) Failure. + */ +#ifdef USE_64BIT_DRM_API +off64_t onLseek(int uniqueId, + DecryptHandle* decryptHandle, + off64_t offset, + int whence); +#else +off_t onLseek(int uniqueId, + DecryptHandle* decryptHandle, + off_t offset, + int whence); +#endif + +/** + * Reads the specified number of bytes from an open DRM file. + * + * @param uniqueId Unique identifier for a session + * @param decryptHandle Handle for the decryption session + * @param buffer Reference to the buffer that should receive the read data. + * @param numBytes Number of bytes to read. + * @param offset Offset with which to update the file position. + * + * @return Number of bytes read. Returns -1 for Failure. + */ +#ifdef USE_64BIT_DRM_API +ssize_t onPread(int uniqueId, + DecryptHandle* decryptHandle, + void* buffer, + ssize_t numBytes, + off64_t offset); +#else +ssize_t onPread(int uniqueId, + DecryptHandle* decryptHandle, + void* buffer, + ssize_t numBytes, + off_t offset); +#endif + +private: + + static const String8 Description; + static const String8 FileSuffixes[]; + static const String8 MimeTypes[]; + static bool IsFileSuffixSupported(const String8& suffix); + static bool IsMimeTypeSupported(const String8& mime); + static void AddSupportedMimeTypes(DrmSupportInfo *info); + static void AddSupportedFileSuffixes(DrmSupportInfo *info); + +/** + * Session Class for Forward Lock Conversion. An object of this class is created + * for every conversion. + */ +class ConvertSession { + public : + int uniqueId; + FwdLockConv_Output_t output; + + ConvertSession() { + uniqueId = 0; + memset(&output, 0, sizeof(FwdLockConv_Output_t)); + } + + virtual ~ConvertSession() {} +}; + +/** + * Session Class for Forward Lock decoder. An object of this class is created + * for every decoding session. + */ +class DecodeSession { + public : + int fileDesc; + off_t offset; + + DecodeSession() { + fileDesc = -1; + offset = 0; + } + + DecodeSession(int fd) { + fileDesc = fd; + offset = 0; + } + + virtual ~DecodeSession() {} +}; + +/** + * Session Map Tables for Conversion and Decoding of forward lock files. + */ +SessionMap<ConvertSession*> convertSessionMap; +SessionMap<DecodeSession*> decodeSessionMap; + +/** + * Converts the error code from Forward Lock Converter to DrmConvertStatus error code. + * + * @param Forward Lock Converter error code + * + * @return Status code from DrmConvertStatus. + */ +static int getConvertedStatus(FwdLockConv_Status_t status); +}; + +}; + +#endif /* __FWDLOCKENGINE_H__ */ diff --git a/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp new file mode 100644 index 0000000..4b1b40e --- /dev/null +++ b/drm/libdrmframework/plugins/forward-lock/FwdLockEngine/src/FwdLockEngine.cpp @@ -0,0 +1,695 @@ +/* + * 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) { + LOG_VERBOSE("FwdLockEngine::onGetOriginalMimeType"); + String8 mimeString = String8(""); + int fileDesc = FwdLockFile_open(path.string()); + + if (-1 < fileDesc) { + 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; +} |