blob: f294d4d7363be972b849f619b235a4210ede4aac [file] [log] [blame]
/*
* 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_