Merge "Fixed WV metrics YAML formating." into udc-dev

This commit is contained in:
Alex Dale
2023-04-24 22:04:34 +00:00
committed by Android (Google) Code Review
3 changed files with 457 additions and 303 deletions

View File

@@ -7,13 +7,14 @@
#ifndef WV_METRICS_H_
#define WV_METRICS_H_
#include <string>
#include <ostream>
#include "wv_metrics.pb.h"
namespace wv_metrics {
void FormatWvCdmMetrics(const drm_metrics::WvCdmMetrics& metrics,
std::string& result);
size_t parent_indent,
std::ostream& os);
}
#endif // WV_METRICS_H_

View File

@@ -43,6 +43,41 @@ using ::aidl::android::hardware::drm::Uuid;
WVGenericCryptoInterface WVDrmFactory::sOemCryptoInterface;
namespace {
void PrintStream(int fd, std::stringstream& ss) {
const std::string content = ss.str();
dprintf(fd, "%s", content.c_str());
}
void FormatIndent(int fd, size_t indent) {
const size_t kMaxIndent = 60;
const size_t real_indent = std::min(indent, kMaxIndent);
char buffer[kMaxIndent + 1];
memset(buffer, ' ', real_indent);
buffer[real_indent] = 0;
dprintf(fd, "%s", buffer);
if (real_indent < indent) FormatIndent(fd, indent - real_indent);
}
void FormatWvMetricsSnapshotItem(int fd, size_t parent_indent,
drm_metrics::WvCdmMetrics& metrics,
size_t item_index) {
const size_t indent = parent_indent + 2;
// TODO(b/239462891): Provide identifier and timestamp for metrics.
// Serialized proto size.
FormatIndent(fd, parent_indent); // First parameter uses indent + list tick.
dprintf(fd, "- serialized_proto_bytes: %zu # [%zu]\n",
metrics.ByteSizeLong(), item_index);
FormatIndent(fd, indent);
dprintf(fd, "cdm_metrics:\n");
std::stringstream ss;
wv_metrics::FormatWvCdmMetrics(metrics, indent, ss);
PrintStream(fd, ss);
}
} // namespace
bool WVDrmFactory::isCryptoSchemeSupported(const Uuid& in_uuid) {
return isWidevineUUID(in_uuid.uuid.data());
}
@@ -182,25 +217,30 @@ void WVDrmFactory::printCdmMetrics(int fd) {
bool full_list_returned = true;
wvcdm::CdmResponseType result =
cdm->GetMetrics(&metrics, &full_list_returned);
if (metrics.empty()) {
dprintf(fd,
" error_message: Metrics not available, please retry while streaming a video.\n");
} else if (!full_list_returned) {
dprintf(fd,
" error_message: Not all metrics are returned due to some GetMetric error, "
"please check logcat for possible GetMetric errors.\n");
}
if (result == wvcdm::NO_ERROR) {
for (auto& metric : metrics) {
dprintf(fd, " - serialized_proto_bytes: %zu\n", metric.ByteSizeLong());
string formatted;
wv_metrics::FormatWvCdmMetrics(metric, formatted);
dprintf(fd, "%s\n", formatted.c_str());
}
if (result != wvcdm::NO_ERROR) {
dprintf(fd, " live_metrics:\n");
dprintf(fd, " error_message: \"%s\"\n", result.ToString().c_str());
dprintf(fd, " error_code: %d\n", static_cast<int>(result.code()));
} else if (metrics.empty()) {
// YAML does not support empty property values.
const char kNoMetricsMessage[] =
"Metrics not available, please retry while streaming a video.";
dprintf(fd, " live_metrics: [] # %s\n", kNoMetricsMessage);
} else {
dprintf(fd, " error_message: %s\n", result.GetCodeString());
dprintf(fd, " error_code: %d\n", result.ToInt());
dprintf(fd, " live_metrics: ");
if (full_list_returned) {
dprintf(fd, "# count = %zu\n", metrics.size());
} else {
const char kPartialListMessage[] =
"Some metrics are missing due to an internal error, "
"check logs for details.";
dprintf(fd, "# count = %zu, %s\n", metrics.size(), kPartialListMessage);
}
for (size_t i = 0; i < metrics.size(); i++) {
FormatWvMetricsSnapshotItem(fd, 2, metrics[i], i);
}
}
// TODO(b/270166158): Print metrics history.
}
void WVDrmFactory::printCdmProperties(int fd) {

View File

@@ -6,364 +6,460 @@
#include "wv_metrics.h"
#include <fstream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <ostream>
#include <aidl/android/hardware/drm/Status.h>
#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 std::string;
using std::to_string;
using ::wvcdm::metrics::OEMCryptoInitializationMode;
namespace {
const string kIndentSpaces = " ";
constexpr size_t kIndentIncrement = 2;
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.";
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);
}
}
string FormatOEMCryptoInitializeMode(const ValueMetric& vm) {
std::map<int, string> 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()];
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<int>(mode));
}
string FormatOEMCryptoHdcpCapability(const ValueMetric& vm) {
std::map<int, string> 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()];
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<int>(hdcp_level));
}
string FormatOEMCryptoProvisioningMethod(const ValueMetric& vm) {
std::map<int, string> translations = {{0, "PROVISIONING_ERROR"},
{1, "DRM_CERTIFICATE"},
{2, "KEYBOX"},
{3, "OEM_CERTIFICATE"}};
return translations[vm.int_value()];
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<int>(method));
}
string FormatAttributes(const string& indent, const Attributes& attributes) {
string result;
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<OEMCryptoResult>(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<wvcdm::CdmResponseEnum>(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()) {
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()));
has_value = true;
FormatIndent(indent, os);
os << "error_code:\n";
FormatCdmErrorCode(attributes.error_code(), indent, os);
}
if (attributes.has_error_code_bool()) {
result.assign(indent);
result.append("success: ");
result.append(attributes.error_code_bool() ? "true" : "false");
has_value = true;
FormatIndent(indent, os);
os << "success: ";
os << (attributes.error_code_bool() ? "true" : "false");
os << '\n';
}
if (attributes.has_cdm_security_level()) {
result.assign(indent);
result.append("cdm_security_level: ");
result.append(to_string(attributes.cdm_security_level()));
has_value = true;
FormatIndent(indent, os);
const wvcdm::CdmSecurityLevel cdm_security_level =
static_cast<wvcdm::CdmSecurityLevel>(attributes.cdm_security_level());
os << "cdm_security_level: ";
FormatString(wvcdm::CdmSecurityLevelToString(cdm_security_level), os);
os << '\n';
}
if (attributes.has_security_level()) {
result.assign(indent);
result.append("security_level: ");
result.append(to_string(attributes.security_level()));
has_value = true;
FormatIndent(indent, os);
const wvcdm::RequestedSecurityLevel security_level =
static_cast<wvcdm::RequestedSecurityLevel>(attributes.security_level());
os << "security_level: ";
FormatString(wvcdm::RequestedSecurityLevelToString(security_level), os);
os << '\n';
}
if (attributes.has_length()) {
result.assign(indent);
result.append("length: ");
result.append(to_string(attributes.length()));
has_value = true;
FormatIndent(indent, os);
os << "length: " << attributes.length() << '\n';
}
if (attributes.has_encryption_algorithm()) {
result.assign(indent);
result.append("encryption_algorithm: ");
result.append(to_string(attributes.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()) {
result.assign(indent);
result.append("signing_algorithm: ");
result.append(to_string(attributes.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()) {
result.assign(indent);
result.append("oemcrypto_result:\n");
string next_indent = indent + kIndentSpaces;
result.append(next_indent + "name: ");
result.append(::wvcdm::OemCryptoResultToString(
static_cast<OEMCryptoResult>(attributes.oem_crypto_result())));
result.append("\n" + next_indent + "value: ");
result.append(to_string(attributes.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()) {
result.assign(indent);
result.append("key_status_type: ");
result.append(to_string(attributes.key_status_type()));
has_value = true;
FormatIndent(indent, os);
os << "key_status_type: " << attributes.key_status_type() << '\n';
}
if (attributes.has_event_type()) {
result.assign(indent);
result.append("event_type: ");
result.append(to_string(attributes.event_type()));
has_value = true;
FormatIndent(indent, os);
os << "event_type: " << attributes.event_type() << '\n';
}
if (attributes.has_key_request_type()) {
result.assign(indent);
result.append("key_request_type: ");
result.append(to_string(attributes.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()) {
result.assign(indent);
result.append("license_type: ");
result.append(to_string(attributes.license_type()));
has_value = true;
FormatIndent(indent, os);
const wvcdm::CdmLicenseType license_type =
static_cast<wvcdm::CdmLicenseType>(attributes.license_type());
os << "license_type: ";
FormatString(wvcdm::CdmLicenseTypeToString(license_type), os);
os << '\n';
}
if (attributes.has_error_detail()) {
result.assign(indent);
result.append("error_detail: ");
result.append(to_string(attributes.error_detail()));
has_value = true;
FormatIndent(indent, os);
os << "error_detail: " << attributes.error_detail() << '\n';
}
if (result.size()) {
return result;
} else {
return " null";
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";
}
}
string FormatCounterMetric(const string& indent, const CounterMetric& cm) {
string result(indent + kIndentSpaces);
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()) {
result.append(string("count: ") + to_string(cm.count()) + "\n");
os << "count: " << cm.count();
} else {
os << "count: null";
}
os << " # [" << item_index << "]\n";
if (cm.has_attributes()) {
string newIndent(indent + kIndentSpaces);
result.append(FormatAttributes(newIndent, cm.attributes()));
FormatIndent(indent, os);
os << "attributes:\n";
FormatAttributes(cm.attributes(), indent, os);
}
}
return result;
}
string FormatDistributionMetric(const string& indent, const DistributionMetric& dm) {
string result;
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()) {
std::ostringstream buffer;
buffer << dm.min();
result.append(indent + kIndentSpaces);
result.append(string("min: ") + buffer.str() + "\n");
os << dm.min() << " # [" << item_index << "]\n";
} else {
os << "null # [" << item_index << "]\n";
}
FormatIndent(indent, os);
os << "max: ";
if (dm.has_max()) {
std::ostringstream buffer;
buffer << dm.max();
result.append(indent + kIndentSpaces);
result.append(string("max: ") + buffer.str() + "\n");
os << dm.max() << '\n';
} else {
os << "null\n";
}
FormatIndent(indent, os);
os << "mean: ";
if (dm.has_mean()) {
std::ostringstream buffer;
buffer << dm.mean();
result.append(indent + kIndentSpaces);
result.append(string("mean: ") + buffer.str() + "\n");
os << dm.mean() << '\n';
} else {
os << "null\n";
}
FormatIndent(indent, os);
os << "variance: ";
if (dm.has_variance()) {
std::ostringstream buffer;
buffer << dm.variance();
result.append(indent + kIndentSpaces);
result.append(string("variance: ") + buffer.str() + "\n");
os << dm.variance() << '\n';
} else {
os << "null\n";
}
FormatIndent(indent, os);
os << "count: ";
if (dm.has_operation_count()) {
result.append(indent + kIndentSpaces);
result.append(string("count: ") + to_string(dm.operation_count()) + "\n");
os << dm.operation_count() << '\n';
} else {
os << "null\n";
}
if (dm.has_attributes()) {
string newIndent(indent + kIndentSpaces);
result.append(FormatAttributes(newIndent, dm.attributes()));
FormatIndent(indent, os);
os << "attributes:\n";
FormatAttributes(dm.attributes(), indent, os);
}
return result;
}
string FormatValueMetric(const ValueMetric& vm) {
string result;
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()) {
result.append("error_code:\n");
result.append(kIndentSpaces + "name: ");
result.append(DrmHalStatusToString(static_cast<Status>(vm.error_code())));
result.append("\n" + kIndentSpaces + "value: ");
result.append(to_string(vm.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()) {
result.append(to_string(vm.int_value()));
has_value = true;
FormatIndent(indent, os);
os << "int_value: " << vm.int_value() << '\n';
}
if (vm.has_double_value()) {
std::ostringstream buffer;
buffer << vm.double_value();
result.append(buffer.str());
has_value = true;
FormatIndent(indent, os);
os << "double_value: " << vm.double_value() << '\n';
}
if (vm.has_string_value()) {
result.append("\"" + vm.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";
}
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 { \
if (metrics.NAME##_size() > 0) { \
FormatIndent(INDENT, os); \
os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \
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"); \
FormatDistributionMetricItem(metrics.NAME(i), INDENT, i, os); \
} \
}
#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 { \
if (metrics.NAME##_size() > 0) { \
FormatIndent(INDENT, os); \
os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \
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"); \
FormatCounterMetricItem(metrics.NAME(i), INDENT, i, os); \
} \
}
#define FORMAT_OPTIONAL_VALUE(NAME, INDENT) \
if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": " + FormatValueMetric(metrics.NAME()) + \
"\n"); \
FormatIndent(INDENT, os); \
os << #NAME ":\n"; \
FormatValueMetric(metrics.NAME(), INDENT, os); \
}
#define FORMAT_OPTIONAL_INITIALIZATION_MODE(NAME, INDENT) \
if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": "); \
result.append(FormatOEMCryptoInitializeMode(metrics.NAME()) + "\n"); \
FormatIndent(INDENT, os); \
os << #NAME ": "; \
const OEMCryptoInitializationMode mode = \
static_cast<OEMCryptoInitializationMode>(metrics.NAME().int_value()); \
FormatString(OEMCryptoInitializeModeToString(mode), os); \
os << '\n'; \
}
#define FORMAT_OPTIONAL_HDCP_CAPABILITY(NAME, INDENT) \
if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": "); \
result.append(FormatOEMCryptoHdcpCapability(metrics.NAME()) + "\n"); \
FormatIndent(INDENT, os); \
os << #NAME ": "; \
const OEMCrypto_HDCP_Capability hdcp_level = \
static_cast<OEMCrypto_HDCP_Capability>(metrics.NAME().int_value()); \
FormatString(OEMCryptoHdcpCapabilityToString(hdcp_level), os); \
os << '\n'; \
}
#define FORMAT_OPTIONAL_PROVISIONING_METHOD(NAME, INDENT) \
if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": "); \
result.append(FormatOEMCryptoProvisioningMethod(metrics.NAME()) + "\n"); \
FormatIndent(INDENT, os); \
os << #NAME ": "; \
const OEMCrypto_ProvisioningMethod method = \
static_cast<OEMCrypto_ProvisioningMethod>(metrics.NAME().int_value()); \
FormatString(OEMCryptoProvisioningMethodToString(method), os); \
os << '\n'; \
}
#define FORMAT_OPTIONAL_CRYPTO_METRICS(NAME, INDENT) \
if (metrics.has_##NAME()) { \
FormatCryptoMetrics(metrics.NAME(), INDENT, result); \
FormatIndent(INDENT, os); \
os << #NAME ":\n"; \
FormatCryptoMetrics(metrics.NAME(), INDENT, os); \
}
void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics,
const string& indent, string& result) {
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);
@@ -401,7 +497,7 @@ void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics,
// CdmUsageEntryStorageType in wv_cdm_types.h.
FORMAT_OPTIONAL_VALUE(usage_table_header_lru_evicted_entry_type, indent);
// OemCrypto metrics.
// 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);
@@ -458,7 +554,7 @@ void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics,
FORMAT_REPEATED_COUNTER(oemcrypto_set_decrypt_hash, indent);
FORMAT_OPTIONAL_VALUE(oemcrypto_resource_rating_tier, indent);
// Oemcrypto V16 metrics below
// 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,
@@ -475,8 +571,21 @@ void FormatCryptoMetrics(const WvCdmMetrics_CryptoMetrics metrics,
FORMAT_OPTIONAL_VALUE(oemcrypto_watermarking_support, indent);
}
void FormatSessionMetrics(const WvCdmMetrics_SessionMetrics& metrics,
const string& indent, string& result) {
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_VALUE(session_id, indent);
FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent);
FORMAT_OPTIONAL_VALUE(cdm_session_life_span_ms, indent);
@@ -490,7 +599,9 @@ void FormatSessionMetrics(const WvCdmMetrics_SessionMetrics& metrics,
}
void FormatEngineMetrics(const WvCdmMetrics_EngineMetrics& metrics,
const string& indent, string& result) {
size_t parent_indent, std::ostream& os) {
const size_t indent = parent_indent + kIndentIncrement;
FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent);
// OEMCrypto Initialize Metrics.
@@ -530,25 +641,27 @@ void FormatEngineMetrics(const WvCdmMetrics_EngineMetrics& metrics,
} // 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:");
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()) {
result.append("\n");
FormatEngineMetrics(metrics.engine_metrics(), indent, result);
os << '\n';
FormatEngineMetrics(metrics.engine_metrics(), indent, os);
} else {
result.append(" null\n");
os << "null\n";
}
result.append(kIndentSpaces + " session_metrics:");
if (metrics.session_metrics_size()) {
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++) {
result.append("\n" + indent + "session[" + to_string(i) + "]:\n");
FormatSessionMetrics(metrics.session_metrics(i), next_indent, result);
FormatSessionMetricsItem(metrics.session_metrics(i), indent, i, os);
}
} else {
result.append(" null\n");
os << " []\n";
}
}
} // namespace wv_metrics