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

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

Merge "Add CounterMetric and a single use case."

parents c3c1fc63 aaf87dd0
Loading
Loading
Loading
Loading
+22 −2
Original line number Diff line number Diff line
@@ -227,6 +227,7 @@ private:
DrmHal::DrmHal()
   : mDrmSessionClient(new DrmSessionClient(this)),
     mFactories(makeDrmFactories()),
     mOpenSessionCounter("/drm/mediadrm/open_session", "status"),
     mInitCheck((mFactories.size() == 0) ? ERROR_UNSUPPORTED : NO_INIT) {
}

@@ -517,6 +518,8 @@ status_t DrmHal::openSession(Vector<uint8_t> &sessionId) {
                mDrmSessionClient, sessionId);
        mOpenSessions.push(sessionId);
    }

    mOpenSessionCounter.Increment(err);
    return err;
}

@@ -985,8 +988,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;
}

+12 −0
Original line number Diff line number Diff line
// 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",
    ],
}
+80 −0
Original line number Diff line number Diff line
/*
 * 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 <gtest/gtest.h>

#include "CounterMetric.h"

namespace android {

/**
 * Unit tests for the CounterMetric class.
 */
class CounterMetricTest : public ::testing::Test {
};

TEST_F(CounterMetricTest, IntDataTypeEmpty) {
  CounterMetric<int> metric("MyMetricName", "MetricAttributeName");

  std::map<int, int64_t> values;

  metric.ExportValues(
      [&] (int attribute_value, int64_t value) {
          values[attribute_value] = value;
      });

  EXPECT_TRUE(values.empty());
}

TEST_F(CounterMetricTest, IntDataType) {
  CounterMetric<int> metric("MyMetricName", "MetricAttributeName");

  std::map<int, int64_t> 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<std::string> metric("MyMetricName", "MetricAttributeName");

  std::map<std::string, int64_t> 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
+1 −0
Original line number Diff line number Diff line
../../media/libmedia/include/media/CounterMetric.h
 No newline at end of file
+90 −0
Original line number Diff line number Diff line
/*
 * 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 <media/MediaAnalyticsItem.h>
#include <utils/Log.h>

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<status_t> 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<int, int64_t> values;
//    metric.ExportValues(
//        [&] (int attribute_value, int64_t value) {
//             values[attribute_value] = value;
//        });
//
//   // Do something with the exported stat.
//
template<typename AttributeType>
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<void (const AttributeType&,
                          const int64_t count)> 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<AttributeType, int64_t> values_;
};

}  // namespace android

#endif  // ANDROID_COUNTER_METRIC_H_
Loading