Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3abf7858 authored by Adam Stone's avatar Adam Stone Committed by Android (Google) Code Review
Browse files

Merge "Fixes serialization of vendor metrics" into pi-dev

parents bebc764c 32494f54
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@ cc_library_shared {
        "liblog",
        "libmediametrics",
        "libprotobuf-cpp-lite",
        "libstagefright_foundation",
        "libutils",
    ],
    cflags: [
@@ -97,6 +98,7 @@ cc_library_shared {
        "liblog",
        "libmediametrics",
        "libprotobuf-cpp-full",
        "libstagefright_foundation",
        "libutils",
    ],
    cflags: [
+30 −16
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include <media/drm/DrmAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/foundation/base64.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/MediaErrors.h>
#include <mediadrm/DrmHal.h>
@@ -63,8 +64,26 @@ namespace {
// This constant corresponds to the PROPERTY_DEVICE_UNIQUE_ID constant
// in the MediaDrm API.
constexpr char kPropertyDeviceUniqueId[] = "deviceUniqueId";
constexpr char kEqualsSign[] = "=";

template<typename T>
std::string toBase64StringNoPad(const T* data, size_t size) {
    if (size == 0) {
      return "";
    }
    CHECK(sizeof(data[0] == 1));

    android::AString outputString;
    encodeBase64(data, size, &outputString);
    // Remove trailing equals padding if it exists.
    while (outputString.size() > 0 && outputString.endsWith(kEqualsSign)) {
        outputString.erase(outputString.size() - 1, 1);
    }

    return std::string(outputString.c_str(), outputString.size());
}

}  // anonymous namespace

namespace android {

@@ -101,15 +120,6 @@ static hidl_string toHidlString(const String8& string) {
    return hidl_string(string.string());
}

std::string toHexString(const std::string& str) {
  std::ostringstream out;
  out << std::hex << std::setfill('0');
  for (size_t i = 0; i < str.size(); i++) {
    out << std::setw(2) << (int)(str[i]);
  }
  return out.str();
}

static DrmPlugin::SecurityLevel toSecurityLevel(SecurityLevel level) {
    switch(level) {
    case SecurityLevel::SW_SECURE_CRYPTO:
@@ -340,6 +350,7 @@ Vector<sp<IDrmFactory>> DrmHal::makeDrmFactories() {

sp<IDrmPlugin> DrmHal::makeDrmPlugin(const sp<IDrmFactory>& factory,
        const uint8_t uuid[16], const String8& appPackageName) {
    mAppPackageName = appPackageName;
    mMetrics.SetAppPackageName(appPackageName);

    sp<IDrmPlugin> plugin;
@@ -1353,9 +1364,10 @@ void DrmHal::reportFrameworkMetrics() const
    if (result != OK) {
        ALOGE("Failed to serialize framework metrics: %d", result);
    }
    serializedMetrics = toHexString(serializedMetrics);
    if (!serializedMetrics.empty()) {
        item.setCString("serialized_metrics", serializedMetrics.c_str());
    std::string b64EncodedMetrics = toBase64StringNoPad(serializedMetrics.data(),
                                                        serializedMetrics.size());
    if (!b64EncodedMetrics.empty()) {
        item.setCString("serialized_metrics", b64EncodedMetrics.c_str());
    }
    if (!item.selfrecord()) {
        ALOGE("Failed to self record framework metrics");
@@ -1364,14 +1376,16 @@ void DrmHal::reportFrameworkMetrics() const

void DrmHal::reportPluginMetrics() const
{
    Vector<uint8_t> metrics;
    Vector<uint8_t> metricsVector;
    String8 vendor;
    String8 description;
    if (getPropertyStringInternal(String8("vendor"), vendor) == OK &&
            getPropertyStringInternal(String8("description"), description) == OK &&
            getPropertyByteArrayInternal(String8("metrics"), metrics) == OK) {
        status_t res = android::reportDrmPluginMetrics(
                metrics, vendor, description);
            getPropertyByteArrayInternal(String8("metrics"), metricsVector) == OK) {
        std::string metricsString = toBase64StringNoPad(metricsVector.array(),
                                                        metricsVector.size());
        status_t res = android::reportDrmPluginMetrics(metricsString, vendor,
                                                       description, mAppPackageName);
        if (res != OK) {
            ALOGE("Metrics were retrieved but could not be reported: %d", res);
        }
+17 −67
Original line number Diff line number Diff line
@@ -16,80 +16,35 @@

//#define LOG_NDEBUG 0
#define LOG_TAG "PluginMetricsReporting"
#include <utils/Log.h>
#include <inttypes.h>

#include <media/PluginMetricsReporting.h>

#include <inttypes.h>

#include <media/MediaAnalyticsItem.h>
#include <utils/Log.h>

#include "protos/metrics.pb.h"

namespace android {

namespace {

using android::drm_metrics::MetricsGroup;
using android::drm_metrics::MetricsGroup_Metric;
using android::drm_metrics::MetricsGroup_Metric_MetricValue;
constexpr char kSerializedMetricsField[] = "serialized_metrics";

const char* const kParentAttribute = "/parent/external";

status_t reportMetricsGroup(const MetricsGroup& metricsGroup,
                            const String8& batchName,
                            const int64_t* parentId) {
    MediaAnalyticsItem analyticsItem(batchName.c_str());
status_t reportVendorMetrics(const std::string& metrics,
                             const String8& name,
                             const String8& appPackageName) {
    MediaAnalyticsItem analyticsItem(name.c_str());
    analyticsItem.generateSessionID();
    int64_t sessionId = analyticsItem.getSessionID();
    if (parentId != NULL) {
        analyticsItem.setInt64(kParentAttribute, *parentId);
    }

    // Report the package name.
    if (metricsGroup.has_app_package_name()) {
        std::string app_package_name(metricsGroup.app_package_name().c_str(),
                               metricsGroup.app_package_name().size());
    std::string app_package_name(appPackageName.c_str(), appPackageName.size());
    analyticsItem.setPkgName(app_package_name);
    }

    for (int i = 0; i < metricsGroup.metric_size(); ++i) {
        const MetricsGroup_Metric& metric = metricsGroup.metric(i);
        if (!metric.has_name()) {
            ALOGE("Metric with no name.");
            return BAD_VALUE;
        }

        if (!metric.has_value()) {
            ALOGE("Metric with no value.");
            return BAD_VALUE;
        }

        const MetricsGroup_Metric_MetricValue& value = metric.value();
        if (value.has_int_value()) {
            analyticsItem.setInt64(metric.name().c_str(),
                                   value.int_value());
        } else if (value.has_double_value()) {
            analyticsItem.setDouble(metric.name().c_str(),
                                    value.double_value());
        } else if (value.has_string_value()) {
            analyticsItem.setCString(metric.name().c_str(),
                                     value.string_value().c_str());
        } else {
            ALOGE("Metric Value with no actual value.");
            return BAD_VALUE;
        }
    if (metrics.size() > 0) {
        analyticsItem.setCString(kSerializedMetricsField, metrics.c_str());
    }

    if (!analyticsItem.selfrecord()) {
      ALOGE("selfrecord() returned false. sessioId %" PRId64, sessionId);
    }

    for (int i = 0; i < metricsGroup.metric_sub_group_size(); ++i) {
        const MetricsGroup& subGroup = metricsGroup.metric_sub_group(i);
        status_t res = reportMetricsGroup(subGroup, batchName, &sessionId);
        if (res != OK) {
            return res;
        }
      ALOGE("selfrecord() returned false. sessioId %" PRId64, analyticsItem.getSessionID());
    }

    return OK;
@@ -111,21 +66,16 @@ String8 sanitize(const String8& input) {

}  // namespace

status_t reportDrmPluginMetrics(const Vector<uint8_t>& serializedMetrics,
status_t reportDrmPluginMetrics(const std::string& b64EncodedMetrics,
                                const String8& vendor,
                                const String8& description) {
    MetricsGroup root_metrics_group;
    if (!root_metrics_group.ParseFromArray(serializedMetrics.array(),
                                           serializedMetrics.size())) {
        ALOGE("Failure to parse.");
        return BAD_VALUE;
    }
                                const String8& description,
                                const String8& appPackageName) {

    String8 name = String8::format("drm.vendor.%s.%s",
                                   sanitize(vendor).c_str(),
                                   sanitize(description).c_str());

    return reportMetricsGroup(root_metrics_group, name, NULL);
    return reportVendorMetrics(b64EncodedMetrics, name, appPackageName);
}

}  // namespace android
+7 −34
Original line number Diff line number Diff line
@@ -18,33 +18,6 @@ syntax = "proto2";

package android.drm_metrics;

// The MetricsGroup is a collection of metric name/value pair instances
// that can be serialized and provided to a caller.
message MetricsGroup {
  message Metric {
    message MetricValue {
      // Exactly one of the following values must be set.
      optional int64 int_value = 1;
      optional double double_value = 2;
      optional string string_value = 3;
    }

    // The name of the metric. Must be valid UTF-8. Required.
    optional string name = 1;

    // The value of the metric. Required.
    optional MetricValue value = 2;
  }

  // The list of name/value pairs of metrics.
  repeated Metric metric = 1;

  // Allow multiple sub groups of metrics.
  repeated MetricsGroup metric_sub_group = 2;

  // Name of the application package associated with the metrics.
  optional string app_package_name = 3;
}

// This message contains the specific metrics captured by DrmMetrics. It is
// used for serializing and logging metrics.
@@ -72,7 +45,7 @@ message DrmFrameworkMetrics {
  // The Counter message is used to store a count value with an associated
  // Attribute.
  message Counter {
    optional int64 count = 1;
    optional uint64 count = 1;
    // Represents the attributes associated with this counter instance.
    optional Attributes attributes = 2;
  }
@@ -80,11 +53,11 @@ message DrmFrameworkMetrics {
  // The DistributionMetric is meant to capture the moments of a normally
  // distributed (or approximately normal) value.
  message DistributionMetric {
    optional double min = 1;
    optional double max = 2;
    optional double mean = 3;
    optional float min = 1;
    optional float max = 2;
    optional float mean = 3;
    optional double variance = 4;
    optional double operation_count = 5;
    optional uint64 operation_count = 5;

    // Represents the attributes assocated with this distribution metric
    // instance.
@@ -93,9 +66,9 @@ message DrmFrameworkMetrics {

  message SessionLifetime {
    // Start time of the session in milliseconds since epoch.
    optional int64 start_time_ms = 1;
    optional uint64 start_time_ms = 1;
    // End time of the session in milliseconds since epoch.
    optional int64 end_time_ms = 2;
    optional uint64 end_time_ms = 2;
  }

  // The count of open session operations. Each instance has a specific error
+1 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ private:
    const Vector<sp<IDrmFactory>> mFactories;
    sp<IDrmPlugin> mPlugin;
    sp<drm::V1_1::IDrmPlugin> mPluginV1_1;
    String8 mAppPackageName;

    // Mutable to allow modification within GetPropertyByteArray.
    mutable MediaDrmMetrics mMetrics;
Loading