From aaf87dd09686bdb47df0a638b622a4c2ea37a331 Mon Sep 17 00:00:00 2001 From: Adam Stone Date: Mon, 8 Jan 2018 11:55:06 -0800 Subject: [PATCH] Add CounterMetric and a single use case. This adds a new class CounterMetric which is used to hold metric information. It also adds a single use case for recording and reporting a counter metric. BUG: 64001676 Test: Added and ran a new test for the specific CounterMetric use case. Change-Id: I39cab8328f135e579f80b6c2fab721da5f569795 --- drm/libmediadrm/DrmHal.cpp | 24 +++++- drm/libmediadrm/tests/Android.bp | 12 +++ drm/libmediadrm/tests/CounterMetric_test.cpp | 80 +++++++++++++++++ include/media/CounterMetric.h | 1 + media/libmedia/include/media/CounterMetric.h | 90 ++++++++++++++++++++ media/libmedia/include/media/DrmHal.h | 3 + 6 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 drm/libmediadrm/tests/Android.bp create mode 100644 drm/libmediadrm/tests/CounterMetric_test.cpp create mode 120000 include/media/CounterMetric.h create mode 100644 media/libmedia/include/media/CounterMetric.h diff --git a/drm/libmediadrm/DrmHal.cpp b/drm/libmediadrm/DrmHal.cpp index c4b197cfe1..9fc7d04fb3 100644 --- a/drm/libmediadrm/DrmHal.cpp +++ b/drm/libmediadrm/DrmHal.cpp @@ -228,6 +228,7 @@ private: DrmHal::DrmHal() : mDrmSessionClient(new DrmSessionClient(this)), mFactories(makeDrmFactories()), + mOpenSessionCounter("/drm/mediadrm/open_session", "status"), mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) { } @@ -518,6 +519,8 @@ status_t DrmHal::openSession(Vector &sessionId) { mDrmSessionClient, sessionId); mOpenSessions.push(sessionId); } + + mOpenSessionCounter.Increment(err); return err; } @@ -946,8 +949,25 @@ status_t DrmHal::setPropertyByteArray(String8 const &name, } status_t DrmHal::getMetrics(MediaAnalyticsItem* metrics) { - // TODO: Replace this with real metrics. - metrics->setCString("/drm/mediadrm/dummymetric", "dummy"); + // TODO: Move mOpenSessionCounter and suffixes to a separate class + // that manages the collection of metrics and exporting them. + std::string success_count_name = + mOpenSessionCounter.metric_name() + "/ok/count"; + std::string error_count_name = + mOpenSessionCounter.metric_name() + "/error/count"; + mOpenSessionCounter.ExportValues( + [&] (status_t status, int64_t value) { + if (status == OK) { + metrics->setInt64(success_count_name.c_str(), value); + } else { + int64_t total_errors(0); + metrics->getInt64(error_count_name.c_str(), &total_errors); + metrics->setInt64(error_count_name.c_str(), + total_errors + value); + // TODO: Add support for exporting the list of error values. + // This probably needs to be added to MediaAnalyticsItem. + } + }); return OK; } diff --git a/drm/libmediadrm/tests/Android.bp b/drm/libmediadrm/tests/Android.bp new file mode 100644 index 0000000000..674d3eb7c9 --- /dev/null +++ b/drm/libmediadrm/tests/Android.bp @@ -0,0 +1,12 @@ +// Build definitions for unit tests. + +cc_test { + name: "CounterMetric_test", + srcs: ["CounterMetric_test.cpp"], + shared_libs: ["libmediadrm"], + include_dirs: ["frameworks/av/include/media"], + cflags: [ + "-Werror", + "-Wall", + ], +} diff --git a/drm/libmediadrm/tests/CounterMetric_test.cpp b/drm/libmediadrm/tests/CounterMetric_test.cpp new file mode 100644 index 0000000000..6bca0dafe2 --- /dev/null +++ b/drm/libmediadrm/tests/CounterMetric_test.cpp @@ -0,0 +1,80 @@ +/* + * Copyright 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "CounterMetric.h" + +namespace android { + +/** + * Unit tests for the CounterMetric class. + */ +class CounterMetricTest : public ::testing::Test { +}; + +TEST_F(CounterMetricTest, IntDataTypeEmpty) { + CounterMetric metric("MyMetricName", "MetricAttributeName"); + + std::map values; + + metric.ExportValues( + [&] (int attribute_value, int64_t value) { + values[attribute_value] = value; + }); + + EXPECT_TRUE(values.empty()); +} + +TEST_F(CounterMetricTest, IntDataType) { + CounterMetric metric("MyMetricName", "MetricAttributeName"); + + std::map values; + + metric.Increment(7); + metric.Increment(8); + metric.Increment(8); + + metric.ExportValues( + [&] (int attribute_value, int64_t value) { + values[attribute_value] = value; + }); + + ASSERT_EQ(2u, values.size()); + EXPECT_EQ(1, values[7]); + EXPECT_EQ(2, values[8]); +} + +TEST_F(CounterMetricTest, StringDataType) { + CounterMetric metric("MyMetricName", "MetricAttributeName"); + + std::map values; + + metric.Increment("a"); + metric.Increment("b"); + metric.Increment("b"); + + metric.ExportValues( + [&] (std::string attribute_value, int64_t value) { + values[attribute_value] = value; + }); + + ASSERT_EQ(2u, values.size()); + EXPECT_EQ(1, values["a"]); + EXPECT_EQ(2, values["b"]); +} + +} // namespace android diff --git a/include/media/CounterMetric.h b/include/media/CounterMetric.h new file mode 120000 index 0000000000..baba043a66 --- /dev/null +++ b/include/media/CounterMetric.h @@ -0,0 +1 @@ +../../media/libmedia/include/media/CounterMetric.h \ No newline at end of file diff --git a/media/libmedia/include/media/CounterMetric.h b/media/libmedia/include/media/CounterMetric.h new file mode 100644 index 0000000000..f39ca7cdd7 --- /dev/null +++ b/media/libmedia/include/media/CounterMetric.h @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_COUNTER_METRIC_H_ +#define ANDROID_COUNTER_METRIC_H_ + +#include +#include + +namespace android { + + +// The CounterMetric class is used to hold counts of operations or events. +// A CounterMetric can break down counts by a dimension specified by the +// application. E.g. an application may want to track counts broken out by +// error code or the size of some parameter. +// +// Example: +// +// CounterMetric workCounter; +// workCounter("workCounterName", "result_status"); +// +// status_t err = DoWork(); +// +// // Increments the number of times called with the given error code. +// workCounter.Increment(err); +// +// std::map values; +// metric.ExportValues( +// [&] (int attribute_value, int64_t value) { +// values[attribute_value] = value; +// }); +// +// // Do something with the exported stat. +// +template +class CounterMetric { + public: + // Instantiate the counter with the given metric name and + // attribute names. |attribute_names| must not be null. + CounterMetric( + const std::string& metric_name, + const std::string& attribute_name) + : metric_name_(metric_name), + attribute_name_(attribute_name) {} + + // Increment the count of times the operation occurred with this + // combination of attributes. + void Increment(AttributeType attribute) { + if (values_.find(attribute) == values_.end()) { + values_[attribute] = 1; + } else { + values_[attribute] = values_[attribute] + 1; + } + }; + + // Export the metrics to the provided |function|. Each value for Attribute + // has a separate count. As such, |function| will be called once per value + // of Attribute. + void ExportValues( + std::function function) { + for (auto it = values_.begin(); it != values_.end(); it++) { + function(it->first, it->second); + } + } + + const std::string& metric_name() { return metric_name_; }; + + private: + const std::string metric_name_; + const std::string attribute_name_; + std::map values_; +}; + +} // namespace android + +#endif // ANDROID_COUNTER_METRIC_H_ diff --git a/media/libmedia/include/media/DrmHal.h b/media/libmedia/include/media/DrmHal.h index 1a0553ef70..f2b25cdaf1 100644 --- a/media/libmedia/include/media/DrmHal.h +++ b/media/libmedia/include/media/DrmHal.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -180,6 +181,8 @@ private: sp mPlugin; sp mPluginV1_1; + CounterMetric mOpenSessionCounter; + Vector> mOpenSessions; void closeOpenSessions();