/*
 * Copyright (C) 2018 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.
 */

#ifndef CLEARKEY_DRM_PLUGIN_H_
#define CLEARKEY_DRM_PLUGIN_H_

#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>

#include <map>
#include <stdio.h>

#include <utils/List.h>

#include "DeviceFiles.h"
#include "SessionLibrary.h"
#include "Utils.h"

namespace android {
namespace hardware {
namespace drm {
namespace V1_2 {
namespace clearkey {

namespace drm = ::android::hardware::drm;
using drm::V1_0::EventType;
using drm::V1_0::IDrmPluginListener;
using drm::V1_0::KeyRequestType;
using drm::V1_0::KeyStatus;
using drm::V1_0::KeyType;
using drm::V1_0::KeyValue;
using drm::V1_0::SecureStop;
using drm::V1_0::SecureStopId;
using drm::V1_0::SessionId;
using drm::V1_0::Status;
using drm::V1_1::DrmMetricGroup;
using drm::V1_1::HdcpLevel;
using drm::V1_1::SecureStopRelease;
using drm::V1_1::SecurityLevel;
using drm::V1_2::IDrmPlugin;
using drm::V1_2::KeySetId;
using drm::V1_2::OfflineLicenseState;

using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::sp;

typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1;
typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2;
typedef drm::V1_2::KeyStatus KeyStatus_V1_2;
typedef drm::V1_2::Status Status_V1_2;
typedef drm::V1_2::HdcpLevel HdcpLevel_V1_2;

struct DrmPlugin : public IDrmPlugin {
    explicit DrmPlugin(SessionLibrary* sessionLibrary);

    virtual ~DrmPlugin() { mFileHandle.DeleteAllLicenses(); }

    Return<void> openSession(openSession_cb _hidl_cb) override;
    Return<void> openSession_1_1(SecurityLevel securityLevel,
            openSession_cb _hidl_cb) override;

    Return<Status> closeSession(const hidl_vec<uint8_t>& sessionId) override;

    Return<void> getKeyRequest(
        const hidl_vec<uint8_t>& scope,
        const hidl_vec<uint8_t>& initData,
        const hidl_string& mimeType,
        KeyType keyType,
        const hidl_vec<KeyValue>& optionalParameters,
        getKeyRequest_cb _hidl_cb) override;

    Return<void> getKeyRequest_1_1(
        const hidl_vec<uint8_t>& scope,
        const hidl_vec<uint8_t>& initData,
        const hidl_string& mimeType,
        KeyType keyType,
        const hidl_vec<KeyValue>& optionalParameters,
        getKeyRequest_1_1_cb _hidl_cb) override;

    Return<void> getKeyRequest_1_2(
        const hidl_vec<uint8_t>& scope,
        const hidl_vec<uint8_t>& initData,
        const hidl_string& mimeType,
        KeyType keyType,
        const hidl_vec<KeyValue>& optionalParameters,
        getKeyRequest_1_2_cb _hidl_cb) override;

    Return<void> provideKeyResponse(
        const hidl_vec<uint8_t>& scope,
        const hidl_vec<uint8_t>& response,
        provideKeyResponse_cb _hidl_cb) override;

    Return<Status> removeKeys(const hidl_vec<uint8_t>& sessionId) {
        if (sessionId.size() == 0) {
            return Status::BAD_VALUE;
        }
        return Status::ERROR_DRM_CANNOT_HANDLE;
    }

    Return<Status> restoreKeys(
        const hidl_vec<uint8_t>& sessionId,
        const hidl_vec<uint8_t>& keySetId) override;

    Return<void> queryKeyStatus(
        const hidl_vec<uint8_t>& sessionId,
        queryKeyStatus_cb _hidl_cb) override;

    Return<void> getProvisionRequest(
        const hidl_string& certificateType,
        const hidl_string& certificateAuthority,
        getProvisionRequest_cb _hidl_cb) {
        UNUSED(certificateType);
        UNUSED(certificateAuthority);

        hidl_string defaultUrl;
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
        return Void();
    }

    Return<void> getProvisionRequest_1_2(
        const hidl_string& certificateType,
        const hidl_string& certificateAuthority,
        getProvisionRequest_1_2_cb _hidl_cb) {
        UNUSED(certificateType);
        UNUSED(certificateAuthority);

        hidl_string defaultUrl;
        _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), defaultUrl);
        return Void();
    }

    Return<void> provideProvisionResponse(
        const hidl_vec<uint8_t>& response,
        provideProvisionResponse_cb _hidl_cb) {

        if (response.size() == 0) {
            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
            return Void();
        }
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>(), hidl_vec<uint8_t>());
        return Void();
    }

