From a00b50095c4a0d4da1010bb91702db8faac63f37 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Wed, 12 Dec 2018 08:52:28 -0800 Subject: [PATCH] Add additional error conditions to MediaDrm Merge of http://go/wvgerrit/70163 New codes are being added to handle resource contention, lost session state, frame size too large and insufficient security level for decryption. Also cleans up inconsistent use of tamper detected error where invalid state error should have been used. bug:111504510 bug:111505796 test: cts and gts media tests, widevine integration tests Change-Id: I96ee441717d32ccbcabaa85c8f6a0013055ce16e --- libwvdrmengine/include_hidl/HidlTypes.h | 62 +++++ libwvdrmengine/include_hidl/TypeConvert.h | 9 +- .../include_hidl/WVCreatePluginFactories.h | 6 +- libwvdrmengine/include_hidl/WVCryptoFactory.h | 9 +- libwvdrmengine/include_hidl/WVDrmFactory.h | 10 +- libwvdrmengine/include_hidl/mapErrors-inl.h | 23 +- .../mediacrypto/include_hidl/WVCryptoPlugin.h | 29 +- .../mediacrypto/src_hidl/WVCryptoPlugin.cpp | 94 +++++-- .../mediacrypto/test/WVCryptoPlugin_test.cpp | 16 +- .../mediadrm/include_hidl/WVDrmPlugin.h | 56 ++-- .../mediadrm/src_hidl/WVDrmPlugin.cpp | 250 +++++++++++++----- .../mediadrm/test/WVDrmPlugin_test.cpp | 13 +- libwvdrmengine/src_hidl/WVCryptoFactory.cpp | 5 +- libwvdrmengine/src_hidl/WVDrmFactory.cpp | 6 +- libwvdrmengine/src_hidl/service.cpp | 12 +- .../test/unit/WVDrmFactory_test.cpp | 7 +- 16 files changed, 390 insertions(+), 217 deletions(-) create mode 100644 libwvdrmengine/include_hidl/HidlTypes.h diff --git a/libwvdrmengine/include_hidl/HidlTypes.h b/libwvdrmengine/include_hidl/HidlTypes.h new file mode 100644 index 00000000..1802d0cb --- /dev/null +++ b/libwvdrmengine/include_hidl/HidlTypes.h @@ -0,0 +1,62 @@ +// +// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary +// source code may only be used and distributed under the Widevine Master +// License Agreement. +// + +#ifndef HIDL_TYPES_H_ +#define HIDL_TYPES_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +using ::android::hardware::configureRpcThreadpool; +using ::android::hardware::hidl_array; +using ::android::hardware::hidl_handle; +using ::android::hardware::hidl_memory; +using ::android::hardware::hidl_string; +using ::android::hardware::hidl_vec; +using ::android::hardware::joinRpcThreadpool; +using ::android::hardware::Return; +using ::android::hardware::Void; +using ::android::sp; + +namespace drm = ::android::hardware::drm; +using drm::V1_0::BufferType; +using drm::V1_0::DestinationBuffer; +using drm::V1_0::EventType; +using drm::V1_0::IDrmPluginListener; +using drm::V1_0::KeyRequestType; +using drm::V1_0::KeyStatus; +using drm::V1_0::KeyStatusType; +using drm::V1_0::KeyType; +using drm::V1_0::KeyValue; +using drm::V1_0::Mode; +using drm::V1_0::Pattern; +using drm::V1_0::SecureStop; +using drm::V1_0::SecureStopId; +using drm::V1_0::SharedBuffer; +using drm::V1_0::Status; +using drm::V1_0::SubSample; +using drm::V1_1::DrmMetricGroup; +using drm::V1_1::HdcpLevel; +using drm::V1_1::SecureStopRelease; +using drm::V1_1::SecurityLevel; +using drm::V1_2::ICryptoFactory; +using drm::V1_2::ICryptoPlugin; +using drm::V1_2::IDrmFactory; +using drm::V1_2::IDrmPlugin; +using drm::V1_2::KeySetId; +using drm::V1_2::OfflineLicenseState; + +typedef drm::V1_1::KeyRequestType KeyRequestType_V1_1; +typedef drm::V1_2::IDrmPluginListener IDrmPluginListener_V1_2; +typedef drm::V1_2::Status Status_V1_2; + +#endif diff --git a/libwvdrmengine/include_hidl/TypeConvert.h b/libwvdrmengine/include_hidl/TypeConvert.h index d251d0b8..f5c8b25b 100644 --- a/libwvdrmengine/include_hidl/TypeConvert.h +++ b/libwvdrmengine/include_hidl/TypeConvert.h @@ -16,12 +16,12 @@ #ifndef WVDRM_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT #define WVDRM_ANDROID_HARDWARE_DRM_V1_1_TYPECONVERT -#include "utils/Errors.h" #include -#include -#include +#include "media/stagefright/MediaErrors.h" +#include "HidlTypes.h" +#include "utils/Errors.h" namespace android { namespace hardware { @@ -29,9 +29,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_vec; - template const hidl_vec toHidlVec(const std::vector &vec) { hidl_vec hVec; hVec.setToExternal(const_cast(vec.data()), vec.size()); diff --git a/libwvdrmengine/include_hidl/WVCreatePluginFactories.h b/libwvdrmengine/include_hidl/WVCreatePluginFactories.h index f41076bd..d177da8f 100644 --- a/libwvdrmengine/include_hidl/WVCreatePluginFactories.h +++ b/libwvdrmengine/include_hidl/WVCreatePluginFactories.h @@ -7,8 +7,7 @@ #ifndef WV_CREATE_PLUGIN_FACTORIES_H_ #define WV_CREATE_PLUGIN_FACTORIES_H_ -#include -#include +#include "HidlTypes.h" namespace wvdrm { namespace hardware { @@ -16,9 +15,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_1::ICryptoFactory; -using ::android::hardware::drm::V1_1::IDrmFactory; - extern "C" { IDrmFactory* createDrmFactory(); ICryptoFactory* createCryptoFactory(); diff --git a/libwvdrmengine/include_hidl/WVCryptoFactory.h b/libwvdrmengine/include_hidl/WVCryptoFactory.h index 057a417d..7197fdd6 100644 --- a/libwvdrmengine/include_hidl/WVCryptoFactory.h +++ b/libwvdrmengine/include_hidl/WVCryptoFactory.h @@ -7,8 +7,7 @@ #ifndef WV_CRYPTO_FACTORY_H_ #define WV_CRYPTO_FACTORY_H_ -#include - +#include "HidlTypes.h" #include "WVTypes.h" namespace wvdrm { @@ -17,12 +16,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_1::ICryptoFactory; -using ::android::hardware::drm::V1_0::ICryptoPlugin; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; - struct WVCryptoFactory : public ICryptoFactory { public: WVCryptoFactory() {} diff --git a/libwvdrmengine/include_hidl/WVDrmFactory.h b/libwvdrmengine/include_hidl/WVDrmFactory.h index 1a10ff7b..89663b25 100644 --- a/libwvdrmengine/include_hidl/WVDrmFactory.h +++ b/libwvdrmengine/include_hidl/WVDrmFactory.h @@ -7,9 +7,7 @@ #ifndef WV_DRM_FACTORY_H_ #define WV_DRM_FACTORY_H_ -#include -#include - +#include "HidlTypes.h" #include "WVGenericCryptoInterface.h" #include "WVTypes.h" @@ -19,12 +17,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_1::IDrmFactory; -using ::android::hardware::drm::V1_2::IDrmPlugin; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_string; -using ::android::hardware::Return; - struct WVDrmFactory : public IDrmFactory { WVDrmFactory() {} virtual ~WVDrmFactory() {} diff --git a/libwvdrmengine/include_hidl/mapErrors-inl.h b/libwvdrmengine/include_hidl/mapErrors-inl.h index e95a3b87..7e1bd855 100644 --- a/libwvdrmengine/include_hidl/mapErrors-inl.h +++ b/libwvdrmengine/include_hidl/mapErrors-inl.h @@ -10,12 +10,11 @@ #include "media/stagefright/MediaErrors.h" #include "utils/Errors.h" #include "wv_cdm_types.h" +#include "HidlTypes.h" #include "WVErrors.h" namespace wvdrm { -using ::android::hardware::drm::V1_0::Status; - static Status mapCdmResponseType(wvcdm::CdmResponseType res) { switch (res) { case wvcdm::KEY_ADDED: @@ -321,6 +320,26 @@ static Status mapCdmResponseType(wvcdm::CdmResponseType res) { return Status::ERROR_DRM_UNKNOWN; } +static Status_V1_2 mapCdmResponseType_1_2( + wvcdm::CdmResponseType res) { + switch(res) { + case wvcdm::KEY_PROHIBITED_FOR_SECURITY_LEVEL: + return Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY; + +// TODO(b/120572706): define in CDM +// case wvcdm::xxx: +// return Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE; +// case wvcdm::xxx: +// return Status_V1_2::ERROR_DRM_SESSION_LOST_STATE; +// case wvcdm::xxx: +// return Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION; + + default: + return static_cast(mapCdmResponseType(res)); + } +} + + static inline bool isCdmResponseTypeSuccess(wvcdm::CdmResponseType res) { return mapCdmResponseType(res) == Status::OK; } diff --git a/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h b/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h index 3e84fc1c..c020bc7e 100644 --- a/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h +++ b/libwvdrmengine/mediacrypto/include_hidl/WVCryptoPlugin.h @@ -7,9 +7,9 @@ #ifndef WV_CRYPTO_PLUGIN_H_ #define WV_CRYPTO_PLUGIN_H_ -#include #include +#include "HidlTypes.h" #include "wv_content_decryption_module.h" #include "WVTypes.h" @@ -19,20 +19,7 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::DestinationBuffer; -using ::android::hardware::drm::V1_0::ICryptoPlugin; -using ::android::hardware::drm::V1_0::Mode; -using ::android::hardware::drm::V1_0::Pattern; -using ::android::hardware::drm::V1_0::SharedBuffer; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_0::SubSample; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::hidl_memory; using ::android::hidl::memory::V1_0::IMemory; -using ::android::sp; struct WVCryptoPlugin : public ICryptoPlugin { WVCryptoPlugin(const void* data, size_t size, @@ -62,6 +49,18 @@ struct WVCryptoPlugin : public ICryptoPlugin { const DestinationBuffer& destination, decrypt_cb _hidl_cb) override; + Return decrypt_1_2( + bool secure, + const hidl_array& keyId, + const hidl_array& iv, + Mode mode, + const Pattern& pattern, + const hidl_vec& subSamples, + const SharedBuffer& source, + uint64_t offset, + const DestinationBuffer& destination, + decrypt_1_2_cb _hidl_cb) override; + private: WVDRM_DISALLOW_COPY_AND_ASSIGN_AND_NEW(WVCryptoPlugin); @@ -70,7 +69,7 @@ struct WVCryptoPlugin : public ICryptoPlugin { sp const mCDM; - Status attemptDecrypt( + Status_V1_2 attemptDecrypt( const wvcdm::CdmDecryptionParameters& params, bool haveEncryptedSubsamples, std::string* errorDetailMsg); static wvcdm::CdmResponseType countEncryptedBlocksInPatternedRange( diff --git a/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp index b557e52e..8ccb3da5 100644 --- a/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp +++ b/libwvdrmengine/mediacrypto/src_hidl/WVCryptoPlugin.cpp @@ -9,13 +9,14 @@ #include #include "WVCryptoPlugin.h" -#include "TypeConvert.h" #include +#include "HidlTypes.h" #include "mapErrors-inl.h" #include "OEMCryptoCENC.h" #include "openssl/sha.h" +#include "TypeConvert.h" #include "wv_cdm_constants.h" #include "WVErrors.h" @@ -23,6 +24,17 @@ namespace { static const size_t kAESBlockSize = 16; +inline Status toStatus_1_0(Status_V1_2 status) { + switch (status) { + case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: + case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: + case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: + return Status::ERROR_DRM_UNKNOWN; + default: + return static_cast(status); + } +} + } // namespace namespace wvdrm { @@ -31,10 +43,7 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::BufferType; -using ::android::hardware::drm::V1_2::widevine::toVector; -using ::android::hardware::Void; - +using android::hardware::drm::V1_2::widevine::toVector; using wvcdm::CdmDecryptionParameters; using wvcdm::CdmQueryMap; using wvcdm::CdmResponseType; @@ -116,8 +125,40 @@ Return WVCryptoPlugin::decrypt( const DestinationBuffer& destination, decrypt_cb _hidl_cb) { + Status status = Status::ERROR_DRM_UNKNOWN; + hidl_string detailedError; + uint32_t bytesWritten = 0; + + Return hResult = decrypt_1_2( + secure, keyId, iv, mode, pattern, subSamples, source, offset, destination, + [&](Status_V1_2 hStatus, uint32_t hBytesWritten, hidl_string hDetailedError) { + status = toStatus_1_0(hStatus); + if (status == Status::OK) { + bytesWritten = hBytesWritten; + detailedError = hDetailedError; + } + } + ); + + status = hResult.isOk() ? status : Status::ERROR_DRM_CANNOT_HANDLE; + _hidl_cb(status, bytesWritten, detailedError); + return Void(); +} + +Return WVCryptoPlugin::decrypt_1_2( + bool secure, + const hidl_array& keyId, + const hidl_array& iv, + Mode mode, + const Pattern& pattern, + const hidl_vec& subSamples, + const SharedBuffer& source, + uint64_t offset, + const DestinationBuffer& destination, + decrypt_1_2_cb _hidl_cb) { + if (mSharedBufferMap.find(source.bufferId) == mSharedBufferMap.end()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source decrypt buffer base not set"); return Void(); } @@ -125,7 +166,7 @@ Return WVCryptoPlugin::decrypt( if (destination.type == BufferType::SHARED_MEMORY) { const SharedBuffer& dest = destination.nonsecureMemory; if (mSharedBufferMap.find(dest.bufferId) == mSharedBufferMap.end()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination decrypt buffer base not set"); return Void(); } @@ -134,7 +175,7 @@ Return WVCryptoPlugin::decrypt( if (mode != Mode::UNENCRYPTED && mode != Mode::AES_CTR && mode != Mode::AES_CBC) { - _hidl_cb(Status::BAD_VALUE, + _hidl_cb(Status_V1_2::BAD_VALUE, 0, "Encryption mode is not supported by Widevine CDM."); return Void(); } @@ -147,12 +188,12 @@ Return WVCryptoPlugin::decrypt( std::string errorDetailMsg; sp sourceBase = mSharedBufferMap[source.bufferId]; if (sourceBase == nullptr) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr"); return Void(); } if (source.offset + offset + source.size > sourceBase->getSize()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } @@ -164,12 +205,12 @@ Return WVCryptoPlugin::decrypt( const SharedBuffer& destBuffer = destination.nonsecureMemory; sp destBase = mSharedBufferMap[destBuffer.bufferId]; if (destBase == nullptr) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr"); return Void(); } if (destBuffer.offset + destBuffer.size > destBase->getSize()) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size"); return Void(); } destPtr = static_cast(base + destination.nonsecureMemory.offset); @@ -218,7 +259,7 @@ Return WVCryptoPlugin::decrypt( const SubSample& subSample = subSamples[i]; if (mode == Mode::UNENCRYPTED && subSample.numBytesOfEncryptedData != 0) { - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Encrypted subsamples found in allegedly unencrypted data."); return Void(); } @@ -256,9 +297,9 @@ Return WVCryptoPlugin::decrypt( params.decrypt_buffer_offset = bufferOffset; params.subsample_flags = clearFlags; - Status res = attemptDecrypt(params, haveEncryptedSubsamples, - &errorDetailMsg); - if (res != Status::OK) { + Status_V1_2 res = attemptDecrypt(params, haveEncryptedSubsamples, + &errorDetailMsg); + if (res != Status_V1_2::OK) { _hidl_cb(res, 0, errorDetailMsg.c_str()); return Void(); } @@ -275,9 +316,9 @@ Return WVCryptoPlugin::decrypt( params.decrypt_buffer_offset = bufferOffset; params.subsample_flags = encryptedFlags; - Status res = attemptDecrypt(params, haveEncryptedSubsamples, - &errorDetailMsg); - if (res != Status::OK) { + Status_V1_2 res = attemptDecrypt(params, haveEncryptedSubsamples, + &errorDetailMsg); + if (res != Status_V1_2::OK) { _hidl_cb(res, 0, errorDetailMsg.c_str()); return Void(); } @@ -301,7 +342,7 @@ Return WVCryptoPlugin::decrypt( subSample.numBytesOfEncryptedData, pattern, &increment); if (!isCdmResponseTypeSuccess(countRes)) { // Swallow the specifics of the error to obscure decrypt internals. - _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, + _hidl_cb(Status_V1_2::ERROR_DRM_CANNOT_HANDLE, 0, "Error decrypting data: unknown error"); return Void(); } @@ -325,18 +366,17 @@ Return WVCryptoPlugin::decrypt( } } - _hidl_cb(Status::OK, bufferOffset, errorDetailMsg.c_str()); + _hidl_cb(Status_V1_2::OK, bufferOffset, errorDetailMsg.c_str()); return Void(); } -Status WVCryptoPlugin::attemptDecrypt(const CdmDecryptionParameters& params, - bool haveEncryptedSubsamples, - std::string* errorDetailMsg) { +Status_V1_2 WVCryptoPlugin::attemptDecrypt(const CdmDecryptionParameters& params, + bool haveEncryptedSubsamples, std::string* errorDetailMsg) { CdmResponseType res = mCDM->Decrypt(mSessionId, haveEncryptedSubsamples, params); if (isCdmResponseTypeSuccess(res)) { - return Status::OK; + return Status_V1_2::OK; } else { ALOGE("Decrypt error result in session %s during %s block: %d", mSessionId.c_str(), @@ -381,10 +421,10 @@ Status WVCryptoPlugin::attemptDecrypt(const CdmDecryptionParameters& params, if (actionableError) { // This error is actionable by the app and should be passed up. - return mapCdmResponseType(res); + return mapCdmResponseType_1_2(res); } else { // Swallow the specifics of other errors to obscure decrypt internals. - return Status::ERROR_DRM_UNKNOWN; + return Status_V1_2::ERROR_DRM_UNKNOWN; } } } diff --git a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp index 0d07c479..577de852 100644 --- a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp +++ b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp @@ -22,6 +22,7 @@ #include "wv_cdm_constants.h" #include "wv_cdm_types.h" #include "wv_content_decryption_module.h" +#include "HidlTypes.h" #include "OEMCryptoCENC.h" #include "TypeConvert.h" #include "WVCryptoPlugin.h" @@ -32,22 +33,7 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::BufferType; -using ::android::hardware::drm::V1_0::DestinationBuffer; -using ::android::hardware::drm::V1_0::Mode; -using ::android::hardware::drm::V1_0::Pattern; -using ::android::hardware::drm::V1_0::SharedBuffer; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_0::SubSample; -using ::android::hardware::drm::V1_2::widevine::toHidlVec; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_handle; -using ::android::hardware::hidl_memory; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Void; using ::android::MemoryDealer; -using ::android::sp; using ::testing::_; using ::testing::DefaultValue; diff --git a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h index 2c1910ac..e465b731 100644 --- a/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h +++ b/libwvdrmengine/mediadrm/include_hidl/WVDrmPlugin.h @@ -9,15 +9,12 @@ #include -#include -#include -#include - #include "cdm_client_property_set.h" #include "cdm_identifier.h" -#include "OEMCryptoCENC.h" #include "wv_cdm_event_listener.h" #include "wv_content_decryption_module.h" +#include "OEMCryptoCENC.h" +#include "HidlTypes.h" #include "WVGenericCryptoInterface.h" #include "WVTypes.h" @@ -27,29 +24,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::IDrmPluginListener; -using ::android::hardware::drm::V1_0::KeyRequestType; -using ::android::hardware::drm::V1_0::KeyStatus; -using ::android::hardware::drm::V1_0::KeyType; -using ::android::hardware::drm::V1_0::KeyValue; -using ::android::hardware::drm::V1_0::SecureStop; -using ::android::hardware::drm::V1_0::SecureStopId; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_1::DrmMetricGroup; -using ::android::hardware::drm::V1_1::HdcpLevel; -using ::android::hardware::drm::V1_1::SecureStopRelease; -using ::android::hardware::drm::V1_1::SecurityLevel; -using ::android::hardware::drm::V1_2::IDrmPlugin; -using ::android::hardware::drm::V1_2::KeySetId; -using ::android::hardware::drm::V1_2::OfflineLicenseState; -using ::android::hardware::hidl_array; -using ::android::hardware::hidl_string; -using ::android::hardware::hidl_vec; -using ::android::hardware::Return; -using ::android::hardware::Void; -using ::android::sp; - using std::map; using wvcdm::CdmIdentifier; using wvcdm::CdmKeyStatusMap; @@ -92,6 +66,14 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, const hidl_vec& optionalParameters, getKeyRequest_1_1_cb _hidl_cb) override; + Return getKeyRequest_1_2( + const hidl_vec& scope, + const hidl_vec& initData, + const hidl_string& mimeType, + KeyType keyType, + const hidl_vec& optionalParameters, + getKeyRequest_1_2_cb _hidl_cb) override; + Return provideKeyResponse( const hidl_vec& scope, const hidl_vec& response, @@ -112,6 +94,11 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, const hidl_string& certificateAuthority, getProvisionRequest_cb _hidl_cb) override; + Return getProvisionRequest_1_2( + const hidl_string& certificateType, + const hidl_string& certificateAuthority, + getProvisionRequest_1_2_cb _hidl_cb) override; + Return provideProvisionResponse( const hidl_vec& response, provideProvisionResponse_cb _hidl_cb) override; @@ -224,6 +211,9 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, const hidl_vec& keyStatusList, bool hasNewUsableKey) override; + Return sendSessionLostState( + const hidl_vec& sessionId) override; + // The following methods do not use hidl interface, it is used internally. virtual Status unprovisionDevice(); @@ -238,6 +228,9 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, const CdmSessionId& cdmSessionId, int64_t newExpiryTimeSeconds); + virtual void OnSessionLostState( + const CdmSessionId& cdmSessionId); + private: WVDRM_DISALLOW_COPY_AND_ASSIGN_AND_NEW(WVDrmPlugin); @@ -408,6 +401,7 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, WVGenericCryptoInterface* mCrypto; map mCryptoSessions; sp mListener; + sp mListenerV1_2; std::string mProvisioningServiceCertificate; @@ -426,6 +420,12 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener, Status mapAndNotifyOfCdmResponseType(const std::vector& sessionId, CdmResponseType res); + Status_V1_2 mapAndNotifyOfCdmResponseType_1_2(const std::vector& sessionId, + CdmResponseType res); + + void notifyOfCdmResponseType(const std::vector& sessionId, + CdmResponseType res); + Status mapAndNotifyOfOEMCryptoResult(const std::vector& sessionId, OEMCryptoResult res); diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index a24816d6..1b1cea13 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -12,7 +12,6 @@ #include #include "WVDrmPlugin.h" -#include "TypeConvert.h" #include "android-base/macros.h" #include "hidl_metrics_adapter.h" @@ -21,6 +20,8 @@ #include "metrics.pb.h" #include "openssl/sha.h" #include "wv_cdm_constants.h" +#include "TypeConvert.h" +#include "HidlTypes.h" namespace { @@ -38,17 +39,8 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::KeyRequestType; -using ::android::hardware::drm::V1_0::KeyStatusType; -using ::android::hardware::drm::V1_0::KeyType; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_1::DrmMetricGroup; -using ::android::hardware::drm::V1_1::SecurityLevel; -using ::android::hardware::drm::V1_2::widevine::toHidlVec; -using ::android::hardware::drm::V1_2::widevine::toVector; -using ::android::hardware::Void; - +using android::hardware::drm::V1_2::widevine::toHidlVec; +using android::hardware::drm::V1_2::widevine::toVector; using wvcdm::kDefaultCdmIdentifier; using wvcdm::CdmAppParameterMap; using wvcdm::CdmCertificateType; @@ -88,6 +80,42 @@ KeyRequestType ConvertFromCdmKeyRequestType( } } +KeyRequestType_V1_1 ConvertFromCdmKeyRequestType_1_1( + CdmKeyRequestType keyRequestType) { + /* TODO - What happened to these? + switch (keyRequestType) { + case wvcdm::kKeyRequestTypeNone: + return KeyRequestType_V1_1::NONE; + case wvcdm::kKeyRequestTypeUpdate: + return KeyRequestType_V1_1::UPDATE; + default: + */ + return static_cast( + ConvertFromCdmKeyRequestType(keyRequestType)); +} + +KeyRequestType toKeyRequestType_V1_0(KeyRequestType_V1_1 keyRequestType) { + switch (keyRequestType) { + case KeyRequestType_V1_1::NONE: + case KeyRequestType_V1_1::UPDATE: + return KeyRequestType::UNKNOWN; + default: + return static_cast(keyRequestType); + } +} + +Status toStatus_1_0(Status_V1_2 status) { + switch (status) { + case Status_V1_2::ERROR_DRM_INSUFFICIENT_SECURITY: + case Status_V1_2::ERROR_DRM_FRAME_TOO_LARGE: + case Status_V1_2::ERROR_DRM_SESSION_LOST_STATE: + case Status_V1_2::ERROR_DRM_RESOURCE_CONTENTION: + return Status::ERROR_DRM_UNKNOWN; + default: + return static_cast(status); + } +} + KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) { switch (keyStatus) { case wvcdm::kKeyStatusUsable: @@ -281,10 +309,8 @@ Return WVDrmPlugin::openSession_1_1( }); if (!hResult.isOk()) { status = Status::ERROR_DRM_INVALID_STATE; - ALOGE("openSession_1_1 fails communication with the remote HAL"); } } - _hidl_cb(status, toHidlVec(sessionId)); return Void(); } @@ -310,21 +336,80 @@ Return WVDrmPlugin::getKeyRequest( KeyType keyType, const hidl_vec& optionalParameters, getKeyRequest_cb _hidl_cb) { + hidl_string defaultUrl; + hidl_vec request; + KeyRequestType requestType = KeyRequestType::UNKNOWN; + Status status = Status::ERROR_DRM_UNKNOWN; + + defaultUrl.clear(); + Return hResult = getKeyRequest_1_1( + scope, initData, mimeType, keyType, optionalParameters, + [&](Status statusCode, const hidl_vec& hRequest, + KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { + defaultUrl = hDefaultUrl; + request = hRequest; + requestType = toKeyRequestType_V1_0(hKeyRequestType); + status = statusCode; + }); + if (!hResult.isOk()) { + status = Status::ERROR_DRM_INVALID_STATE; + } + _hidl_cb(status, request, requestType, defaultUrl); + return Void(); +} + +Return WVDrmPlugin::getKeyRequest_1_1( + const hidl_vec& scope, + const hidl_vec& initData, + const hidl_string& mimeType, + KeyType keyType, + const hidl_vec& optionalParameters, + getKeyRequest_1_1_cb _hidl_cb) { + hidl_string defaultUrl; + hidl_vec request; + KeyRequestType_V1_1 requestType = KeyRequestType_V1_1::UNKNOWN; + Status status = Status::ERROR_DRM_UNKNOWN; + + defaultUrl.clear(); + Return hResult = getKeyRequest_1_2( + scope, initData, mimeType, keyType, optionalParameters, + [&](Status_V1_2 statusCode, const hidl_vec& hRequest, + KeyRequestType_V1_1 hKeyRequestType, const hidl_string& hDefaultUrl) { + defaultUrl = hDefaultUrl; + request = hRequest; + requestType = hKeyRequestType; + status = toStatus_1_0(statusCode); + }); + if (!hResult.isOk()) { + status = Status::ERROR_DRM_INVALID_STATE; + } + _hidl_cb(status, request, requestType, defaultUrl); + return Void(); +} + +Return WVDrmPlugin::getKeyRequest_1_2( + const hidl_vec& scope, + const hidl_vec& initData, + const hidl_string& mimeType, + KeyType keyType, + const hidl_vec& optionalParameters, + getKeyRequest_1_2_cb _hidl_cb) { if (!scope.size()) { - _hidl_cb(Status::BAD_VALUE, hidl_vec(), - KeyRequestType::UNKNOWN, ""); + _hidl_cb(Status_V1_2::BAD_VALUE, hidl_vec(), + KeyRequestType_V1_1::UNKNOWN, ""); return Void(); } - KeyRequestType requestType = KeyRequestType::UNKNOWN; - Status status = Status::OK; + KeyRequestType_V1_1 requestType = KeyRequestType_V1_1::UNKNOWN; + Status_V1_2 status = Status_V1_2::OK; std::string defaultUrl; std::vector request; const std::vector scopeId = toVector(scope); CdmIdentifier identifier; - status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier); - if (status != Status::OK) { + status = static_cast( + mCdmIdentifierBuilder.getCdmIdentifier(&identifier)); + if (status != Status_V1_2::OK) { _hidl_cb(status, toHidlVec(request), requestType, defaultUrl.c_str()); return Void(); @@ -343,7 +428,7 @@ Return WVDrmPlugin::getKeyRequest( cdmLicenseType = wvcdm::kLicenseTypeRelease; cdmKeySetId.assign(scopeId.begin(), scopeId.end()); } else { - _hidl_cb(Status::BAD_VALUE, toHidlVec(request), KeyRequestType::UNKNOWN, + _hidl_cb(Status_V1_2::BAD_VALUE, toHidlVec(request), KeyRequestType_V1_1::UNKNOWN, defaultUrl.c_str()); return Void(); } @@ -404,7 +489,7 @@ Return WVDrmPlugin::getKeyRequest( cdmSessionId, cdmKeySetId, cdmInitDataType, processedInitData, cdmLicenseType, cdmParameters, &mPropertySet, identifier, &keyRequest); - requestType = ConvertFromCdmKeyRequestType(keyRequest.type); + requestType = ConvertFromCdmKeyRequestType_1_1(keyRequest.type); if (isCdmResponseTypeSuccess(res)) { defaultUrl.clear(); @@ -415,48 +500,16 @@ Return WVDrmPlugin::getKeyRequest( if (keyType == KeyType::RELEASE) { // When releasing keys, we do not have a session ID. - status = mapCdmResponseType(res); + status = mapCdmResponseType_1_2(res); } else { // For all other requests, we have a session ID. - status = mapAndNotifyOfCdmResponseType(scopeId, res); + status = mapAndNotifyOfCdmResponseType_1_2(scopeId, res); } _hidl_cb(status, toHidlVec(request), requestType, defaultUrl.c_str()); return Void(); } -Return WVDrmPlugin::getKeyRequest_1_1( - const hidl_vec& scope, - const hidl_vec& initData, - const hidl_string& mimeType, - KeyType keyType, - const hidl_vec& optionalParameters, - getKeyRequest_1_1_cb _hidl_cb) { - hidl_string defaultUrl; - hidl_vec request; - ::android::hardware::drm::V1_1::KeyRequestType requestType = - static_cast<::android::hardware::drm::V1_1::KeyRequestType>(KeyRequestType::UNKNOWN); - Status status = Status::ERROR_DRM_UNKNOWN; - - defaultUrl.clear(); - Return hResult = getKeyRequest(scope, initData, mimeType, keyType, optionalParameters, - [&](Status statusCode, const hidl_vec& hRequest, - KeyRequestType hKeyRequestType, - const hidl_string& hDefaultUrl) { - defaultUrl = hDefaultUrl; - request = hRequest; - requestType = static_cast<::android::hardware::drm::V1_1::KeyRequestType>(hKeyRequestType); - status = statusCode; - }); - if (!hResult.isOk()) { - status = Status::ERROR_DRM_INVALID_STATE; - ALOGE("getKeyRequest_1_1 fails communication with the remote HAL"); - } - - _hidl_cb(status, request, requestType, defaultUrl); - return Void(); -} - Return WVDrmPlugin::provideKeyResponse( const hidl_vec& scope, const hidl_vec& response, @@ -575,7 +628,7 @@ Return WVDrmPlugin::restoreKeys(const hidl_vec& sessionId, return Void(); } - Return WVDrmPlugin::getProvisionRequest( +Return WVDrmPlugin::getProvisionRequest( const hidl_string& certificateType, const hidl_string& certificateAuthority, getProvisionRequest_cb _hidl_cb) { @@ -583,9 +636,33 @@ Return WVDrmPlugin::restoreKeys(const hidl_vec& sessionId, std::string defaultUrl; std::vector request; + Return hResult = getProvisionRequest_1_2( + certificateType, certificateAuthority, + [&](Status_V1_2 statusCode, const hidl_vec& hRequest, + const hidl_string& hDefaultUrl) { + request = hRequest; + status = toStatus_1_0(statusCode); + defaultUrl = hDefaultUrl; + }); + if (!hResult.isOk()) { + status = Status::ERROR_DRM_INVALID_STATE; + } + + _hidl_cb(status, toHidlVec(request), hidl_string(defaultUrl)); + return Void(); +} + +Return WVDrmPlugin::getProvisionRequest_1_2( + const hidl_string& certificateType, + const hidl_string& certificateAuthority, + getProvisionRequest_1_2_cb _hidl_cb) { + Status_V1_2 status = Status_V1_2::OK; + std::string defaultUrl; + std::vector request; + CdmIdentifier identifier; - status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier); - if (status != Status::OK) { + status = static_cast(mCdmIdentifierBuilder.getCdmIdentifier(&identifier)); + if (status != Status_V1_2::OK) { _hidl_cb(status, toHidlVec(request), hidl_string(defaultUrl)); return Void(); } @@ -609,7 +686,7 @@ Return WVDrmPlugin::restoreKeys(const hidl_vec& sessionId, defaultUrl.assign(cdmDefaultUrl.data(), cdmDefaultUrl.size()); } - _hidl_cb(mapCdmResponseType(res), toHidlVec(request), + _hidl_cb(mapCdmResponseType_1_2(res), toHidlVec(request), hidl_string(defaultUrl)); return Void(); } @@ -1542,13 +1619,17 @@ Return WVDrmPlugin::signRSA( Return WVDrmPlugin::setListener(const sp& listener) { mListener = listener; + mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener); return Void(); } Return WVDrmPlugin::sendEvent( EventType eventType, - const hidl_vec& sessionId, const hidl_vec& data) { - if (mListener != NULL) { + const hidl_vec& sessionId, + const hidl_vec& 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"); @@ -1557,10 +1638,12 @@ Return WVDrmPlugin::sendEvent( } Return WVDrmPlugin::sendExpirationUpdate( - const hidl_vec& sessionId, - int64_t expiryTimeInMS) { - if (mListener != NULL) { - mListener->sendExpirationUpdate(sessionId, expiryTimeInMS); + const hidl_vec& 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"); } @@ -1570,8 +1653,20 @@ Return WVDrmPlugin::sendExpirationUpdate( Return WVDrmPlugin::sendKeysChange( const hidl_vec& sessionId, const hidl_vec& keyStatusList, bool hasNewUsableKey) { - if (mListener != NULL) { - mListener->sendKeysChange(sessionId, keyStatusList, 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 WVDrmPlugin::sendSessionLostState( + const hidl_vec& sessionId) { + if (mListenerV1_2 != NULL) { + mListenerV1_2->sendSessionLostState(sessionId); } else { ALOGE("Null event listener, event not sent"); } @@ -1622,6 +1717,11 @@ void WVDrmPlugin::OnExpirationUpdate(const CdmSessionId& cdmSessionId, sendExpirationUpdate(toHidlVec(sessionId), newExpiryTimeMilliseconds); } +void WVDrmPlugin::OnSessionLostState(const CdmSessionId& cdmSessionId) { + const std::vector sessionId = StrToVector(cdmSessionId); + sendSessionLostState(toHidlVec(sessionId)); +} + Status WVDrmPlugin::queryProperty(const std::string& property, std::string& stringValue) const { wvcdm::SecurityLevel securityLevel = @@ -1654,6 +1754,18 @@ Status WVDrmPlugin::queryProperty(const std::string& property, } Status WVDrmPlugin::mapAndNotifyOfCdmResponseType( + const std::vector& sessionId, CdmResponseType res) { + notifyOfCdmResponseType(sessionId, res); + return mapCdmResponseType(res); +} + +Status_V1_2 WVDrmPlugin::mapAndNotifyOfCdmResponseType_1_2( + const std::vector& sessionId, CdmResponseType res) { + notifyOfCdmResponseType(sessionId, res); + return mapCdmResponseType_1_2(res); +} + +void WVDrmPlugin::notifyOfCdmResponseType( const std::vector& sessionId, CdmResponseType res) { @@ -1663,8 +1775,6 @@ Status WVDrmPlugin::mapAndNotifyOfCdmResponseType( } else if (res == wvcdm::NEED_KEY) { sendEvent(EventType::KEY_NEEDED, toHidlVec(sessionId), data); } - - return mapCdmResponseType(res); } Status WVDrmPlugin::mapAndNotifyOfOEMCryptoResult( diff --git a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp index d4fc8e6c..2967f715 100644 --- a/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp +++ b/libwvdrmengine/mediadrm/test/WVDrmPlugin_test.cpp @@ -7,10 +7,6 @@ #define LOG_TAG "WVDrmPluginTest" #include -#include -#include -#include - #include #include #include @@ -26,6 +22,7 @@ #include "wv_cdm_constants.h" #include "wv_cdm_types.h" #include "wv_content_decryption_module.h" +#include "HidlTypes.h" #include "TypeConvert.h" #include "WVDrmPlugin.h" #include "WVErrors.h" @@ -36,13 +33,7 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::EventType; -using ::android::hardware::drm::V1_0::KeyStatus; -using ::android::hardware::drm::V1_0::KeyStatusType; -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::drm::V1_2::widevine::toHidlVec; -using ::android::hardware::hidl_vec; - +using android::hardware::drm::V1_2::widevine::toHidlVec; using ::testing::_; using ::testing::AllOf; using ::testing::Args; diff --git a/libwvdrmengine/src_hidl/WVCryptoFactory.cpp b/libwvdrmengine/src_hidl/WVCryptoFactory.cpp index b47ce580..dce5c4ec 100644 --- a/libwvdrmengine/src_hidl/WVCryptoFactory.cpp +++ b/libwvdrmengine/src_hidl/WVCryptoFactory.cpp @@ -9,6 +9,8 @@ #include #include "WVCryptoFactory.h" + +#include "HidlTypes.h" #include "WVCDMSingleton.h" #include "WVCryptoPlugin.h" #include "WVUUID.h" @@ -19,9 +21,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::Void; - Return WVCryptoFactory::isCryptoSchemeSupported( const hidl_array& uuid) { return isWidevineUUID(uuid.data()); diff --git a/libwvdrmengine/src_hidl/WVDrmFactory.cpp b/libwvdrmengine/src_hidl/WVDrmFactory.cpp index 92ad6f15..35c58806 100644 --- a/libwvdrmengine/src_hidl/WVDrmFactory.cpp +++ b/libwvdrmengine/src_hidl/WVDrmFactory.cpp @@ -12,8 +12,9 @@ #include "cutils/properties.h" #include "wv_cdm_constants.h" -#include "WVCDMSingleton.h" #include "wv_content_decryption_module.h" +#include "HidlTypes.h" +#include "WVCDMSingleton.h" #include "WVDrmPlugin.h" #include "WVUUID.h" @@ -23,9 +24,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::drm::V1_0::Status; -using ::android::hardware::Void; - WVGenericCryptoInterface WVDrmFactory::sOemCryptoInterface; Return WVDrmFactory::isCryptoSchemeSupported( diff --git a/libwvdrmengine/src_hidl/service.cpp b/libwvdrmengine/src_hidl/service.cpp index 1e8013f6..e052097d 100644 --- a/libwvdrmengine/src_hidl/service.cpp +++ b/libwvdrmengine/src_hidl/service.cpp @@ -14,20 +14,14 @@ * limitations under the License. */ #define LOG_TAG "WidevineHidlService" -#include -#include #include +#include #include -#include +#include "WVCryptoFactory.h" +#include "WVDrmFactory.h" -using ::android::hardware::configureRpcThreadpool; -using ::android::hardware::joinRpcThreadpool; -using ::android::sp; - -using android::hardware::drm::V1_1::ICryptoFactory; -using android::hardware::drm::V1_1::IDrmFactory; using wvdrm::hardware::drm::V1_2::widevine::WVCryptoFactory; using wvdrm::hardware::drm::V1_2::widevine::WVDrmFactory; diff --git a/libwvdrmengine/test/unit/WVDrmFactory_test.cpp b/libwvdrmengine/test/unit/WVDrmFactory_test.cpp index 690bd8ff..7d972596 100644 --- a/libwvdrmengine/test/unit/WVDrmFactory_test.cpp +++ b/libwvdrmengine/test/unit/WVDrmFactory_test.cpp @@ -4,10 +4,10 @@ * License Agreement. */ +#include "cutils/properties.h" #include "gtest/gtest.h" #include "WVDrmFactory.h" - -#include "cutils/properties.h" +#include "HidlTypes.h" namespace wvdrm { namespace hardware { @@ -15,9 +15,6 @@ namespace drm { namespace V1_2 { namespace widevine { -using ::android::hardware::hidl_string; -using wvdrm::hardware::drm::V1_2::widevine::WVDrmFactory; - using namespace android; const uint8_t kWidevineUUID[16] = {