// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. // // Format widevine protobuf metrics #include "wv_metrics.h" #include #include #include "OEMCryptoCENC.h" #include "metrics_collections.h" #include "string_conversions.h" #include "wv_cdm_types.h" using namespace drm_metrics; using ::aidl::android::hardware::drm::Status; using ::wvcdm::metrics::OEMCryptoInitializationMode; namespace { constexpr size_t kIndentIncrement = 2; void FormatIndent(size_t indent, std::ostream& os) { for (size_t i = 0; i < indent; i++) os.put(' '); } void FormatListIndent(size_t parent_indent, std::ostream& os) { FormatIndent(parent_indent, os); os.put('-'); FormatIndent(kIndentIncrement - 1, os); } void FormatString(const std::string& s, std::ostream& os) { os << '"'; if (std::any_of(s.begin(), s.end(), [](char c) { return c == '"'; })) { // Escape any double quotes. for (char c : s) { if (c == '"') { os << "\\\""; } else { os << c; } } } else { os << s; } os << '"'; } void FormatString(const char* s, std::ostream& os) { if (s == nullptr) { os << "null"; } else { FormatString(std::string(s), os); } } const char* OEMCryptoInitializeModeToString(OEMCryptoInitializationMode mode) { using namespace wvcdm::metrics; switch (mode) { case OEMCrypto_INITIALIZED_USING_IN_APP: return "USING_IN_APP"; case OEMCrypto_INITIALIZED_FORCING_L3: return "FORCING_L3"; case OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH: return "USING_L3_NO_L1_LIBRARY_PATH"; case OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED: return "USING_L3_L1_OPEN_FAILED"; case OEMCrypto_INITIALIZED_USING_L3_L1_LOAD_FAILED: return "USING_L3_L1_LOAD_FAILED"; case OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1: return "USING_L3_COULD_NOT_INITIALIZE_L1"; case OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION: return "USING_L3_WRONG_L1_VERSION"; case OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX: return "USING_L1_WITH_KEYBOX"; case OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE: return "USING_L1_WITH_CERTIFICATE"; case OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX: return "USING_L1_CERTIFICATE_MIX"; case OEMCrypto_INITIALIZED_USING_L3_BAD_KEYBOX: return "USING_L3_BAD_KEYBOX"; case OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX: return "USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX"; case OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INSTALL_KEYBOX: return "USING_L3_COULD_NOT_INSTALL_KEYBOX"; case OEMCrypto_INITIALIZED_USING_L1_INSTALLED_KEYBOX: return "USING_L1_INSTALLED_KEYBOX"; case OEMCrypto_INITIALIZED_USING_L3_INVALID_L1: return "USING_L3_INVALID_L1"; case OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_3_0: return "USING_L1_WITH_PROVISIONING_3_0"; case OEMCrypto_INITIALIZED_L3_INITIALIZATION_FAILED: return "L3_INITIALIZATION_FAILED"; case OEMCrypto_INITIALIZED_L3_RNG_FAILED: return "L3_RNG_FAILED"; case OEMCrypto_INITIALIZED_L3_SAVE_DEVICE_KEYS_FAILED: return "L3_SAVE_DEVICE_KEYS_FAILED"; case OEMCrypto_INITIALIZED_L3_READ_DEVICE_KEYS_FAILED: return "L3_READ_DEVICE_KEYS_FAILED"; case OEMCrypto_INITIALIZED_L3_VERIFY_DEVICE_KEYS_FAILED: return "L3_VERIFY_DEVICE_KEYS_FAILED"; case OEMCrypto_INITIALIZED_USING_L1_WITH_PROVISIONING_4_0: return "USING_L1_WITH_PROVISIONING_4_0"; } return wvcdm::UnknownEnumValueToString(static_cast(mode)); } const char* OEMCryptoHdcpCapabilityToString( OEMCrypto_HDCP_Capability hdcp_level) { switch (hdcp_level) { case HDCP_NONE: return "HDCP_NONE"; case HDCP_V1: return "HDCP_V1"; case HDCP_V2: return "HDCP_V2"; case HDCP_V2_1: return "HDCP_V2_1"; case HDCP_V2_2: return "HDCP_V2_2"; case HDCP_V2_3: return "HDCP_V2_3"; case HDCP_V1_0: return "HDCP_V1_0"; case HDCP_V1_1: return "HDCP_V1_1"; case HDCP_V1_2: return "HDCP_V1_2"; case HDCP_V1_3: return "HDCP_V1_3"; case HDCP_V1_4: return "HDCP_V1_4"; case HDCP_NO_DIGITAL_OUTPUT: return "HDCP_NO_DIGITAL_OUTPUT"; } return wvcdm::UnknownEnumValueToString(static_cast(hdcp_level)); } const char* OEMCryptoProvisioningMethodToString( OEMCrypto_ProvisioningMethod method) { switch (method) { case OEMCrypto_ProvisioningError: return "PROVISIONING_ERROR"; case OEMCrypto_DrmCertificate: return "DRM_CERTIFICATE"; case OEMCrypto_Keybox: return "KEYBOX"; case OEMCrypto_OEMCertificate: return "OEM_CERTIFICATE"; case OEMCrypto_BootCertificateChain: return "BOOT_CERTIFICATE_CHAIN"; } return wvcdm::UnknownEnumValueToString(static_cast(method)); } void FormatOEMCryptoResult(int oemcrypto_result, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FormatIndent(indent, os); os << "value: " << oemcrypto_result << '\n'; FormatIndent(indent, os); os << "name: "; FormatString(::wvcdm::OemCryptoResultToString( static_cast(oemcrypto_result)), os); os << '\n'; } void FormatCdmErrorCode(int error_code, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FormatIndent(indent, os); os << "value: " << error_code << '\n'; FormatIndent(indent, os); os << "name: "; FormatString(::wvcdm::CdmResponseEnumToString( static_cast(error_code)), os); os << '\n'; } void FormatAttributes(const Attributes& attributes, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; bool has_value = false; if (attributes.has_error_code()) { has_value = true; FormatIndent(indent, os); os << "error_code:\n"; FormatCdmErrorCode(attributes.error_code(), indent, os); } if (attributes.has_error_code_bool()) { has_value = true; FormatIndent(indent, os); os << "success: "; os << (attributes.error_code_bool() ? "true" : "false"); os << '\n'; } if (attributes.has_cdm_security_level()) { has_value = true; FormatIndent(indent, os); const wvcdm::CdmSecurityLevel cdm_security_level = static_cast(attributes.cdm_security_level()); os << "cdm_security_level: "; FormatString(wvcdm::CdmSecurityLevelToString(cdm_security_level), os); os << '\n'; } if (attributes.has_security_level()) { has_value = true; FormatIndent(indent, os); const wvcdm::RequestedSecurityLevel security_level = static_cast(attributes.security_level()); os << "security_level: "; FormatString(wvcdm::RequestedSecurityLevelToString(security_level), os); os << '\n'; } if (attributes.has_length()) { has_value = true; FormatIndent(indent, os); os << "length: " << attributes.length() << '\n'; } if (attributes.has_encryption_algorithm()) { has_value = true; FormatIndent(indent, os); // TODO(sigquit): Create a formatter for CdmEncryptionAlgorithm. os << "encryption_algorithm: " << attributes.encryption_algorithm() << '\n'; } if (attributes.has_signing_algorithm()) { has_value = true; FormatIndent(indent, os); // TODO(sigquit): Create a formatter for CdmSigningAlgorithm. os << "signing_algorithm: " << attributes.signing_algorithm() << '\n'; } if (attributes.has_oem_crypto_result()) { has_value = true; FormatIndent(indent, os); os << "oemcrypto_result:\n"; FormatOEMCryptoResult(attributes.oem_crypto_result(), indent, os); } if (attributes.has_key_status_type()) { has_value = true; FormatIndent(indent, os); os << "key_status_type: " << attributes.key_status_type() << '\n'; } if (attributes.has_event_type()) { has_value = true; FormatIndent(indent, os); os << "event_type: " << attributes.event_type() << '\n'; } if (attributes.has_key_request_type()) { has_value = true; FormatIndent(indent, os); // TODO(sigquit): Create a formatter for CdmKeyRequestType. os << "key_request_type: " << attributes.key_request_type() << '\n'; } if (attributes.has_license_type()) { has_value = true; FormatIndent(indent, os); const wvcdm::CdmLicenseType license_type = static_cast(attributes.license_type()); os << "license_type: "; FormatString(wvcdm::CdmLicenseTypeToString(license_type), os); os << '\n'; } if (attributes.has_error_detail()) { has_value = true; FormatIndent(indent, os); os << "error_detail: " << attributes.error_detail() << '\n'; } if (attributes.has_oem_crypto_signature_hash_algorithm()) { has_value = true; FormatIndent(indent, os); // TODO(sigquit): Create a formatter for OEMCrypto_SignatureHashAlgorithm. os << "oem_crypto_signature_hash_algorithm: "; os << attributes.oem_crypto_signature_hash_algorithm() << '\n'; } if (!has_value) { FormatIndent(indent, os); os << "value: null\n"; } } void FormatCounterMetricItem(const CounterMetric& cm, size_t parent_indent, int item_index, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FormatListIndent(parent_indent, os); if (cm.has_count()) { os << "count: " << cm.count(); } else { os << "count: null"; } os << " # [" << item_index << "]\n"; if (cm.has_attributes()) { FormatIndent(indent, os); os << "attributes:\n"; FormatAttributes(cm.attributes(), indent, os); } } void FormatDistributionMetricItem(const DistributionMetric& dm, size_t parent_indent, int item_index, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FormatListIndent(parent_indent, os); os << "min: "; if (dm.has_min()) { os << dm.min() << " # [" << item_index << "]\n"; } else { os << "null # [" << item_index << "]\n"; } FormatIndent(indent, os); os << "max: "; if (dm.has_max()) { os << dm.max() << '\n'; } else { os << "null\n"; } FormatIndent(indent, os); os << "mean: "; if (dm.has_mean()) { os << dm.mean() << '\n'; } else { os << "null\n"; } FormatIndent(indent, os); os << "variance: "; if (dm.has_variance()) { os << dm.variance() << '\n'; } else { os << "null\n"; } FormatIndent(indent, os); os << "count: "; if (dm.has_operation_count()) { os << dm.operation_count() << '\n'; } else { os << "null\n"; } if (dm.has_attributes()) { FormatIndent(indent, os); os << "attributes:\n"; FormatAttributes(dm.attributes(), indent, os); } } void FormatValueMetric(const ValueMetric& vm, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; bool has_value = false; // For value metrics, only one of their fields should be set; however, // this is not properly enforced by the protobuf, and all fields must be // checked. if (vm.has_error_code()) { has_value = true; FormatIndent(indent, os); os << "error_code:\n"; // Nearly every error code set for a value metric is OEMCryptoResult. FormatOEMCryptoResult(vm.error_code(), indent, os); } if (vm.has_int_value()) { has_value = true; FormatIndent(indent, os); os << "int_value: " << vm.int_value() << '\n'; } if (vm.has_double_value()) { has_value = true; FormatIndent(indent, os); os << "double_value: " << vm.double_value() << '\n'; } if (vm.has_string_value()) { has_value = true; FormatIndent(indent, os); os << "string_value: "; FormatString(vm.string_value(), os); os << '\n'; } if (!has_value) { // Can't be empty, need to provide some field. FormatIndent(indent, os); os << "value: null\n"; } } #define FORMAT_REPEATED_DISTRIBUTION(NAME, INDENT) \ if (metrics.NAME##_size() > 0) { \ FormatIndent(INDENT, os); \ os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \ for (int i = 0; i < metrics.NAME##_size(); i++) { \ FormatDistributionMetricItem(metrics.NAME(i), INDENT, i, os); \ } \ } #define FORMAT_REPEATED_COUNTER(NAME, INDENT) \ if (metrics.NAME##_size() > 0) { \ FormatIndent(INDENT, os); \ os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \ for (int i = 0; i < metrics.NAME##_size(); i++) { \ FormatCounterMetricItem(metrics.NAME(i), INDENT, i, os); \ } \ } #define FORMAT_OPTIONAL_VALUE(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatIndent(INDENT, os); \ os << #NAME ":\n"; \ FormatValueMetric(metrics.NAME(), INDENT, os); \ } #define FORMAT_OPTIONAL_INITIALIZATION_MODE(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatIndent(INDENT, os); \ os << #NAME ": "; \ const OEMCryptoInitializationMode mode = \ static_cast(metrics.NAME().int_value()); \ FormatString(OEMCryptoInitializeModeToString(mode), os); \ os << '\n'; \ } #define FORMAT_OPTIONAL_HDCP_CAPABILITY(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatIndent(INDENT, os); \ os << #NAME ": "; \ const OEMCrypto_HDCP_Capability hdcp_level = \ static_cast(metrics.NAME().int_value()); \ FormatString(OEMCryptoHdcpCapabilityToString(hdcp_level), os); \ os << '\n'; \ } #define FORMAT_OPTIONAL_PROVISIONING_METHOD(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatIndent(INDENT, os); \ os << #NAME ": "; \ const OEMCrypto_ProvisioningMethod method = \ static_cast(metrics.NAME().int_value()); \ FormatString(OEMCryptoProvisioningMethodToString(method), os); \ os << '\n'; \ } #define FORMAT_OPTIONAL_CRYPTO_METRICS(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatIndent(INDENT, os); \ os << #NAME ":\n"; \ FormatCryptoMetrics(metrics.NAME(), INDENT, os); \ } void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; // Crypto Session Metrics. FORMAT_OPTIONAL_VALUE(crypto_session_security_level, indent); FORMAT_REPEATED_COUNTER(crypto_session_delete_all_usage_reports, indent); FORMAT_REPEATED_COUNTER(crypto_session_delete_multiple_usage_information, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_generic_decrypt_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_generic_encrypt_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_generic_sign_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_generic_verify_time_us, indent); FORMAT_REPEATED_COUNTER(crypto_session_get_device_unique_id, indent); FORMAT_REPEATED_COUNTER(crypto_session_get_token, indent); FORMAT_OPTIONAL_VALUE(crypto_session_life_span, indent); FORMAT_REPEATED_DISTRIBUTION( crypto_session_load_certificate_private_key_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_open_time_us, indent); FORMAT_OPTIONAL_VALUE(crypto_session_system_id, indent); FORMAT_REPEATED_DISTRIBUTION(crypto_session_update_usage_information_time_us, indent); FORMAT_OPTIONAL_VALUE(crypto_session_usage_information_support, indent); // Usage Table Metrics FORMAT_OPTIONAL_VALUE(usage_table_header_initial_size, indent); FORMAT_REPEATED_COUNTER(usage_table_header_add_entry, indent); FORMAT_REPEATED_COUNTER(usage_table_header_delete_entry, indent); FORMAT_REPEATED_DISTRIBUTION(usage_table_header_update_entry_time_us, indent); FORMAT_REPEATED_COUNTER(usage_table_header_load_entry, indent); // Usage Table LRU Metrics FORMAT_OPTIONAL_VALUE(usage_table_header_lru_usage_info_count, indent); FORMAT_OPTIONAL_VALUE(usage_table_header_lru_offline_license_count, indent); FORMAT_OPTIONAL_VALUE(usage_table_header_lru_evicted_entry_staleness_s, indent); // |usage_table_header_lru_evicted_entry_type| refers to the enumeration // CdmUsageEntryStorageType in wv_cdm_types.h. FORMAT_OPTIONAL_VALUE(usage_table_header_lru_evicted_entry_type, indent); // OEMCrypto metrics. FORMAT_OPTIONAL_VALUE(oemcrypto_api_version, indent); FORMAT_REPEATED_COUNTER(oemcrypto_close_session, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_copy_buffer_time_us, indent); FORMAT_OPTIONAL_HDCP_CAPABILITY(oemcrypto_current_hdcp_capability, indent); FORMAT_REPEATED_COUNTER(oemcrypto_deactivate_usage_entry, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_decrypt_cenc_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_delete_usage_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_delete_usage_table, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_derive_keys_from_session_key_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_force_delete_usage_entry, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generate_derived_keys_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_generate_nonce, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generate_rsa_signature_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generate_signature_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generic_decrypt_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generic_encrypt_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generic_sign_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_generic_verify_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_get_device_id, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_get_key_data_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_get_oem_public_certificate, indent); FORMAT_REPEATED_COUNTER(oemcrypto_get_random, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_initialize_time_us, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_is_anti_rollback_hw_present, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_is_keybox_valid, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_device_drm_key_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_entitled_keys_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_keys_time_us, indent); FORMAT_OPTIONAL_HDCP_CAPABILITY(oemcrypto_max_hdcp_capability, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_max_number_of_sessions, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_number_of_open_sessions, indent); FORMAT_OPTIONAL_PROVISIONING_METHOD(oemcrypto_provisioning_method, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_refresh_keys_time_us, indent); FORMAT_REPEATED_COUNTER(oemcrypto_report_usage, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_rewrap_device_rsa_key_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_rewrap_device_rsa_key_30_time_us, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_security_patch_level, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_select_key_time_us, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_usage_table_support, indent); FORMAT_REPEATED_COUNTER(oemcrypto_update_usage_table, indent); FORMAT_REPEATED_COUNTER(oemcrypto_update_usage_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_create_usage_table_header, indent); FORMAT_REPEATED_COUNTER(oemcrypto_load_usage_table_header, indent); FORMAT_REPEATED_COUNTER(oemcrypto_shrink_usage_table_header, indent); FORMAT_REPEATED_COUNTER(oemcrypto_create_new_usage_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_load_usage_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_move_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_create_old_usage_entry, indent); FORMAT_REPEATED_COUNTER(oemcrypto_copy_old_usage_entry, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_set_sandbox, indent); FORMAT_REPEATED_COUNTER(oemcrypto_set_decrypt_hash, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_resource_rating_tier, indent); // OEMCrypto V16 metrics below FORMAT_REPEATED_DISTRIBUTION(oemcrypto_prep_and_sign_license_request_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_prep_and_sign_renewal_request_time_us, indent); FORMAT_REPEATED_DISTRIBUTION( oemcrypto_prep_and_sign_provisioning_request_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_license_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_renewal_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(oemcrypto_load_provisioning_time_us, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_minor_api_version, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_maximum_usage_table_header_size, indent); // OEMCrypto V17 metrics below. FORMAT_OPTIONAL_VALUE(oemcrypto_watermarking_support, indent); } void FormatSessionMetricsItem(const WvCdmMetrics_SessionMetrics& metrics, size_t parent_indent, int item_index, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; // Session ID needs special formatting because the index // of this element must be commented on the first line. FormatListIndent(parent_indent, os); os << "session_id:"; if (metrics.has_session_id()) { os << " # [" << item_index << "]\n"; FormatValueMetric(metrics.session_id(), indent, os); } else { os << " null # [" << item_index << "]\n"; } FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent); FORMAT_OPTIONAL_VALUE(cdm_session_life_span_ms, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_session_renew_key_time_us, indent); FORMAT_REPEATED_COUNTER(cdm_session_restore_offline_session, indent); FORMAT_REPEATED_COUNTER(cdm_session_restore_usage_session, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_session_license_request_latency_ms, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_build_info, indent); FORMAT_OPTIONAL_VALUE(license_sdk_version, indent); FORMAT_OPTIONAL_VALUE(license_service_version, indent); } void FormatEngineMetrics(const WvCdmMetrics_EngineMetrics& metrics, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent); // OEMCrypto Initialize Metrics. FORMAT_OPTIONAL_INITIALIZATION_MODE(oemcrypto_initialization_mode, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_l1_api_version, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_l1_min_api_version, indent); FORMAT_OPTIONAL_VALUE(level3_oemcrypto_initialization_error, indent); FORMAT_OPTIONAL_VALUE(previous_oemcrypto_initialization_failure, indent); // CdmEngine Metrics. FORMAT_OPTIONAL_VALUE(app_package_name, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_add_key_time_us, indent); FORMAT_OPTIONAL_VALUE(cdm_engine_cdm_version, indent); FORMAT_REPEATED_COUNTER(cdm_engine_close_session, indent); FORMAT_OPTIONAL_VALUE(cdm_engine_creation_time_millis, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_decrypt_time_us, indent); FORMAT_REPEATED_COUNTER(cdm_engine_find_session_for_key, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_generate_key_request_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_get_provisioning_request_time_us, indent); FORMAT_REPEATED_COUNTER(cdm_engine_get_secure_stop_ids, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_get_usage_info_time_us, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_handle_provisioning_response_time_us, indent); FORMAT_OPTIONAL_VALUE(cdm_engine_life_span_ms, indent); FORMAT_REPEATED_COUNTER(cdm_engine_open_key_set_session, indent); FORMAT_REPEATED_COUNTER(cdm_engine_open_session, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_query_key_status_time_us, indent); FORMAT_REPEATED_COUNTER(cdm_engine_release_all_usage_info, indent); FORMAT_REPEATED_COUNTER(cdm_engine_release_usage_info, indent); FORMAT_REPEATED_COUNTER(cdm_engine_remove_all_usage_info, indent); FORMAT_REPEATED_COUNTER(cdm_engine_remove_keys, indent); FORMAT_REPEATED_COUNTER(cdm_engine_remove_usage_info, indent); FORMAT_REPEATED_DISTRIBUTION(cdm_engine_restore_key_time_us, indent); FORMAT_REPEATED_COUNTER(cdm_engine_unprovision, indent); } } // anonymous namespace namespace wv_metrics { void FormatWvCdmMetrics(const WvCdmMetrics& metrics, size_t parent_indent, std::ostream& os) { const size_t indent = parent_indent + kIndentIncrement; FormatIndent(indent, os); os << "engine_metrics:"; if (metrics.has_engine_metrics()) { os << '\n'; FormatEngineMetrics(metrics.engine_metrics(), indent, os); } else { os << "null\n"; } FormatIndent(indent, os); os << "session_metrics:"; if (metrics.session_metrics_size() > 0) { os << " # count = " << metrics.session_metrics_size() << '\n'; for (int i = 0; i < metrics.session_metrics_size(); i++) { FormatSessionMetricsItem(metrics.session_metrics(i), indent, i, os); } } else { os << " []\n"; } } } // namespace wv_metrics