    Return<void> getHdcpLevels(getHdcpLevels_cb _hidl_cb) {
        HdcpLevel connectedLevel = HdcpLevel::HDCP_NONE;
        HdcpLevel maxLevel = HdcpLevel::HDCP_NO_OUTPUT;
        _hidl_cb(Status::OK, connectedLevel, maxLevel);
        return Void();
    }

    Return<void> getHdcpLevels_1_2(getHdcpLevels_1_2_cb _hidl_cb) {
        HdcpLevel_V1_2 connectedLevel = HdcpLevel_V1_2::HDCP_NONE;
        HdcpLevel_V1_2 maxLevel = HdcpLevel_V1_2::HDCP_NO_OUTPUT;
        _hidl_cb(Status_V1_2::OK, connectedLevel, maxLevel);
        return Void();
    }

    Return<void> getNumberOfSessions(getNumberOfSessions_cb _hidl_cb) override;

    Return<void> getSecurityLevel(const hidl_vec<uint8_t>& sessionId,
            getSecurityLevel_cb _hidl_cb) override;

    Return<void> getMetrics(getMetrics_cb _hidl_cb) override;

    Return<void> getOfflineLicenseKeySetIds(getOfflineLicenseKeySetIds_cb _hidl_cb) override;

    Return<Status> removeOfflineLicense(const KeySetId &keySetId) override;

    Return<void> getOfflineLicenseState(const KeySetId &keySetId,
            getOfflineLicenseState_cb _hidl_cb) override;

    Return<void> getPropertyString(
        const hidl_string& name,
        getPropertyString_cb _hidl_cb) override;

    Return<void> getPropertyByteArray(
        const hidl_string& name,
        getPropertyByteArray_cb _hidl_cb) override;

    Return<Status> setPropertyString(
            const hidl_string& name, const hidl_string& value) override;

    Return<Status> setPropertyByteArray(
            const hidl_string& name, const hidl_vec<uint8_t>& value) override;

    Return<Status> setCipherAlgorithm(
            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
        if (sessionId.size() == 0 || algorithm.size() == 0) {
            return Status::BAD_VALUE;
        }
        return Status::ERROR_DRM_CANNOT_HANDLE;
    }

    Return<Status> setMacAlgorithm(
            const hidl_vec<uint8_t>& sessionId, const hidl_string& algorithm) {
        if (sessionId.size() == 0 || algorithm.size() == 0) {
            return Status::BAD_VALUE;
        }
        return Status::ERROR_DRM_CANNOT_HANDLE;
    }

    Return<void> encrypt(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<uint8_t>& keyId,
            const hidl_vec<uint8_t>& input,
            const hidl_vec<uint8_t>& iv,
            encrypt_cb _hidl_cb) {
        if (sessionId.size() == 0 || keyId.size() == 0 ||
                input.size() == 0 || iv.size() == 0) {
            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
            return Void();
        }
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
        return Void();
    }

    Return<void> decrypt(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<uint8_t>& keyId,
            const hidl_vec<uint8_t>& input,
            const hidl_vec<uint8_t>& iv,
            decrypt_cb _hidl_cb) {
        if (sessionId.size() == 0 || keyId.size() == 0 ||
                input.size() == 0 || iv.size() == 0) {
            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
            return Void();
        }
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
        return Void();
    }

    Return<void> sign(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<uint8_t>& keyId,
            const hidl_vec<uint8_t>& message,
            sign_cb _hidl_cb) {
        if (sessionId.size() == 0 || keyId.size() == 0 ||
                message.size() == 0) {
            _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
            return Void();
        }
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
        return Void();
    }

    Return<void> verify(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<uint8_t>& keyId,
            const hidl_vec<uint8_t>& message,
            const hidl_vec<uint8_t>& signature,
            verify_cb _hidl_cb) {

        if (sessionId.size() == 0 || keyId.size() == 0 ||
                message.size() == 0 || signature.size() == 0) {
            _hidl_cb(Status::BAD_VALUE, false);
            return Void();
        }
        _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, false);
        return Void();
    }

