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],
     72                                              const void * /* data */,
     73                                              size_t /* size */, CryptoPlugin **plugin)
     74     {
     75         *plugin = new MockCryptoPlugin();
     76         return OK;
     77     }
     78 
     79 
     80     // MockDrmPlugin methods
     81 
     82     status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId)
     83     {
     84         const size_t kSessionIdSize = 8;
     85 
     86         Mutex::Autolock lock(mLock);
     87         for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) {
     88             long r = random();
     89             sessionId.appendArray((uint8_t *)&r, sizeof(long));
     90         }
     91         mSessions.add(sessionId);
     92 
     93         ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
     94         return OK;
     95     }
     96 
     97     status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
     98     {
     99         Mutex::Autolock lock(mLock);
    100         ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
    101         ssize_t index = findSession(sessionId);
    102         if (index == kNotFound) {
    103             ALOGD("Invalid sessionId");
    104             return BAD_VALUE;
    105         }
    106         mSessions.removeAt(index);
    107         return OK;
    108     }
    109 
    110 
    111     status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId,
    112                                           Vector<uint8_t> const &initData,
    113                                           String8 const &mimeType, KeyType keyType,
    114                                           KeyedVector<String8, String8> const &optionalParameters,
    115                                           Vector<uint8_t> &request, String8 &defaultUrl,
    116                                           KeyRequestType *keyRequestType)
    117     {
    118         Mutex::Autolock lock(mLock);
    119         ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
    120               ", keyType=%d, optionalParameters=%s))",
    121               vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
    122               keyType, stringMapToString(optionalParameters).string());
    123 
    124         ssize_t index = findSession(sessionId);
    125         if (index == kNotFound) {
    126             ALOGD("Invalid sessionId");
    127             return BAD_VALUE;
    128         }
    129 
    130         // Properties used in mock test, set by mock plugin and verifed cts test app
    131         //   byte[] initData           -> mock-initdata
    132         //   string mimeType           -> mock-mimetype
    133         //   string keyType            -> mock-keytype
    134         //   string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2}
    135 
    136         mByteArrayProperties.add(String8("mock-initdata"), initData);
    137         mStringProperties.add(String8("mock-mimetype"), mimeType);
    138 
    139         String8 keyTypeStr;
    140         keyTypeStr.appendFormat("%d", (int)keyType);
    141         mStringProperties.add(String8("mock-keytype"), keyTypeStr);
    142 
    143         String8 params;
    144         for (size_t i = 0; i < optionalParameters.size(); i++) {
    145             params.appendFormat("%s{%s,%s}", i ? "," : "",
    146                                 optionalParameters.keyAt(i).string(),
    147                                 optionalParameters.valueAt(i).string());
    148         }
    149         mStringProperties.add(String8("mock-optparams"), params);
    150 
    151         // Properties used in mock test, set by cts test app returned from mock plugin
    152         //   byte[] mock-request       -> request
    153         //   string mock-default-url   -> defaultUrl
    154         //   string mock-keyRequestType -> keyRequestType
    155 
    156         index = mByteArrayProperties.indexOfKey(String8("mock-request"));
    157         if (index < 0) {
    158             ALOGD("Missing 'mock-request' parameter for mock");
    159             return BAD_VALUE;
    160         } else {
    161             request = mByteArrayProperties.valueAt(index);
    162         }
    163 
    164         index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
    165         if (index < 0) {
    166             ALOGD("Missing 'mock-defaultUrl' parameter for mock");
    167             return BAD_VALUE;
    168         } else {
    169             defaultUrl = mStringProperties.valueAt(index);
    170         }
    171 
    172         index = mStringProperties.indexOfKey(String8("mock-keyRequestType"));
    173         if (index < 0) {
    174             ALOGD("Missing 'mock-keyRequestType' parameter for mock");
    175             return BAD_VALUE;
    176         } else {
    177             *keyRequestType = static_cast<KeyRequestType>(
    178                 atoi(mStringProperties.valueAt(index).string()));
    179         }
    180 
    181         return OK;
    182     }
    183 
    184     status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId,
    185                                                Vector<uint8_t> const &response,
    186                                                Vector<uint8_t> &keySetId)
    187     {
    188         Mutex::Autolock lock(mLock);
    189         ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
    190               vectorToString(sessionId).string(), vectorToString(response).string());
    191         ssize_t index = findSession(sessionId);
    192         if (index == kNotFound) {
    193             ALOGD("Invalid sessionId");
    194             return BAD_VALUE;
    195         }
    196         if (response.size() == 0) {
    197             return BAD_VALUE;
    198         }
    199 
    200         // Properties used in mock test, set by mock plugin and verifed cts test app
    201         //   byte[] response            -> mock-response
    202         mByteArrayProperties.add(String8("mock-response"), response);
    203 
    204         const size_t kKeySetIdSize = 8;
    205 
    206         for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) {
    207             long r = random();
    208             keySetId.appendArray((uint8_t *)&r, sizeof(long));
    209         }
    210         mKeySets.add(keySetId);
    211 
    212         return OK;
    213     }
    214 
    215     status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId)
    216     {
    217         Mutex::Autolock lock(mLock);
    218         ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
    219               vectorToString(keySetId).string());
    220 
    221         ssize_t index = findKeySet(keySetId);
    222         if (index == kNotFound) {
    223             ALOGD("Invalid keySetId");
    224             return BAD_VALUE;
    225         }
    226         mKeySets.removeAt(index);
    227 
    228         return OK;
    229     }
    230 
    231     status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId,
    232                                         Vector<uint8_t> const &keySetId)
    233     {
    234         Mutex::Autolock lock(mLock);
    235         ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
    236               vectorToString(sessionId).string(),
    237               vectorToString(keySetId).string());
    238         ssize_t index = findSession(sessionId);
    239         if (index == kNotFound) {
    240             ALOGD("Invalid sessionId");
    241             return BAD_VALUE;
    242         }
    243 
    244         index = findKeySet(keySetId);
    245         if (index == kNotFound) {
    246             ALOGD("Invalid keySetId");
    247             return BAD_VALUE;
    248         }
    249 
    250         return OK;
    251     }
    252 
    253     status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId,
    254                                                KeyedVector<String8, String8> &infoMap) const
    255     {
    256         ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
    257               vectorToString(sessionId).string());
    258 
    259         ssize_t index = findSession(sessionId);
    260         if (index == kNotFound) {
    261             ALOGD("Invalid sessionId");
    262             return BAD_VALUE;
    263         }
    264 
    265         infoMap.add(String8("purchaseDuration"), String8("1000"));
    266         infoMap.add(String8("licenseDuration"), String8("100"));
    267         return OK;
    268     }
    269 
    270     status_t MockDrmPlugin::getProvisionRequest(String8 const & /* certType */,
    271                                                 String8 const & /* certAuthority */,
    272                                                 Vector<uint8_t> &request,
    273                                                 String8 &defaultUrl)
    274     {
    275         Mutex::Autolock lock(mLock);
    276         ALOGD("MockDrmPlugin::getProvisionRequest()");
    277 
    278         // Properties used in mock test, set by cts test app returned from mock plugin
    279         //   byte[] mock-request       -> request
    280         //   string mock-default-url   -> defaultUrl
    281 
    282         ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request"));
    283         if (index < 0) {
    284             ALOGD("Missing 'mock-request' parameter for mock");
    285             return BAD_VALUE;
    286         } else {
    287             request = mByteArrayProperties.valueAt(index);
    288         }
    289 
    290         index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
    291         if (index < 0) {
    292             ALOGD("Missing 'mock-defaultUrl' parameter for mock");
    293             return BAD_VALUE;
    294         } else {
    295             defaultUrl = mStringProperties.valueAt(index);
    296         }
    297         return OK;
    298     }
    299 
    300     status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response,
    301                                                      Vector<uint8_t> & /* certificate */,
    302                                                      Vector<uint8_t> & /* wrappedKey */)
    303     {
    304         Mutex::Autolock lock(mLock);
    305         ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
    306               vectorToString(response).string());
    307 
    308         // Properties used in mock test, set by mock plugin and verifed cts test app
    309         //   byte[] response            -> mock-response
    310 
    311         mByteArrayProperties.add(String8("mock-response"), response);
    312         return OK;
    313     }
    314 
    315     status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */,
    316                                           Vector<uint8_t> & secureStop)
    317     {
    318         Mutex::Autolock lock(mLock);
    319         ALOGD("MockDrmPlugin::getSecureStop()");
    320 
    321         // Properties used in mock test, set by cts test app returned from mock plugin
    322         //   byte[] mock-secure-stop  -> first secure stop in list
    323 
    324         ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop"));
    325         if (index < 0) {
    326             ALOGD("Missing 'mock-secure-stop' parameter for mock");
    327             return BAD_VALUE;
    328         } else {
    329             secureStop = mByteArrayProperties.valueAt(index);
    330         }
    331         return OK;
    332     }
    333 
    334     status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
    335     {
    336         Mutex::Autolock lock(mLock);
    337         ALOGD("MockDrmPlugin::getSecureStops()");
    338 
    339         // Properties used in mock test, set by cts test app returned from mock plugin
    340         //   byte[] mock-secure-stop1  -> first secure stop in list
    341         //   byte[] mock-secure-stop2  -> second secure stop in list
    342 
    343         Vector<uint8_t> ss1, ss2;
    344         ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
    345         if (index < 0) {
    346             ALOGD("Missing 'mock-secure-stop1' parameter for mock");
    347             return BAD_VALUE;
    348         } else {
    349             ss1 = mByteArrayProperties.valueAt(index);
    350         }
    351 
    352         index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
    353         if (index < 0) {
    354             ALOGD("Missing 'mock-secure-stop2' parameter for mock");
    355             return BAD_VALUE;
    356         } else {
    357             ss2 = mByteArrayProperties.valueAt(index);
    358         }
    359 
    360         secureStops.push_back(ss1);
    361         secureStops.push_back(ss2);
    362         return OK;
    363     }
    364 
    365     status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease)
    366     {
    367         Mutex::Autolock lock(mLock);
    368         ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
    369               vectorToString(ssRelease).string());
    370 
    371         // Properties used in mock test, set by mock plugin and verifed cts test app
    372         //   byte[] secure-stop-release  -> mock-ssrelease
    373         mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);
    374 
    375         return OK;
    376     }
    377 
    378     status_t MockDrmPlugin::releaseAllSecureStops()
    379     {
    380         Mutex::Autolock lock(mLock);
    381         ALOGD("MockDrmPlugin::releaseAllSecureStops()");
    382         return OK;
    383     }
    384 
    385     status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
    386     {
    387         ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
    388         ssize_t index = mStringProperties.indexOfKey(name);
    389         if (index < 0) {
    390             ALOGD("no property for '%s'", name.string());
    391             return BAD_VALUE;
    392         }
    393         value = mStringProperties.valueAt(index);
    394         return OK;
    395     }
    396 
    397     status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
    398                                                  Vector<uint8_t> &value) const
    399     {
    400         ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
    401         ssize_t index = mByteArrayProperties.indexOfKey(name);
    402         if (index < 0) {
    403             ALOGD("no property for '%s'", name.string());
    404             return BAD_VALUE;
    405         }
    406         value = mByteArrayProperties.valueAt(index);
    407         return OK;
    408     }
    409 
    410     status_t MockDrmPlugin::setPropertyString(String8 const &name,
    411                                               String8 const &value)
    412     {
    413         Mutex::Autolock lock(mLock);
    414         ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
    415               name.string(), value.string());
    416 
    417         if (name == "mock-send-event") {
    418             unsigned code, extra;
    419             sscanf(value.string(), "%d %d", &code, &extra);
    420             DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;
    421 
    422             Vector<uint8_t> const *pSessionId = NULL;
    423             ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
    424             if (index >= 0) {
    425                 pSessionId = &mByteArrayProperties[index];
    426             }
    427 
    428             Vector<uint8_t> const *pData = NULL;
    429             index = mByteArrayProperties.indexOfKey(String8("mock-event-data"));
    430             if (index >= 0) {
    431                 pData = &mByteArrayProperties[index];
    432             }
    433             ALOGD("sending event from mock drm plugin: %d %d %s %s",
    434                   (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}",
    435                   pData ? vectorToString(*pData) : "{}");
    436 
    437             sendEvent(eventType, extra, pSessionId, pData);
    438         } else if (name == "mock-send-expiration-update") {
    439             int64_t expiryTimeMS;
    440             sscanf(value.string(), "%jd", &expiryTimeMS);
    441 
    442             Vector<uint8_t> const *pSessionId = NULL;
    443             ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
    444             if (index >= 0) {
    445                 pSessionId = &mByteArrayProperties[index];
    446             }
    447 
    448             ALOGD("sending expiration-update from mock drm plugin: %jd %s",
    449                   expiryTimeMS, pSessionId ? vectorToString(*pSessionId) : "{}");
    450 
    451             sendExpirationUpdate(pSessionId, expiryTimeMS);
    452         } else if (name == "mock-send-keys-change") {
    453             Vector<uint8_t> const *pSessionId = NULL;
    454             ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
    455             if (index >= 0) {
    456                 pSessionId = &mByteArrayProperties[index];
    457             }
    458 
    459             ALOGD("sending keys-change from mock drm plugin: %s",
    460                   pSessionId ? vectorToString(*pSessionId) : "{}");
    461 
    462             Vector<DrmPlugin::KeyStatus> keyStatusList;
    463             DrmPlugin::KeyStatus keyStatus;
    464             uint8_t keyId1[] = {'k', 'e', 'y', '1'};
    465             keyStatus.mKeyId.clear();
    466             keyStatus.mKeyId.appendArray(keyId1, sizeof(keyId1));
    467             keyStatus.mType = DrmPlugin::kKeyStatusType_Usable;
    468             keyStatusList.add(keyStatus);
    469 
    470             uint8_t keyId2[] = {'k', 'e', 'y', '2'};
    471             keyStatus.mKeyId.clear();
    472             keyStatus.mKeyId.appendArray(keyId2, sizeof(keyId2));
    473             keyStatus.mType = DrmPlugin::kKeyStatusType_Expired;
    474             keyStatusList.add(keyStatus);
    475 
    476             uint8_t keyId3[] = {'k', 'e', 'y', '3'};
    477             keyStatus.mKeyId.clear();
    478             keyStatus.mKeyId.appendArray(keyId3, sizeof(keyId3));
    479             keyStatus.mType = DrmPlugin::kKeyStatusType_OutputNotAllowed;
    480             keyStatusList.add(keyStatus);
    481 
    482             uint8_t keyId4[] = {'k', 'e', 'y', '4'};
    483             keyStatus.mKeyId.clear();
    484             keyStatus.mKeyId.appendArray(keyId4, sizeof(keyId4));
    485             keyStatus.mType = DrmPlugin::kKeyStatusType_StatusPending;
    486             keyStatusList.add(keyStatus);
    487 
    488             uint8_t keyId5[] = {'k', 'e', 'y', '5'};
    489             keyStatus.mKeyId.clear();
    490             keyStatus.mKeyId.appendArray(keyId5, sizeof(keyId5));
    491             keyStatus.mType = DrmPlugin::kKeyStatusType_InternalError;
    492             keyStatusList.add(keyStatus);
    493 
    494             sendKeysChange(pSessionId, &keyStatusList, true);
    495         } else {
    496             mStringProperties.add(name, value);
    497         }
    498         return OK;
    499     }
    500 
    501     status_t MockDrmPlugin::setPropertyByteArray(String8 const &name,
    502                                                  Vector<uint8_t> const &value)
    503     {
    504         Mutex::Autolock lock(mLock);
    505         ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
    506               name.string(), vectorToString(value).string());
    507         mByteArrayProperties.add(name, value);
    508         return OK;
    509     }
    510 
    511     status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
    512                                                String8 const &algorithm)
    513     {
    514         Mutex::Autolock lock(mLock);
    515 
    516         ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
    517               vectorToString(sessionId).string(), algorithm.string());
    518 
    519         ssize_t index = findSession(sessionId);
    520         if (index == kNotFound) {
    521             ALOGD("Invalid sessionId");
    522             return BAD_VALUE;
    523         }
    524 
    525         if (algorithm == "AES/CBC/NoPadding") {
    526             return OK;
    527         }
    528         return BAD_VALUE;
    529     }
    530 
    531     status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId,
    532                                             String8 const &algorithm)
    533     {
    534         Mutex::Autolock lock(mLock);
    535 
    536         ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
    537               vectorToString(sessionId).string(), algorithm.string());
    538 
    539         ssize_t index = findSession(sessionId);
    540         if (index == kNotFound) {
    541             ALOGD("Invalid sessionId");
    542             return BAD_VALUE;
    543         }
    544 
    545         if (algorithm == "HmacSHA256") {
    546             return OK;
    547         }
    548         return BAD_VALUE;
    549     }
    550 
    551     status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId,
    552                                     Vector<uint8_t> const &keyId,
    553                                     Vector<uint8_t> const &input,
    554                                     Vector<uint8_t> const &iv,
    555                                     Vector<uint8_t> &output)
    556     {
    557         Mutex::Autolock lock(mLock);
    558         ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
    559               vectorToString(sessionId).string(),
    560               vectorToString(keyId).string(),
    561               vectorToString(input).string(),
    562               vectorToString(iv).string());
    563 
    564         ssize_t index = findSession(sessionId);
    565         if (index == kNotFound) {
    566             ALOGD("Invalid sessionId");
    567             return BAD_VALUE;
    568         }
    569 
    570         // Properties used in mock test, set by mock plugin and verifed cts test app
    571         //   byte[] keyId              -> mock-keyid
    572         //   byte[] input              -> mock-input
    573         //   byte[] iv                 -> mock-iv
    574         mByteArrayProperties.add(String8("mock-keyid"), keyId);
    575         mByteArrayProperties.add(String8("mock-input"), input);
    576         mByteArrayProperties.add(String8("mock-iv"), iv);
    577 
    578         // Properties used in mock test, set by cts test app returned from mock plugin
    579         //   byte[] mock-output        -> output
    580         index = mByteArrayProperties.indexOfKey(String8("mock-output"));
    581         if (index < 0) {
    582             ALOGD("Missing 'mock-request' parameter for mock");
    583             return BAD_VALUE;
    584         } else {
    585             output = mByteArrayProperties.valueAt(index);
    586         }
    587         return OK;
    588     }
    589 
    590     status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId,
    591                                     Vector<uint8_t> const &keyId,
    592                                     Vector<uint8_t> const &input,
    593                                     Vector<uint8_t> const &iv,
    594                                     Vector<uint8_t> &output)
    595     {
    596         Mutex::Autolock lock(mLock);
    597         ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
    598               vectorToString(sessionId).string(),
    599               vectorToString(keyId).string(),
    600               vectorToString(input).string(),
    601               vectorToString(iv).string());
    602 
    603         ssize_t index = findSession(sessionId);
    604         if (index == kNotFound) {
    605             ALOGD("Invalid sessionId");
    606             return BAD_VALUE;
    607         }
    608 
    609         // Properties used in mock test, set by mock plugin and verifed cts test app
    610         //   byte[] keyId              -> mock-keyid
    611         //   byte[] input              -> mock-input
    612         //   byte[] iv                 -> mock-iv
    613         mByteArrayProperties.add(String8("mock-keyid"), keyId);
    614         mByteArrayProperties.add(String8("mock-input"), input);
    615         mByteArrayProperties.add(String8("mock-iv"), iv);
    616 
    617         // Properties used in mock test, set by cts test app returned from mock plugin
    618         //   byte[] mock-output        -> output
    619         index = mByteArrayProperties.indexOfKey(String8("mock-output"));
    620         if (index < 0) {
    621             ALOGD("Missing 'mock-request' parameter for mock");
    622             return BAD_VALUE;
    623         } else {
    624             output = mByteArrayProperties.valueAt(index);
    625         }
    626         return OK;
    627     }
    628 
    629     status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId,
    630                                  Vector<uint8_t> const &keyId,
    631                                  Vector<uint8_t> const &message,
    632                                  Vector<uint8_t> &signature)
    633     {
    634         Mutex::Autolock lock(mLock);
    635         ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
    636               vectorToString(sessionId).string(),
    637               vectorToString(keyId).string(),
    638               vectorToString(message).string());
    639 
    640         ssize_t index = findSession(sessionId);
    641         if (index == kNotFound) {
    642             ALOGD("Invalid sessionId");
    643             return BAD_VALUE;
    644         }
    645 
    646         // Properties used in mock test, set by mock plugin and verifed cts test app
    647         //   byte[] keyId              -> mock-keyid
    648         //   byte[] message            -> mock-message
    649         mByteArrayProperties.add(String8("mock-keyid"), keyId);
    650         mByteArrayProperties.add(String8("mock-message"), message);
    651 
    652         // Properties used in mock test, set by cts test app returned from mock plugin
    653         //   byte[] mock-signature        -> signature
    654         index = mByteArrayProperties.indexOfKey(String8("mock-signature"));
    655         if (index < 0) {
    656             ALOGD("Missing 'mock-request' parameter for mock");
    657             return BAD_VALUE;
    658         } else {
    659             signature = mByteArrayProperties.valueAt(index);
    660         }
    661         return OK;
    662     }
    663 
    664     status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId,
    665                                    Vector<uint8_t> const &keyId,
    666                                    Vector<uint8_t> const &message,
    667                                    Vector<uint8_t> const &signature,
    668                                    bool &match)
    669     {
    670         Mutex::Autolock lock(mLock);
    671         ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
    672               vectorToString(sessionId).string(),
    673               vectorToString(keyId).string(),
    674               vectorToString(message).string(),
    675               vectorToString(signature).string());
    676 
    677         ssize_t index = findSession(sessionId);
    678         if (index == kNotFound) {
    679             ALOGD("Invalid sessionId");
    680             return BAD_VALUE;
    681         }
    682 
    683         // Properties used in mock test, set by mock plugin and verifed cts test app
    684         //   byte[] keyId              -> mock-keyid
    685         //   byte[] message            -> mock-message
    686         //   byte[] signature          -> mock-signature
    687         mByteArrayProperties.add(String8("mock-keyid"), keyId);
    688         mByteArrayProperties.add(String8("mock-message"), message);
    689         mByteArrayProperties.add(String8("mock-signature"), signature);
    690 
    691         // Properties used in mock test, set by cts test app returned from mock plugin
    692         //   String mock-match "1" or "0"         -> match
    693         index = mStringProperties.indexOfKey(String8("mock-match"));
    694         if (index < 0) {
    695             ALOGD("Missing 'mock-request' parameter for mock");
    696             return BAD_VALUE;
    697         } else {
    698             match = atol(mStringProperties.valueAt(index).string());
    699         }
    700         return OK;
    701     }
    702 
    703     status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
    704                                     String8 const &algorithm,
    705                                     Vector<uint8_t> const &message,
    706                                     Vector<uint8_t> const &wrappedKey,
    707                                     Vector<uint8_t> &signature)
    708     {
    709         Mutex::Autolock lock(mLock);
    710         ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
    711               "message=%s, signature=%s)",
    712               vectorToString(sessionId).string(),
    713               algorithm.string(),
    714               vectorToString(message).string(),
    715               vectorToString(wrappedKey).string(),
    716               vectorToString(signature).string());
    717 
    718         // Properties used in mock test, set by mock plugin and verifed cts test app
    719         //   byte[] wrappedKey         -> mock-wrappedkey
    720         //   byte[] message            -> mock-message
    721         //   byte[] signature          -> mock-signature
    722         mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
    723         mStringProperties.add(String8("mock-algorithm"), algorithm);
    724         mByteArrayProperties.add(String8("mock-message"), message);
    725         mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
    726         mByteArrayProperties.add(String8("mock-signature"), signature);
    727         return OK;
    728     }
    729 
    730     ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
    731     {
    732         ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
    733         for (size_t i = 0; i < mSessions.size(); ++i) {
    734             if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
    735                 return i;
    736             }
    737         }
    738         return kNotFound;
    739     }
    740 
    741     ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
    742     {
    743         ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size());
    744         for (size_t i = 0; i < mKeySets.size(); ++i) {
    745             if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
    746                 return i;
    747             }
    748         }
    749         return kNotFound;
    750     }
    751 
    752 
    753     // Conversion utilities
    754     String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const
    755     {
    756         return arrayToString(vector.array(), vector.size());
    757     }
    758 
    759     String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const
    760     {
    761         String8 result("{ ");
    762         for (size_t i = 0; i < len; i++) {
    763             result.appendFormat("0x%02x ", array[i]);
    764         }
    765         result += "}";
    766         return result;
    767     }
    768 
    769     String8 MockDrmPlugin::stringMapToString(KeyedVector<String8, String8> map) const
    770     {
    771         String8 result("{ ");
    772         for (size_t i = 0; i < map.size(); i++) {
    773             result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
    774                                 map.keyAt(i).string(), map.valueAt(i).string());
    775         }
    776         return result + " }";
    777     }
    778 
    779     bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) {
    780         return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0);
    781     }
    782 
    783     //
    784     // Crypto Plugin
    785     //
    786 
    787     bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
    788     {
    789         ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime);
    790         return false;
    791     }
    792 
    793     ssize_t
    794     MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16],
    795             Mode mode, const Pattern &pattern, const void *srcPtr,
    796             const SubSample *subSamples, size_t numSubSamples,
    797             void *dstPtr, AString * /* errorDetailMsg */)
    798     {
    799         ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, "
    800               "pattern:{encryptBlocks=%d, skipBlocks=%d} src=%p, "
    801               "subSamples=%s, dst=%p)",
    802               (int)secure,
    803               arrayToString(key, sizeof(key)).string(),
    804               arrayToString(iv, sizeof(iv)).string(),
    805               (int)mode, pattern.mEncryptBlocks, pattern.mSkipBlocks, srcPtr,
    806               subSamplesToString(subSamples, numSubSamples).string(),
    807               dstPtr);
    808         return OK;
    809     }
    810 
    811     // Conversion utilities
    812     String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const
    813     {
    814         String8 result("{ ");
    815         for (size_t i = 0; i < len; i++) {
    816             result.appendFormat("0x%02x ", array[i]);
    817         }
    818         result += "}";
    819         return result;
    820     }
    821 
    822     String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples,
    823                                                  size_t numSubSamples) const
    824     {
    825         String8 result;
    826         for (size_t i = 0; i < numSubSamples; i++) {
    827             result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
    828                                 subSamples[i].mNumBytesOfClearData,
    829                                 subSamples[i].mNumBytesOfEncryptedData);
    830         }
    831         return result;
    832     }
    833 
    834 };
    835