// 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 #include #include #include #include "OEMCryptoCENC.h" #include "error_string_util.h" #include "wv_cdm_types.h" using namespace drm_metrics; using ::aidl::android::hardware::drm::Status; using std::string; using std::to_string; namespace { const string kIndentSpaces = " "; const string DrmHalStatusToString(Status hal_status) { switch (hal_status) { case Status::OK: return "OK"; case Status::ERROR_DRM_NO_LICENSE: return "ERROR_DRM_NO_LICENSE"; case Status::ERROR_DRM_LICENSE_EXPIRED: return "ERROR_DRM_LICENSE_EXPIRED"; case Status::ERROR_DRM_SESSION_NOT_OPENED: return "ERROR_DRM_SESSION_NOT_OPENED"; case Status::ERROR_DRM_CANNOT_HANDLE: return "ERROR_DRM_CANNOT_HANDLE"; case Status::ERROR_DRM_INVALID_STATE: return "ERROR_DRM_INVALID_STATE,"; case Status::BAD_VALUE: return "BAD_VALUE"; case Status::ERROR_DRM_NOT_PROVISIONED: return "ERROR_DRM_NOT_PROVISIONED"; case Status::ERROR_DRM_RESOURCE_BUSY: return "ERROR_DRM_RESOURCE_BUSY"; case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION: return "ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION"; case Status::ERROR_DRM_DEVICE_REVOKED: return "ERROR_DRM_DEVICE_REVOKED"; case Status::ERROR_DRM_DECRYPT: return "ERROR_DRM_DECRYPT"; case Status::ERROR_DRM_UNKNOWN: return "ERROR_DRM_UNKNOWN"; case Status::ERROR_DRM_INSUFFICIENT_SECURITY: return "ERROR_DRM_INSUFFICIENT_SECURITY"; case Status::ERROR_DRM_FRAME_TOO_LARGE: return "ERROR_DRM_FRAME_TOO_LARGE"; case Status::ERROR_DRM_SESSION_LOST_STATE: return "ERROR_DRM_SESSION_LOST_STATE"; case Status::ERROR_DRM_RESOURCE_CONTENTION: return "ERROR_DRM_RESOURCE_CONTENTION"; case Status::CANNOT_DECRYPT_ZERO_SUBSAMPLES: return "CANNOT_DECRYPT_ZERO_SUBSAMPLES"; case Status::CRYPTO_LIBRARY_ERROR: return "CRYPTO_LIBRARY_ERROR"; case Status::GENERAL_OEM_ERROR: return "GENERAL_OEM_ERROR"; case Status::GENERAL_PLUGIN_ERROR: return "GENERAL_PLUGIN_ERROR"; case Status::INIT_DATA_INVALID: return "INIT_DATA_INVALID"; case Status::KEY_NOT_LOADED: return "KEY_NOT_LOADED"; case Status::LICENSE_PARSE_ERROR: return "LICENSE_PARSE_ERROR"; case Status::LICENSE_POLICY_ERROR: return "LICENSE_POLICY_ERROR"; case Status::LICENSE_RELEASE_ERROR: return "LICENSE_RELEASE_ERROR"; case Status::LICENSE_REQUEST_REJECTED: return "LICENSE_REQUEST_REJECTED"; case Status::LICENSE_RESTORE_ERROR: return "LICENSE_RESTORE_ERROR"; case Status::LICENSE_STATE_ERROR: return "LICENSE_STATE_ERROR"; case Status::MALFORMED_CERTIFICATE: return "MALFORMED_CERTIFICATE"; case Status::MEDIA_FRAMEWORK_ERROR: return "MEDIA_FRAMEWORK_ERROR"; case Status::MISSING_CERTIFICATE: return "MISSING_CERTIFICATE"; case Status::PROVISIONING_CERTIFICATE_ERROR: return "PROVISIONING_CERTIFICATE_ERROR"; case Status::PROVISIONING_CONFIGURATION_ERROR: return "PROVISIONING_CONFIGURATION_ERROR"; case Status::PROVISIONING_PARSE_ERROR: return "PROVISIONING_PARSE_ERROR"; case Status::PROVISIONING_REQUEST_REJECTED: return "PROVISIONING_REQUEST_REJECTED"; case Status::RETRYABLE_PROVISIONING_ERROR: return "RETRYABLE_PROVISIONING_ERROR"; case Status::SECURE_STOP_RELEASE_ERROR: return "SECURE_STOP_RELEASE_ERROR"; case Status::STORAGE_READ_FAILURE: return "STORAGE_READ_FAILURE"; case Status::STORAGE_WRITE_FAILURE: return "STORAGE_WRITE_FAILURE"; default: return "Invalid Drm HAL status."; } } string FormatOEMCryptoInitializeMode(const ValueMetric& vm) { std::map translations = { {0, "USING_IN_APP"}, {1, "FORCING_L3"}, {2, "USING_L3_NO_L1_LIBRARY_PATH"}, {3, "USING_L3_L1_OPEN_FAILED"}, {4, "USING_L3_L1_LOAD_FAILED"}, {5, "USING_L3_COULD_NOT_INITIALIZE_L1"}, {6, "USING_L3_WRONG_L1_VERSION"}, {7, "USING_L1_WITH_KEYBOX"}, {8, "USING_L1_WITH_CERTIFICATE"}, {9, "USING_L1_CERTIFICATE_MIX"}, {10, "USING_L3_BAD_KEYBOX"}, {11, "USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX"}, {12, "USING_L3_COULD_NOT_INSTALL_KEYBOX"}, {13, "USING_L1_INSTALLED_KEYBOX"}, {14, "USING_L3_INVALID_L1"}, {15, "USING_L1_WITH_PROVISIONING_3_0"}, {16, "L3_INITIALIZATION_GENERAL_FAILED"}, {17, "L3_INITIALIZATION_RNG_FAILED"}, {18, "L3_INITIALIZATION_SAVE_DEVICE_KEYS_FAILED"}, {19, "L3_INITIALIZATION_READ_DEVICE_KEYS_FAILED"}, {20, "L3_INITIALIZATION_VERIFY_DEVIE_KEYS_FAILED"}}; return translations[vm.int_value()]; } string FormatOEMCryptoHdcpCapability(const ValueMetric& vm) { std::map translations = { {0, "HDCP_NONE"}, {1, "HDCP_V1"}, {2, "HDCP_V2"}, {3, "HDCP_V2_1"}, {4, "HDCP_V2_2"}, {5, "HDCP_V2_3"}, {0xff, "NO_DIGITAL_OUTPUT"}}; return translations[vm.int_value()]; } string FormatOEMCryptoProvisioningMethod(const ValueMetric& vm) { std::map translations = {{0, "PROVISIONING_ERROR"}, {1, "DRM_CERTIFICATE"}, {2, "KEYBOX"}, {3, "OEM_CERTIFICATE"}}; return translations[vm.int_value()]; } string FormatAttributes(const string& indent, const Attributes& attributes) { string result; if (attributes.has_error_code()) { result.assign(indent); result.append("error_code:\n"); string next_indent = indent + kIndentSpaces; result.append(next_indent + "name: "); result.append(wvcdm::CdmResponseEnumToString( wvcdm::CdmResponseEnum(attributes.error_code()))); result.append("\n" + next_indent + "value: "); result.append(to_string(attributes.error_code())); } if (attributes.has_error_code_bool()) { result.assign(indent); result.append("success: "); result.append(attributes.error_code_bool() ? "true" : "false"); } if (attributes.has_cdm_security_level()) { result.assign(indent); result.append("cdm_security_level: "); result.append(to_string(attributes.cdm_security_level())); } if (attributes.has_security_level()) { result.assign(indent); result.append("security_level: "); result.append(to_string(attributes.security_level())); } if (attributes.has_length()) { result.assign(indent); result.append("length: "); result.append(to_string(attributes.length())); } if (attributes.has_encryption_algorithm()) { result.assign(indent); result.append("encryption_algorithm: "); result.append(to_string(attributes.encryption_algorithm())); } if (attributes.has_signing_algorithm()) { result.assign(indent); result.append("signing_algorithm: "); result.append(to_string(attributes.signing_algorithm())); } if (attributes.has_oem_crypto_result()) { result.assign(indent); result.append("oemcrypto_result:\n"); string next_indent = indent + kIndentSpaces; result.append(next_indent + "name: "); result.append(::wvutil::OEMCryptoResultToString(attributes.oem_crypto_result())); result.append("\n" + next_indent + "value: "); result.append(to_string(attributes.oem_crypto_result())); } if (attributes.has_key_status_type()) { result.assign(indent); result.append("key_status_type: "); result.append(to_string(attributes.key_status_type())); } if (attributes.has_event_type()) { result.assign(indent); result.append("event_type: "); result.append(to_string(attributes.event_type())); } if (attributes.has_key_request_type()) { result.assign(indent); result.append("key_request_type: "); result.append(to_string(attributes.key_request_type())); } if (attributes.has_license_type()) { result.assign(indent); result.append("license_type: "); result.append(to_string(attributes.license_type())); } if (attributes.has_error_detail()) { result.assign(indent); result.append("error_detail: "); result.append(to_string(attributes.error_detail())); } if (result.size()) { return result; } else { return " null"; } } string FormatCounterMetric(const string& indent, const CounterMetric& cm) { string result(indent + kIndentSpaces); if (cm.has_count()) { result.append(string("count: ") + to_string(cm.count()) + "\n"); if (cm.has_attributes()) { string newIndent(indent + kIndentSpaces); result.append(FormatAttributes(newIndent, cm.attributes())); } } return result; } string FormatDistributionMetric(const string& indent, const DistributionMetric& dm) { string result; if (dm.has_min()) { std::ostringstream buffer; buffer << dm.min(); result.append(indent + kIndentSpaces); result.append(string("min: ") + buffer.str() + "\n"); } if (dm.has_max()) { std::ostringstream buffer; buffer << dm.max(); result.append(indent + kIndentSpaces); result.append(string("max: ") + buffer.str() + "\n"); } if (dm.has_mean()) { std::ostringstream buffer; buffer << dm.mean(); result.append(indent + kIndentSpaces); result.append(string("mean: ") + buffer.str() + "\n"); } if (dm.has_variance()) { std::ostringstream buffer; buffer << dm.variance(); result.append(indent + kIndentSpaces); result.append(string("variance: ") + buffer.str() + "\n"); } if (dm.has_operation_count()) { result.append(indent + kIndentSpaces); result.append(string("count: ") + to_string(dm.operation_count()) + "\n"); } if (dm.has_attributes()) { string newIndent(indent + kIndentSpaces); result.append(FormatAttributes(newIndent, dm.attributes())); } return result; } string FormatValueMetric(const ValueMetric& vm) { string result; if (vm.has_error_code()) { result.append("error_code:\n"); result.append(kIndentSpaces + "name: "); result.append(DrmHalStatusToString(static_cast(vm.error_code()))); result.append("\n" + kIndentSpaces + "value: "); result.append(to_string(vm.error_code())); } if (vm.has_int_value()) { result.append(to_string(vm.int_value())); } if (vm.has_double_value()) { std::ostringstream buffer; buffer << vm.double_value(); result.append(buffer.str()); } if (vm.has_string_value()) { result.append("\"" + vm.string_value() + "\""); } return result; } #define FORMAT_REPEATED_DISTRIBUTION(NAME, INDENT) \ if (metrics.NAME##_size() == 1) { \ result.append(INDENT + #NAME + ":\n"); \ result.append(FormatDistributionMetric(INDENT, metrics.NAME(0)) + "\n"); \ } else { \ for (int i = 0; i < metrics.NAME##_size(); i++) { \ result.append(INDENT + #NAME "[" + to_string(i) + "]:\n"); \ result.append(FormatDistributionMetric(INDENT, metrics.NAME(i)) + "\n"); \ } \ } #define FORMAT_REPEATED_COUNTER(NAME, INDENT) \ if (metrics.NAME##_size() == 1) { \ result.append(INDENT + #NAME ":\n"); \ result.append(FormatCounterMetric(INDENT, metrics.NAME(0)) + "\n"); \ } else { \ for (int i = 0; i < metrics.NAME##_size(); i++) { \ result.append(INDENT + #NAME "[" + to_string(i) + "]: [\n"); \ result.append(FormatCounterMetric(INDENT, metrics.NAME(i)) + "\n"); \ result.append("]\n"); \ } \ } #define FORMAT_OPTIONAL_VALUE(NAME, INDENT) \ if (metrics.has_##NAME()) { \ result.append(INDENT + #NAME ": " + FormatValueMetric(metrics.NAME()) + \ "\n"); \ } #define FORMAT_OPTIONAL_INITIALIZATION_MODE(NAME, INDENT) \ if (metrics.has_##NAME()) { \ result.append(INDENT + #NAME ": "); \ result.append(FormatOEMCryptoInitializeMode(metrics.NAME()) + "\n"); \ } #define FORMAT_OPTIONAL_HDCP_CAPABILITY(NAME, INDENT) \ if (metrics.has_##NAME()) { \ result.append(INDENT + #NAME ": "); \ result.append(FormatOEMCryptoHdcpCapability(metrics.NAME()) + "\n"); \ } #define FORMAT_OPTIONAL_PROVISIONING_METHOD(NAME, INDENT) \ if (metrics.has_##NAME()) { \ result.append(INDENT + #NAME ": "); \ result.append(FormatOEMCryptoProvisioningMethod(metrics.NAME()) + "\n"); \ } #define FORMAT_OPTIONAL_CRYPTO_METRICS(NAME, INDENT) \ if (metrics.has_##NAME()) { \ FormatCryptoMetrics(metrics.NAME(), INDENT, result); \ } void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics, const string& indent, string& result) { // 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 FormatSessionMetrics(const WvCdmMetrics_SessionMetrics& metrics, const string& indent, string& result) { FORMAT_OPTIONAL_VALUE(session_id, indent); 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, const string& indent, string& result) { 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, string& result) { string indent = kIndentSpaces + kIndentSpaces + kIndentSpaces; string next_indent = indent + kIndentSpaces; result.append(kIndentSpaces + " engine_metrics:"); if (metrics.has_engine_metrics()) { result.append("\n"); FormatEngineMetrics(metrics.engine_metrics(), indent, result); } else { result.append(" null\n"); } result.append(kIndentSpaces + " session_metrics:"); if (metrics.session_metrics_size()) { for (int i = 0; i < metrics.session_metrics_size(); i++) { result.append("\n" + indent + "session[" + to_string(i) + "]:\n"); FormatSessionMetrics(metrics.session_metrics(i), next_indent, result); } } else { result.append(" null\n"); } } } // namespace wv_metrics