/*
 * 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 "Drm"
#include <utils/Log.h>

#include <dirent.h>
#include <dlfcn.h>

#include "Drm.h"

#include "DrmSessionClientInterface.h"
#include "DrmSessionManager.h"
#include <media/drm/DrmAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>

namespace android {

static inline int getCallingPid() {
    return IPCThreadState::self()->getCallingPid();
}

static bool checkPermission(const char* permissionString) {
#ifndef HAVE_ANDROID_OS
    return true;
#endif
    if (getpid() == IPCThreadState::self()->getCallingPid()) return true;
    bool ok = checkCallingPermission(String16(permissionString));
    if (!ok) ALOGE("Request requires %s", permissionString);
    return ok;
}

KeyedVector<Vector<uint8_t>, String8> Drm::mUUIDToLibraryPathMap;
KeyedVector<String8, wp<SharedLibrary> > Drm::mLibraryPathToOpenLibraryMap;
Mutex Drm::mMapLock;
Mutex Drm::mLock;

static bool operator<(const Vector<uint8_t> &lhs, const Vector<uint8_t> &rhs) {
    if (lhs.size() < rhs.size()) {
        return true;
    } else if (lhs.size() > rhs.size()) {
        return false;
    }

    return memcmp((void *)lhs.array(), (void *)rhs.array(), rhs.size()) < 0;
}

struct DrmSessionClient : public DrmSessionClientInterface {
    DrmSessionClient(Drm* drm) : mDrm(drm) {}

    virtual bool reclaimSession(const Vector<uint8_t>& sessionId) {
        sp<Drm> drm = mDrm.promote();
        if (drm == NULL) {
            return true;
        }
        status_t err = drm->closeSession(sessionId);
        if (err != OK) {
            return false;
        }
        drm->sendEvent(DrmPlugin::kDrmPluginEventSessionReclaimed, 0, &sessionId, NULL);
        return true;
    }

protected:
    virtual ~DrmSessionClient() {}

private:
    wp<Drm> mDrm;

    DISALLOW_EVIL_CONSTRUCTORS(DrmSessionClient);
};

Drm::Drm()
    : mInitCheck(NO_INIT),
      mDrmSessionClient(new DrmSessionClient(this)),
      mListener(NULL),
      mFactory(NULL),
      mPlugin(NULL) {
}

Drm::~Drm() {
    DrmSessionManager::Instance()->removeDrm(mDrmSessionClient);
    delete mPlugin;
    mPlugin = NULL;
    closeFactory();
}

void Drm::closeFactory() {
    delete mFactory;
    mFactory = NULL;
    mLibrary.clear();
}

status_t Drm::initCheck() const {
    return mInitCheck;
}

status_t Drm::setListener(const sp<IDrmClient>& listener)
{
    Mutex::Autolock lock(mEventLock);
    if (mListener != NULL){
        IInterface::asBinder(mListener)->unlinkToDeath(this);
    }
    if (listener != NULL) {
        IInterface::asBinder(listener)->linkToDeath(this);
    }
    mListener = listener;
    return NO_ERROR;
}

void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
                    Vector<uint8_t> const *sessionId,
                    Vector<uint8_t> const *data)
{
    mEventLock.lock();
    sp<IDrmClient> listener = mListener;
    mEventLock.unlock();

    if (listener != NULL) {
        Parcel obj;
        writeByteArray(obj, sessionId);
        writeByteArray(obj, data);

        Mutex::Autolock lock(mNotifyLock);
        listener->notify(eventType, extra, &obj);
    }
}

void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
                               int64_t expiryTimeInMS)
{
    mEventLock.lock();
    sp<IDrmClient> listener = mListener;
    mEventLock.unlock();

    if (listener != NULL) {
        Parcel obj;
        writeByteArray(obj, sessionId);
        obj.writeInt64(expiryTimeInMS);

        Mutex::Autolock lock(mNotifyLock);
        listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
    }
}

void Drm::sendKeysChange(Vector<uint8_t> const *sessionId,
                         Vector<DrmPlugin::KeyStatus> const *keyStatusList,
                         bool hasNewUsableKey)
{
    mEventLock.lock();
    sp<IDrmClient> listener = mListener;
    mEventLock.unlock();

    if (listener != NULL) {
        Parcel obj;
        writeByteArray(obj, sessionId);

        size_t nkeys = keyStatusList->size();
        obj.writeInt32(keyStatusList->size());
        for (size_t i = 0; i < nkeys; ++i) {
            const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i);
            writeByteArray(obj, &keyStatus->mKeyId);
            obj.writeInt32(keyStatus->mType);
        }
        obj.writeInt32(hasNewUsableKey);

        Mutex::Autolock lock(mNotifyLock);
        listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
    }
}

/*
 * Search the plugins directory for a plugin that supports the scheme
 * specified by uuid
 *
 * If found:
 *    mLibrary holds a strong pointer to the dlopen'd library
 *    mFactory is set to the library's factory method
 *    mInitCheck is set to OK
 *
 * If not found:
 *    mLibrary is cleared and mFactory are set to NULL
 *    mInitCheck is set to an error (!OK)
 */
