/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "MockDrmCryptoPlugin"
#include <utils/Log.h>


#include "drm/DrmAPI.h"
#include "MockDrmCryptoPlugin.h"
#include "media/stagefright/MediaErrors.h"

using namespace android;

// Shared library entry point
DrmFactory *createDrmFactory()
{
    return new MockDrmFactory();
}

// Shared library entry point
CryptoFactory *createCryptoFactory()
{
    return new MockCryptoFactory();
}

const uint8_t mock_uuid[16] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                               0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};

namespace android {

    // MockDrmFactory
    bool MockDrmFactory::isCryptoSchemeSupported(const uint8_t uuid[16])
    {
        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
    }

    bool MockDrmFactory::isContentTypeSupported(const String8 &mimeType)
    {
        if (mimeType != "video/mp4") {
            return false;
        }
        return true;
    }

    status_t MockDrmFactory::createDrmPlugin(const uint8_t /* uuid */[16], DrmPlugin **plugin)
    {
        *plugin = new MockDrmPlugin();
        return OK;
    }

    // MockCryptoFactory
    bool MockCryptoFactory::isCryptoSchemeSupported(const uint8_t uuid[16]) const
    {
        return (!memcmp(uuid, mock_uuid, sizeof(mock_uuid)));
    }

    status_t MockCryptoFactory::createPlugin(const uint8_t /* uuid */[16],
                                             const void * /* data */,
                                             size_t /* size */, CryptoPlugin **plugin)
    {
        *plugin = new MockCryptoPlugin();
        return OK;
    }


    // MockDrmPlugin methods

    status_t MockDrmPlugin::openSession(Vector<uint8_t> &sessionId)
    {
        const size_t kSessionIdSize = 8;

        Mutex::Autolock lock(mLock);
        for (size_t i = 0; i < kSessionIdSize / sizeof(long); i++) {
            long r = random();
            sessionId.appendArray((uint8_t *)&r, sizeof(long));
        }
        mSessions.add(sessionId);

        ALOGD("MockDrmPlugin::openSession() -> %s", vectorToString(sessionId).string());
        return OK;
    }

