diff --git a/libwvdrmengine/aidl_src/WVDrmFactory.cpp b/libwvdrmengine/aidl_src/WVDrmFactory.cpp index fed48a64..5c89e3c6 100644 --- a/libwvdrmengine/aidl_src/WVDrmFactory.cpp +++ b/libwvdrmengine/aidl_src/WVDrmFactory.cpp @@ -238,6 +238,7 @@ void WVDrmFactory::printCdmProperties(int fd) { {"can disable analog output:", wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT}, {"watermarking support:", wvcdm::QUERY_KEY_WATERMARKING_SUPPORT}, + {"production ready:", wvcdm::QUERY_KEY_PRODUCTION_READY}, }; string value; diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 8c02db2a..15ce3278 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -221,6 +221,11 @@ class CryptoSession { RequestedSecurityLevel requested_security_level, CdmWatermarkingSupport* support); + virtual bool GetProductionReadiness(CdmProductionReadiness* readiness); + virtual bool GetProductionReadiness( + RequestedSecurityLevel requested_security_level, + CdmProductionReadiness* readiness); + virtual bool GetMaximumUsageTableEntries( RequestedSecurityLevel security_level, size_t* number_of_entries); diff --git a/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h b/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h index 6d292eaf..33a10e1f 100644 --- a/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h +++ b/libwvdrmengine/cdm/core/include/oemcrypto_adapter.h @@ -72,6 +72,7 @@ OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(uint8_t* public_cert, RequestedSecurityLevel level); OEMCrypto_WatermarkingSupport OEMCrypto_GetWatermarkingSupport( RequestedSecurityLevel level); +OEMCryptoResult OEMCrypto_ProductionReady(RequestedSecurityLevel level); } // namespace wvcdm /* The following functions are deprecated in OEMCrypto v13. They are defined diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h index 2e1a1d5d..acf1387d 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_constants.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_constants.h @@ -112,6 +112,7 @@ static const std::string QUERY_KEY_ANALOG_OUTPUT_CAPABILITIES = static const std::string QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT = "CanDisableAnalogOutput"; static const std::string QUERY_KEY_WATERMARKING_SUPPORT = "WatermarkingSupport"; +static const std::string QUERY_KEY_PRODUCTION_READY = "ProductionReady"; static const std::string QUERY_VALUE_TRUE = "True"; static const std::string QUERY_VALUE_FALSE = "False"; diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index 7c9e2459..a8598896 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -599,6 +599,12 @@ enum CdmWatermarkingSupport : int32_t { kWatermarkingAlwaysOn }; +enum CdmProductionReadiness : int32_t { + kProductionReadinessUnknown, + kProductionReadinessTrue, + kProductionReadinessFalse, +}; + class CdmKeyAllowedUsage { public: CdmKeyAllowedUsage() { Clear(); } @@ -842,6 +848,7 @@ const char* CdmUsageEntryStorageTypeToString(CdmUsageEntryStorageType type); const char* RequestedSecurityLevelToString( RequestedSecurityLevel security_level); const char* CdmWatermarkingSupportToString(CdmWatermarkingSupport support); +const char* CdmProductionReadinessToString(CdmProductionReadiness readiness); // Converts a generic, unknown enum value to a string representation // containing its numeric value. // The pointer returned from this function is thread_local. diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 4a6a94f8..b422978b 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -817,6 +817,28 @@ CdmResponseType CdmEngine::QueryStatus(RequestedSecurityLevel security_level, } return NO_ERROR; } + if (query_token == QUERY_KEY_PRODUCTION_READY) { + CdmProductionReadiness readiness; + if (!crypto_session->GetProductionReadiness(security_level, &readiness)) { + LOGW("GetProductionReadiness failed"); + return UNKNOWN_ERROR; + } + switch (readiness) { + case kProductionReadinessUnknown: + *query_response = QUERY_VALUE_UNKNOWN; + break; + case kProductionReadinessTrue: + *query_response = QUERY_VALUE_TRUE; + break; + case kProductionReadinessFalse: + *query_response = QUERY_VALUE_FALSE; + break; + default: + LOGW("Unknown readiness: %d", static_cast(readiness)); + return UNKNOWN_ERROR; + } + return NO_ERROR; + } CdmResponseType status; 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 1cefc7b5..517436e2 100644 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -2350,6 +2350,34 @@ bool CryptoSession::GetWatermarkingSupport( return true; } +bool CryptoSession::GetProductionReadiness(CdmProductionReadiness* readiness) { + RETURN_IF_NOT_OPEN(false); + return GetProductionReadiness(requested_security_level_, readiness); +} + +bool CryptoSession::GetProductionReadiness( + RequestedSecurityLevel security_level, CdmProductionReadiness* readiness) { + LOGV("security_level = %s", RequestedSecurityLevelToString(security_level)); + RETURN_IF_UNINITIALIZED(false); + RETURN_IF_NULL(readiness, false); + const OEMCryptoResult result = WithOecReadLock("GetProductionReadiness", [&] { + return OEMCrypto_ProductionReady(security_level); + }); + switch (result) { + case OEMCrypto_SUCCESS: + *readiness = kProductionReadinessTrue; + break; + case OEMCrypto_ERROR_NOT_IMPLEMENTED: + *readiness = kProductionReadinessUnknown; + break; + case OEMCrypto_ERROR_UNKNOWN_FAILURE: + default: // Other vendor-defined codes indicate not production ready. + *readiness = kProductionReadinessFalse; + break; + } + return true; +} + bool CryptoSession::GetMaximumUsageTableEntries( RequestedSecurityLevel security_level, size_t* number_of_entries) { LOGV("Getting maximum usage table entries: security_level = %s", diff --git a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp index 0a2ecc63..7d032581 100644 --- a/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp +++ b/libwvdrmengine/cdm/core/src/oemcrypto_adapter_dynamic.cpp @@ -1912,6 +1912,15 @@ OEMCrypto_WatermarkingSupport OEMCrypto_GetWatermarkingSupport( return OEMCrypto_WatermarkingError; return fcn->GetWatermarkingSupport(); } + +OEMCryptoResult OEMCrypto_ProductionReady(wvcdm::RequestedSecurityLevel level) { + if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; + const FunctionPointers* fcn = gAdapter->GetFunctionPointers(level); + if (!fcn) return OEMCrypto_ERROR_NOT_IMPLEMENTED; + if (fcn->version < 17) return OEMCrypto_ERROR_NOT_IMPLEMENTED; + if (fcn->ProductionReady == nullptr) return OEMCrypto_ERROR_NOT_IMPLEMENTED; + return fcn->ProductionReady(); +} } // namespace wvcdm extern "C" OEMCryptoResult OEMCrypto_SetSandbox(const uint8_t* sandbox_id, @@ -3310,15 +3319,6 @@ extern "C" OEMCryptoResult OEMCrypto_LoadCasECMKeys( odd_key); } -extern "C" OEMCryptoResult OEMCrypto_ProductionReady() { - if (!gAdapter) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const FunctionPointers* fcn = gAdapter->GetFunctionPointers(kLevelDefault); - if (!fcn) return OEMCrypto_ERROR_NOT_IMPLEMENTED; - if (fcn->version < 17) return OEMCrypto_ERROR_NOT_IMPLEMENTED; - if (fcn->ProductionReady == nullptr) return OEMCrypto_ERROR_NOT_IMPLEMENTED; - return fcn->ProductionReady(); -} - extern "C" OEMCryptoResult OEMCrypto_OPK_SerializationVersion( uint32_t* ree_major, uint32_t* ree_minor, uint32_t* tee_major, uint32_t* tee_minor) { @@ -3423,3 +3423,7 @@ extern "C" OEMCrypto_WatermarkingSupport OEMCrypto_GetWatermarkingSupport( void) { return wvcdm::OEMCrypto_GetWatermarkingSupport(kLevelDefault); } + +extern "C" OEMCryptoResult OEMCrypto_ProductionReady(void) { + return wvcdm::OEMCrypto_ProductionReady(kLevelDefault); +} diff --git a/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp b/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp index 51336811..3ba2d4b4 100644 --- a/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp +++ b/libwvdrmengine/cdm/core/src/wv_cdm_types.cpp @@ -131,6 +131,18 @@ const char* CdmWatermarkingSupportToString(CdmWatermarkingSupport support) { return UnknownValueRep(support); } +const char* CdmProductionReadinessToString(CdmProductionReadiness readiness) { + switch (readiness) { + case kProductionReadinessUnknown: + return QUERY_VALUE_UNKNOWN.c_str(); + case kProductionReadinessTrue: + return QUERY_VALUE_TRUE.c_str(); + case kProductionReadinessFalse: + return QUERY_VALUE_FALSE.c_str(); + } + return UnknownValueRep(readiness); +} + const char* UnknownEnumValueToString(int value) { snprintf(tl_unknown_rep_buf, sizeof(tl_unknown_rep_buf), "", value); diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 9ac5384f..c892345b 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -5284,6 +5284,14 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) { value == wvcdm::QUERY_VALUE_CONFIGURABLE || value == wvcdm::QUERY_VALUE_ALWAYS_ON) << "Watermarking support"; + + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_->QueryStatus(kLevelDefault, + wvcdm::QUERY_KEY_PRODUCTION_READY, &value)); + EXPECT_TRUE(value == wvcdm::QUERY_VALUE_TRUE || + value == wvcdm::QUERY_VALUE_FALSE || + value == wvcdm::QUERY_VALUE_UNKNOWN) + << "Production ready"; } TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) { @@ -5427,11 +5435,19 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatusL3) { EXPECT_EQ(wvcdm::NO_ERROR, decryptor_->QueryStatus( - kLevelDefault, wvcdm::QUERY_KEY_WATERMARKING_SUPPORT, &value)); + kLevel3, wvcdm::QUERY_KEY_WATERMARKING_SUPPORT, &value)); EXPECT_TRUE(value == wvcdm::QUERY_VALUE_NOT_SUPPORTED || value == wvcdm::QUERY_VALUE_CONFIGURABLE || value == wvcdm::QUERY_VALUE_ALWAYS_ON) << "Watermarking support"; + + EXPECT_EQ(wvcdm::NO_ERROR, + decryptor_->QueryStatus(kLevel3, wvcdm::QUERY_KEY_PRODUCTION_READY, + &value)); + EXPECT_TRUE(value == wvcdm::QUERY_VALUE_TRUE || + value == wvcdm::QUERY_VALUE_FALSE || + value == wvcdm::QUERY_VALUE_UNKNOWN) + << "Production ready"; } TEST_F(WvCdmRequestLicenseTest, QueryOemCryptoSessionId) { diff --git a/libwvdrmengine/mediadrm/aidl_src/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/aidl_src/WVDrmPlugin.cpp index 8600c26d..745c15fc 100644 --- a/libwvdrmengine/mediadrm/aidl_src/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/aidl_src/WVDrmPlugin.cpp @@ -1152,6 +1152,8 @@ Status WVDrmPlugin::unprovisionDevice() { } } else if (name == "watermarkingSupport") { status = queryProperty(wvcdm::QUERY_KEY_WATERMARKING_SUPPORT, value); + } else if (name == "productionReady") { + status = queryProperty(wvcdm::QUERY_KEY_PRODUCTION_READY, value); } else { ALOGE("App requested unknown string property %s", name.c_str()); *_aidl_return = value; diff --git a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp index 77f36508..ab6b0ecb 100644 --- a/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp +++ b/libwvdrmengine/mediadrm/src_hidl/WVDrmPlugin.cpp @@ -1261,6 +1261,8 @@ Return WVDrmPlugin::getPropertyString(const hidl_string& propertyName, } } else if (name == "watermarkingSupport") { status = queryProperty(wvcdm::QUERY_KEY_WATERMARKING_SUPPORT, value); + } else if (name == "productionReady") { + status = queryProperty(wvcdm::QUERY_KEY_PRODUCTION_READY, value); } else { ALOGE("App requested unknown string property %s", name.c_str()); status = Status::ERROR_DRM_CANNOT_HANDLE; diff --git a/libwvdrmengine/src_hidl/WVDrmFactory.cpp b/libwvdrmengine/src_hidl/WVDrmFactory.cpp index 785c35e6..9ba12b34 100644 --- a/libwvdrmengine/src_hidl/WVDrmFactory.cpp +++ b/libwvdrmengine/src_hidl/WVDrmFactory.cpp @@ -217,6 +217,7 @@ void WVDrmFactory::printCdmProperties(FILE* out) { {"can disable analog output:", wvcdm::QUERY_KEY_CAN_DISABLE_ANALOG_OUTPUT}, {"watermarking support:", wvcdm::QUERY_KEY_WATERMARKING_SUPPORT}, + {"production ready:", wvcdm::QUERY_KEY_PRODUCTION_READY}, }; std::string value;