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
This commit is contained in:
Jeff Tinker
2018-12-12 08:52:28 -08:00
parent 40bd0d5209
commit a00b50095c
16 changed files with 390 additions and 217 deletions

View File

@@ -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 <android/hardware/drm/1.1/types.h>
#include <android/hardware/drm/1.2/ICryptoFactory.h>
#include <android/hardware/drm/1.2/ICryptoPlugin.h>
#include <android/hardware/drm/1.2/types.h>
#include <android/hardware/drm/1.2/IDrmFactory.h>
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <android/hardware/drm/1.2/IDrmPluginListener.h>
#include <hidl/HidlTransportSupport.h>
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

View File

@@ -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 <vector>
#include <android/hardware/drm/1.0/types.h>
#include <media/stagefright/MediaErrors.h>
#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<typename T> const hidl_vec<T> toHidlVec(const std::vector<T> &vec) {
hidl_vec<T> hVec;
hVec.setToExternal(const_cast<T *>(vec.data()), vec.size());

View File

@@ -7,8 +7,7 @@
#ifndef WV_CREATE_PLUGIN_FACTORIES_H_
#define WV_CREATE_PLUGIN_FACTORIES_H_
#include <android/hardware/drm/1.1/ICryptoFactory.h>
#include <android/hardware/drm/1.1/IDrmFactory.h>
#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();

View File

@@ -7,8 +7,7 @@
#ifndef WV_CRYPTO_FACTORY_H_
#define WV_CRYPTO_FACTORY_H_
#include <android/hardware/drm/1.1/ICryptoFactory.h>
#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() {}

View File

@@ -7,9 +7,7 @@
#ifndef WV_DRM_FACTORY_H_
#define WV_DRM_FACTORY_H_
#include <android/hardware/drm/1.1/IDrmFactory.h>
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#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() {}

View File

@@ -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<Status_V1_2>(mapCdmResponseType(res));
}
}
static inline bool isCdmResponseTypeSuccess(wvcdm::CdmResponseType res) {
return mapCdmResponseType(res) == Status::OK;
}

View File

