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

View File

@@ -43,6 +43,41 @@ using ::aidl::android::hardware::drm::Uuid;
WVGenericCryptoInterface WVDrmFactory::sOemCryptoInterface; 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) { bool WVDrmFactory::isCryptoSchemeSupported(const Uuid& in_uuid) {
return isWidevineUUID(in_uuid.uuid.data()); return isWidevineUUID(in_uuid.uuid.data());
} }
@@ -182,25 +217,30 @@ void WVDrmFactory::printCdmMetrics(int fd) {
bool full_list_returned = true; bool full_list_returned = true;
wvcdm::CdmResponseType result = wvcdm::CdmResponseType result =
cdm->GetMetrics(&metrics, &full_list_returned); cdm->GetMetrics(&metrics, &full_list_returned);
if (metrics.empty()) { if (result != wvcdm::NO_ERROR) {
dprintf(fd, dprintf(fd, " live_metrics:\n");
" error_message: Metrics not available, please retry while streaming a video.\n"); dprintf(fd, " error_message: \"%s\"\n", result.ToString().c_str());
} else if (!full_list_returned) { dprintf(fd, " error_code: %d\n", static_cast<int>(result.code()));
dprintf(fd, } else if (metrics.empty()) {
" error_message: Not all metrics are returned due to some GetMetric error, " // YAML does not support empty property values.
"please check logcat for possible GetMetric errors.\n"); const char kNoMetricsMessage[] =
} "Metrics not available, please retry while streaming a video.";
if (result == wvcdm::NO_ERROR) { dprintf(fd, " live_metrics: [] # %s\n", kNoMetricsMessage);
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());
}
} else { } else {
dprintf(fd, " error_message: %s\n", result.GetCodeString()); dprintf(fd, " live_metrics: ");
dprintf(fd, " error_code: %d\n", result.ToInt()); 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) { void WVDrmFactory::printCdmProperties(int fd) {

View File

@@ -6,364 +6,460 @@
#include "wv_metrics.h" #include "wv_metrics.h"
#include <fstream> #include <ostream>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <aidl/android/hardware/drm/Status.h> #include <aidl/android/hardware/drm/Status.h>
#include "OEMCryptoCENC.h" #include "OEMCryptoCENC.h"
#include "metrics_collections.h"
#include "string_conversions.h"
#include "wv_cdm_types.h" #include "wv_cdm_types.h"
using namespace drm_metrics; using namespace drm_metrics;
using ::aidl::android::hardware::drm::Status; using ::aidl::android::hardware::drm::Status;
using std::string; using ::wvcdm::metrics::OEMCryptoInitializationMode;
using std::to_string;
namespace { namespace {
const string kIndentSpaces = " "; constexpr size_t kIndentIncrement = 2;
const string DrmHalStatusToString(Status hal_status) { void FormatIndent(size_t indent, std::ostream& os) {
switch (hal_status) { for (size_t i = 0; i < indent; i++) os.put(' ');
case Status::OK: }
return "OK";
case Status::ERROR_DRM_NO_LICENSE: void FormatListIndent(size_t parent_indent, std::ostream& os) {
return "ERROR_DRM_NO_LICENSE"; FormatIndent(parent_indent, os);
case Status::ERROR_DRM_LICENSE_EXPIRED: os.put('-');
return "ERROR_DRM_LICENSE_EXPIRED"; FormatIndent(kIndentIncrement - 1, os);
case Status::ERROR_DRM_SESSION_NOT_OPENED: }
return "ERROR_DRM_SESSION_NOT_OPENED";
case Status::ERROR_DRM_CANNOT_HANDLE: void FormatString(const std::string& s, std::ostream& os) {
return "ERROR_DRM_CANNOT_HANDLE"; os << '"';
case Status::ERROR_DRM_INVALID_STATE: if (std::any_of(s.begin(), s.end(), [](char c) { return c == '"'; })) {
return "ERROR_DRM_INVALID_STATE,"; // Escape any double quotes.
case Status::BAD_VALUE: for (char c : s) {
return "BAD_VALUE"; if (c == '"') {
case Status::ERROR_DRM_NOT_PROVISIONED: os << "\\\"";
return "ERROR_DRM_NOT_PROVISIONED"; } else {
case Status::ERROR_DRM_RESOURCE_BUSY: os << c;
return "ERROR_DRM_RESOURCE_BUSY"; }
case Status::ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION: }
return "ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION"; } else {
case Status::ERROR_DRM_DEVICE_REVOKED: os << s;
return "ERROR_DRM_DEVICE_REVOKED"; }
case Status::ERROR_DRM_DECRYPT: os << '"';
return "ERROR_DRM_DECRYPT"; }
case Status::ERROR_DRM_UNKNOWN:
return "ERROR_DRM_UNKNOWN"; void FormatString(const char* s, std::ostream& os) {
case Status::ERROR_DRM_INSUFFICIENT_SECURITY: if (s == nullptr) {
return "ERROR_DRM_INSUFFICIENT_SECURITY"; os << "null";
case Status::ERROR_DRM_FRAME_TOO_LARGE: } else {
return "ERROR_DRM_FRAME_TOO_LARGE"; FormatString(std::string(s), os);
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) { const char* OEMCryptoInitializeModeToString(OEMCryptoInitializationMode mode) {
std::map<int, string> translations = { using namespace wvcdm::metrics;
{0, "USING_IN_APP"}, switch (mode) {
{1, "FORCING_L3"}, case OEMCrypto_INITIALIZED_USING_IN_APP:
{2, "USING_L3_NO_L1_LIBRARY_PATH"}, return "USING_IN_APP";
{3, "USING_L3_L1_OPEN_FAILED"}, case OEMCrypto_INITIALIZED_FORCING_L3:
{4, "USING_L3_L1_LOAD_FAILED"}, return "FORCING_L3";
{5, "USING_L3_COULD_NOT_INITIALIZE_L1"}, case OEMCrypto_INITIALIZED_USING_L3_NO_L1_LIBRARY_PATH:
{6, "USING_L3_WRONG_L1_VERSION"}, return "USING_L3_NO_L1_LIBRARY_PATH";
{7, "USING_L1_WITH_KEYBOX"}, case OEMCrypto_INITIALIZED_USING_L3_L1_OPEN_FAILED:
{8, "USING_L1_WITH_CERTIFICATE"}, return "USING_L3_L1_OPEN_FAILED";
{9, "USING_L1_CERTIFICATE_MIX"}, case OEMCrypto_INITIALIZED_USING_L3_L1_LOAD_FAILED:
{10, "USING_L3_BAD_KEYBOX"}, return "USING_L3_L1_LOAD_FAILED";
{11, "USING_L3_COULD_NOT_OPEN_FACTORY_KEYBOX"}, case OEMCrypto_INITIALIZED_USING_L3_COULD_NOT_INITIALIZE_L1:
{12, "USING_L3_COULD_NOT_INSTALL_KEYBOX"}, return "USING_L3_COULD_NOT_INITIALIZE_L1";
{13, "USING_L1_INSTALLED_KEYBOX"}, case OEMCrypto_INITIALIZED_USING_L3_WRONG_L1_VERSION:
{14, "USING_L3_INVALID_L1"}, return "USING_L3_WRONG_L1_VERSION";
{15, "USING_L1_WITH_PROVISIONING_3_0"}, case OEMCrypto_INITIALIZED_USING_L1_WITH_KEYBOX:
{16, "L3_INITIALIZATION_GENERAL_FAILED"}, return "USING_L1_WITH_KEYBOX";
{17, "L3_INITIALIZATION_RNG_FAILED"}, case OEMCrypto_INITIALIZED_USING_L1_WITH_CERTIFICATE:
{18, "L3_INITIALIZATION_SAVE_DEVICE_KEYS_FAILED"}, return "USING_L1_WITH_CERTIFICATE";
{19, "L3_INITIALIZATION_READ_DEVICE_KEYS_FAILED"}, case OEMCrypto_INITIALIZED_USING_L1_CERTIFICATE_MIX:
{20, "L3_INITIALIZATION_VERIFY_DEVIE_KEYS_FAILED"}}; return "USING_L1_CERTIFICATE_MIX";
return translations[vm.int_value()]; 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) { const char* OEMCryptoHdcpCapabilityToString(
std::map<int, string> translations = { OEMCrypto_HDCP_Capability hdcp_level) {
{0, "HDCP_NONE"}, {1, "HDCP_V1"}, {2, "HDCP_V2"}, switch (hdcp_level) {
{3, "HDCP_V2_1"}, {4, "HDCP_V2_2"}, {5, "HDCP_V2_3"}, case HDCP_NONE:
{0xff, "NO_DIGITAL_OUTPUT"}}; return "HDCP_NONE";
return translations[vm.int_value()]; 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) { const char* OEMCryptoProvisioningMethodToString(
std::map<int, string> translations = {{0, "PROVISIONING_ERROR"}, OEMCrypto_ProvisioningMethod method) {
{1, "DRM_CERTIFICATE"}, switch (method) {
{2, "KEYBOX"}, case OEMCrypto_ProvisioningError:
{3, "OEM_CERTIFICATE"}}; return "PROVISIONING_ERROR";
return translations[vm.int_value()]; 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) { void FormatOEMCryptoResult(int oemcrypto_result, size_t parent_indent,
string result; 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()) { if (attributes.has_error_code()) {
result.assign(indent); has_value = true;
result.append("error_code:\n"); FormatIndent(indent, os);
string next_indent = indent + kIndentSpaces; os << "error_code:\n";
result.append(next_indent + "name: "); FormatCdmErrorCode(attributes.error_code(), indent, os);
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()) { if (attributes.has_error_code_bool()) {
result.assign(indent); has_value = true;
result.append("success: "); FormatIndent(indent, os);
result.append(attributes.error_code_bool() ? "true" : "false"); os << "success: ";
os << (attributes.error_code_bool() ? "true" : "false");
os << '\n';
} }
if (attributes.has_cdm_security_level()) { if (attributes.has_cdm_security_level()) {
result.assign(indent); has_value = true;
result.append("cdm_security_level: "); FormatIndent(indent, os);
result.append(to_string(attributes.cdm_security_level())); 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()) { if (attributes.has_security_level()) {
result.assign(indent); has_value = true;
result.append("security_level: "); FormatIndent(indent, os);
result.append(to_string(attributes.security_level())); 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()) { if (attributes.has_length()) {
result.assign(indent); has_value = true;
result.append("length: "); FormatIndent(indent, os);
result.append(to_string(attributes.length())); os << "length: " << attributes.length() << '\n';
} }
if (attributes.has_encryption_algorithm()) { if (attributes.has_encryption_algorithm()) {
result.assign(indent); has_value = true;
result.append("encryption_algorithm: "); FormatIndent(indent, os);
result.append(to_string(attributes.encryption_algorithm())); // TODO(sigquit): Create a formatter for CdmEncryptionAlgorithm.
os << "encryption_algorithm: " << attributes.encryption_algorithm() << '\n';
} }
if (attributes.has_signing_algorithm()) { if (attributes.has_signing_algorithm()) {
result.assign(indent); has_value = true;
result.append("signing_algorithm: "); FormatIndent(indent, os);
result.append(to_string(attributes.signing_algorithm())); // TODO(sigquit): Create a formatter for CdmSigningAlgorithm.
os << "signing_algorithm: " << attributes.signing_algorithm() << '\n';
} }
if (attributes.has_oem_crypto_result()) { if (attributes.has_oem_crypto_result()) {
result.assign(indent); has_value = true;
result.append("oemcrypto_result:\n"); FormatIndent(indent, os);
string next_indent = indent + kIndentSpaces; os << "oemcrypto_result:\n";
result.append(next_indent + "name: "); FormatOEMCryptoResult(attributes.oem_crypto_result(), indent, os);
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()));
} }
if (attributes.has_key_status_type()) { if (attributes.has_key_status_type()) {
result.assign(indent); has_value = true;
result.append("key_status_type: "); FormatIndent(indent, os);
result.append(to_string(attributes.key_status_type())); os << "key_status_type: " << attributes.key_status_type() << '\n';
} }
if (attributes.has_event_type()) { if (attributes.has_event_type()) {
result.assign(indent); has_value = true;
result.append("event_type: "); FormatIndent(indent, os);
result.append(to_string(attributes.event_type())); os << "event_type: " << attributes.event_type() << '\n';
} }
if (attributes.has_key_request_type()) { if (attributes.has_key_request_type()) {
result.assign(indent); has_value = true;
result.append("key_request_type: "); FormatIndent(indent, os);
result.append(to_string(attributes.key_request_type())); // TODO(sigquit): Create a formatter for CdmKeyRequestType.
os << "key_request_type: " << attributes.key_request_type() << '\n';
} }
if (attributes.has_license_type()) { if (attributes.has_license_type()) {
result.assign(indent); has_value = true;
result.append("license_type: "); FormatIndent(indent, os);
result.append(to_string(attributes.license_type())); 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()) { if (attributes.has_error_detail()) {
result.assign(indent); has_value = true;
result.append("error_detail: "); FormatIndent(indent, os);
result.append(to_string(attributes.error_detail())); os << "error_detail: " << attributes.error_detail() << '\n';
} }
if (result.size()) { if (attributes.has_oem_crypto_signature_hash_algorithm()) {
return result; has_value = true;
} else { FormatIndent(indent, os);
return " null"; // 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) { void FormatCounterMetricItem(const CounterMetric& cm, size_t parent_indent,
string result(indent + kIndentSpaces); int item_index, std::ostream& os) {
const size_t indent = parent_indent + kIndentIncrement;
FormatListIndent(parent_indent, os);
if (cm.has_count()) { if (cm.has_count()) {
result.append(string("count: ") + to_string(cm.count()) + "\n"); os << "count: " << cm.count();
if (cm.has_attributes()) { } else {
string newIndent(indent + kIndentSpaces); os << "count: null";
result.append(FormatAttributes(newIndent, cm.attributes())); }
} os << " # [" << item_index << "]\n";
if (cm.has_attributes()) {
FormatIndent(indent, os);
os << "attributes:\n";
FormatAttributes(cm.attributes(), indent, os);
} }
return result;
} }
string FormatDistributionMetric(const string& indent, const DistributionMetric& dm) { void FormatDistributionMetricItem(const DistributionMetric& dm,
string result; 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()) { if (dm.has_min()) {
std::ostringstream buffer; os << dm.min() << " # [" << item_index << "]\n";
buffer << dm.min(); } else {
result.append(indent + kIndentSpaces); os << "null # [" << item_index << "]\n";
result.append(string("min: ") + buffer.str() + "\n");
} }
FormatIndent(indent, os);
os << "max: ";
if (dm.has_max()) { if (dm.has_max()) {
std::ostringstream buffer; os << dm.max() << '\n';
buffer << dm.max(); } else {
result.append(indent + kIndentSpaces); os << "null\n";
result.append(string("max: ") + buffer.str() + "\n");
} }
FormatIndent(indent, os);
os << "mean: ";
if (dm.has_mean()) { if (dm.has_mean()) {
std::ostringstream buffer; os << dm.mean() << '\n';
buffer << dm.mean(); } else {
result.append(indent + kIndentSpaces); os << "null\n";
result.append(string("mean: ") + buffer.str() + "\n");
} }
FormatIndent(indent, os);
os << "variance: ";
if (dm.has_variance()) { if (dm.has_variance()) {
std::ostringstream buffer; os << dm.variance() << '\n';
buffer << dm.variance(); } else {
result.append(indent + kIndentSpaces); os << "null\n";
result.append(string("variance: ") + buffer.str() + "\n");
} }
FormatIndent(indent, os);
os << "count: ";
if (dm.has_operation_count()) { if (dm.has_operation_count()) {
result.append(indent + kIndentSpaces); os << dm.operation_count() << '\n';
result.append(string("count: ") + to_string(dm.operation_count()) + "\n"); } else {
os << "null\n";
} }
if (dm.has_attributes()) { if (dm.has_attributes()) {
string newIndent(indent + kIndentSpaces); FormatIndent(indent, os);
result.append(FormatAttributes(newIndent, dm.attributes())); os << "attributes:\n";
FormatAttributes(dm.attributes(), indent, os);
} }
return result;
} }
string FormatValueMetric(const ValueMetric& vm) { void FormatValueMetric(const ValueMetric& vm, size_t parent_indent,
string result; 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()) { if (vm.has_error_code()) {
result.append("error_code:\n"); has_value = true;
result.append(kIndentSpaces + "name: "); FormatIndent(indent, os);
result.append(DrmHalStatusToString(static_cast<Status>(vm.error_code()))); os << "error_code:\n";
result.append("\n" + kIndentSpaces + "value: "); // Nearly every error code set for a value metric is OEMCryptoResult.
result.append(to_string(vm.error_code())); FormatOEMCryptoResult(vm.error_code(), indent, os);
} }
if (vm.has_int_value()) { 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()) { if (vm.has_double_value()) {
std::ostringstream buffer; has_value = true;
buffer << vm.double_value(); FormatIndent(indent, os);
result.append(buffer.str()); os << "double_value: " << vm.double_value() << '\n';
} }
if (vm.has_string_value()) { 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) \ #define FORMAT_REPEATED_DISTRIBUTION(NAME, INDENT) \
if (metrics.NAME##_size() == 1) { \ if (metrics.NAME##_size() > 0) { \
result.append(INDENT + #NAME + ":\n"); \ FormatIndent(INDENT, os); \
result.append(FormatDistributionMetric(INDENT, metrics.NAME(0)) + "\n"); \ os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \
} else { \ for (int i = 0; i < metrics.NAME##_size(); i++) { \
for (int i = 0; i < metrics.NAME##_size(); i++) { \ FormatDistributionMetricItem(metrics.NAME(i), INDENT, i, os); \
result.append(INDENT + #NAME "[" + to_string(i) + "]:\n"); \ } \
result.append(FormatDistributionMetric(INDENT, metrics.NAME(i)) + "\n"); \
} \
} }
#define FORMAT_REPEATED_COUNTER(NAME, INDENT) \ #define FORMAT_REPEATED_COUNTER(NAME, INDENT) \
if (metrics.NAME##_size() == 1) { \ if (metrics.NAME##_size() > 0) { \
result.append(INDENT + #NAME ":\n"); \ FormatIndent(INDENT, os); \
result.append(FormatCounterMetric(INDENT, metrics.NAME(0)) + "\n"); \ os << #NAME ": # count = " << metrics.NAME##_size() << '\n'; \
} else { \
for (int i = 0; i < metrics.NAME##_size(); i++) { \ for (int i = 0; i < metrics.NAME##_size(); i++) { \
result.append(INDENT + #NAME "[" + to_string(i) + "]: [\n"); \ FormatCounterMetricItem(metrics.NAME(i), INDENT, i, os); \
result.append(FormatCounterMetric(INDENT, metrics.NAME(i)) + "\n"); \
result.append("]\n"); \
} \ } \
} }
#define FORMAT_OPTIONAL_VALUE(NAME, INDENT) \ #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<OEMCryptoInitializationMode>(metrics.NAME().int_value()); \
FormatString(OEMCryptoInitializeModeToString(mode), os); \
os << '\n'; \
}
#define FORMAT_OPTIONAL_HDCP_CAPABILITY(NAME, INDENT) \
if (metrics.has_##NAME()) { \ if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": " + FormatValueMetric(metrics.NAME()) + \ FormatIndent(INDENT, os); \
"\n"); \ 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_INITIALIZATION_MODE(NAME, INDENT) \ #define FORMAT_OPTIONAL_PROVISIONING_METHOD(NAME, INDENT) \
if (metrics.has_##NAME()) { \ if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": "); \ FormatIndent(INDENT, os); \
result.append(FormatOEMCryptoInitializeMode(metrics.NAME()) + "\n"); \ os << #NAME ": "; \
const OEMCrypto_ProvisioningMethod method = \
static_cast<OEMCrypto_ProvisioningMethod>(metrics.NAME().int_value()); \
FormatString(OEMCryptoProvisioningMethodToString(method), os); \
os << '\n'; \
} }
#define FORMAT_OPTIONAL_HDCP_CAPABILITY(NAME, INDENT) \ #define FORMAT_OPTIONAL_CRYPTO_METRICS(NAME, INDENT) \
if (metrics.has_##NAME()) { \ if (metrics.has_##NAME()) { \
result.append(INDENT + #NAME ": "); \ FormatIndent(INDENT, os); \
result.append(FormatOEMCryptoHdcpCapability(metrics.NAME()) + "\n"); \ os << #NAME ":\n"; \
} FormatCryptoMetrics(metrics.NAME(), INDENT, os); \
#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, 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. // Crypto Session Metrics.
FORMAT_OPTIONAL_VALUE(crypto_session_security_level, indent); FORMAT_OPTIONAL_VALUE(crypto_session_security_level, indent);
FORMAT_REPEATED_COUNTER(crypto_session_delete_all_usage_reports, 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. // CdmUsageEntryStorageType in wv_cdm_types.h.
FORMAT_OPTIONAL_VALUE(usage_table_header_lru_evicted_entry_type, indent); FORMAT_OPTIONAL_VALUE(usage_table_header_lru_evicted_entry_type, indent);
// OemCrypto metrics. // OEMCrypto metrics.
FORMAT_OPTIONAL_VALUE(oemcrypto_api_version, indent); FORMAT_OPTIONAL_VALUE(oemcrypto_api_version, indent);
FORMAT_REPEATED_COUNTER(oemcrypto_close_session, indent); FORMAT_REPEATED_COUNTER(oemcrypto_close_session, indent);
FORMAT_REPEATED_DISTRIBUTION(oemcrypto_copy_buffer_time_us, 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_REPEATED_COUNTER(oemcrypto_set_decrypt_hash, indent);
FORMAT_OPTIONAL_VALUE(oemcrypto_resource_rating_tier, 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, FORMAT_REPEATED_DISTRIBUTION(oemcrypto_prep_and_sign_license_request_time_us,
indent); indent);
FORMAT_REPEATED_DISTRIBUTION(oemcrypto_prep_and_sign_renewal_request_time_us, 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); FORMAT_OPTIONAL_VALUE(oemcrypto_watermarking_support, indent);
} }
void FormatSessionMetrics(const WvCdmMetrics_SessionMetrics& metrics, void FormatSessionMetricsItem(const WvCdmMetrics_SessionMetrics& metrics,
const string& indent, string& result) { 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_VALUE(session_id, indent);
FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent); FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent);
FORMAT_OPTIONAL_VALUE(cdm_session_life_span_ms, 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, 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); FORMAT_OPTIONAL_CRYPTO_METRICS(crypto_metrics, indent);
// OEMCrypto Initialize Metrics. // OEMCrypto Initialize Metrics.
@@ -530,25 +641,27 @@ void FormatEngineMetrics(const WvCdmMetrics_EngineMetrics& metrics,
} // anonymous namespace } // anonymous namespace
namespace wv_metrics { namespace wv_metrics {
void FormatWvCdmMetrics(const WvCdmMetrics& metrics, string& result) { void FormatWvCdmMetrics(const WvCdmMetrics& metrics, size_t parent_indent,
string indent = kIndentSpaces + kIndentSpaces + kIndentSpaces; std::ostream& os) {
string next_indent = indent + kIndentSpaces; const size_t indent = parent_indent + kIndentIncrement;
FormatIndent(indent, os);
result.append(kIndentSpaces + " engine_metrics:"); os << "engine_metrics:";
if (metrics.has_engine_metrics()) { if (metrics.has_engine_metrics()) {
result.append("\n"); os << '\n';
FormatEngineMetrics(metrics.engine_metrics(), indent, result); FormatEngineMetrics(metrics.engine_metrics(), indent, os);
} else { } 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++) { for (int i = 0; i < metrics.session_metrics_size(); i++) {
result.append("\n" + indent + "session[" + to_string(i) + "]:\n"); FormatSessionMetricsItem(metrics.session_metrics(i), indent, i, os);
FormatSessionMetrics(metrics.session_metrics(i), next_indent, result);
} }
} else { } else {
result.append(" null\n"); os << " []\n";
} }
} }
} // namespace wv_metrics } // namespace wv_metrics