void Drm::findFactoryForScheme(const uint8_t uuid[16]) {

    closeFactory();

    // lock static maps
    Mutex::Autolock autoLock(mMapLock);

    // first check cache
    Vector<uint8_t> uuidVector;
    uuidVector.appendArray(uuid, sizeof(uuid[0]) * 16);
    ssize_t index = mUUIDToLibraryPathMap.indexOfKey(uuidVector);
    if (index >= 0) {
        if (loadLibraryForScheme(mUUIDToLibraryPathMap[index], uuid)) {
            mInitCheck = OK;
            return;
        } else {
            ALOGE("Failed to load from cached library path!");
            mInitCheck = ERROR_UNSUPPORTED;
            return;
        }
    }

    // no luck, have to search
    String8 dirPath("/vendor/lib/mediadrm");
    DIR* pDir = opendir(dirPath.string());

    if (pDir == NULL) {
        mInitCheck = ERROR_UNSUPPORTED;
        ALOGE("Failed to open plugin directory %s", dirPath.string());
        return;
    }


    struct dirent* pEntry;
    while ((pEntry = readdir(pDir))) {

        String8 pluginPath = dirPath + "/" + pEntry->d_name;

        if (pluginPath.getPathExtension() == ".so") {

            if (loadLibraryForScheme(pluginPath, uuid)) {
                mUUIDToLibraryPathMap.add(uuidVector, pluginPath);
                mInitCheck = OK;
                closedir(pDir);
                return;
            }
        }
    }

    closedir(pDir);

    ALOGE("Failed to find drm plugin");
    mInitCheck = ERROR_UNSUPPORTED;
}

bool Drm::loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]) {

    // get strong pointer to open shared library
    ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
    if (index >= 0) {
        mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
    } else {
        index = mLibraryPathToOpenLibraryMap.add(path, NULL);
    }

    if (!mLibrary.get()) {
        mLibrary = new SharedLibrary(path);
        if (!*mLibrary) {
            return false;
        }

        mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
    }

    typedef DrmFactory *(*CreateDrmFactoryFunc)();

    CreateDrmFactoryFunc createDrmFactory =
        (CreateDrmFactoryFunc)mLibrary->lookup("createDrmFactory");

    if (createDrmFactory == NULL ||
        (mFactory = createDrmFactory()) == NULL ||
        !mFactory->isCryptoSchemeSupported(uuid)) {
        closeFactory();
        return false;
    }
    return true;
}

bool Drm::isCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {

    Mutex::Autolock autoLock(mLock);

    if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
        findFactoryForScheme(uuid);
        if (mInitCheck != OK) {
            return false;
        }
    }

    if (mimeType != "") {
        return mFactory->isContentTypeSupported(mimeType);
    }

    return true;
}

status_t Drm::createPlugin(const uint8_t uuid[16]) {
    Mutex::Autolock autoLock(mLock);

    if (mPlugin != NULL) {
        return -EINVAL;
    }

    if (!mFactory || !mFactory->isCryptoSchemeSupported(uuid)) {
        findFactoryForScheme(uuid);
    }

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    status_t result = mFactory->createDrmPlugin(uuid, &mPlugin);
    mPlugin->setListener(this);
    return result;
}

status_t Drm::destroyPlugin() {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    delete mPlugin;
    mPlugin = NULL;

    return OK;
}

status_t Drm::openSession(Vector<uint8_t> &sessionId) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    status_t err = mPlugin->openSession(sessionId);
    if (err == ERROR_DRM_RESOURCE_BUSY) {
        bool retry = false;
        mLock.unlock();
        // reclaimSession may call back to closeSession, since mLock is shared between Drm
        // instances, we should unlock here to avoid deadlock.
        retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
        mLock.lock();
        if (mInitCheck != OK) {
            return mInitCheck;
        }

        if (mPlugin == NULL) {
            return -EINVAL;
        }
        if (retry) {
            err = mPlugin->openSession(sessionId);
        }
    }
    if (err == OK) {
        DrmSessionManager::Instance()->addSession(getCallingPid(), mDrmSessionClient, sessionId);
    }
    return err;
}

status_t Drm::closeSession(Vector<uint8_t> const &sessionId) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    status_t err = mPlugin->closeSession(sessionId);
    if (err == OK) {
        DrmSessionManager::Instance()->removeSession(sessionId);
    }
    return err;
}

