Home | History | Annotate | Download | only in mock
      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 
     26 using namespace android;
     27 
     28 // Shared library entry point
     29 DrmFactory *createDrmFactory()
     30 {
     31     return new MockDrmFactory();
     32 }
     33 
     34 // Shared library entry point
     35 CryptoFactory *createCryptoFactory()
     36 {
     37     return new MockCryptoFactory();
     38 }
     39 
     40 const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
     41                                0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
     42 
     43 namespace 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