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

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