MockDrmCryptoPlugin.cpp revision 68d9d71a792deed75d32fe13febc07c9c12c8449
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (C) 2013 The Android Open Source Project
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * you may not use this file except in compliance with the License.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * You may obtain a copy of the License at
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *      http://www.apache.org/licenses/LICENSE-2.0
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the License for the specific language governing permissions and
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * limitations under the License.
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci//#define LOG_NDEBUG 0
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOG_TAG "MockDrmCryptoPlugin"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <utils/Log.h>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "drm/DrmAPI.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "MockDrmCryptoPlugin.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/stagefright/MediaErrors.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace android;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shared library entry point
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DrmFactory *createDrmFactory()
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MockDrmFactory();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Shared library entry point
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CryptoFactory *createCryptoFactory()
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new MockCryptoFactory();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace android {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // MockDrmFactory
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16])
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (mimeType != "video/mp4") {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return false;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_t MockDrmFactory::createDrmPlugin(const uint8_t uuid[16], DrmPlugin **plugin)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *plugin = new MockDrmPlugin();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return OK;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // MockCryptoFactory
668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const
678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    {
688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    status_t MockCryptoFactory::createPlugin(const uint8_t uuid[16], const void *data,
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                                             size_t size, CryptoPlugin **plugin)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *plugin = new MockCryptoPlugin();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return OK;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // MockDrmPlugin methods
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId)
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    {
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        const size_t kSessionIdSize = 8;
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
8503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        Mutex::Autolock lock(mLock);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            long r = random();
8803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            sessionId.appendArray((uint8_t *)&r, sizeof(long));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSessions.add(sessionId);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
9303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)        return OK;
9403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    }
9503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Mutex::Autolock lock(mLock);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssize_t index = findSession(sessionId);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (index == kNotFound) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ALOGD("Invalid sessionId");
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)            return BAD_VALUE;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        mSessions.removeAt(index);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return OK;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Vector<uint8_t> const &initData,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          String8 const &mimeType, KeyType keyType,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          KeyedVector<String8, String8> const &optionalParameters,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Vector<uint8_t> &request, String8 &defaultUrl)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Mutex::Autolock lock(mLock);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              ", keyType=%d, optionalParameters=%s))",
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              keyType, stringMapToString(optionalParameters).string());
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssize_t index = findSession(sessionId);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (index == kNotFound) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ALOGD("Invalid sessionId");
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return BAD_VALUE;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Properties used in mock test, set by mock plugin and verifed cts test app
129        //   byte[] initData           -> mock-initdata
130        //   string mimeType           -> mock-mimetype
131        //   string keyType            -> mock-keytype
132        //   string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2}
133
134        mByteArrayProperties.add(String8("mock-initdata"), initData);
135        mStringProperties.add(String8("mock-mimetype"), mimeType);
136
137        String8 keyTypeStr;
138        keyTypeStr.appendFormat("%d", (int)keyType);
139        mStringProperties.add(String8("mock-keytype"), keyTypeStr);
140
141        String8 params;
142        for (size_t i = 0; i < optionalParameters.size(); i++) {
143            params.appendFormat("%s{%s,%s}", i ? "," : "",
144                                optionalParameters.keyAt(i).string(),
145                                optionalParameters.valueAt(i).string());
146        }
147        mStringProperties.add(String8("mock-optparams"), params);
148
149        // Properties used in mock test, set by cts test app returned from mock plugin
150        //   byte[] mock-request       -> request
151        //   string mock-default-url   -> defaultUrl
152
153        index = mByteArrayProperties.indexOfKey(String8("mock-request"));
154        if (index < 0) {
155            ALOGD("Missing 'mock-request' parameter for mock");
156            return BAD_VALUE;
157        } else {
158            request = mByteArrayProperties.valueAt(index);
159        }
160
161        index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
162        if (index < 0) {
163            ALOGD("Missing 'mock-defaultUrl' parameter for mock");
164            return BAD_VALUE;
165        } else {
166            defaultUrl = mStringProperties.valueAt(index);
167        }
168        return OK;
169    }
170
171    status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId,
172                                               Vector<uint8_t> const &response,
173                                               Vector<uint8_t> &keySetId)
174    {
175        Mutex::Autolock lock(mLock);
176        ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
177              vectorToString(sessionId).string(), vectorToString(response).string());
178        ssize_t index = findSession(sessionId);
179        if (index == kNotFound) {
180            ALOGD("Invalid sessionId");
181            return BAD_VALUE;
182        }
183        if (response.size() == 0) {
184            return BAD_VALUE;
185        }
186
187        // Properties used in mock test, set by mock plugin and verifed cts test app
188        //   byte[] response            -> mock-response
189        mByteArrayProperties.add(String8("mock-response"), response);
190
191        const size_t kKeySetIdSize = 8;
192
193        for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) {
194            long r = random();
195            keySetId.appendArray((uint8_t *)&r, sizeof(long));
196        }
197        mKeySets.add(keySetId);
198
199        return OK;
200    }
201
202    status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId)
203    {
204        Mutex::Autolock lock(mLock);
205        ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
206              vectorToString(keySetId).string());
207
208        ssize_t index = findKeySet(keySetId);
209        if (index == kNotFound) {
210            ALOGD("Invalid keySetId");
211            return BAD_VALUE;
212        }
213        mKeySets.removeAt(index);
214
215        return OK;
216    }
217
218    status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId,
219                                        Vector<uint8_t> const &keySetId)
220    {
221        Mutex::Autolock lock(mLock);
222        ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
223              vectorToString(sessionId).string(),
224              vectorToString(keySetId).string());
225        ssize_t index = findSession(sessionId);
226        if (index == kNotFound) {
227            ALOGD("Invalid sessionId");
228            return BAD_VALUE;
229        }
230
231        index = findKeySet(keySetId);
232        if (index == kNotFound) {
233            ALOGD("Invalid keySetId");
234            return BAD_VALUE;
235        }
236
237        return OK;
238    }
239
240    status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId,
241                                               KeyedVector<String8, String8> &infoMap) const
242    {
243        ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
244              vectorToString(sessionId).string());
245
246        ssize_t index = findSession(sessionId);
247        if (index == kNotFound) {
248            ALOGD("Invalid sessionId");
249            return BAD_VALUE;
250        }
251
252        infoMap.add(String8("purchaseDuration"), String8("1000"));
253        infoMap.add(String8("licenseDuration"), String8("100"));
254        return OK;
255    }
256
257    status_t MockDrmPlugin::getProvisionRequest(String8 const &certType,
258                                                String8 const &certAuthority,
259                                                Vector<uint8_t> &request,
260                                                String8 &defaultUrl)
261    {
262        Mutex::Autolock lock(mLock);
263        ALOGD("MockDrmPlugin::getProvisionRequest()");
264
265        // Properties used in mock test, set by cts test app returned from mock plugin
266        //   byte[] mock-request       -> request
267        //   string mock-default-url   -> defaultUrl
268
269        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request"));
270        if (index < 0) {
271            ALOGD("Missing 'mock-request' parameter for mock");
272            return BAD_VALUE;
273        } else {
274            request = mByteArrayProperties.valueAt(index);
275        }
276
277        index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
278        if (index < 0) {
279            ALOGD("Missing 'mock-defaultUrl' parameter for mock");
280            return BAD_VALUE;
281        } else {
282            defaultUrl = mStringProperties.valueAt(index);
283        }
284        return OK;
285    }
286
287    status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response,
288                                                     Vector<uint8_t> &certificate,
289                                                     Vector<uint8_t> &wrappedKey)
290    {
291        Mutex::Autolock lock(mLock);
292        ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
293              vectorToString(response).string());
294
295        // Properties used in mock test, set by mock plugin and verifed cts test app
296        //   byte[] response            -> mock-response
297
298        mByteArrayProperties.add(String8("mock-response"), response);
299        return OK;
300    }
301
302    status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
303    {
304        Mutex::Autolock lock(mLock);
305        ALOGD("MockDrmPlugin::getSecureStops()");
306
307        // Properties used in mock test, set by cts test app returned from mock plugin
308        //   byte[] mock-secure-stop1  -> first secure stop in list
309        //   byte[] mock-secure-stop2  -> second secure stop in list
310
311        Vector<uint8_t> ss1, ss2;
312        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
313        if (index < 0) {
314            ALOGD("Missing 'mock-secure-stop1' parameter for mock");
315            return BAD_VALUE;
316        } else {
317            ss1 = mByteArrayProperties.valueAt(index);
318        }
319
320        index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
321        if (index < 0) {
322            ALOGD("Missing 'mock-secure-stop2' parameter for mock");
323            return BAD_VALUE;
324        } else {
325            ss2 = mByteArrayProperties.valueAt(index);
326        }
327
328        secureStops.push_back(ss1);
329        secureStops.push_back(ss2);
330        return OK;
331    }
332
333    status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease)
334    {
335        Mutex::Autolock lock(mLock);
336        ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
337              vectorToString(ssRelease).string());
338
339        // Properties used in mock test, set by mock plugin and verifed cts test app
340        //   byte[] secure-stop-release  -> mock-ssrelease
341        mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);
342
343        return OK;
344    }
345
346    status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
347    {
348        ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
349        ssize_t index = mStringProperties.indexOfKey(name);
350        if (index < 0) {
351            ALOGD("no property for '%s'", name.string());
352            return BAD_VALUE;
353        }
354        value = mStringProperties.valueAt(index);
355        return OK;
356    }
357
358    status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
359                                                 Vector<uint8_t> &value) const
360    {
361        ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
362        ssize_t index = mByteArrayProperties.indexOfKey(name);
363        if (index < 0) {
364            ALOGD("no property for '%s'", name.string());
365            return BAD_VALUE;
366        }
367        value = mByteArrayProperties.valueAt(index);
368        return OK;
369    }
370
371    status_t MockDrmPlugin::setPropertyString(String8 const &name,
372                                              String8 const &value)
373    {
374        Mutex::Autolock lock(mLock);
375        ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
376              name.string(), value.string());
377
378        if (name == "mock-send-event") {
379            unsigned code, extra;
380            sscanf(value.string(), "%d %d", &code, &extra);
381            DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
382
383            Vector<uint8_t> const *pSessionId = NULL;
384            ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
385            if (index >= 0) {
386                pSessionId = &mByteArrayProperties[index];
387            }
388
389            Vector<uint8_t> const *pData = NULL;
390            index = mByteArrayProperties.indexOfKey(String8("mock-event-data"));
391            if (index >= 0) {
392                pData = &mByteArrayProperties[index];
393            }
394            ALOGD("sending event from mock drm plugin: %d %d %s %s",
395                  (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}",
396                  pData ? vectorToString(*pData) : "{}");
397
398            sendEvent(eventType, extra, pSessionId, pData);
399        } else {
400            mStringProperties.add(name, value);
401        }
402        return OK;
403    }
404
405    status_t MockDrmPlugin::setPropertyByteArray(String8 const &name,
406                                                 Vector<uint8_t> const &value)
407    {
408        Mutex::Autolock lock(mLock);
409        ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
410              name.string(), vectorToString(value).string());
411        mByteArrayProperties.add(name, value);
412        return OK;
413    }
414
415    status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
416                                               String8 const &algorithm)
417    {
418        Mutex::Autolock lock(mLock);
419
420        ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
421              vectorToString(sessionId).string(), algorithm.string());
422
423        ssize_t index = findSession(sessionId);
424        if (index == kNotFound) {
425            ALOGD("Invalid sessionId");
426            return BAD_VALUE;
427        }
428
429        if (algorithm == "AES/CBC/NoPadding") {
430            return OK;
431        }
432        return BAD_VALUE;
433    }
434
435    status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId,
436                                            String8 const &algorithm)
437    {
438        Mutex::Autolock lock(mLock);
439
440        ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
441              vectorToString(sessionId).string(), algorithm.string());
442
443        ssize_t index = findSession(sessionId);
444        if (index == kNotFound) {
445            ALOGD("Invalid sessionId");
446            return BAD_VALUE;
447        }
448
449        if (algorithm == "HmacSHA256") {
450            return OK;
451        }
452        return BAD_VALUE;
453    }
454
455    status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId,
456                                    Vector<uint8_t> const &keyId,
457                                    Vector<uint8_t> const &input,
458                                    Vector<uint8_t> const &iv,
459                                    Vector<uint8_t> &output)
460    {
461        Mutex::Autolock lock(mLock);
462        ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
463              vectorToString(sessionId).string(),
464              vectorToString(keyId).string(),
465              vectorToString(input).string(),
466              vectorToString(iv).string());
467
468        ssize_t index = findSession(sessionId);
469        if (index == kNotFound) {
470            ALOGD("Invalid sessionId");
471            return BAD_VALUE;
472        }
473
474        // Properties used in mock test, set by mock plugin and verifed cts test app
475        //   byte[] keyId              -> mock-keyid
476        //   byte[] input              -> mock-input
477        //   byte[] iv                 -> mock-iv
478        mByteArrayProperties.add(String8("mock-keyid"), keyId);
479        mByteArrayProperties.add(String8("mock-input"), input);
480        mByteArrayProperties.add(String8("mock-iv"), iv);
481
482        // Properties used in mock test, set by cts test app returned from mock plugin
483        //   byte[] mock-output        -> output
484        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
485        if (index < 0) {
486            ALOGD("Missing 'mock-request' parameter for mock");
487            return BAD_VALUE;
488        } else {
489            output = mByteArrayProperties.valueAt(index);
490        }
491        return OK;
492    }
493
494    status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId,
495                                    Vector<uint8_t> const &keyId,
496                                    Vector<uint8_t> const &input,
497                                    Vector<uint8_t> const &iv,
498                                    Vector<uint8_t> &output)
499    {
500        Mutex::Autolock lock(mLock);
501        ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
502              vectorToString(sessionId).string(),
503              vectorToString(keyId).string(),
504              vectorToString(input).string(),
505              vectorToString(iv).string());
506
507        ssize_t index = findSession(sessionId);
508        if (index == kNotFound) {
509            ALOGD("Invalid sessionId");
510            return BAD_VALUE;
511        }
512
513        // Properties used in mock test, set by mock plugin and verifed cts test app
514        //   byte[] keyId              -> mock-keyid
515        //   byte[] input              -> mock-input
516        //   byte[] iv                 -> mock-iv
517        mByteArrayProperties.add(String8("mock-keyid"), keyId);
518        mByteArrayProperties.add(String8("mock-input"), input);
519        mByteArrayProperties.add(String8("mock-iv"), iv);
520
521        // Properties used in mock test, set by cts test app returned from mock plugin
522        //   byte[] mock-output        -> output
523        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
524        if (index < 0) {
525            ALOGD("Missing 'mock-request' parameter for mock");
526            return BAD_VALUE;
527        } else {
528            output = mByteArrayProperties.valueAt(index);
529        }
530        return OK;
531    }
532
533    status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId,
534                                 Vector<uint8_t> const &keyId,
535                                 Vector<uint8_t> const &message,
536                                 Vector<uint8_t> &signature)
537    {
538        Mutex::Autolock lock(mLock);
539        ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
540              vectorToString(sessionId).string(),
541              vectorToString(keyId).string(),
542              vectorToString(message).string());
543
544        ssize_t index = findSession(sessionId);
545        if (index == kNotFound) {
546            ALOGD("Invalid sessionId");
547            return BAD_VALUE;
548        }
549
550        // Properties used in mock test, set by mock plugin and verifed cts test app
551        //   byte[] keyId              -> mock-keyid
552        //   byte[] message            -> mock-message
553        mByteArrayProperties.add(String8("mock-keyid"), keyId);
554        mByteArrayProperties.add(String8("mock-message"), message);
555
556        // Properties used in mock test, set by cts test app returned from mock plugin
557        //   byte[] mock-signature        -> signature
558        index = mByteArrayProperties.indexOfKey(String8("mock-signature"));
559        if (index < 0) {
560            ALOGD("Missing 'mock-request' parameter for mock");
561            return BAD_VALUE;
562        } else {
563            signature = mByteArrayProperties.valueAt(index);
564        }
565        return OK;
566    }
567
568    status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId,
569                                   Vector<uint8_t> const &keyId,
570                                   Vector<uint8_t> const &message,
571                                   Vector<uint8_t> const &signature,
572                                   bool &match)
573    {
574        Mutex::Autolock lock(mLock);
575        ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
576              vectorToString(sessionId).string(),
577              vectorToString(keyId).string(),
578              vectorToString(message).string(),
579              vectorToString(signature).string());
580
581        ssize_t index = findSession(sessionId);
582        if (index == kNotFound) {
583            ALOGD("Invalid sessionId");
584            return BAD_VALUE;
585        }
586
587        // Properties used in mock test, set by mock plugin and verifed cts test app
588        //   byte[] keyId              -> mock-keyid
589        //   byte[] message            -> mock-message
590        //   byte[] signature          -> mock-signature
591        mByteArrayProperties.add(String8("mock-keyid"), keyId);
592        mByteArrayProperties.add(String8("mock-message"), message);
593        mByteArrayProperties.add(String8("mock-signature"), signature);
594
595        // Properties used in mock test, set by cts test app returned from mock plugin
596        //   String mock-match "1" or "0"         -> match
597        index = mStringProperties.indexOfKey(String8("mock-match"));
598        if (index < 0) {
599            ALOGD("Missing 'mock-request' parameter for mock");
600            return BAD_VALUE;
601        } else {
602            match = atol(mStringProperties.valueAt(index).string());
603        }
604        return OK;
605    }
606
607    status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
608                                    String8 const &algorithm,
609                                    Vector<uint8_t> const &message,
610                                    Vector<uint8_t> const &wrappedKey,
611                                    Vector<uint8_t> &signature)
612    {
613        Mutex::Autolock lock(mLock);
614        ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
615              "message=%s, signature=%s)",
616              vectorToString(sessionId).string(),
617              algorithm.string(),
618              vectorToString(message).string(),
619              vectorToString(wrappedKey).string(),
620              vectorToString(signature).string());
621
622        // Properties used in mock test, set by mock plugin and verifed cts test app
623        //   byte[] wrappedKey         -> mock-wrappedkey
624        //   byte[] message            -> mock-message
625        //   byte[] signature          -> mock-signature
626        mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
627        mStringProperties.add(String8("mock-algorithm"), algorithm);
628        mByteArrayProperties.add(String8("mock-message"), message);
629        mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
630        mByteArrayProperties.add(String8("mock-signature"), signature);
631        return OK;
632    }
633
634    ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
635    {
636        ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
637        for (size_t i = 0; i < mSessions.size(); ++i) {
638            if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
639                return i;
640            }
641        }
642        return kNotFound;
643    }
644
645    ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
646    {
647        ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size());
648        for (size_t i = 0; i < mKeySets.size(); ++i) {
649            if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
650                return i;
651            }
652        }
653        return kNotFound;
654    }
655
656
657    // Conversion utilities
658    String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const
659    {
660        return arrayToString(vector.array(), vector.size());
661    }
662
663    String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const
664    {
665        String8 result("{ ");
666        for (size_t i = 0; i < len; i++) {
667            result.appendFormat("0x%02x ", array[i]);
668        }
669        result += "}";
670        return result;
671    }
672
673    String8 MockDrmPlugin::stringMapToString(KeyedVector<String8, String8> map) const
674    {
675        String8 result("{ ");
676        for (size_t i = 0; i < map.size(); i++) {
677            result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
678                                map.keyAt(i).string(), map.valueAt(i).string());
679        }
680        return result + " }";
681    }
682
683    bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) {
684        return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0);
685    }
686
687    //
688    // Crypto Plugin
689    //
690
691    bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
692    {
693        ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime);
694        return false;
695    }
696
697    ssize_t
698    MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16],
699                              Mode mode, const void *srcPtr, const SubSample *subSamples,
700                              size_t numSubSamples, void *dstPtr, AString *errorDetailMsg)
701    {
702        ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, "
703              "subSamples=%s, dst=%p)",
704              (int)secure,
705              arrayToString(key, sizeof(key)).string(),
706              arrayToString(iv, sizeof(iv)).string(),
707              (int)mode, srcPtr,
708              subSamplesToString(subSamples, numSubSamples).string(),
709              dstPtr);
710        return OK;
711    }
712
713    // Conversion utilities
714    String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const
715    {
716        String8 result("{ ");
717        for (size_t i = 0; i < len; i++) {
718            result.appendFormat("0x%02x ", array[i]);
719        }
720        result += "}";
721        return result;
722    }
723
724    String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples,
725                                                 size_t numSubSamples) const
726    {
727        String8 result;
728        for (size_t i = 0; i < numSubSamples; i++) {
729            result.appendFormat("[%d] {clear:%d, encrypted:%d} ", i,
730                                subSamples[i].mNumBytesOfClearData,
731                                subSamples[i].mNumBytesOfEncryptedData);
732        }
733        return result;
734    }
735
736};
737