    status_t MockDrmPlugin::closeSession(Vector<uint8_t> const &sessionId)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::closeSession(%s)", vectorToString(sessionId).string());
        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }
        mSessions.removeAt(index);
        return OK;
    }


    status_t MockDrmPlugin::getKeyRequest(Vector<uint8_t> const &sessionId,
                                          Vector<uint8_t> const &initData,
                                          String8 const &mimeType, KeyType keyType,
                                          KeyedVector<String8, String8> const &optionalParameters,
                                          Vector<uint8_t> &request, String8 &defaultUrl,
                                          KeyRequestType *keyRequestType)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::getKeyRequest(sessionId=%s, initData=%s, mimeType=%s"
              ", keyType=%d, optionalParameters=%s))",
              vectorToString(sessionId).string(), vectorToString(initData).string(), mimeType.string(),
              keyType, stringMapToString(optionalParameters).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] initData           -> mock-initdata
        //   string mimeType           -> mock-mimetype
        //   string keyType            -> mock-keytype
        //   string optionalParameters -> mock-optparams formatted as {key1,value1},{key2,value2}

        mByteArrayProperties.add(String8("mock-initdata"), initData);
        mStringProperties.add(String8("mock-mimetype"), mimeType);

        String8 keyTypeStr;
        keyTypeStr.appendFormat("%d", (int)keyType);
        mStringProperties.add(String8("mock-keytype"), keyTypeStr);

        String8 params;
        for (size_t i = 0; i < optionalParameters.size(); i++) {
            params.appendFormat("%s{%s,%s}", i ? "," : "",
                                optionalParameters.keyAt(i).string(),
                                optionalParameters.valueAt(i).string());
        }
        mStringProperties.add(String8("mock-optparams"), params);

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-request       -> request
        //   string mock-default-url   -> defaultUrl
        //   string mock-keyRequestType -> keyRequestType

        index = mByteArrayProperties.indexOfKey(String8("mock-request"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            request = mByteArrayProperties.valueAt(index);
        }

        index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
        if (index < 0) {
            ALOGD("Missing 'mock-defaultUrl' parameter for mock");
            return BAD_VALUE;
        } else {
            defaultUrl = mStringProperties.valueAt(index);
        }

        index = mStringProperties.indexOfKey(String8("mock-keyRequestType"));
        if (index < 0) {
            ALOGD("Missing 'mock-keyRequestType' parameter for mock");
            return BAD_VALUE;
        } else {
            *keyRequestType = static_cast<KeyRequestType>(
                atoi(mStringProperties.valueAt(index).string()));
        }

        return OK;
    }

    status_t MockDrmPlugin::provideKeyResponse(Vector<uint8_t> const &sessionId,
                                               Vector<uint8_t> const &response,
                                               Vector<uint8_t> &keySetId)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::provideKeyResponse(sessionId=%s, response=%s)",
              vectorToString(sessionId).string(), vectorToString(response).string());
        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }
        if (response.size() == 0) {
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] response            -> mock-response
        mByteArrayProperties.add(String8("mock-response"), response);

        const size_t kKeySetIdSize = 8;

        for (size_t i = 0; i < kKeySetIdSize / sizeof(long); i++) {
            long r = random();
            keySetId.appendArray((uint8_t *)&r, sizeof(long));
        }
        mKeySets.add(keySetId);

        return OK;
    }

    status_t MockDrmPlugin::removeKeys(Vector<uint8_t> const &keySetId)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::removeKeys(keySetId=%s)",
              vectorToString(keySetId).string());

        ssize_t index = findKeySet(keySetId);
        if (index == kNotFound) {
            ALOGD("Invalid keySetId");
            return BAD_VALUE;
        }
        mKeySets.removeAt(index);

        return OK;
    }

    status_t MockDrmPlugin::restoreKeys(Vector<uint8_t> const &sessionId,
                                        Vector<uint8_t> const &keySetId)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::restoreKeys(sessionId=%s, keySetId=%s)",
              vectorToString(sessionId).string(),
              vectorToString(keySetId).string());
        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        index = findKeySet(keySetId);
        if (index == kNotFound) {
            ALOGD("Invalid keySetId");
            return BAD_VALUE;
        }

        return OK;
    }

    status_t MockDrmPlugin::queryKeyStatus(Vector<uint8_t> const &sessionId,
                                               KeyedVector<String8, String8> &infoMap) const
    {
        ALOGD("MockDrmPlugin::queryKeyStatus(sessionId=%s)",
              vectorToString(sessionId).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        infoMap.add(String8("purchaseDuration"), String8("1000"));
        infoMap.add(String8("licenseDuration"), String8("100"));
        return OK;
    }

    status_t MockDrmPlugin::getProvisionRequest(String8 const & /* certType */,
                                                String8 const & /* certAuthority */,
                                                Vector<uint8_t> &request,
                                                String8 &defaultUrl)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::getProvisionRequest()");

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-request       -> request
        //   string mock-default-url   -> defaultUrl

        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-request"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            request = mByteArrayProperties.valueAt(index);
        }

        index = mStringProperties.indexOfKey(String8("mock-defaultUrl"));
        if (index < 0) {
            ALOGD("Missing 'mock-defaultUrl' parameter for mock");
            return BAD_VALUE;
        } else {
            defaultUrl = mStringProperties.valueAt(index);
        }
        return OK;
    }

    status_t MockDrmPlugin::provideProvisionResponse(Vector<uint8_t> const &response,
                                                     Vector<uint8_t> & /* certificate */,
                                                     Vector<uint8_t> & /* wrappedKey */)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::provideProvisionResponse(%s)",
              vectorToString(response).string());

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] response            -> mock-response

        mByteArrayProperties.add(String8("mock-response"), response);
        return OK;
    }

    status_t MockDrmPlugin::unprovisionDevice()
    {
        ALOGD("MockDrmPlugin::unprovisionDevice()");
        return OK;
    }

    status_t MockDrmPlugin::getSecureStop(Vector<uint8_t> const & /* ssid */,
                                          Vector<uint8_t> & secureStop)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::getSecureStop()");

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-secure-stop  -> first secure stop in list

        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop"));
        if (index < 0) {
            ALOGD("Missing 'mock-secure-stop' parameter for mock");
            return BAD_VALUE;
        } else {
            secureStop = mByteArrayProperties.valueAt(index);
        }
        return OK;
    }

    status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::getSecureStops()");

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-secure-stop1  -> first secure stop in list
        //   byte[] mock-secure-stop2  -> second secure stop in list

        Vector<uint8_t> ss1, ss2;
        ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop1"));
        if (index < 0) {
            ALOGD("Missing 'mock-secure-stop1' parameter for mock");
            return BAD_VALUE;
        } else {
            ss1 = mByteArrayProperties.valueAt(index);
        }

        index = mByteArrayProperties.indexOfKey(String8("mock-secure-stop2"));
        if (index < 0) {
            ALOGD("Missing 'mock-secure-stop2' parameter for mock");
            return BAD_VALUE;
        } else {
            ss2 = mByteArrayProperties.valueAt(index);
        }

        secureStops.push_back(ss1);
        secureStops.push_back(ss2);
        return OK;
    }

    status_t MockDrmPlugin::releaseSecureStops(Vector<uint8_t> const &ssRelease)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::releaseSecureStops(%s)",
              vectorToString(ssRelease).string());

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] secure-stop-release  -> mock-ssrelease
        mByteArrayProperties.add(String8("mock-ssrelease"), ssRelease);

        return OK;
    }

    status_t MockDrmPlugin::releaseAllSecureStops()
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::releaseAllSecureStops()");
        return OK;
    }

    status_t MockDrmPlugin::getPropertyString(String8 const &name, String8 &value) const
    {
        ALOGD("MockDrmPlugin::getPropertyString(name=%s)", name.string());
        ssize_t index = mStringProperties.indexOfKey(name);
        if (index < 0) {
            ALOGD("no property for '%s'", name.string());
            return BAD_VALUE;
        }
        value = mStringProperties.valueAt(index);
        return OK;
    }

    status_t MockDrmPlugin::getPropertyByteArray(String8 const &name,
                                                 Vector<uint8_t> &value) const
    {
        ALOGD("MockDrmPlugin::getPropertyByteArray(name=%s)", name.string());
        ssize_t index = mByteArrayProperties.indexOfKey(name);
        if (index < 0) {
            ALOGD("no property for '%s'", name.string());
            return BAD_VALUE;
        }
        value = mByteArrayProperties.valueAt(index);
        return OK;
    }

    status_t MockDrmPlugin::setPropertyString(String8 const &name,
                                              String8 const &value)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::setPropertyString(name=%s, value=%s)",
              name.string(), value.string());

        if (name == "mock-send-event") {
            unsigned code, extra;
            sscanf(value.string(), "%d %d", &code, &extra);
            DrmPlugin::EventType eventType = (DrmPlugin::EventType)code;

            Vector<uint8_t> const *pSessionId = NULL;
            ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
            if (index >= 0) {
                pSessionId = &mByteArrayProperties[index];
            }

            Vector<uint8_t> const *pData = NULL;
            index = mByteArrayProperties.indexOfKey(String8("mock-event-data"));
            if (index >= 0) {
                pData = &mByteArrayProperties[index];
            }
            ALOGD("sending event from mock drm plugin: %d %d %s %s",
                  (int)code, extra, pSessionId ? vectorToString(*pSessionId) : "{}",
                  pData ? vectorToString(*pData) : "{}");

            sendEvent(eventType, extra, pSessionId, pData);
        } else if (name == "mock-send-expiration-update") {
            int64_t expiryTimeMS;
            sscanf(value.string(), "%jd", &expiryTimeMS);

            Vector<uint8_t> const *pSessionId = NULL;
            ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
            if (index >= 0) {
                pSessionId = &mByteArrayProperties[index];
            }

            ALOGD("sending expiration-update from mock drm plugin: %jd %s",
                  expiryTimeMS, pSessionId ? vectorToString(*pSessionId) : "{}");

            sendExpirationUpdate(pSessionId, expiryTimeMS);
        } else if (name == "mock-send-keys-change") {
            Vector<uint8_t> const *pSessionId = NULL;
            ssize_t index = mByteArrayProperties.indexOfKey(String8("mock-event-session-id"));
            if (index >= 0) {
                pSessionId = &mByteArrayProperties[index];
            }

            ALOGD("sending keys-change from mock drm plugin: %s",
                  pSessionId ? vectorToString(*pSessionId) : "{}");

            Vector<DrmPlugin::KeyStatus> keyStatusList;
            DrmPlugin::KeyStatus keyStatus;
            uint8_t keyId1[] = {'k', 'e', 'y', '1'};
            keyStatus.mKeyId.clear();
            keyStatus.mKeyId.appendArray(keyId1, sizeof(keyId1));
            keyStatus.mType = DrmPlugin::kKeyStatusType_Usable;
            keyStatusList.add(keyStatus);

            uint8_t keyId2[] = {'k', 'e', 'y', '2'};
            keyStatus.mKeyId.clear();
            keyStatus.mKeyId.appendArray(keyId2, sizeof(keyId2));
            keyStatus.mType = DrmPlugin::kKeyStatusType_Expired;
            keyStatusList.add(keyStatus);

            uint8_t keyId3[] = {'k', 'e', 'y', '3'};
            keyStatus.mKeyId.clear();
            keyStatus.mKeyId.appendArray(keyId3, sizeof(keyId3));
            keyStatus.mType = DrmPlugin::kKeyStatusType_OutputNotAllowed;
            keyStatusList.add(keyStatus);

            uint8_t keyId4[] = {'k', 'e', 'y', '4'};
            keyStatus.mKeyId.clear();
            keyStatus.mKeyId.appendArray(keyId4, sizeof(keyId4));
            keyStatus.mType = DrmPlugin::kKeyStatusType_StatusPending;
            keyStatusList.add(keyStatus);

            uint8_t keyId5[] = {'k', 'e', 'y', '5'};
            keyStatus.mKeyId.clear();
            keyStatus.mKeyId.appendArray(keyId5, sizeof(keyId5));
            keyStatus.mType = DrmPlugin::kKeyStatusType_InternalError;
            keyStatusList.add(keyStatus);

            sendKeysChange(pSessionId, &keyStatusList, true);
        } else {
            mStringProperties.add(name, value);
        }
        return OK;
    }

    status_t MockDrmPlugin::setPropertyByteArray(String8 const &name,
                                                 Vector<uint8_t> const &value)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::setPropertyByteArray(name=%s, value=%s)",
              name.string(), vectorToString(value).string());
        mByteArrayProperties.add(name, value);
        return OK;
    }

    status_t MockDrmPlugin::setCipherAlgorithm(Vector<uint8_t> const &sessionId,
                                               String8 const &algorithm)
    {
        Mutex::Autolock lock(mLock);

        ALOGD("MockDrmPlugin::setCipherAlgorithm(sessionId=%s, algorithm=%s)",
              vectorToString(sessionId).string(), algorithm.string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        if (algorithm == "AES/CBC/NoPadding") {
            return OK;
        }
        return BAD_VALUE;
    }

    status_t MockDrmPlugin::setMacAlgorithm(Vector<uint8_t> const &sessionId,
                                            String8 const &algorithm)
    {
        Mutex::Autolock lock(mLock);

        ALOGD("MockDrmPlugin::setMacAlgorithm(sessionId=%s, algorithm=%s)",
              vectorToString(sessionId).string(), algorithm.string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        if (algorithm == "HmacSHA256") {
            return OK;
        }
        return BAD_VALUE;
    }

    status_t MockDrmPlugin::encrypt(Vector<uint8_t> const &sessionId,
                                    Vector<uint8_t> const &keyId,
                                    Vector<uint8_t> const &input,
                                    Vector<uint8_t> const &iv,
                                    Vector<uint8_t> &output)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::encrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
              vectorToString(sessionId).string(),
              vectorToString(keyId).string(),
              vectorToString(input).string(),
              vectorToString(iv).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] keyId              -> mock-keyid
        //   byte[] input              -> mock-input
        //   byte[] iv                 -> mock-iv
        mByteArrayProperties.add(String8("mock-keyid"), keyId);
        mByteArrayProperties.add(String8("mock-input"), input);
        mByteArrayProperties.add(String8("mock-iv"), iv);

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-output        -> output
        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            output = mByteArrayProperties.valueAt(index);
        }
        return OK;
    }

    status_t MockDrmPlugin::decrypt(Vector<uint8_t> const &sessionId,
                                    Vector<uint8_t> const &keyId,
                                    Vector<uint8_t> const &input,
                                    Vector<uint8_t> const &iv,
                                    Vector<uint8_t> &output)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::decrypt(sessionId=%s, keyId=%s, input=%s, iv=%s)",
              vectorToString(sessionId).string(),
              vectorToString(keyId).string(),
              vectorToString(input).string(),
              vectorToString(iv).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] keyId              -> mock-keyid
        //   byte[] input              -> mock-input
        //   byte[] iv                 -> mock-iv
        mByteArrayProperties.add(String8("mock-keyid"), keyId);
        mByteArrayProperties.add(String8("mock-input"), input);
        mByteArrayProperties.add(String8("mock-iv"), iv);

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-output        -> output
        index = mByteArrayProperties.indexOfKey(String8("mock-output"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            output = mByteArrayProperties.valueAt(index);
        }
        return OK;
    }

    status_t MockDrmPlugin::sign(Vector<uint8_t> const &sessionId,
                                 Vector<uint8_t> const &keyId,
                                 Vector<uint8_t> const &message,
                                 Vector<uint8_t> &signature)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::sign(sessionId=%s, keyId=%s, message=%s)",
              vectorToString(sessionId).string(),
              vectorToString(keyId).string(),
              vectorToString(message).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] keyId              -> mock-keyid
        //   byte[] message            -> mock-message
        mByteArrayProperties.add(String8("mock-keyid"), keyId);
        mByteArrayProperties.add(String8("mock-message"), message);

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   byte[] mock-signature        -> signature
        index = mByteArrayProperties.indexOfKey(String8("mock-signature"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            signature = mByteArrayProperties.valueAt(index);
        }
        return OK;
    }

    status_t MockDrmPlugin::verify(Vector<uint8_t> const &sessionId,
                                   Vector<uint8_t> const &keyId,
                                   Vector<uint8_t> const &message,
                                   Vector<uint8_t> const &signature,
                                   bool &match)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::verify(sessionId=%s, keyId=%s, message=%s, signature=%s)",
              vectorToString(sessionId).string(),
              vectorToString(keyId).string(),
              vectorToString(message).string(),
              vectorToString(signature).string());

        ssize_t index = findSession(sessionId);
        if (index == kNotFound) {
            ALOGD("Invalid sessionId");
            return BAD_VALUE;
        }

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] keyId              -> mock-keyid
        //   byte[] message            -> mock-message
        //   byte[] signature          -> mock-signature
        mByteArrayProperties.add(String8("mock-keyid"), keyId);
        mByteArrayProperties.add(String8("mock-message"), message);
        mByteArrayProperties.add(String8("mock-signature"), signature);

        // Properties used in mock test, set by cts test app returned from mock plugin
        //   String mock-match "1" or "0"         -> match
        index = mStringProperties.indexOfKey(String8("mock-match"));
        if (index < 0) {
            ALOGD("Missing 'mock-request' parameter for mock");
            return BAD_VALUE;
        } else {
            match = atol(mStringProperties.valueAt(index).string());
        }
        return OK;
    }

    status_t MockDrmPlugin::signRSA(Vector<uint8_t> const &sessionId,
                                    String8 const &algorithm,
                                    Vector<uint8_t> const &message,
                                    Vector<uint8_t> const &wrappedKey,
                                    Vector<uint8_t> &signature)
    {
        Mutex::Autolock lock(mLock);
        ALOGD("MockDrmPlugin::signRSA(sessionId=%s, algorithm=%s, keyId=%s, "
              "message=%s, signature=%s)",
              vectorToString(sessionId).string(),
              algorithm.string(),
              vectorToString(message).string(),
              vectorToString(wrappedKey).string(),
              vectorToString(signature).string());

        // Properties used in mock test, set by mock plugin and verifed cts test app
        //   byte[] wrappedKey         -> mock-wrappedkey
        //   byte[] message            -> mock-message
        //   byte[] signature          -> mock-signature
        mByteArrayProperties.add(String8("mock-sessionid"), sessionId);
        mStringProperties.add(String8("mock-algorithm"), algorithm);
        mByteArrayProperties.add(String8("mock-message"), message);
        mByteArrayProperties.add(String8("mock-wrappedkey"), wrappedKey);
        mByteArrayProperties.add(String8("mock-signature"), signature);
        return OK;
    }

    ssize_t MockDrmPlugin::findSession(Vector<uint8_t> const &sessionId) const
    {
        ALOGD("findSession: nsessions=%d, size=%d", mSessions.size(), sessionId.size());
        for (size_t i = 0; i < mSessions.size(); ++i) {
            if (memcmp(mSessions[i].array(), sessionId.array(), sessionId.size()) == 0) {
                return i;
            }
        }
        return kNotFound;
    }

    ssize_t MockDrmPlugin::findKeySet(Vector<uint8_t> const &keySetId) const
    {
        ALOGD("findKeySet: nkeySets=%d, size=%d", mKeySets.size(), keySetId.size());
        for (size_t i = 0; i < mKeySets.size(); ++i) {
            if (memcmp(mKeySets[i].array(), keySetId.array(), keySetId.size()) == 0) {
                return i;
            }
        }
        return kNotFound;
    }


    // Conversion utilities
    String8 MockDrmPlugin::vectorToString(Vector<uint8_t> const &vector) const
    {
        return arrayToString(vector.array(), vector.size());
    }

    String8 MockDrmPlugin::arrayToString(uint8_t const *array, size_t len) const
    {
        String8 result("{ ");
        for (size_t i = 0; i < len; i++) {
            result.appendFormat("0x%02x ", array[i]);
        }
        result += "}";
        return result;
    }

    String8 MockDrmPlugin::stringMapToString(const KeyedVector<String8, String8>& map) const
    {
        String8 result("{ ");
        for (size_t i = 0; i < map.size(); i++) {
            result.appendFormat("%s{name=%s, value=%s}", i > 0 ? ", " : "",
                                map.keyAt(i).string(), map.valueAt(i).string());
        }
        return result + " }";
    }

    bool operator<(Vector<uint8_t> const &lhs, Vector<uint8_t> const &rhs) {
        return lhs.size() < rhs.size() || (memcmp(lhs.array(), rhs.array(), lhs.size()) < 0);
    }

    //
    // Crypto Plugin
    //

    bool MockCryptoPlugin::requiresSecureDecoderComponent(const char *mime) const
    {
        ALOGD("MockCryptoPlugin::requiresSecureDecoderComponent(mime=%s)", mime);
        return false;
    }

    ssize_t
    MockCryptoPlugin::decrypt(bool secure, const uint8_t key[16], const uint8_t iv[16],
                              Mode mode, const void *srcPtr, const SubSample *subSamples,
                              size_t numSubSamples, void *dstPtr, AString * /* errorDetailMsg */)
    {
        ALOGD("MockCryptoPlugin::decrypt(secure=%d, key=%s, iv=%s, mode=%d, src=%p, "
              "subSamples=%s, dst=%p)",
              (int)secure,
              arrayToString(key, sizeof(key)).string(),
              arrayToString(iv, sizeof(iv)).string(),
              (int)mode, srcPtr,
              subSamplesToString(subSamples, numSubSamples).string(),
              dstPtr);
        return OK;
    }

    // Conversion utilities
    String8 MockCryptoPlugin::arrayToString(uint8_t const *array, size_t len) const
    {
        String8 result("{ ");
        for (size_t i = 0; i < len; i++) {
            result.appendFormat("0x%02x ", array[i]);
        }
        result += "}";
        return result;
    }

    String8 MockCryptoPlugin::subSamplesToString(SubSample const *subSamples,
                                                 size_t numSubSamples) const
    {
        String8 result;
        for (size_t i = 0; i < numSubSamples; i++) {
            result.appendFormat("[%zu] {clear:%u, encrypted:%u} ", i,
                                subSamples[i].mNumBytesOfClearData,
                                subSamples[i].mNumBytesOfEncryptedData);
        }
        return result;
    }

};
