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
create()36 extern "C" IDrmEngine* create() {
37 return new DrmPassthruPlugIn();
38 }
39
40 // This extern "C" is mandatory to be managed by TPlugInManager
destroy(IDrmEngine * pPlugIn)41 extern "C" void destroy(IDrmEngine* pPlugIn) {
42 delete pPlugIn;
43 pPlugIn = NULL;
44 }
45
DrmPassthruPlugIn()46 DrmPassthruPlugIn::DrmPassthruPlugIn()
47 : DrmEngineBase() {
48
49 }
50
~DrmPassthruPlugIn()51 DrmPassthruPlugIn::~DrmPassthruPlugIn() {
52
53 }
54
onGetMetadata(int uniqueId,const String8 * path)55 DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int uniqueId, const String8* path) {
56 return NULL;
57 }
58
onGetConstraints(int uniqueId,const String8 * path,int action)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
onProcessDrmInfo(int uniqueId,const DrmInfo * drmInfo)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
onSetOnInfoListener(int uniqueId,const IDrmEngine::OnInfoListener * infoListener)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
onInitialize(int uniqueId)116 status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
117 ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
118 return DRM_NO_ERROR;
119 }
120
onTerminate(int uniqueId)121 status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
122 ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
123 return DRM_NO_ERROR;
124 }
125
onGetSupportInfo(int uniqueId)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
onSaveRights(int uniqueId,const DrmRights & drmRights,const String8 & rightsPath,const String8 & contentPath)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
onAcquireDrmInfo(int uniqueId,const DrmInfoRequest * drmInfoRequest)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
onCanHandle(int uniqueId,const String8 & path)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
onGetOriginalMimeType(int uniqueId,const String8 & path,int fd)167 String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path, int fd) {
168 ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
169 return String8("video/passthru");
170 }
171
onGetDrmObjectType(int uniqueId,const String8 & path,const String8 & mimeType)172 int DrmPassthruPlugIn::onGetDrmObjectType(
173 int uniqueId, const String8& path, const String8& mimeType) {
174 ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
175 return DrmObjectType::UNKNOWN;
176 }
177
onCheckRightsStatus(int uniqueId,const String8 & path,int action)178 int DrmPassthruPlugIn::onCheckRightsStatus(int uniqueId, const String8& path, int action) {
179 ALOGV("DrmPassthruPlugIn::onCheckRightsStatus() : %d", uniqueId);
180 int rightsStatus = RightsStatus::RIGHTS_VALID;
181 return rightsStatus;
182 }
183
onConsumeRights(int uniqueId,DecryptHandle * decryptHandle,int action,bool reserve)184 status_t DrmPassthruPlugIn::onConsumeRights(int uniqueId, DecryptHandle* decryptHandle,
185 int action, bool reserve) {
186 ALOGV("DrmPassthruPlugIn::onConsumeRights() : %d", uniqueId);
187 return DRM_NO_ERROR;
188 }
189
onSetPlaybackStatus(int uniqueId,DecryptHandle * decryptHandle,int playbackStatus,int64_t position)190 status_t DrmPassthruPlugIn::onSetPlaybackStatus(int uniqueId, DecryptHandle* decryptHandle,
191 int playbackStatus, int64_t position) {
192 ALOGV("DrmPassthruPlugIn::onSetPlaybackStatus() : %d", uniqueId);
193 return DRM_NO_ERROR;
194 }
195
onValidateAction(int uniqueId,const String8 & path,int action,const ActionDescription & description)196 bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
197 int action, const ActionDescription& description) {
198 ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
199 return true;
200 }
201
onRemoveRights(int uniqueId,const String8 & path)202 status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
203 ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
204 return DRM_NO_ERROR;
205 }
206
onRemoveAllRights(int uniqueId)207 status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
208 ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
209 return DRM_NO_ERROR;
210 }
211
onOpenConvertSession(int uniqueId,int convertId)212 status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
213 ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
214 return DRM_NO_ERROR;
215 }
216
onConvertData(int uniqueId,int convertId,const DrmBuffer * inputData)217 DrmConvertedStatus* DrmPassthruPlugIn::onConvertData(
218 int uniqueId, int convertId, const DrmBuffer* inputData) {
219 ALOGV("DrmPassthruPlugIn::onConvertData() : %d", uniqueId);
220 DrmBuffer* convertedData = NULL;
221
222 if (NULL != inputData && 0 < inputData->length) {
223 int length = inputData->length;
224 char* data = NULL;
225 data = new char[length];
226 convertedData = new DrmBuffer(data, length);
227 memcpy(convertedData->data, inputData->data, length);
228 }
229 return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, convertedData, 0 /*offset*/);
230 }
231
onCloseConvertSession(int uniqueId,int convertId)232 DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
233 ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
234 return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
235 }
236
onOpenDecryptSession(int uniqueId,DecryptHandle * decryptHandle,int fd,off64_t offset,off64_t length)237 status_t DrmPassthruPlugIn::onOpenDecryptSession(
238 int uniqueId, DecryptHandle* decryptHandle, int fd, off64_t offset, off64_t length) {
239 ALOGV("DrmPassthruPlugIn::onOpenDecryptSession() : %d", uniqueId);
240
241 #ifdef ENABLE_PASSTHRU_DECRYPTION
242 decryptHandle->mimeType = String8("video/passthru");
243 decryptHandle->decryptApiType = DecryptApiType::ELEMENTARY_STREAM_BASED;
244 decryptHandle->status = DRM_NO_ERROR;
245 decryptHandle->decryptInfo = NULL;
246 return DRM_NO_ERROR;
247 #endif
248
249 return DRM_ERROR_CANNOT_HANDLE;
250 }
251
onOpenDecryptSession(int uniqueId,DecryptHandle * decryptHandle,const char * uri)252 status_t DrmPassthruPlugIn::onOpenDecryptSession(
253 int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
254 return DRM_ERROR_CANNOT_HANDLE;
255 }
256
onCloseDecryptSession(int uniqueId,DecryptHandle * decryptHandle)257 status_t DrmPassthruPlugIn::onCloseDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
258 ALOGV("DrmPassthruPlugIn::onCloseDecryptSession() : %d", uniqueId);
259 if (NULL != decryptHandle) {
260 if (NULL != decryptHandle->decryptInfo) {
261 delete decryptHandle->decryptInfo; decryptHandle->decryptInfo = NULL;
262 }
263 delete decryptHandle; decryptHandle = NULL;
264 }
265 return DRM_NO_ERROR;
266 }
267
onInitializeDecryptUnit(int uniqueId,DecryptHandle * decryptHandle,int decryptUnitId,const DrmBuffer * headerInfo)268 status_t DrmPassthruPlugIn::onInitializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
269 int decryptUnitId, const DrmBuffer* headerInfo) {
270 ALOGV("DrmPassthruPlugIn::onInitializeDecryptUnit() : %d", uniqueId);
271 return DRM_NO_ERROR;
272 }
273
onDecrypt(int uniqueId,DecryptHandle * decryptHandle,int decryptUnitId,const DrmBuffer * encBuffer,DrmBuffer ** decBuffer,DrmBuffer * IV)274 status_t DrmPassthruPlugIn::onDecrypt(int uniqueId, DecryptHandle* decryptHandle,
275 int decryptUnitId, const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
276 ALOGV("DrmPassthruPlugIn::onDecrypt() : %d", uniqueId);
277 /**
278 * As a workaround implementation passthru would copy the given
279 * encrypted buffer as it is to decrypted buffer. Note, decBuffer
280 * memory has to be allocated by the caller.
281 */
282 if (NULL != (*decBuffer) && 0 < (*decBuffer)->length) {
283 if ((*decBuffer)->length >= encBuffer->length) {
284 memcpy((*decBuffer)->data, encBuffer->data, encBuffer->length);
285 (*decBuffer)->length = encBuffer->length;
286 } else {
287 ALOGE("decBuffer size (%d) too small to hold %d bytes",
288 (*decBuffer)->length, encBuffer->length);
289 return DRM_ERROR_UNKNOWN;
290 }
291 }
292 return DRM_NO_ERROR;
293 }
294
onFinalizeDecryptUnit(int uniqueId,DecryptHandle * decryptHandle,int decryptUnitId)295 status_t DrmPassthruPlugIn::onFinalizeDecryptUnit(
296 int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
297 ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
298 return DRM_NO_ERROR;
299 }
300
onPread(int uniqueId,DecryptHandle * decryptHandle,void * buffer,ssize_t numBytes,off64_t offset)301 ssize_t DrmPassthruPlugIn::onPread(int uniqueId, DecryptHandle* decryptHandle,
302 void* buffer, ssize_t numBytes, off64_t offset) {
303 ALOGV("DrmPassthruPlugIn::onPread() : %d", uniqueId);
304 return 0;
305 }
306
307