1/*
2 * Copyright (C) 2013 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 "MockDrmCryptoPlugin"
19#include <utils/Log.h>
20
21
22#include "drm/DrmAPI.h"
23#include "MockDrmCryptoPlugin.h"
24#include "media/stagefright/MediaErrors.h"
25
26using namespace android;
27
28// Shared library entry point
29DrmFactory *createDrmFactory()
30{
31    return new MockDrmFactory();
32}
33
34// Shared library entry point
35CryptoFactory *createCryptoFactory()
36{
37    return new MockCryptoFactory();
38}
39
40const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
41                               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
42
43namespace android {
44
45    // MockDrmFactory
46    bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16])
47    {
48        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
49    }
50
51    bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType)
52    {
53        if (mimeType != "video/mp4") {
54            return false;
55        }
56        return true;
57    }
58
59    status_t MockDrmFactory::createDrmPlugin(const uint8_t uuid[16], DrmPlugin **plugin)
60    {
61        *plugin = new MockDrmPlugin();
62        return OK;
63    }
64
65    // MockCryptoFactory
66    bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const
67    {
68        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
69    }
70
71    status_t MockCryptoFactory::createPlugin(const uint8_t uuid[16], const void *data,
72                                             size_t size, CryptoPlugin **plugin)
73    {
74        *plugin = new MockCryptoPlugin();
75        return OK;
76    }
77
78
79    // MockDrmPlugin methods
80
81    status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId)
82    {
83        const size_t kSessionIdSize = 8;
84
85        Mutex::Autolock lock(mLock);
86        for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) {
87            long r = random();
88            sessionId.appendArray((uint8_t *)&r, sizeof(long));
89        }
90        mSessions.add(sessionId);
91
92        ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
93        return OK;
94    }
95
96    status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
97    {
98        Mutex::Autolock lock(mLock);
99        ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
100        ssize_t index = findSession(sessionId);
101        if (index == kNotFound) {
102            ALOGD("Invalid sessionId");
103            return BAD_VALUE;
104        }
105        mSessions.removeAt(index);
106        return OK;
107    }
108
109
110    status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId,
111                                          Vector<uint8_t> const &initData,
112                                          String8 const &mimeType, KeyType keyType,
113                                          KeyedVector<String8, String8> const &optionalParameters,
114                                          Vector<uint8_t> &request, String8 &defaultUrl)
115    {
116        Mutex::Autolock lock(mLock);
117        ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
118              ", keyType=%d, optionalParameters=%s))",
119              vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
120              keyType, stringMapToString(optionalParameters).string());
121
122        ssize_t index = findSession(sessionId);
123        if (index == kNotFound) {
124            ALOGD("Invalid sessionId");
125            return BAD_VALUE;
126        }
127
128        // 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::unprovisionDevice()
303    {
304        ALOGD("MockDrmPlugin::unprovisionDevice()");
305        return OK;
306    }
307
308    status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop)
309    {
310        Mutex::Autolock lock(mLock);
311        ALOGD("MockDrmPlugin::getSecureStop()");
312
313        // Properties used in mock test, set by cts test app returned from mock plugin
314        //   byte[] mock-secure-stop  -> first secure stop in list
315
316        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop"));
317        if (index < 0) {
318            ALOGD("Missing 'mock-secure-stop' parameter for mock");
319            return BAD_VALUE;
320        } else {
321            secureStop = mByteArrayProperties.valueAt(index);
322        }
323        return OK;
324    }
325
326    status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
327    {
328        Mutex::Autolock lock(mLock);
329        ALOGD("MockDrmPlugin::getSecureStops()");
330
331        // Properties used in mock test, set by cts test app returned from mock plugin
332        //   byte[] mock-secure-stop1  -> first secure stop in list
333        //   byte[] mock-secure-stop2  -> second secure stop in list
334
335        Vector<uint8_t> ss1, ss2;
336        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
337        if (index < 0) {
338            ALOGD("Missing 'mock-secure-stop1' parameter for mock");
339            return BAD_VALUE;
340        } else {
341            ss1 = mByteArrayProperties.valueAt(index);
342        }
343
344        index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
345        if (index < 0) {
346            ALOGD("Missing 'mock-secure-stop2' parameter for mock");
347            return BAD_VALUE;
348        } else {
349            ss2 = mByteArrayProperties.valueAt(index);
350        }
351
352        secureStops.push_back(ss1);
353        secureStops.push_back(ss2);
354        return OK;
355    }
356
357    status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease)
358    {
359        Mutex::Autolock lock(mLock);
360        ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
361              vectorToString(ssRelease).string());
362
363        // Properties used in mock test, set by mock plugin and verifed cts test app
364        //   byte[] secure-stop-release  -> mock-ssrelease
365        mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);
366
367        return OK;
368    }
369
370    status_t MockDrmPlugin::releaseAllSecureStops()
371    {
372        Mutex::Autolock lock(mLock);
373        ALOGD("MockDrmPlugin::releaseAllSecureStops()");
374        return OK;
375    }
376
377    status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
378    {
379        ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
380        ssize_t index = mStringProperties.indexOfKey(name);
381        if (index < 0) {
382            ALOGD("no property for '%s'", name.string());
383            return BAD_VALUE;
384        }
385        value = mStringProperties.valueAt(index);
386        return OK;
387    }
388
389    status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
390                                                 Vector<uint8_t> &value) const
391    {
392        ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
393        ssize_t index = mByteArrayProperties.indexOfKey(name);
394        if (index < 0) {
395            ALOGD("no property for '%s'", name.string());
396            return BAD_VALUE;
397        }
398        value = mByteArrayProperties.valueAt(index);
399        return OK;
400    }
401
402    status_t MockDrmPlugin::setPropertyString(String8 const &name,
403                                              String8 const &value)
404    {
405        Mutex::Autolock lock(mLock);
406        ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
407              name.string(), value.string());
408
409        if (name == "mock-send-event") {
410            unsigned code, extra;
411            sscanf(value.string(), "%d %d", &code, &extra);
412            DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
413
414            Vector<uint8_t> const *pSessionId = NULL;
415            ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
416            if (index >= 0) {
417                pSessionId = &mByteArrayProperties[index];
418            }
419
420            Vector<uint8_t> const *pData = NULL;
421            index = mByteArrayProperties.indexOfKey(String8("mock-event-data"));
422            if (index >= 0) {
423                pData = &mByteArrayProperties[index];
424            }
425            ALOGD("sending event from mock drm plugin: %d %d %s %s",
426                  (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}",
427                  pData ? vectorToString(*pData) : "{}");
428
429            sendEvent(eventType, extra, pSessionId, pData);
430        } else {
431            mStringProperties.add(name, value);
432        }
433        return OK;
434    }
435
436    status_t MockDrmPlugin::setPropertyByteArray(String8 const &name,
437                                                 Vector<uint8_t> const &value)
438    {
439        Mutex::Autolock lock(mLock);
440        ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
441              name.string(), vectorToString(value).string());
442        mByteArrayProperties.add(name, value);
443        return OK;
444    }
445
446    status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
447                                               String8 const &algorithm)
448    {
449        Mutex::Autolock lock(mLock);
450
451        ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
452              vectorToString(sessionId).string(), algorithm.string());
453
454        ssize_t index = findSession(sessionId);
455        if (index == kNotFound) {
456            ALOGD("Invalid sessionId");
457            return BAD_VALUE;
458        }
459
460        if (algorithm == "AES/CBC/NoPadding") {
461            return OK;
462        }
463        return BAD_VALUE;
464    }
465
466    status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId,
467                                            String8 const &algorithm)
468    {
469        Mutex::Autolock lock(mLock);
470
471        ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
472              vectorToString(sessionId).string(), algorithm.string());
473
474        ssize_t index = findSession(sessionId);
475        if (index == kNotFound) {
476            ALOGD("Invalid sessionId");
477            return BAD_VALUE;
478        }
479
480        if (algorithm == "HmacSHA256") {
481            return OK;
482        }
483        return BAD_VALUE;
484    }
485
486    status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId,
487                                    Vector<uint8_t> const &keyId,
488                                    Vector<uint8_t> const &input,
489                                    Vector<uint8_t> const &iv,
490                                    Vector<uint8_t> &output)
491    {
492        Mutex::Autolock lock(mLock);
493        ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
494              vectorToString(sessionId).string(),
495              vectorToString(keyId).string(),
496              vectorToString(input).string(),
497              vectorToString(iv).string());
498
499        ssize_t index = findSession(sessionId);
500        if (index == kNotFound) {
501            ALOGD("Invalid sessionId");
502            return BAD_VALUE;
503        }
504
505        // Properties used in mock test, set by mock plugin and verifed cts test app
506        //   byte[] keyId              -> mock-keyid
507        //   byte[] input              -> mock-input
508        //   byte[] iv                 -> mock-iv
509        mByteArrayProperties.add(String8("mock-keyid"), keyId);
510        mByteArrayProperties.add(String8("mock-input"), input);
511        mByteArrayProperties.add(String8("mock-iv"), iv);
512
513        // Properties used in mock test, set by cts test app returned from mock plugin
514        //   byte[] mock-output        -> output
515        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
516        if (index < 0) {
517            ALOGD("Missing 'mock-request' parameter for mock");
518            return BAD_VALUE;
519        } else {
520            output = mByteArrayProperties.valueAt(index);
521        }
522        return OK;
523    }
524
525    status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId,
526                                    Vector<uint8_t> const &keyId,
527                                    Vector<uint8_t> const &input,
528                                    Vector<uint8_t> const &iv,
529                                    Vector<uint8_t> &output)
530    {
531        Mutex::Autolock lock(mLock);
532        ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
533              vectorToString(sessionId).string(),
534              vectorToString(keyId).string(),
535              vectorToString(input).string(),
536              vectorToString(iv).string());
537
538        ssize_t index = findSession(sessionId);
539        if (index == kNotFound) {
540            ALOGD("Invalid sessionId");
541            return BAD_VALUE;
542        }
543
544        // Properties used in mock test, set by mock plugin and verifed cts test app
545        //   byte[] keyId              -> mock-keyid
546        //   byte[] input              -> mock-input
547        //   byte[] iv                 -> mock-iv
548        mByteArrayProperties.add(String8("mock-keyid"), keyId);
549        mByteArrayProperties.add(String8("mock-input"), input);
550        mByteArrayProperties.add(String8("mock-iv"), iv);
551
552        // Properties used in mock test, set by cts test app returned from mock plugin
553        //   byte[] mock-output        -> output
554        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
555        if (index < 0) {
556            ALOGD("Missing 'mock-request' parameter for mock");
557            return BAD_VALUE;
558        } else {
559            output = mByteArrayProperties.valueAt(index);
560        }
561        return OK;
562    }
563
564    status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId,
565                                 Vector<uint8_t> const &keyId,
566                                 Vector<uint8_t> const &message,
567                                 Vector<uint8_t> &signature)
568    {
569        Mutex::Autolock lock(mLock);
570        ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
571              vectorToString(sessionId).string(),
572              vectorToString(keyId).string(),
573              vectorToString(message).string());
574
575        ssize_t index = findSession(sessionId);
576        if (index == kNotFound) {
577            ALOGD("Invalid sessionId");
578            return BAD_VALUE;
579        }
580
581        // Properties used in mock test, set by mock plugin and verifed cts test app
582        //   byte[] keyId              -> mock-keyid
583        //   byte[] message            -> mock-message
584        mByteArrayProperties.add(String8("mock-keyid"), keyId);
585        mByteArrayProperties.add(String8("mock-message"), message);
586
587        // Properties used in mock test, set by cts test app returned from mock plugin
588        //   byte[] mock-signature        -> signature
589        index = mByteArrayProperties.indexOfKey(String8("mock-signature"));
590        if (index < 0) {
591            ALOGD("Missing 'mock-request' parameter for mock");
592            return BAD_VALUE;
593        } else {
594            signature = mByteArrayProperties.valueAt(index);
595        }
596        return OK;
597    }
598
599    status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId,
600                                   Vector<uint8_t> const &keyId,
601                                   Vector<uint8_t> const &message,
602                                   Vector<uint8_t> const &signature,
603                                   bool &match)
604    {
605        Mutex::Autolock lock(mLock);
606        ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
607              vectorToString(sessionId).string(),
608              vectorToString(keyId).string(),
609              vectorToString(message).string(),
610              vectorToString(signature).string());
611
612        ssize_t index = findSession(sessionId);
613        if (index == kNotFound) {
614            ALOGD("Invalid sessionId");
615            return BAD_VALUE;
616        }
617
618        // Properties used in mock test, set by mock plugin and verifed cts test app
619        //   byte[] keyId              -> mock-keyid
620        //   byte[] message            -> mock-message
621        //   byte[] signature          -> mock-signature
622        mByteArrayProperties.add(String8("mock-keyid"), keyId);
623        mByteArrayProperties.add(String8("mock-message"), message);
624        mByteArrayProperties.add(String8("mock-signature"), signature);
625
626        // Properties used in mock test, set by cts test app returned from mock plugin
627        //   String mock-match "1" or "0"         -> match
628        index = mStringProperties.indexOfKey(String8("mock-match"));
629        if (index < 0) {
630            ALOGD("Missing 'mock-request' parameter for mock");
631            return BAD_VALUE;
632        } else {
633            match = atol(mStringProperties.valueAt(index).string());
634        }
635        return OK;
636    }
637
638    status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
639                                    String8 const &algorithm,
640                                    Vector<uint8_t> const &message,
641                                    Vector<uint8_t> const &wrappedKey,
642                                    Vector<uint8_t> &signature)
643    {
644        Mutex::Autolock lock(mLock);
645        ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
646              "message=%s, signature=%s)",
647              vectorToString(sessionId).string(),
648              algorithm.string(),
649              vectorToString(message).string(),
650              vectorToString(wrappedKey).string(),
651              vectorToString(signature).string());
652
653        // Properties used in mock test, set by mock plugin and verifed cts test app
654        //   byte[] wrappedKey         -> mock-wrappedkey
655        //   byte[] message            -> mock-message
656        //   byte[] signature          -> mock-signature
657        mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
658        mStringProperties.add(String8("mock-algorithm"), algorithm);
659        mByteArrayProperties.add(String8("mock-message"), message);
660        mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
661        mByteArrayProperties.add(String8("mock-signature"), signature);
662        return OK;
663    }
664
665    ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
666    {
667        ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
668        for (size_t i = 0; i < mSessions.size(); ++i) {
669            if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
670                return i;
671            }
672        }
673        return kNotFound;
674    }
675
676    ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
677    {
678        ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size());
679        for (size_t i = 0; i < mKeySets.size(); ++i) {
680            if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
681                return i;
682            }
683        }
684        return kNotFound;
685    }
686
687
688    // Conversion utilities
689    String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const
690    {
691        return arrayToString(vector.array(), vector.size());
692    }
693
694    String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const
695    {
696        String8 result("{ ");
697        for (size_t i = 0; i < len; i++) {
698            result.appendFormat("0x%02x ", array[i]);
699        }
700        result += "}";
701        return result;
702    }
703
704    String8 MockDrmPlugin::stringMapToString(KeyedVector<String8, String8> map) const
705    {
706        String8 result("{ ");
707        for (size_t i = 0; i < map.size(); i++) {
708            result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
709                                map.keyAt(i).string(), map.valueAt(i).string());
710        }
711        return result + " }";
712    }
713
714    bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) {
715        return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0);
716    }
717
718    //
719    // Crypto Plugin
720    //
721
722    bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
723    {
724        ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime);
725        return false;
726    }
727
728    ssize_t
729    MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16],
730                              Mode mode, const void *srcPtr, const SubSample *subSamples,
731                              size_t numSubSamples, void *dstPtr, AString *errorDetailMsg)
732    {
733        ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, "
734              "subSamples=%s, dst=%p)",
735              (int)secure,
736              arrayToString(key, sizeof(key)).string(),
737              arrayToString(iv, sizeof(iv)).string(),
738              (int)mode, srcPtr,
739              subSamplesToString(subSamples, numSubSamples).string(),
740              dstPtr);
741        return OK;
742    }
743
744    // Conversion utilities
745    String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const
746    {
747        String8 result("{ ");
748        for (size_t i = 0; i < len; i++) {
749            result.appendFormat("0x%02x ", array[i]);
750        }
751        result += "}";
752        return result;
753    }
754
755    String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples,
756                                                 size_t numSubSamples) const
757    {
758        String8 result;
759        for (size_t i = 0; i < numSubSamples; i++) {
760            result.appendFormat("[%zu] {clear:%zu, encrypted:%zu} ", i,
761                                subSamples[i].mNumBytesOfClearData,
762                                subSamples[i].mNumBytesOfEncryptedData);
763        }
764        return result;
765    }
766
767};
768