1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2018 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "DrmMetrics"
17*ec779b8eSAndroid Build Coastguard Worker #include <iomanip>
18*ec779b8eSAndroid Build Coastguard Worker #include <utility>
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <android-base/macros.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/base64.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <mediadrm/DrmMetrics.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <sys/time.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <utils/Timers.h>
26*ec779b8eSAndroid Build Coastguard Worker
27*ec779b8eSAndroid Build Coastguard Worker #include "protos/metrics.pb.h"
28*ec779b8eSAndroid Build Coastguard Worker
29*ec779b8eSAndroid Build Coastguard Worker using ::android::String16;
30*ec779b8eSAndroid Build Coastguard Worker using ::android::String8;
31*ec779b8eSAndroid Build Coastguard Worker using ::android::drm_metrics::DrmFrameworkMetrics;
32*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_0::EventType;
33*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_2::KeyStatusType;
34*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_1::DrmMetricGroup;
35*ec779b8eSAndroid Build Coastguard Worker
36*ec779b8eSAndroid Build Coastguard Worker namespace {
37*ec779b8eSAndroid Build Coastguard Worker
ToHexString(const android::Vector<uint8_t> & sessionId)38*ec779b8eSAndroid Build Coastguard Worker std::string ToHexString(const android::Vector<uint8_t> &sessionId) {
39*ec779b8eSAndroid Build Coastguard Worker std::ostringstream out;
40*ec779b8eSAndroid Build Coastguard Worker out << std::hex << std::setfill('0');
41*ec779b8eSAndroid Build Coastguard Worker for (size_t i = 0; i < sessionId.size(); i++) {
42*ec779b8eSAndroid Build Coastguard Worker out << std::setw(2) << (int)(sessionId[i]);
43*ec779b8eSAndroid Build Coastguard Worker }
44*ec779b8eSAndroid Build Coastguard Worker return out.str();
45*ec779b8eSAndroid Build Coastguard Worker }
46*ec779b8eSAndroid Build Coastguard Worker
47*ec779b8eSAndroid Build Coastguard Worker } // namespace
48*ec779b8eSAndroid Build Coastguard Worker
49*ec779b8eSAndroid Build Coastguard Worker namespace android {
50*ec779b8eSAndroid Build Coastguard Worker
MediaDrmMetrics()51*ec779b8eSAndroid Build Coastguard Worker MediaDrmMetrics::MediaDrmMetrics()
52*ec779b8eSAndroid Build Coastguard Worker : mOpenSessionCounter("drm.mediadrm.open_session", "status"),
53*ec779b8eSAndroid Build Coastguard Worker mCloseSessionCounter("drm.mediadrm.close_session", "status"),
54*ec779b8eSAndroid Build Coastguard Worker mGetKeyRequestTimeUs("drm.mediadrm.get_key_request", "status"),
55*ec779b8eSAndroid Build Coastguard Worker mProvideKeyResponseTimeUs("drm.mediadrm.provide_key_response", "status"),
56*ec779b8eSAndroid Build Coastguard Worker mGetProvisionRequestCounter("drm.mediadrm.get_provision_request",
57*ec779b8eSAndroid Build Coastguard Worker "status"),
58*ec779b8eSAndroid Build Coastguard Worker mProvideProvisionResponseCounter(
59*ec779b8eSAndroid Build Coastguard Worker "drm.mediadrm.provide_provision_response", "status"),
60*ec779b8eSAndroid Build Coastguard Worker mKeyStatusChangeCounter("drm.mediadrm.key_status_change",
61*ec779b8eSAndroid Build Coastguard Worker "key_status_type"),
62*ec779b8eSAndroid Build Coastguard Worker mEventCounter("drm.mediadrm.event", "event_type"),
63*ec779b8eSAndroid Build Coastguard Worker mGetDeviceUniqueIdCounter("drm.mediadrm.get_device_unique_id", "status") {
64*ec779b8eSAndroid Build Coastguard Worker }
65*ec779b8eSAndroid Build Coastguard Worker
SetSessionStart(const android::Vector<uint8_t> & sessionId)66*ec779b8eSAndroid Build Coastguard Worker void MediaDrmMetrics::SetSessionStart(
67*ec779b8eSAndroid Build Coastguard Worker const android::Vector<uint8_t> &sessionId) {
68*ec779b8eSAndroid Build Coastguard Worker std::string sessionIdHex = ToHexString(sessionId);
69*ec779b8eSAndroid Build Coastguard Worker mSessionLifespans[sessionIdHex] =
70*ec779b8eSAndroid Build Coastguard Worker std::make_pair(GetCurrentTimeMs(), (int64_t)0);
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker
SetSessionEnd(const android::Vector<uint8_t> & sessionId)73*ec779b8eSAndroid Build Coastguard Worker void MediaDrmMetrics::SetSessionEnd(const android::Vector<uint8_t> &sessionId) {
74*ec779b8eSAndroid Build Coastguard Worker std::string sessionIdHex = ToHexString(sessionId);
75*ec779b8eSAndroid Build Coastguard Worker int64_t endTimeMs = GetCurrentTimeMs();
76*ec779b8eSAndroid Build Coastguard Worker if (mSessionLifespans.find(sessionIdHex) != mSessionLifespans.end()) {
77*ec779b8eSAndroid Build Coastguard Worker mSessionLifespans[sessionIdHex] =
78*ec779b8eSAndroid Build Coastguard Worker std::make_pair(mSessionLifespans[sessionIdHex].first, endTimeMs);
79*ec779b8eSAndroid Build Coastguard Worker } else {
80*ec779b8eSAndroid Build Coastguard Worker mSessionLifespans[sessionIdHex] = std::make_pair((int64_t)0, endTimeMs);
81*ec779b8eSAndroid Build Coastguard Worker }
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker
GetSerializedMetrics(std::string * serializedMetrics)84*ec779b8eSAndroid Build Coastguard Worker status_t MediaDrmMetrics::GetSerializedMetrics(std::string *serializedMetrics) {
85*ec779b8eSAndroid Build Coastguard Worker
86*ec779b8eSAndroid Build Coastguard Worker if (!serializedMetrics) {
87*ec779b8eSAndroid Build Coastguard Worker ALOGE("serializedMetrics was unexpectedly null.");
88*ec779b8eSAndroid Build Coastguard Worker return UNEXPECTED_NULL;
89*ec779b8eSAndroid Build Coastguard Worker }
90*ec779b8eSAndroid Build Coastguard Worker
91*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics metrics;
92*ec779b8eSAndroid Build Coastguard Worker
93*ec779b8eSAndroid Build Coastguard Worker mOpenSessionCounter.ExportValues(
94*ec779b8eSAndroid Build Coastguard Worker [&](const android::status_t status, const int64_t value) {
95*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
96*ec779b8eSAndroid Build Coastguard Worker metrics.add_open_session_counter();
97*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
98*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_error_code(status);
99*ec779b8eSAndroid Build Coastguard Worker });
100*ec779b8eSAndroid Build Coastguard Worker
101*ec779b8eSAndroid Build Coastguard Worker mCloseSessionCounter.ExportValues(
102*ec779b8eSAndroid Build Coastguard Worker [&](const android::status_t status, const int64_t value) {
103*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
104*ec779b8eSAndroid Build Coastguard Worker metrics.add_close_session_counter();
105*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
106*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_error_code(status);
107*ec779b8eSAndroid Build Coastguard Worker });
108*ec779b8eSAndroid Build Coastguard Worker
109*ec779b8eSAndroid Build Coastguard Worker mGetProvisionRequestCounter.ExportValues(
110*ec779b8eSAndroid Build Coastguard Worker [&](const android::status_t status, const int64_t value) {
111*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
112*ec779b8eSAndroid Build Coastguard Worker metrics.add_get_provisioning_request_counter();
113*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
114*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_error_code(status);
115*ec779b8eSAndroid Build Coastguard Worker });
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker mProvideProvisionResponseCounter.ExportValues(
118*ec779b8eSAndroid Build Coastguard Worker [&](const android::status_t status, const int64_t value) {
119*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
120*ec779b8eSAndroid Build Coastguard Worker metrics.add_provide_provisioning_response_counter();
121*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
122*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_error_code(status);
123*ec779b8eSAndroid Build Coastguard Worker });
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker mKeyStatusChangeCounter.ExportValues(
126*ec779b8eSAndroid Build Coastguard Worker [&](const uint32_t key_status_type, const int64_t value) {
127*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
128*ec779b8eSAndroid Build Coastguard Worker metrics.add_key_status_change_counter();
129*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
130*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_key_status_type(key_status_type);
131*ec779b8eSAndroid Build Coastguard Worker });
132*ec779b8eSAndroid Build Coastguard Worker
133*ec779b8eSAndroid Build Coastguard Worker mEventCounter.ExportValues(
134*ec779b8eSAndroid Build Coastguard Worker [&](const uint32_t event_type, const int64_t value) {
135*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
136*ec779b8eSAndroid Build Coastguard Worker metrics.add_event_callback_counter();
137*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
138*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_event_type(event_type);
139*ec779b8eSAndroid Build Coastguard Worker });
140*ec779b8eSAndroid Build Coastguard Worker
141*ec779b8eSAndroid Build Coastguard Worker mGetDeviceUniqueIdCounter.ExportValues(
142*ec779b8eSAndroid Build Coastguard Worker [&](const status_t status, const int64_t value) {
143*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::Counter *counter =
144*ec779b8eSAndroid Build Coastguard Worker metrics.add_get_device_unique_id_counter();
145*ec779b8eSAndroid Build Coastguard Worker counter->set_count(value);
146*ec779b8eSAndroid Build Coastguard Worker counter->mutable_attributes()->set_error_code(status);
147*ec779b8eSAndroid Build Coastguard Worker });
148*ec779b8eSAndroid Build Coastguard Worker
149*ec779b8eSAndroid Build Coastguard Worker mGetKeyRequestTimeUs.ExportValues(
150*ec779b8eSAndroid Build Coastguard Worker [&](const status_t status, const EventStatistics &stats) {
151*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::DistributionMetric *metric =
152*ec779b8eSAndroid Build Coastguard Worker metrics.add_get_key_request_time_us();
153*ec779b8eSAndroid Build Coastguard Worker metric->set_min(stats.min);
154*ec779b8eSAndroid Build Coastguard Worker metric->set_max(stats.max);
155*ec779b8eSAndroid Build Coastguard Worker metric->set_mean(stats.mean);
156*ec779b8eSAndroid Build Coastguard Worker metric->set_operation_count(stats.count);
157*ec779b8eSAndroid Build Coastguard Worker metric->set_variance(stats.sum_squared_deviation / stats.count);
158*ec779b8eSAndroid Build Coastguard Worker metric->mutable_attributes()->set_error_code(status);
159*ec779b8eSAndroid Build Coastguard Worker });
160*ec779b8eSAndroid Build Coastguard Worker
161*ec779b8eSAndroid Build Coastguard Worker mProvideKeyResponseTimeUs.ExportValues(
162*ec779b8eSAndroid Build Coastguard Worker [&](const status_t status, const EventStatistics &stats) {
163*ec779b8eSAndroid Build Coastguard Worker DrmFrameworkMetrics::DistributionMetric *metric =
164*ec779b8eSAndroid Build Coastguard Worker metrics.add_provide_key_response_time_us();
165*ec779b8eSAndroid Build Coastguard Worker metric->set_min(stats.min);
166*ec779b8eSAndroid Build Coastguard Worker metric->set_max(stats.max);
167*ec779b8eSAndroid Build Coastguard Worker metric->set_mean(stats.mean);
168*ec779b8eSAndroid Build Coastguard Worker metric->set_operation_count(stats.count);
169*ec779b8eSAndroid Build Coastguard Worker metric->set_variance(stats.sum_squared_deviation / stats.count);
170*ec779b8eSAndroid Build Coastguard Worker metric->mutable_attributes()->set_error_code(status);
171*ec779b8eSAndroid Build Coastguard Worker });
172*ec779b8eSAndroid Build Coastguard Worker
173*ec779b8eSAndroid Build Coastguard Worker for (const auto &sessionLifespan : mSessionLifespans) {
174*ec779b8eSAndroid Build Coastguard Worker auto *map = metrics.mutable_session_lifetimes();
175*ec779b8eSAndroid Build Coastguard Worker
176*ec779b8eSAndroid Build Coastguard Worker (*map)[sessionLifespan.first].set_start_time_ms(
177*ec779b8eSAndroid Build Coastguard Worker sessionLifespan.second.first);
178*ec779b8eSAndroid Build Coastguard Worker (*map)[sessionLifespan.first].set_end_time_ms(
179*ec779b8eSAndroid Build Coastguard Worker sessionLifespan.second.second);
180*ec779b8eSAndroid Build Coastguard Worker }
181*ec779b8eSAndroid Build Coastguard Worker
182*ec779b8eSAndroid Build Coastguard Worker if (!metrics.SerializeToString(serializedMetrics)) {
183*ec779b8eSAndroid Build Coastguard Worker ALOGE("Failed to serialize metrics.");
184*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
185*ec779b8eSAndroid Build Coastguard Worker }
186*ec779b8eSAndroid Build Coastguard Worker
187*ec779b8eSAndroid Build Coastguard Worker return OK;
188*ec779b8eSAndroid Build Coastguard Worker }
189*ec779b8eSAndroid Build Coastguard Worker
GetSessionLifespans() const190*ec779b8eSAndroid Build Coastguard Worker std::map<std::string, std::pair<int64_t, int64_t>> MediaDrmMetrics::GetSessionLifespans() const {
191*ec779b8eSAndroid Build Coastguard Worker return mSessionLifespans;
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
GetCurrentTimeMs()194*ec779b8eSAndroid Build Coastguard Worker int64_t MediaDrmMetrics::GetCurrentTimeMs() {
195*ec779b8eSAndroid Build Coastguard Worker struct timeval tv;
196*ec779b8eSAndroid Build Coastguard Worker gettimeofday(&tv, NULL);
197*ec779b8eSAndroid Build Coastguard Worker return ((int64_t)tv.tv_sec * 1000) + ((int64_t)tv.tv_usec / 1000);
198*ec779b8eSAndroid Build Coastguard Worker }
199*ec779b8eSAndroid Build Coastguard Worker
200*ec779b8eSAndroid Build Coastguard Worker } // namespace android
201