@@ -7,9 +7,9 @@
#ifndef WV_CRYPTO_PLUGIN_H_
#define WV_CRYPTO_PLUGIN_H_
#include <android/hardware/drm/1.0/ICryptoPlugin.h>
#include <android/hidl/memory/1.0/IMemory.h>
#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<void> decrypt_1_2(
bool secure,
const hidl_array<uint8_t, 16>& keyId,
const hidl_array<uint8_t, 16>& iv,
Mode mode,
const Pattern& pattern,
const hidl_vec<SubSample>& 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<wvcdm::WvContentDecryptionModule> const mCDM;
Status attemptDecrypt(
Status_V1_2 attemptDecrypt(
const wvcdm::CdmDecryptionParameters& params,
bool haveEncryptedSubsamples, std::string* errorDetailMsg);
static wvcdm::CdmResponseType countEncryptedBlocksInPatternedRange(

View File

@@ -9,13 +9,14 @@
#include <utils/Log.h>
#include "WVCryptoPlugin.h"
#include "TypeConvert.h"
#include <hidlmemory/mapping.h>
#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>(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<void> WVCryptoPlugin::decrypt(
const DestinationBuffer& destination,
decrypt_cb _hidl_cb) {
Status status = Status::ERROR_DRM_UNKNOWN;
hidl_string detailedError;
uint32_t bytesWritten = 0;
Return<void> 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<void> WVCryptoPlugin::decrypt_1_2(
bool secure,
const hidl_array<uint8_t, 16>& keyId,
const hidl_array<uint8_t, 16>& iv,
Mode mode,
const Pattern& pattern,
const hidl_vec<SubSample>& 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<void> 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<void> 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<void> WVCryptoPlugin::decrypt(
std::string errorDetailMsg;
sp<IMemory> 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<void> WVCryptoPlugin::decrypt(
const SharedBuffer& destBuffer = destination.nonsecureMemory;
sp<IMemory> 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<void *>(base + destination.nonsecureMemory.offset);
@@ -218,7 +259,7 @@ Return<void> 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<void> 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<void> 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<void> 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<void> 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;
}
}
}

View File

@@ -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;

View File

@@ -9,15 +9,12 @@
#include <map>
#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.1/types.h>
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#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<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,
@@ -112,6 +94,11 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
const hidl_string& certificateAuthority,
getProvisionRequest_cb _hidl_cb) override;
Return<void> getProvisionRequest_1_2(
const hidl_string& certificateType,
const hidl_string& certificateAuthority,
getProvisionRequest_1_2_cb _hidl_cb) override;
Return<void> provideProvisionResponse(
const hidl_vec<uint8_t>& response,
provideProvisionResponse_cb _hidl_cb) override;
@@ -224,6 +211,9 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
const hidl_vec<KeyStatus>& keyStatusList,
bool hasNewUsableKey) override;
Return<void> sendSessionLostState(
const hidl_vec<uint8_t>& 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<CdmSessionId, CryptoSession> mCryptoSessions;
sp<IDrmPluginListener> mListener;
sp<IDrmPluginListener_V1_2> mListenerV1_2;
std::string mProvisioningServiceCertificate;
@@ -426,6 +420,12 @@ struct WVDrmPlugin : public IDrmPlugin, IDrmPluginListener,
Status mapAndNotifyOfCdmResponseType(const std::vector<uint8_t>& sessionId,
CdmResponseType res);
Status_V1_2 mapAndNotifyOfCdmResponseType_1_2(const std::vector<uint8_t>& sessionId,
CdmResponseType res);
void notifyOfCdmResponseType(const std::vector<uint8_t>& sessionId,
CdmResponseType res);
Status mapAndNotifyOfOEMCryptoResult(const std::vector<uint8_t>& sessionId,
OEMCryptoResult res);

View File

@@ -12,7 +12,6 @@
#include <stdlib.h>
#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<KeyRequestType_V1_1>(
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>(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>(status);
}
}
KeyStatusType ConvertFromCdmKeyStatus(CdmKeyStatus keyStatus) {
switch (keyStatus) {
case wvcdm::kKeyStatusUsable:
@@ -281,10 +309,8 @@ Return<void> 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<void> WVDrmPlugin::getKeyRequest(
KeyType keyType,
const hidl_vec<KeyValue>& optionalParameters,
getKeyRequest_cb _hidl_cb) {
hidl_string defaultUrl;
hidl_vec<uint8_t> request;
KeyRequestType requestType = KeyRequestType::UNKNOWN;
Status status = Status::ERROR_DRM_UNKNOWN;
defaultUrl.clear();
Return<void> hResult = getKeyRequest_1_1(
scope, initData, mimeType, keyType, optionalParameters,
[&](Status statusCode, const hidl_vec<uint8_t>& 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<void> WVDrmPlugin::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) {
hidl_string defaultUrl;
hidl_vec<uint8_t> request;
KeyRequestType_V1_1 requestType = KeyRequestType_V1_1::UNKNOWN;
Status status = Status::ERROR_DRM_UNKNOWN;
defaultUrl.clear();
Return<void> hResult = getKeyRequest_1_2(
scope, initData, mimeType, keyType, optionalParameters,
[&](Status_V1_2 statusCode, const hidl_vec<uint8_t>& 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<void> WVDrmPlugin::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) {
if (!scope.size()) {
_hidl_cb(Status::BAD_VALUE, hidl_vec<uint8_t>(),
KeyRequestType::UNKNOWN, "");
_hidl_cb(Status_V1_2::BAD_VALUE, hidl_vec<uint8_t>(),
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<uint8_t> request;
const std::vector<uint8_t> scopeId = toVector(scope);
CdmIdentifier identifier;
status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
status = static_cast<Status_V1_2>(
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<void> 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<void> 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<void> 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<void> WVDrmPlugin::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) {
hidl_string defaultUrl;
hidl_vec<uint8_t> 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<void> hResult = getKeyRequest(scope, initData, mimeType, keyType, optionalParameters,
[&](Status statusCode, const hidl_vec<uint8_t>& 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<void> WVDrmPlugin::provideKeyResponse(
const hidl_vec<uint8_t>& scope,
const hidl_vec<uint8_t>& response,
@@ -575,7 +628,7 @@ Return<Status> WVDrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
return Void();
}
Return<void> WVDrmPlugin::getProvisionRequest(
Return<void> WVDrmPlugin::getProvisionRequest(
const hidl_string& certificateType,
const hidl_string& certificateAuthority,
getProvisionRequest_cb _hidl_cb) {
@@ -583,9 +636,33 @@ Return<Status> WVDrmPlugin::restoreKeys(const hidl_vec<uint8_t>& sessionId,
std::string defaultUrl;
std::vector<uint8_t> request;
Return<void> hResult = getProvisionRequest_1_2(
certificateType, certificateAuthority,
[&](Status_V1_2 statusCode, const hidl_vec<uint8_t>& 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<void> 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<uint8_t> request;
CdmIdentifier identifier;
status = mCdmIdentifierBuilder.getCdmIdentifier(&identifier);
if (status != Status::OK) {
status = static_cast<Status_V1_2>(mCdmIdentifierBuilder.getCdmIdentifier(&identifier));
if (status != Status_V1_2::OK) {
_hidl_cb(status, toHidlVec(request), hidl_string(defaultUrl));
return Void();
}
@@ -609,7 +686,7 @@ Return<Status> WVDrmPlugin::restoreKeys(const hidl_vec<uint8_t>& 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<void> WVDrmPlugin::signRSA(
Return<void> WVDrmPlugin::setListener(const sp<IDrmPluginListener>& listener) {
mListener = listener;
mListenerV1_2 = IDrmPluginListener_V1_2::castFrom(listener);
return Void();
}
Return<void> WVDrmPlugin::sendEvent(
EventType eventType,
const hidl_vec<uint8_t>& sessionId, const hidl_vec<uint8_t>& data) {
if (mListener != NULL) {
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");
@@ -1557,10 +1638,12 @@ Return<void> WVDrmPlugin::sendEvent(
}
Return<void> WVDrmPlugin::sendExpirationUpdate(
const hidl_vec<uint8_t>& sessionId,
int64_t expiryTimeInMS) {
if (mListener != NULL) {
mListener->sendExpirationUpdate(sessionId, expiryTimeInMS);
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");
}
@@ -1570,8 +1653,20 @@ Return<void> WVDrmPlugin::sendExpirationUpdate(
Return<void> WVDrmPlugin::sendKeysChange(
const hidl_vec<uint8_t>& sessionId,
const hidl_vec<KeyStatus>& 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<void> WVDrmPlugin::sendSessionLostState(
const hidl_vec<uint8_t>& 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<uint8_t> 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<uint8_t>& sessionId, CdmResponseType res) {
notifyOfCdmResponseType(sessionId, res);
return mapCdmResponseType(res);
}
Status_V1_2 WVDrmPlugin::mapAndNotifyOfCdmResponseType_1_2(
const std::vector<uint8_t>& sessionId, CdmResponseType res) {
notifyOfCdmResponseType(sessionId, res);
return mapCdmResponseType_1_2(res);
}
void WVDrmPlugin::notifyOfCdmResponseType(
const std::vector<uint8_t>& 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(

View File

@@ -7,10 +7,6 @@
#define LOG_TAG "WVDrmPluginTest"
#include <utils/Log.h>
#include <android/hardware/drm/1.0/IDrmPluginListener.h>
#include <android/hardware/drm/1.1/types.h>
#include <android/hardware/drm/1.2/IDrmPlugin.h>
#include <stdio.h>
#include <ostream>
#include <string>
@@ -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;

View File

@@ -9,6 +9,8 @@
#include <utils/Log.h>
#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<bool> WVCryptoFactory::isCryptoSchemeSupported(
const hidl_array<uint8_t, 16>& uuid) {
return isWidevineUUID(uuid.data());

View File

@@ -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<bool> WVDrmFactory::isCryptoSchemeSupported(

View File

@@ -14,20 +14,14 @@
* limitations under the License.
*/
#define LOG_TAG "WidevineHidlService"
#include <WVCryptoFactory.h>
#include <WVDrmFactory.h>
#include <android-base/logging.h>
#include <binder/ProcessState.h>
#include <hidl/HidlTransportSupport.h>
#include <binder/ProcessState.h>
#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;

View File

@@ -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] = {