    Return<void> signRSA(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_string& algorithm,
            const hidl_vec<uint8_t>& message,
            const hidl_vec<uint8_t>& wrappedKey,
            signRSA_cb _hidl_cb) {
        if (sessionId.size() == 0 || algorithm.size() == 0 ||
                message.size() == 0 || wrappedKey.size() == 0) {
             _hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>());
             return Void();
         }
         _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, hidl_vec<uint8_t>());
         return Void();
    }

    Return<void> setListener(const sp<IDrmPluginListener>& listener) {
        mListener = listener;
        mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener);
        return Void();
    };

    Return<void> sendEvent(
            EventType eventType,
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<uint8_t>& data) {
        if (mListenerV1_2 != NULL) {
            mListenerV1_2->sendEvent(eventType, sessionId, data);
        } else if (mListener != NULL) {
            mListener->sendEvent(eventType, sessionId, data);
        } else {
            ALOGE("Null event listener, event not sent");
        }
        return Void();
    }

    Return<void> sendExpirationUpdate(
            const hidl_vec<uint8_t>& sessionId,
            int64_t expiryTimeInMS) {
        if (mListenerV1_2 != NULL) {
            mListenerV1_2->sendExpirationUpdate(sessionId, expiryTimeInMS);
        } else if (mListener != NULL) {
            mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
        } else {
            ALOGE("Null event listener, event not sent");
        }
        return Void();
    }

    Return<void> sendKeysChange(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<KeyStatus>& keyStatusList, bool hasNewUsableKey) {
        if (mListenerV1_2 != NULL) {
            mListenerV1_2->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
        } else if (mListener != NULL) {
            mListener->sendKeysChange(sessionId, keyStatusList, hasNewUsableKey);
        } else {
            ALOGE("Null event listener, event not sent");
        }
        return Void();
    }

    Return<void> sendKeysChange_1_2(
            const hidl_vec<uint8_t>& sessionId,
            const hidl_vec<KeyStatus_V1_2>& keyStatusList, bool hasNewUsableKey) {
        if (mListenerV1_2 != NULL) {
            mListenerV1_2->sendKeysChange_1_2(sessionId, keyStatusList, hasNewUsableKey);
        }
        return Void();
    }

    Return<void> sendSessionLostState(
            const hidl_vec<uint8_t>& sessionId) {
        if (mListenerV1_2 != NULL) {
            mListenerV1_2->sendSessionLostState(sessionId);
        }
        return Void();
    }

    Return<void> getSecureStops(getSecureStops_cb _hidl_cb);

    Return<void> getSecureStop(const hidl_vec<uint8_t>& secureStopId,
            getSecureStop_cb _hidl_cb);

    Return<Status> releaseSecureStop(const hidl_vec<uint8_t>& ssRelease);

    Return<Status> releaseAllSecureStops();

    Return<void> getSecureStopIds(getSecureStopIds_cb _hidl_cb);

    Return<Status> releaseSecureStops(const SecureStopRelease& ssRelease);

    Return<Status> removeSecureStop(const hidl_vec<uint8_t>& secureStopId);

    Return<Status> removeAllSecureStops();

private:
    void initProperties();
    void installSecureStop(const hidl_vec<uint8_t>& sessionId);
    bool makeKeySetId(std::string* keySetId);
    void setPlayPolicy();

    Return<Status> setSecurityLevel(const hidl_vec<uint8_t>& sessionId,
            SecurityLevel level);

    Status_V1_2 getKeyRequestCommon(const hidl_vec<uint8_t>& scope,
            const hidl_vec<uint8_t>& initData,
            const hidl_string& mimeType,
            KeyType keyType,
            const hidl_vec<KeyValue>& optionalParameters,
            std::vector<uint8_t> *request,
            KeyRequestType_V1_1 *getKeyRequestType,
            std::string *defaultUrl);

    struct ClearkeySecureStop {
        std::vector<uint8_t> id;
        std::vector<uint8_t> data;
    };

    std::map<std::vector<uint8_t>, ClearkeySecureStop> mSecureStops;
    std::vector<KeyValue> mPlayPolicy;
    std::map<std::string, std::string> mStringProperties;
    std::map<std::string, std::vector<uint8_t> > mByteArrayProperties;
    std::map<std::string, std::vector<uint8_t> > mReleaseKeysMap;
    std::map<std::vector<uint8_t>, SecurityLevel> mSecurityLevel;
    sp<IDrmPluginListener> mListener;
    sp<IDrmPluginListener_V1_2> mListenerV1_2;
    SessionLibrary *mSessionLibrary;
    int64_t mOpenSessionOkCount;
    int64_t mCloseSessionOkCount;
    int64_t mCloseSessionNotOpenedCount;
    uint32_t mNextSecureStopId;

    // set by property to mock error scenarios
    Status_V1_2 mMockError;

    void processMockError(const sp<Session> &session) {
        session->setMockError(mMockError);
        mMockError = Status_V1_2::OK;
    }

    DeviceFiles mFileHandle;

    CLEARKEY_DISALLOW_COPY_AND_ASSIGN_AND_NEW(DrmPlugin);
};

} // namespace clearkey
} // namespace V1_2
} // namespace drm
} // namespace hardware
} // namespace android

#endif // CLEARKEY_DRM_PLUGIN_H_
