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 //#define LOG_NDEBUG 0 18 #define LOG_TAG "DrmPassthruPlugIn" 19 #include <utils/Log.h> 20 21 #include <drm/DrmRights.h> 22 #include <drm/DrmConstraints.h> 23 #include <drm/DrmMetadata.h> 24 #include <drm/DrmInfo.h> 25 #include <drm/DrmInfoEvent.h> 26 #include <drm/DrmInfoStatus.h> 27 #include <drm/DrmConvertedStatus.h> 28 #include <drm/DrmInfoRequest.h> 29 #include <drm/DrmSupportInfo.h> 30 #include <DrmPassthruPlugIn.h> 31 32 using namespace android; 33 34 35 // This extern "C" is mandatory to be managed by TPlugInManager 36 extern "C" IDrmEngine* create() { 37 return new DrmPassthruPlugIn(); 38 } 39 40 // This extern "C" is mandatory to be managed by TPlugInManager 41 extern "C" void destroy(IDrmEngine* pPlugIn) { 42 delete pPlugIn; 43 pPlugIn = NULL; 44 } 45 46 DrmPassthruPlugIn::DrmPassthruPlugIn() 47 : DrmEngineBase() { 48 49 } 50 51 DrmPassthruPlugIn::~DrmPassthruPlugIn() { 52 53 } 54 55 DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int /*uniqueId*/, const String8* /*path*/) { 56 return NULL; 57 } 58 59 DrmConstraints* DrmPassthruPlugIn::onGetConstraints( 60 int uniqueId, const String8* /*path*/, int /*action*/) { 61 ALOGV("DrmPassthruPlugIn::onGetConstraints From Path: %d", uniqueId); 62 DrmConstraints* drmConstraints = new DrmConstraints(); 63 64 String8 value("dummy_available_time"); 65 char* charValue = NULL; 66 charValue = new char[value.length() + 1]; 67 strncpy(charValue, value.string(), value.length()); 68 charValue[value.length()] = '\0'; 69 70 //Just add dummy available time for verification 71 drmConstraints->put(&(DrmConstraints::LICENSE_AVAILABLE_TIME), charValue); 72 delete[] charValue; 73 return drmConstraints; 74 } 75 76 DrmInfoStatus* DrmPassthruPlugIn::onProcessDrmInfo(int uniqueId, const DrmInfo* drmInfo) { 77 ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Enter : %d", uniqueId); 78 DrmInfoStatus* drmInfoStatus = NULL; 79 if (NULL != drmInfo) { 80 switch (drmInfo->getInfoType()) { 81 case DrmInfoRequest::TYPE_REGISTRATION_INFO: { 82 const DrmBuffer* emptyBuffer = new DrmBuffer(); 83 drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, 84 DrmInfoRequest::TYPE_REGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType()); 85 break; 86 } 87 case DrmInfoRequest::TYPE_UNREGISTRATION_INFO: { 88 const DrmBuffer* emptyBuffer = new DrmBuffer(); 89 drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, 90 DrmInfoRequest::TYPE_UNREGISTRATION_INFO, emptyBuffer, drmInfo->getMimeType()); 91 break; 92 } 93 case DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO: { 94 String8 licenseString("dummy_license_string"); 95 const int bufferSize = licenseString.size(); 96 char* data = NULL; 97 data = new char[bufferSize]; 98 memcpy(data, licenseString.string(), bufferSize); 99 const DrmBuffer* buffer = new DrmBuffer(data, bufferSize); 100 drmInfoStatus = new DrmInfoStatus(DrmInfoStatus::STATUS_OK, 101 DrmInfoRequest::TYPE_RIGHTS_ACQUISITION_INFO, buffer, drmInfo->getMimeType()); 102 break; 103 } 104 } 105 } 106 ALOGV("DrmPassthruPlugIn::onProcessDrmInfo - Exit"); 107 return drmInfoStatus; 108 } 109 110 status_t DrmPassthruPlugIn::onSetOnInfoListener( 111 int uniqueId, const IDrmEngine::OnInfoListener* /*infoListener*/) { 112 ALOGV("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId); 113 return DRM_NO_ERROR; 114 } 115 116 status_t DrmPassthruPlugIn::onInitialize(int uniqueId) { 117 ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId); 118 return DRM_NO_ERROR; 119 } 120 121 status_t DrmPassthruPlugIn::onTerminate(int uniqueId) { 122 ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId); 123 return DRM_NO_ERROR; 124 } 125 126 DrmSupportInfo* DrmPassthruPlugIn::onGetSupportInfo(int uniqueId) { 127 ALOGV("DrmPassthruPlugIn::onGetSupportInfo : %d", uniqueId); 128 DrmSupportInfo* drmSupportInfo = new DrmSupportInfo(); 129 // Add mimetype's 130 drmSupportInfo->addMimeType(String8("application/vnd.passthru.drm")); 131 // Add File Suffixes 132 drmSupportInfo->addFileSuffix(String8(".passthru")); 133 // Add plug-in description 134 drmSupportInfo->setDescription(String8("Passthru plug-in")); 135 return drmSupportInfo; 136 } 137 138 status_t DrmPassthruPlugIn::onSaveRights(int uniqueId, const DrmRights& /*drmRights*/, 139 const String8& /*rightsPath*/, const String8& /*contentPath*/) { 140 ALOGV("DrmPassthruPlugIn::onSaveRights : %d", uniqueId); 141 return DRM_NO_ERROR; 142 } 143 144 DrmInfo* DrmPassthruPlugIn::onAcquireDrmInfo(int uniqueId, const DrmInfoRequest* drmInfoRequest) { 145 ALOGV("DrmPassthruPlugIn::onAcquireDrmInfo : %d", uniqueId); 146 DrmInfo* drmInfo = NULL; 147 148 if (NULL != drmInfoRequest) { 149 String8 dataString("dummy_acquistion_string"); 150 int length = dataString.length(); 151 char* data = NULL; 152 data = new char[length]; 153 memcpy(data, dataString.string(), length); 154 drmInfo = new DrmInfo(drmInfoRequest->getInfoType(), 155 DrmBuffer(data, length), drmInfoRequest->getMimeType()); 156 } 157 return drmInfo; 158 } 159 160 bool DrmPassthruPlugIn::onCanHandle(int /*uniqueId*/, const String8& path) { 161 ALOGV("DrmPassthruPlugIn::canHandle: %s ", path.string()); 162 String8 extension = path.getPathExtension(); 163 extension.toLower(); 164 return (String8(".passthru") == extension); 165 } 166 167 String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, 168 const String8& /*path*/, int /*fd*/) { 169 ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId); 170 return String8("video/passthru"); 171 } 172 173 int DrmPassthruPlugIn::onGetDrmObjectType( 174 int uniqueId, const String8& /*path*/, const String8& /*mimeType*/) { 175 ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId); 176 return DrmObjectType::UNKNOWN; 177 } 178 179 int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& /*path*/, int /*action*/) { 180 ALOGV("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId); 181 int rightsStatus = RightsStatus::RIGHTS_VALID; 182 return rightsStatus; 183 } 184 185 status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, 186 sp<DecryptHandle>& /*decryptHandle*/, int /*action*/, bool /*reserve*/) { 187 ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId); 188 return DRM_NO_ERROR; 189 } 190 191 status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, 192 sp<DecryptHandle>& /*decryptHandle*/, int /*playbackStatus*/, int64_t /*position*/) { 193 ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId); 194 return DRM_NO_ERROR; 195 } 196 197 bool DrmPassthruPlugIn::onValidateAction(int uniqueId, 198 const String8& /*path*/, int /*action*/, const ActionDescription& /*description*/) { 199 ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId); 200 return true; 201 } 202 203 status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& /*path*/) { 204 ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId); 205 return DRM_NO_ERROR; 206 } 207 208 status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) { 209 ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId); 210 return DRM_NO_ERROR; 211 } 212 213 status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int /*convertId*/) { 214 ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId); 215 return DRM_NO_ERROR; 216 } 217 218 DrmConvertedStatus* DrmPassthruPlugIn::onConvertData( 219 int uniqueId, int /*convertId*/, const DrmBuffer* inputData) { 220 ALOGV("DrmPassthruPlugIn::onConvertData() : %d", uniqueId); 221 DrmBuffer* convertedData = NULL; 222 223 if (NULL != inputData && 0 < inputData->length) { 224 int length = inputData->length; 225 char* data = NULL; 226 data = new char[length]; 227 convertedData = new DrmBuffer(data, length); 228 memcpy(convertedData->data, inputData->data, length); 229 } 230 return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/); 231 } 232 233 DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int /*convertId*/) { 234 ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId); 235 return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/); 236 } 237 238 status_t DrmPassthruPlugIn::onOpenDecryptSession( 239 int uniqueId, sp<DecryptHandle>& decryptHandle, int /*fd*/, off64_t /*offset*/, 240 off64_t /*length*/) { 241 ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId); 242 243 #ifdef ENABLE_PASSTHRU_DECRYPTION 244 decryptHandle->mimeType = String8("video/passthru"); 245 decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED; 246 decryptHandle->status = DRM_NO_ERROR; 247 decryptHandle->decryptInfo = NULL; 248 return DRM_NO_ERROR; 249 #else 250 (void)(decryptHandle.get()); // unused 251 #endif 252 253 return DRM_ERROR_CANNOT_HANDLE; 254 } 255 256 status_t DrmPassthruPlugIn::onOpenDecryptSession( 257 int /*uniqueId*/, sp<DecryptHandle>& /*decryptHandle*/, const char* /*uri*/) { 258 return DRM_ERROR_CANNOT_HANDLE; 259 } 260 261 status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, sp<DecryptHandle>& decryptHandle) { 262 ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId); 263 if (NULL != decryptHandle.get()) { 264 if (NULL != decryptHandle->decryptInfo) { 265 delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL; 266 } 267 decryptHandle.clear(); 268 } 269 return DRM_NO_ERROR; 270 } 271 272 status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, 273 sp<DecryptHandle>& /*decryptHandle*/, 274 int /*decryptUnitId*/, const DrmBuffer* /*headerInfo*/) { 275 ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId); 276 return DRM_NO_ERROR; 277 } 278 279 status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, 280 int /*decryptUnitId*/, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, 281 DrmBuffer* /*IV*/) { 282 ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId); 283 /** 284 * As a workaround implementation passthru would copy the given 285 * encrypted buffer as it is to decrypted buffer. Note, decBuffer 286 * memory has to be allocated by the caller. 287 */ 288 if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) { 289 if ((*decBuffer)->length >= encBuffer->length) { 290 memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length); 291 (*decBuffer)->length = encBuffer->length; 292 } else { 293 ALOGE("decBuffer size (%d) too small to hold %d bytes", 294 (*decBuffer)->length, encBuffer->length); 295 return DRM_ERROR_UNKNOWN; 296 } 297 } 298 return DRM_NO_ERROR; 299 } 300 301 status_t DrmPassthruPlugIn::onFinalizeDecryptUnit( 302 int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, int /*decryptUnitId*/) { 303 ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId); 304 return DRM_NO_ERROR; 305 } 306 307 ssize_t DrmPassthruPlugIn::onPread(int uniqueId, sp<DecryptHandle>& /*decryptHandle*/, 308 void* /*buffer*/, ssize_t /*numBytes*/, off64_t /*offset*/) { 309 ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId); 310 return 0; 311 } 312 313