| /* |
| * 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. |
| */ |
| |
| //#define LOG_NDEBUG 0 |
| #define LOG_TAG "DrmPassthruPlugIn" |
| #include <utils/Log.h> |
| |
| #include <drm/DrmRights.h> |
| #include <drm/DrmConstraints.h> |
| #include <drm/DrmMetadata.h> |
| #include <drm/DrmInfo.h> |
| #include <drm/DrmInfoEvent.h> |
| #include <drm/DrmInfoStatus.h> |
| #include <drm/DrmConvertedStatus.h> |
| #include <drm/DrmInfoRequest.h> |
| #include <drm/DrmSupportInfo.h> |
| #include <DrmPassthruPlugIn.h> |
| |
| using namespace android; |
| |
| |
| // This extern "C" is mandatory to be managed by TPlugInManager |
| extern "C" IDrmEngine* create() { |
| return new DrmPassthruPlugIn(); |
| } |
| |
| // This extern "C" is mandatory to be managed by TPlugInManager |
| extern "C" void destroy(IDrmEngine* pPlugIn) { |
| delete pPlugIn; |
| pPlugIn = NULL; |
| } |
| |
| DrmPassthruPlugIn::DrmPassthruPlugIn() |
| : DrmEngineBase() { |
| |
| } |
| |
| DrmPassthruPlugIn::~DrmPassthruPlugIn() { |
| |
| } |
| |
| DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int /*uniqueId*/, const String8* /*path*/) { |
| return NULL; |
| } |
| |
| DrmConstraints* DrmPassthruPlugIn::onGetConstraints( |
| int uniqueId, const String8* /*path*/, int /*action*/) { |
| ALOGV("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId); |
| DrmConstraints* drmConstraints = new DrmConstraints(); |
| |
| String8 value("dummy_available_time"); |
| char* charValue = NULL; |
| charValue = new char[value.length() + 1]; |
| strncpy(charValue, value.string(), value.length()); |
| charValue[value.length()] = '\0'; |
| |
| //Just add dummy available time for verification |
| drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue); |
| delete[] charValue; |
| return drmConstraints; |
| } |
| |
| DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) { |
| ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId); |
| DrmInfoStatus* drmInfoStatus = NULL; |
| if (NULL != drmInfo) { |
| switch (drmInfo->getInfoType()) { |
| case DrmInfoRequest::TYPE_REGISTRATION_INFO: { |
| const DrmBuffer* emptyBuffer = new DrmBuffer(); |
| drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, |
| DrmInfoRequest::TYPE_REGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType()); |
| break; |
| } |
| case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: { |
| const DrmBuffer* emptyBuffer = new DrmBuffer(); |
| drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, |
| DrmInfoRequest::TYPE_UNREGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType()); |
| break; |
| } |
| case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: { |
| String8 licenseString("dummy_license_string"); |
| const int bufferSize = licenseString.size(); |
| char* data = NULL; |
| data = new char[bufferSize]; |
| memcpy(data, licenseString.string(), bufferSize); |
| const DrmBuffer* buffer = new DrmBuffer(data, bufferSize); |
| drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, |
| DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType()); |
| break; |
| } |
| } |
| } |
| ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Exit"); |
| return drmInfoStatus; |
| } |
| |
| status_t DrmPassthruPlugIn::onSetOnInfoListener( |
| int uniqueId, const IDrmEngine::OnInfoListener* /*infoListener*/) { |
| ALOGV("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onInitialize(int uniqueId) { |
| ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onTerminate(int uniqueId) { |
| ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) { |
| ALOGV("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId); |
| DrmSupportInfo* drmSupportInfo = new DrmSupportInfo(); |
| // Add mimetype's |
| drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm")); |
| // Add File Suffixes |
| drmSupportInfo->addFileSuffix(String8(".passthru")); |
| // Add plug-in description |
| drmSupportInfo->setDescription(String8("Passthru plug-in")); |
| return drmSupportInfo; |
| } |
| |
| status_t DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& /*drmRights*/, |
| const String8& /*rightsPath*/, const String8& /*contentPath*/) { |
| ALOGV("DrmPassthruPlugIn::onSaveRights : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { |
| ALOGV("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId); |
| DrmInfo* drmInfo = NULL; |
| |
| if (NULL != drmInfoRequest) { |
| String8 dataString("dummy_acquistion_string"); |
| int length = dataString.length(); |
| char* data = NULL; |
| data = new char[length]; |
| memcpy(data, dataString.string(), length); |
| drmInfo = new DrmInfo(drmInfoRequest->getInfoType(), |
| DrmBuffer(data, length), drmInfoRequest->getMimeType()); |
| } |
| return drmInfo; |
| } |
| |
| bool DrmPassthruPlugIn::onCanHandle(int /*uniqueId*/, const String8& path) { |
| ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string()); |
| String8 extension = path.getPathExtension(); |
| extension.toLower(); |
| return (String8(".passthru") == extension); |
| } |
| |
| String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, |
| const String8& /*path*/, int /*fd*/) { |
| ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId); |
| return String8("video/passthru"); |
| } |
| |
| int DrmPassthruPlugIn::onGetDrmObjectType( |
| int uniqueId, const String8& /*path*/, const String8& /*mimeType*/) { |
| ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId); |
| return DrmObjectType::UNKNOWN; |
| } |
| |
| int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& /*path*/, int /*action*/) { |
| ALOGV("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId); |
| int rightsStatus = RightsStatus::RIGHTS_VALID; |
| return rightsStatus; |
| } |
| |
| status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, |
| DecryptHandle* /*decryptHandle*/, int /*action*/, bool /*reserve*/) { |
| ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, |
| DecryptHandle* /*decryptHandle*/, int /*playbackStatus*/, int64_t /*position*/) { |
| ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| bool DrmPassthruPlugIn::onValidateAction(int uniqueId, |
| const String8& /*path*/, int /*action*/, const ActionDescription& /*description*/) { |
| ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId); |
| return true; |
| } |
| |
| status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& /*path*/) { |
| ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) { |
| ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int /*convertId*/) { |
| ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| DrmConvertedStatus* DrmPassthruPlugIn::onConvertData( |
| int uniqueId, int /*convertId*/, const DrmBuffer* inputData) { |
| ALOGV("DrmPassthruPlugIn::onConvertData() : %d", uniqueId); |
| DrmBuffer* convertedData = NULL; |
| |
| if (NULL != inputData && 0 < inputData->length) { |
| int length = inputData->length; |
| char* data = NULL; |
| data = new char[length]; |
| convertedData = new DrmBuffer(data, length); |
| memcpy(convertedData->data, inputData->data, length); |
| } |
| return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/); |
| } |
| |
| DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int /*convertId*/) { |
| ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId); |
| return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/); |
| } |
| |
| status_t DrmPassthruPlugIn::onOpenDecryptSession( |
| int uniqueId, DecryptHandle* decryptHandle, int /*fd*/, off64_t /*offset*/, off64_t /*length*/) { |
| ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId); |
| |
| #ifdef ENABLE_PASSTHRU_DECRYPTION |
| decryptHandle->mimeType = String8("video/passthru"); |
| decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED; |
| decryptHandle->status = DRM_NO_ERROR; |
| decryptHandle->decryptInfo = NULL; |
| return DRM_NO_ERROR; |
| #endif |
| |
| return DRM_ERROR_CANNOT_HANDLE; |
| } |
| |
| status_t DrmPassthruPlugIn::onOpenDecryptSession( |
| int /*uniqueId*/, DecryptHandle* /*decryptHandle*/, const char* /*uri*/) { |
| return DRM_ERROR_CANNOT_HANDLE; |
| } |
| |
| status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) { |
| ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId); |
| if (NULL != decryptHandle) { |
| if (NULL != decryptHandle->decryptInfo) { |
| delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL; |
| } |
| delete decryptHandle; decryptHandle = NULL; |
| } |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* /*decryptHandle*/, |
| int /*decryptUnitId*/, const DrmBuffer* /*headerInfo*/) { |
| ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* /*decryptHandle*/, |
| int /*decryptUnitId*/, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* /*IV*/) { |
| ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId); |
| /** |
| * As a workaround implementation passthru would copy the given |
| * encrypted buffer as it is to decrypted buffer. Note, decBuffer |
| * memory has to be allocated by the caller. |
| */ |
| if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) { |
| if ((*decBuffer)->length >= encBuffer->length) { |
| memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length); |
| (*decBuffer)->length = encBuffer->length; |
| } else { |
| ALOGE("decBuffer size (%d) too small to hold %d bytes", |
| (*decBuffer)->length, encBuffer->length); |
| return DRM_ERROR_UNKNOWN; |
| } |
| } |
| return DRM_NO_ERROR; |
| } |
| |
| status_t DrmPassthruPlugIn::onFinalizeDecryptUnit( |
| int uniqueId, DecryptHandle* /*decryptHandle*/, int /*decryptUnitId*/) { |
| ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId); |
| return DRM_NO_ERROR; |
| } |
| |
| ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* /*decryptHandle*/, |
| void* /*buffer*/, ssize_t /*numBytes*/, off64_t /*offset*/) { |
| ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId); |
| return 0; |
| } |
| |