From fb847c470495b2f9cd4dd6012d4b5f22a8932f23 Mon Sep 17 00:00:00 2001 From: Alex Dale Date: Mon, 12 Oct 2020 17:01:43 -0700 Subject: [PATCH] Query analog output capabilities. [ Merge of http://go/wvgerrit/107763 ] This CL enables the ability to query the CDM for the analog output capabilites of the device. Due to the number of possibilities that OEMCrypto can report, two queries are exposed: - Output capabilities: None, Supported, CGMS-C, Unknown - Can disable: True, False, Unknown Bug: 168322023 Test: Android integration test Change-Id: I8036a89237d698f170d2c1901c41d1d6b708c917 --- .../cdm/core/include/wv_cdm_constants.h | 16 +++++++++- libwvdrmengine/cdm/core/src/cdm_engine.cpp | 26 ++++++++++++++++ .../cdm/core/src/crypto_session.cpp | 6 ++-- .../cdm/test/request_license_test.cpp | 30 +++++++++++++++++++ libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp | 4 +++ .../mediadrm/src_hidl/WVDrmPlugin.cpp | 4 +++ libwvdrmengine/src_hidl/WVDrmFactory.cpp | 5 +++- 7 files changed, 86 insertions(+), 5 deletions(-) diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 3db2a051..9724011e 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -48,7 +48,14 @@ static const char KEY_SET_ID_PREFIX[] = "ksid"; static const char KEY_SYSTEM[] = "com.widevine"; static const char ATSC_APP_PACKAGE_NAME[] = "org.atsc"; -// define query keys, values here +// Define query keys, values here. +// To expose these query items to Android update: +// android/mediadrm/src/WVDrmPlugin.cpp +// android/mediadrm/src_hidl/WVDrmPlugin.cpp +// Update test QueryStatus and QueryStatusL3 test for all possible outputs: +// android/cdm/test/request_license_test.cpp +// Update HIDL debug output: +// android/src_hidl/WVDrmFactory.cpp static const std::string QUERY_KEY_LICENSE_TYPE = "LicenseType"; // "Streaming", "Offline" static const std::string QUERY_KEY_PLAY_ALLOWED = @@ -96,10 +103,16 @@ static const std::string QUERY_KEY_MAX_USAGE_TABLE_ENTRIES = "MaxNumberOfUsageTableEntries"; static const std::string QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION = "OemCryptoApiMinorVersion"; +static const std::string QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES = + "AnalogOutputCapabilities"; +static const std::string QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT = + "CanDisableAnalogOutput"; static const std::string QUERY_VALUE_TRUE = "True"; static const std::string QUERY_VALUE_FALSE = "False"; static const std::string QUERY_VALUE_NONE = "None"; +static const std::string QUERY_VALUE_SUPPORTED = "Supported"; +static const std::string QUERY_VALUE_UNKNOWN = "Unknown"; static const std::string QUERY_VALUE_STREAMING = "Streaming"; static const std::string QUERY_VALUE_OFFLINE = "Offline"; static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1"; @@ -118,6 +131,7 @@ static const std::string QUERY_VALUE_HDCP_LEVEL_UNKNOWN = "HDCP-LevelUnknown"; static const std::string QUERY_VALUE_DRM_CERTIFICATE = "DrmCertificate"; static const std::string QUERY_VALUE_KEYBOX = "Keybox"; static const std::string QUERY_VALUE_OEM_CERTIFICATE = "OEMCertificate"; +static const std::string QUERY_VALUE_CGMS_A = "CGMS-A"; static const std::string ISO_BMFF_VIDEO_MIME_TYPE = "video/mp4"; static const std::string ISO_BMFF_AUDIO_MIME_TYPE = "audio/mp4"; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index ec6fdc78..0d7745cb 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -720,6 +720,32 @@ CdmResponseType CdmEngine::QueryStatus(SecurityLevel security_level, *query_response = std::to_string(api_minor_version); return NO_ERROR; + } else if (query_token == QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES) { + bool supported = false, can_disable = false, cgms_a = false; + if (crypto_session->GetAnalogOutputCapabilities(&supported, &can_disable, + &cgms_a)) { + if (supported) { + if (cgms_a) { + *query_response = QUERY_VALUE_CGMS_A; + } else { + *query_response = QUERY_VALUE_SUPPORTED; + } + } else { + *query_response = QUERY_VALUE_NONE; + } + } else { + *query_response = QUERY_VALUE_UNKNOWN; + } + return NO_ERROR; + } else if (query_token == QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT) { + bool supported = false, can_disable = false, cgms_a = false; + if (crypto_session->GetAnalogOutputCapabilities(&supported, &can_disable, + &cgms_a)) { + *query_response = can_disable ? QUERY_VALUE_TRUE : QUERY_VALUE_FALSE; + } else { + *query_response = QUERY_VALUE_UNKNOWN; + } + return NO_ERROR; } M_TIME(status = crypto_session->Open(security_level), diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index ba939545..c2f186d9 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -2648,9 +2648,9 @@ bool CryptoSession::GetAnalogOutputCapabilities(bool* can_support_output, bool* can_disable_output, bool* can_support_cgms_a) { LOGV("Getting analog output capabilities: id = %u", oec_session_id_); - uint32_t flags; - WithOecReadLock("GetAnalogOutputCapabilities", [&] { - flags = OEMCrypto_GetAnalogOutputFlags(requested_security_level_); + RETURN_IF_UNINITIALIZED(false); + const uint32_t flags = WithOecReadLock("GetAnalogOutputCapabilities", [&] { + return OEMCrypto_GetAnalogOutputFlags(requested_security_level_); }); if ((flags & OEMCrypto_Unknown_Analog_Output) != 0) return false; diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 6d612707..83a130a7 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -63,6 +63,14 @@ const wvcdm::CdmIdentifier kAlternateCdmIdentifier2 = { const std::string kEmptyServiceCertificate; const std::string kComma = ","; +// Analog output capabilities constants. +const std::vector kAnalogOutputCapabilities = { + wvcdm::QUERY_VALUE_NONE, wvcdm::QUERY_VALUE_SUPPORTED, + wvcdm::QUERY_VALUE_CGMS_A, wvcdm::QUERY_VALUE_UNKNOWN}; +const std::vector kCanDisableAnalogOutput = { + wvcdm::QUERY_VALUE_TRUE, wvcdm::QUERY_VALUE_FALSE, + wvcdm::QUERY_VALUE_UNKNOWN}; + // Protobuf generated classes using video_widevine::LicenseIdentification; using video_widevine::LicenseRequest_ContentIdentification; @@ -4985,6 +4993,18 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) { ASSERT_FALSE(ss.fail()); EXPECT_TRUE(ss.eof()); EXPECT_LE(0u, api_minor_version); + + EXPECT_EQ( + wvcdm::NO_ERROR, + decryptor_->QueryStatus( + kLevelDefault, wvcdm::QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES, &value)); + EXPECT_THAT(kAnalogOutputCapabilities, Contains(value)); + + EXPECT_EQ( + wvcdm::NO_ERROR, + decryptor_->QueryStatus( + kLevelDefault, wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT, &value)); + EXPECT_THAT(kCanDisableAnalogOutput, Contains(value)); } TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) { @@ -5115,6 +5135,16 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) { ASSERT_FALSE(ss.fail()); EXPECT_TRUE(ss.eof()); EXPECT_LE(200u, max_usage_table_entries); + + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_->QueryStatus( + kLevel3, wvcdm::QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES, &value)); + EXPECT_THAT(kAnalogOutputCapabilities, Contains(value)); + + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_->QueryStatus( + kLevel3, wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT, &value)); + EXPECT_THAT(kCanDisableAnalogOutput, Contains(value)); } TEST_F(WvCdmRequestLicenseTest, QueryOemCryptoSessionId) { diff --git a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp index 70164ae4..7641e83a 100644 --- a/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src/WVDrmPlugin.cpp @@ -555,6 +555,10 @@ status_t WVDrmPlugin::getPropertyString(const String8& name, return queryProperty(QUERY_KEY_MAX_USAGE_TABLE_ENTRIES, value); } else if (name == "oemCryptoApiMinorVersion") { return queryProperty(QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION, value); + } else if (name == "analogOutputCapabilities") { + return queryProperty(QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES, value); + } else if (name == "canDisableAnalogOutput") { + return queryProperty(QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT, value); } else if (name == "atscMode") { if (mPropertySet.use_atsc_mode()) { value = kEnable; diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index 0bbb2dc9..78393f6d 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -1267,6 +1267,10 @@ Return WVDrmPlugin::getPropertyString(const hidl_string& propertyName, status = queryProperty(wvcdm::QUERY_KEY_MAX_USAGE_TABLE_ENTRIES, value); } else if (name == "oemCryptoApiMinorVersion") { status = queryProperty(wvcdm::QUERY_KEY_OEMCRYPTO_API_MINOR_VERSION, value); + } else if (name == "analogOutputCapabilities") { + status = queryProperty(wvcdm::QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES, value); + } else if (name == "canDisableAnalogOutput") { + status = queryProperty(wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT, value); } else if (name == "atscMode") { if (mPropertySet.use_atsc_mode()) { value = kEnable; diff --git a/libwvdrmengine/src_hidl/WVDrmFactory.cpp b/libwvdrmengine/src_hidl/WVDrmFactory.cpp index b4ecfacd..3b9e7704 100644 --- a/libwvdrmengine/src_hidl/WVDrmFactory.cpp +++ b/libwvdrmengine/src_hidl/WVDrmFactory.cpp @@ -191,7 +191,7 @@ void WVDrmFactory::printCdmProperties(FILE* out) { cdm->IsSecurityLevelSupported(wvcdm::CdmSecurityLevel::kSecurityLevelL1); fprintf(out, "default security level: [%s]\n", isLevel1 ? "L1" : "L3"); - std::map cdmProperties = { + const std::map cdmProperties = { {"version- Widevine CDM:", wvcdm::QUERY_KEY_WVCDM_VERSION}, {"version- current SRM:", wvcdm::QUERY_KEY_CURRENT_SRM_VERSION}, {"version(major)- OEM Crypto API:", @@ -213,6 +213,9 @@ void WVDrmFactory::printCdmProperties(FILE* out) { {"OEM Crypto build info:", wvcdm::QUERY_KEY_OEMCRYPTO_BUILD_INFORMATION}, {"provisioning id:", wvcdm::QUERY_KEY_PROVISIONING_ID}, {"provisioning model:", wvcdm::QUERY_KEY_PROVISIONING_MODEL}, + {"analog capabilities:", wvcdm::QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES}, + {"can disable analog output:", + wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT}, }; std::string value;