Add HDCP cap logging on HDCP-based failures. am: 3ea91f35dd

Original change: https://googleplex-android-review.googlesource.com/c/platform/vendor/widevine/+/24314234

Change-Id: I9922ade447d574ce02f0a21fc9a47f526c83b3c1
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Alex Dale
2023-08-07 18:24:14 +00:00
committed by Automerger Merge Worker
4 changed files with 113 additions and 6 deletions

View File

@@ -69,6 +69,8 @@ class CryptoSession {
static CryptoSession* MakeCryptoSession(
metrics::CryptoMetrics* crypto_metrics);
static const char* HdcpCapabilityToString(HdcpCapability hdcp_level);
virtual ~CryptoSession();
// This method will try to terminate OEMCrypto if |session_size_| is 0.
@@ -542,6 +544,9 @@ class CryptoSession {
// same error code in sequence of each other. A value of
// OEMCrypto_SUCCESS indicates that no error have yet occurred.
OEMCryptoResult last_decrypt_error_ = OEMCrypto_SUCCESS;
// Similar to |last_decrypt_error_|, but intended for calls to
// SelectKey().
OEMCryptoResult last_select_key_error_ = OEMCrypto_SUCCESS;
// In order to avoid creating a deadlock if instantiation needs to take any
// of the CryptoSession static mutexes, |factory_| is protected by its own

View File

@@ -161,6 +161,8 @@ class LicenseKeyStatus {
bool meets_security_level_constraints_ = true;
CdmKeyAllowedUsage allowed_usage_;
CryptoSession::HdcpCapability default_hdcp_level_ = HDCP_NONE;
CryptoSession::HdcpCapability last_reported_device_hdcp_level_ = HDCP_NONE;
CryptoSession::HdcpCapability last_reported_license_hdcp_level_ = HDCP_NONE;
ConstraintList constraints_;
CORE_DISALLOW_COPY_AND_ASSIGN(LicenseKeyStatus);

View File

@@ -93,6 +93,8 @@ constexpr size_t kAes128BlockSize = 16;
constexpr int kMaxTerminateCountDown = 5;
constexpr char kUnavailableHdcpLevel[] = "<unavailable>";
const std::string kStringNotAvailable = "NA";
// TODO(b/174412779): Remove when b/170704368 is fixed.
@@ -292,6 +294,37 @@ OEMCryptoCipherMode ToOEMCryptoCipherMode(CdmCipherMode cipher_mode) {
: OEMCrypto_CipherMode_CBCS;
}
// static
const char* CryptoSession::HdcpCapabilityToString(HdcpCapability hdcp_level) {
switch (hdcp_level) {
case HDCP_NONE:
return "None";
case HDCP_V1: // Means v1.x
return "v1.x";
case HDCP_V2: // Means v2.0
return "v2.0";
case HDCP_V2_1:
return "v2.1";
case HDCP_V2_2:
return "v2.2";
case HDCP_V2_3:
return "v2.3";
case HDCP_V1_0:
return "v1.0";
case HDCP_V1_1:
return "v1.1";
case HDCP_V1_2:
return "v1.2";
case HDCP_V1_3:
return "v1.3";
case HDCP_V1_4:
return "v1.4";
case HDCP_NO_DIGITAL_OUTPUT:
return "No-Digital-Output";
}
return UnknownEnumValueToString(static_cast<int>(hdcp_level));
}
CryptoSession::CryptoSession(metrics::CryptoMetrics* metrics)
: metrics_(metrics),
system_id_(NULL_SYSTEM_ID),
@@ -1513,6 +1546,35 @@ CdmResponseType CryptoSession::SelectKey(const std::string& key_id,
return key_session_->SelectKey(key_id, cipher_mode);
});
if (sts != last_select_key_error_) {
// Only log errors on first occurrence. Calls to SelectKey from
// the app are typically queued. If an error occurs, then it is
// expected that multiple failures will occur before the app is
// notified and stops queueing calls to the CDM.
last_select_key_error_ = sts;
if (sts == OEMCrypto_ERROR_INSUFFICIENT_HDCP ||
sts == OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION) {
const char* status_message = OemCryptoResultToString(sts);
HdcpCapability current_hdcp_level;
HdcpCapability max_hdcp_level;
const CdmResponseType hdcp_status =
GetHdcpCapabilities(&current_hdcp_level, &max_hdcp_level);
const char* current_hdcp_message = kUnavailableHdcpLevel;
const char* max_hdcp_message = kUnavailableHdcpLevel;
if (hdcp_status == NO_ERROR) {
current_hdcp_message = HdcpCapabilityToString(current_hdcp_level);
max_hdcp_message = HdcpCapabilityToString(max_hdcp_level);
}
LOGE(
"oec_session_id = %u, security_level = %s, "
"status = %s, current_hdcp_level = %s, "
"max_hdcp_level = %s",
oec_session_id_,
RequestedSecurityLevelToString(requested_security_level_),
status_message, current_hdcp_message, max_hdcp_message);
}
}
switch (sts) {
// SelectKey errors.
case OEMCrypto_SUCCESS:
@@ -1790,11 +1852,26 @@ CdmResponseType CryptoSession::Decrypt(
// the next call. The calling application may make several more
// decrypt requests before the error is handled by the app.
last_decrypt_error_ = sts;
if (sts == OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION) {
LOGW(
"OEMCrypto_DecryptCENC is warning of mixed HDCP output protection: "
"oec_session_id = %u",
oec_session_id_);
if (sts == OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION ||
sts == OEMCrypto_ERROR_INSUFFICIENT_HDCP) {
const char* status_message = OemCryptoResultToString(sts);
HdcpCapability current_hdcp_level;
HdcpCapability max_hdcp_level;
const CdmResponseType hdcp_status =
GetHdcpCapabilities(&current_hdcp_level, &max_hdcp_level);
const char* current_hdcp_message = kUnavailableHdcpLevel;
const char* max_hdcp_message = kUnavailableHdcpLevel;
if (hdcp_status == NO_ERROR) {
current_hdcp_message = HdcpCapabilityToString(current_hdcp_level);
max_hdcp_message = HdcpCapabilityToString(max_hdcp_level);
}
LOGE(
"OEMCrypto_DecryptCENC failed: oec_session_id = %u, "
"security_level = %s, status = %s, current_hdcp_level = %s, "
"max_hdcp_level = %s",
oec_session_id_,
RequestedSecurityLevelToString(requested_security_level_),
status_message, current_hdcp_message, max_hdcp_message);
} else {
LOGE(
"OEMCrypto_DecryptCENC failed: oec_session_id = %u, "

View File

@@ -316,6 +316,7 @@ void LicenseKeyStatus::ParseContentKey(const KeyContainer& key,
if (key.has_required_protection()) {
default_hdcp_level_ =
ProtobufHdcpToOemCryptoHdcp(key.required_protection().hdcp());
last_reported_license_hdcp_level_ = default_hdcp_level_;
}
}
@@ -399,14 +400,36 @@ void LicenseKeyStatus::ApplyConstraints(
}
}
const bool device_hdcp_level_change =
(last_reported_device_hdcp_level_ != new_hdcp_level);
last_reported_device_hdcp_level_ = new_hdcp_level;
CryptoSession::HdcpCapability desired_hdcp_level = default_hdcp_level_;
if (current_constraint && current_constraint->has_required_protection()) {
desired_hdcp_level = ProtobufHdcpToOemCryptoHdcp(
current_constraint->required_protection().hdcp());
}
const bool license_hdcp_level_change =
(desired_hdcp_level != last_reported_license_hdcp_level_);
last_reported_license_hdcp_level_ = desired_hdcp_level;
meets_constraints_ =
const bool meets_new_constrains =
MeetsHdcpRequirements(desired_hdcp_level, new_hdcp_level);
const bool meets_constraints_change =
(meets_new_constrains != meets_constraints_);
meets_constraints_ = meets_new_constrains;
const bool change = device_hdcp_level_change || license_hdcp_level_change ||
meets_constraints_change;
if (!meets_constraints_ && change) {
LOGD(
"new_hdcp_level = %s, desired_hdcp_level = %s, "
"default_hdcp_level = %s, video_pixels = %u",
CryptoSession::HdcpCapabilityToString(new_hdcp_level),
CryptoSession::HdcpCapabilityToString(desired_hdcp_level),
CryptoSession::HdcpCapabilityToString(default_hdcp_level_),
video_pixels);
}
}
void LicenseKeyStatus::SetConstraints(const ConstraintList& constraints) {