status_t Drm::getKeyRequest(Vector<uint8_t> const &sessionId,
                            Vector<uint8_t> const &initData,
                            String8 const &mimeType, DrmPlugin::KeyType keyType,
                            KeyedVector<String8, String8> const &optionalParameters,
                            Vector<uint8_t> &request, String8 &defaultUrl,
                            DrmPlugin::KeyRequestType *keyRequestType) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->getKeyRequest(sessionId, initData, mimeType, keyType,
                                  optionalParameters, request, defaultUrl,
                                  keyRequestType);
}

status_t Drm::provideKeyResponse(Vector<uint8_t> const &sessionId,
                                 Vector<uint8_t> const &response,
                                 Vector<uint8_t> &keySetId) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->provideKeyResponse(sessionId, response, keySetId);
}

status_t Drm::removeKeys(Vector<uint8_t> const &keySetId) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->removeKeys(keySetId);
}

status_t Drm::restoreKeys(Vector<uint8_t> const &sessionId,
                          Vector<uint8_t> const &keySetId) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->restoreKeys(sessionId, keySetId);
}

status_t Drm::queryKeyStatus(Vector<uint8_t> const &sessionId,
                             KeyedVector<String8, String8> &infoMap) const {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->queryKeyStatus(sessionId, infoMap);
}

status_t Drm::getProvisionRequest(String8 const &certType, String8 const &certAuthority,
                                  Vector<uint8_t> &request, String8 &defaultUrl) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->getProvisionRequest(certType, certAuthority,
                                        request, defaultUrl);
}

status_t Drm::provideProvisionResponse(Vector<uint8_t> const &response,
                                       Vector<uint8_t> &certificate,
                                       Vector<uint8_t> &wrappedKey) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
}

status_t Drm::unprovisionDevice() {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    if (!checkPermission("android.permission.REMOVE_DRM_CERTIFICATES")) {
        return -EPERM;
    }

    return mPlugin->unprovisionDevice();
}

status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->getSecureStops(secureStops);
}

status_t Drm::getSecureStop(Vector<uint8_t> const &ssid, Vector<uint8_t> &secureStop) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->getSecureStop(ssid, secureStop);
}

status_t Drm::releaseSecureStops(Vector<uint8_t> const &ssRelease) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->releaseSecureStops(ssRelease);
}

status_t Drm::releaseAllSecureStops() {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->releaseAllSecureStops();
}

status_t Drm::getPropertyString(String8 const &name, String8 &value ) const {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->getPropertyString(name, value);
}

status_t Drm::getPropertyByteArray(String8 const &name, Vector<uint8_t> &value ) const {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->getPropertyByteArray(name, value);
}

status_t Drm::setPropertyString(String8 const &name, String8 const &value ) const {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->setPropertyString(name, value);
}

status_t Drm::setPropertyByteArray(String8 const &name,
                                   Vector<uint8_t> const &value ) const {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    return mPlugin->setPropertyByteArray(name, value);
}


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

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->setCipherAlgorithm(sessionId, algorithm);
}

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

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->setMacAlgorithm(sessionId, algorithm);
}

status_t Drm::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 autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->encrypt(sessionId, keyId, input, iv, output);
}

status_t Drm::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 autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->decrypt(sessionId, keyId, input, iv, output);
}

status_t Drm::sign(Vector<uint8_t> const &sessionId,
                   Vector<uint8_t> const &keyId,
                   Vector<uint8_t> const &message,
                   Vector<uint8_t> &signature) {
    Mutex::Autolock autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->sign(sessionId, keyId, message, signature);
}

status_t Drm::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 autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->verify(sessionId, keyId, message, signature, match);
}

status_t Drm::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 autoLock(mLock);

    if (mInitCheck != OK) {
        return mInitCheck;
    }

    if (mPlugin == NULL) {
        return -EINVAL;
    }

    if (!checkPermission("android.permission.ACCESS_DRM_CERTIFICATES")) {
        return -EPERM;
    }

    DrmSessionManager::Instance()->useSession(sessionId);

    return mPlugin->signRSA(sessionId, algorithm, message, wrappedKey, signature);
}

void Drm::binderDied(const wp<IBinder> &the_late_who __unused)
{
    mEventLock.lock();
    mListener.clear();
    mEventLock.unlock();

    Mutex::Autolock autoLock(mLock);
    delete mPlugin;
    mPlugin = NULL;
    closeFactory();
}

void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array)
{
    if (array && array->size()) {
        obj.writeInt32(array->size());
        obj.write(array->array(), array->size());
    } else {
        obj.writeInt32(0);
    }
}

}  // namespace android
