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

Commit 28f27c3b authored by Adam Stone's avatar Adam Stone
Browse files

Adds HAL metrics support for Media Drm

Adds support to fetch metrics from vendor and convert them to a proto
bundle returned from a call to getMetrics.

Bug: 64001676

Test: CTS test for metrics and GPlay test
Change-Id: I05634dd1bf092e64e2d0e77c4c0e243340af48e3
parent f51cb695
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -7,7 +7,6 @@
cc_library {
    name: "libmediadrm",


    srcs: [
        "DrmPluginPath.cpp",
        "DrmSessionManager.cpp",
@@ -62,6 +61,7 @@ cc_library_shared {
        "android.hardware.drm@1.1",
        "libbase",
        "libbinder",
	"libhidlbase",
        "liblog",
        "libmediametrics",
        "libprotobuf-cpp-lite",
@@ -93,6 +93,7 @@ cc_library_shared {
        "android.hardware.drm@1.1",
        "libbase",
        "libbinder",
	"libhidlbase",
        "liblog",
        "libmediametrics",
        "libprotobuf-cpp-full",
+41 −4
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ using drm::V1_1::SecureStopRelease;
using drm::V1_0::SecureStopId;
using drm::V1_1::SecurityLevel;
using drm::V1_0::Status;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::hardware::hidl_array;
using ::android::hardware::hidl_string;
using ::android::hardware::hidl_vec;
@@ -1111,12 +1112,48 @@ status_t DrmHal::setPropertyByteArray(String8 const &name,
    return toStatusT(status);
}

status_t DrmHal::getMetrics(PersistableBundle* item) {
    if (item == nullptr) {
status_t DrmHal::getMetrics(PersistableBundle* metrics) {
    if (metrics == nullptr) {
        return UNEXPECTED_NULL;
    }
    mMetrics.Export(metrics);

    // Append vendor metrics if they are supported.
    if (mPluginV1_1 != NULL) {
        String8 vendor;
        String8 description;
        if (getPropertyStringInternal(String8("vendor"), vendor) != OK
            || vendor.isEmpty()) {
          ALOGE("Get vendor failed or is empty");
          vendor = "NONE";
        }
        if (getPropertyStringInternal(String8("description"), description) != OK
            || description.isEmpty()) {
          ALOGE("Get description failed or is empty.");
          description = "NONE";
        }
        vendor += ".";
        vendor += description;

        hidl_vec<DrmMetricGroup> pluginMetrics;
        status_t err = UNKNOWN_ERROR;

        Return<void> status = mPluginV1_1->getMetrics(
                [&](Status status, hidl_vec<DrmMetricGroup> pluginMetrics) {
                    if (status != Status::OK) {
                      ALOGV("Error getting plugin metrics: %d", status);
                    } else {
                        PersistableBundle pluginBundle;
                        if (MediaDrmMetrics::HidlMetricsToBundle(
                                pluginMetrics, &pluginBundle) == OK) {
                            metrics->putPersistableBundle(String16(vendor), pluginBundle);
                        }
                    }
                    err = toStatusT(status);
                });
        return status.isOk() ? err : DEAD_OBJECT;
    }

    mMetrics.Export(item);
    return OK;
}

+62 −0
Original line number Diff line number Diff line
@@ -29,8 +29,10 @@
using ::android::String16;
using ::android::String8;
using ::android::drm_metrics::DrmFrameworkMetrics;
using ::android::hardware::hidl_vec;
using ::android::hardware::drm::V1_0::EventType;
using ::android::hardware::drm::V1_0::KeyStatusType;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::os::PersistableBundle;

namespace {
@@ -172,6 +174,24 @@ std::string ToHexString(const android::Vector<uint8_t> &sessionId) {
    return out.str();
}

template <typename CT>
void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
              const CT &value, PersistableBundle *bundle) {
    switch (type) {
    case DrmMetricGroup::ValueType::INT64_TYPE:
        bundle->putLong(name, value.int64Value);
        break;
    case DrmMetricGroup::ValueType::DOUBLE_TYPE:
        bundle->putDouble(name, value.doubleValue);
        break;
    case DrmMetricGroup::ValueType::STRING_TYPE:
        bundle->putString(name, String16(value.stringValue.c_str()));
        break;
    default:
        ALOGE("Unexpected value type: %hhu", type);
    }
}

} // namespace

namespace android {
@@ -339,4 +359,46 @@ int64_t MediaDrmMetrics::GetCurrentTimeMs() {
    return ((int64_t)tv.tv_sec * 1000) + ((int64_t)tv.tv_usec / 1000);
}

status_t MediaDrmMetrics::HidlMetricsToBundle(
    const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
    PersistableBundle *bundleMetricGroups) {
    if (bundleMetricGroups == nullptr) {
        return UNEXPECTED_NULL;
    }
    if (hidlMetricGroups.size() == 0) {
        return OK;
    }

    int groupIndex = 0;
    for (const auto &hidlMetricGroup : hidlMetricGroups) {
        PersistableBundle bundleMetricGroup;
        for (const auto &hidlMetric : hidlMetricGroup.metrics) {
            PersistableBundle bundleMetric;
            // Add metric component values.
            for (const auto &value : hidlMetric.values) {
                SetValue(String16(value.componentName.c_str()), value.type,
                         value, &bundleMetric);
            }
            // Set metric attributes.
            PersistableBundle bundleMetricAttributes;
            for (const auto &attribute : hidlMetric.attributes) {
                SetValue(String16(attribute.name.c_str()), attribute.type,
                         attribute, &bundleMetricAttributes);
            }
            // Add attributes to the bundle metric.
            bundleMetric.putPersistableBundle(String16("attributes"),
                                              bundleMetricAttributes);
            // Add the bundle metric to the group of metrics.
            bundleMetricGroup.putPersistableBundle(
                String16(hidlMetric.name.c_str()), bundleMetric);
        }
        // Add the bundle metric group to the collection of groups.
        bundleMetricGroups->putPersistableBundle(
            String16(std::to_string(groupIndex).c_str()), bundleMetricGroup);
        groupIndex++;
    }

    return OK;
}

} // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@ cc_test {
    srcs: ["DrmMetrics_test.cpp"],
    shared_libs: [
      "android.hardware.drm@1.0",
      "android.hardware.drm@1.1",
      "libbinder",
      "libhidlbase",
      "liblog",
      "libmediadrmmetrics_full",
      "libmediametrics",
+60 −4
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
#define LOG_TAG "DrmMetricsTest"
#include "DrmMetrics.h"

#include <android/hardware/drm/1.0/types.h>
#include <android/hardware/drm/1.1/types.h>
#include <binder/PersistableBundle.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/util/message_differencer.h>
@@ -26,8 +28,11 @@
#include "protos/metrics.pb.h"

using ::android::drm_metrics::DrmFrameworkMetrics;
using ::android::hardware::hidl_vec;
using ::android::hardware::drm::V1_0::EventType;
using ::android::hardware::drm::V1_0::KeyStatusType;
using ::android::hardware::drm::V1_0::Status;
using ::android::hardware::drm::V1_1::DrmMetricGroup;
using ::android::os::PersistableBundle;
using ::google::protobuf::util::MessageDifferencer;
using ::google::protobuf::TextFormat;
@@ -343,19 +348,19 @@ TEST_F(MediaDrmMetricsTest, TimeMetricsProtoSerialization) {
  ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));

  std::string expectedMetrics =
      "get_key_request_timing { "
      "get_key_request_time_us { "
      "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
      "  attributes { error_code: -0x7FFFFFF8 } "
      "} "
      "get_key_request_timing { "
      "get_key_request_time_us { "
      "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
      "  attributes { error_code: 0 } "
      "} "
      "provide_key_response_timing { "
      "provide_key_response_time_us { "
      "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
      "  attributes { error_code: -0x7FFFFFF8 } "
      "} "
      "provide_key_response_timing { "
      "provide_key_response_time_us { "
      "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
      "  attributes { error_code: 0 } "
      "} ";
@@ -412,4 +417,55 @@ TEST_F(MediaDrmMetricsTest, SessionLifetimeProtoSerialization) {
      << diffString;
}

TEST_F(MediaDrmMetricsTest, HidlToBundleMetricsEmpty) {
  hidl_vec<DrmMetricGroup> hidlMetricGroups;
  PersistableBundle bundleMetricGroups;

  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
  ASSERT_EQ(0U, bundleMetricGroups.size());
}

TEST_F(MediaDrmMetricsTest, HidlToBundleMetricsMultiple) {
  DrmMetricGroup hidlMetricGroup =
      { { {
              "open_session_ok",
              { { "status", DrmMetricGroup::ValueType::INT64_TYPE, (int64_t) Status::OK, 0.0, "" } },
              { { "count", DrmMetricGroup::ValueType::INT64_TYPE, 3, 0.0, "" } }
          },
          {
              "close_session_not_opened",
              { { "status", DrmMetricGroup::ValueType::INT64_TYPE,
                  (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, "" } },
              { { "count", DrmMetricGroup::ValueType::INT64_TYPE, 7, 0.0, "" } }
          } } };

  PersistableBundle bundleMetricGroups;
  ASSERT_EQ(OK, MediaDrmMetrics::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
                                                     &bundleMetricGroups));
  ASSERT_EQ(1U, bundleMetricGroups.size());
  PersistableBundle bundleMetricGroup;
  ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("0"), &bundleMetricGroup));
  ASSERT_EQ(2U, bundleMetricGroup.size());

  // Verify each metric.
  PersistableBundle metric;
  ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("open_session_ok"), &metric));
  int64_t value = 0;
  ASSERT_TRUE(metric.getLong(String16("count"), &value));
  ASSERT_EQ(3, value);
  PersistableBundle attributeBundle;
  ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
  ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
  ASSERT_EQ((int64_t) Status::OK, value);

  ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("close_session_not_opened"),
                                                     &metric));
  ASSERT_TRUE(metric.getLong(String16("count"), &value));
  ASSERT_EQ(7, value);
  ASSERT_TRUE(metric.getPersistableBundle(String16("attributes"), &attributeBundle));
  value = 0;
  ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
  ASSERT_EQ((int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, value);
}

}  // namespace android
Loading