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
32using namespace android;
33
34
35// This extern "C" is mandatory to be managed by TPlugInManager
36extern "C" IDrmEngine* create() {
37    return new DrmPassthruPlugIn();
38}
39
40// This extern "C" is mandatory to be managed by TPlugInManager
41extern "C" void destroy(IDrmEngine* pPlugIn) {
42    delete pPlugIn;
43    pPlugIn = NULL;
44}
45
46DrmPassthruPlugIn::DrmPassthruPlugIn()
47    : DrmEngineBase() {
48
49}
50
51DrmPassthruPlugIn::~DrmPassthruPlugIn() {
52
53}
54
55DrmMetadata* DrmPassthruPlugIn::onGetMetadata(int uniqueId, const String8* path) {
56    return NULL;
57}
58
59DrmConstraints* 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
76DrmInfoStatus* 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
110status_t DrmPassthruPlugIn::onSetOnInfoListener(
111            int uniqueId, const IDrmEngine::OnInfoListener* infoListener) {
112    ALOGV("DrmPassthruPlugIn::onSetOnInfoListener : %d", uniqueId);
113    return DRM_NO_ERROR;
114}
115
116status_t DrmPassthruPlugIn::onInitialize(int uniqueId) {
117    ALOGV("DrmPassthruPlugIn::onInitialize : %d", uniqueId);
118    return DRM_NO_ERROR;
119}
120
121status_t DrmPassthruPlugIn::onTerminate(int uniqueId) {
122    ALOGV("DrmPassthruPlugIn::onTerminate : %d", uniqueId);
123    return DRM_NO_ERROR;
124}
125
126DrmSupportInfo* 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
138status_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
144DrmInfo* 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
160bool 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
167String8 DrmPassthruPlugIn::onGetOriginalMimeType(int uniqueId, const String8& path, int fd) {
168    ALOGV("DrmPassthruPlugIn::onGetOriginalMimeType() : %d", uniqueId);
169    return String8("video/passthru");
170}
171
172int DrmPassthruPlugIn::onGetDrmObjectType(
173            int uniqueId, const String8& path, const String8& mimeType) {
174    ALOGV("DrmPassthruPlugIn::onGetDrmObjectType() : %d", uniqueId);
175    return DrmObjectType::UNKNOWN;
176}
177
178int 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
184status_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
190status_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
196bool DrmPassthruPlugIn::onValidateAction(int uniqueId, const String8& path,
197            int action, const ActionDescription& description) {
198    ALOGV("DrmPassthruPlugIn::onValidateAction() : %d", uniqueId);
199    return true;
200}
201
202status_t DrmPassthruPlugIn::onRemoveRights(int uniqueId, const String8& path) {
203    ALOGV("DrmPassthruPlugIn::onRemoveRights() : %d", uniqueId);
204    return DRM_NO_ERROR;
205}
206
207status_t DrmPassthruPlugIn::onRemoveAllRights(int uniqueId) {
208    ALOGV("DrmPassthruPlugIn::onRemoveAllRights() : %d", uniqueId);
209    return DRM_NO_ERROR;
210}
211
212status_t DrmPassthruPlugIn::onOpenConvertSession(int uniqueId, int convertId) {
213    ALOGV("DrmPassthruPlugIn::onOpenConvertSession() : %d", uniqueId);
214    return DRM_NO_ERROR;
215}
216
217DrmConvertedStatus* 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
232DrmConvertedStatus* DrmPassthruPlugIn::onCloseConvertSession(int uniqueId, int convertId) {
233    ALOGV("DrmPassthruPlugIn::onCloseConvertSession() : %d", uniqueId);
234    return new DrmConvertedStatus(DrmConvertedStatus::STATUS_OK, NULL, 0 /*offset*/);
235}
236
237status_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
252status_t DrmPassthruPlugIn::onOpenDecryptSession(
253            int uniqueId, DecryptHandle* decryptHandle, const char* uri) {
254    return DRM_ERROR_CANNOT_HANDLE;
255}
256
257status_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
268status_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
274status_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
295status_t DrmPassthruPlugIn::onFinalizeDecryptUnit(
296            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
297    ALOGV("DrmPassthruPlugIn::onFinalizeDecryptUnit() : %d", uniqueId);
298    return DRM_NO_ERROR;
299}
300
301ssize_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