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