blob: dd91058ba45a05fd73e685fde2c34c46843ff491 [file] [log] [blame]
Adam Stonef0e618d2018-01-17 19:20:41 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Stone568b3c42018-01-31 12:57:16 -080017#include <utility>
18
Adam Stonecea91ce2018-01-22 19:23:28 -080019#include <android-base/macros.h>
Adam Stonef0e618d2018-01-17 19:20:41 -080020#include <media/DrmMetrics.h>
Adam Stone568b3c42018-01-31 12:57:16 -080021#include <media/stagefright/foundation/base64.h>
22#include <sys/time.h>
23#include <utils/Timers.h>
Adam Stonef0e618d2018-01-17 19:20:41 -080024
Adam Stonecea91ce2018-01-22 19:23:28 -080025using ::android::hardware::drm::V1_0::EventType;
26using ::android::hardware::drm::V1_0::KeyStatusType;
Adam Stone637b7852018-01-30 12:09:36 -080027using ::android::os::PersistableBundle;
Adam Stonecea91ce2018-01-22 19:23:28 -080028
Adam Stonef0e618d2018-01-17 19:20:41 -080029namespace {
30
Adam Stone568b3c42018-01-31 12:57:16 -080031template <typename T> std::string GetAttributeName(T type);
Adam Stonecea91ce2018-01-22 19:23:28 -080032
Adam Stone568b3c42018-01-31 12:57:16 -080033template <> std::string GetAttributeName<KeyStatusType>(KeyStatusType type) {
34 static const char *type_names[] = {"USABLE", "EXPIRED",
35 "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
36 "INTERNAL_ERROR"};
37 if (((size_t)type) > arraysize(type_names)) {
38 return "UNKNOWN_TYPE";
39 }
40 return type_names[(size_t)type];
Adam Stonecea91ce2018-01-22 19:23:28 -080041}
42
Adam Stone568b3c42018-01-31 12:57:16 -080043template <> std::string GetAttributeName<EventType>(EventType type) {
44 static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
45 "KEY_EXPIRED", "VENDOR_DEFINED",
46 "SESSION_RECLAIMED"};
47 if (((size_t)type) > arraysize(type_names)) {
48 return "UNKNOWN_TYPE";
49 }
50 return type_names[(size_t)type];
Adam Stonecea91ce2018-01-22 19:23:28 -080051}
52
Adam Stone568b3c42018-01-31 12:57:16 -080053template <typename T>
54void ExportCounterMetric(const android::CounterMetric<T> &counter,
55 PersistableBundle *metrics) {
56 if (!metrics) {
57 ALOGE("metrics was unexpectedly null.");
58 return;
59 }
60 std::string success_count_name = counter.metric_name() + ".ok.count";
61 std::string error_count_name = counter.metric_name() + ".error.count";
62 std::vector<int64_t> status_values;
63 counter.ExportValues(
64 [&](const android::status_t status, const int64_t value) {
65 if (status == android::OK) {
66 metrics->putLong(android::String16(success_count_name.c_str()),
67 value);
68 } else {
69 int64_t total_errors(0);
70 metrics->getLong(android::String16(error_count_name.c_str()),
71 &total_errors);
72 metrics->putLong(android::String16(error_count_name.c_str()),
73 total_errors + value);
74 status_values.push_back(status);
75 }
76 });
77 if (!status_values.empty()) {
78 std::string error_list_name = counter.metric_name() + ".error.list";
79 metrics->putLongVector(android::String16(error_list_name.c_str()),
80 status_values);
81 }
Adam Stonef0e618d2018-01-17 19:20:41 -080082}
83
Adam Stone568b3c42018-01-31 12:57:16 -080084template <typename T>
Adam Stonecea91ce2018-01-22 19:23:28 -080085void ExportCounterMetricWithAttributeNames(
Adam Stone568b3c42018-01-31 12:57:16 -080086 const android::CounterMetric<T> &counter, PersistableBundle *metrics) {
87 if (!metrics) {
88 ALOGE("metrics was unexpectedly null.");
89 return;
90 }
91 counter.ExportValues([&](const T &attribute, const int64_t value) {
92 std::string name = counter.metric_name() + "." +
93 GetAttributeName(attribute) + ".count";
94 metrics->putLong(android::String16(name.c_str()), value);
95 });
Adam Stonecea91ce2018-01-22 19:23:28 -080096}
97
Adam Stone568b3c42018-01-31 12:57:16 -080098template <typename T>
99void ExportEventMetric(const android::EventMetric<T> &event,
100 PersistableBundle *metrics) {
101 if (!metrics) {
102 ALOGE("metrics was unexpectedly null.");
103 return;
104 }
105 std::string success_count_name = event.metric_name() + ".ok.count";
106 std::string error_count_name = event.metric_name() + ".error.count";
107 std::string timing_name = event.metric_name() + ".ok.average_time_micros";
108 std::vector<int64_t> status_values;
109 event.ExportValues([&](const android::status_t &status,
110 const android::EventStatistics &value) {
111 if (status == android::OK) {
112 metrics->putLong(android::String16(success_count_name.c_str()),
113 value.count);
114 metrics->putLong(android::String16(timing_name.c_str()),
115 value.mean);
116 } else {
117 int64_t total_errors(0);
118 metrics->getLong(android::String16(error_count_name.c_str()),
119 &total_errors);
120 metrics->putLong(android::String16(error_count_name.c_str()),
121 total_errors + value.count);
122 status_values.push_back(status);
123 }
124 });
125 if (!status_values.empty()) {
126 std::string error_list_name = event.metric_name() + ".error.list";
127 metrics->putLongVector(android::String16(error_list_name.c_str()),
128 status_values);
129 }
Adam Stonef0e618d2018-01-17 19:20:41 -0800130}
131
Adam Stone568b3c42018-01-31 12:57:16 -0800132void ExportSessionLifespans(
133 const std::map<android::String16, std::pair<int64_t, int64_t>>
134 &mSessionLifespans,
135 PersistableBundle *metrics) {
136 if (!metrics) {
137 ALOGE("metrics was unexpectedly null.");
138 return;
139 }
140
141 if (mSessionLifespans.empty()) {
142 return;
143 }
144
145 PersistableBundle startTimesBundle;
146 PersistableBundle endTimesBundle;
147 for (auto it = mSessionLifespans.begin(); it != mSessionLifespans.end();
148 it++) {
149 startTimesBundle.putLong(android::String16(it->first),
150 it->second.first);
151 endTimesBundle.putLong(android::String16(it->first), it->second.second);
152 }
153 metrics->putPersistableBundle(
154 android::String16("drm.mediadrm.session_start_times_ms"),
155 startTimesBundle);
156 metrics->putPersistableBundle(
157 android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
158}
159
160android::String8 ToHexString(const android::Vector<uint8_t> &sessionId) {
161 android::String8 result;
162 for (size_t i = 0; i < sessionId.size(); i++) {
163 result.appendFormat("%02x", sessionId[i]);
164 }
165 return result;
166}
167
168int64_t getCurrentTimeMs() {
169 struct timeval tv;
170 gettimeofday(&tv, NULL);
171 return ((int64_t)tv.tv_sec * 1000) + ((int64_t)tv.tv_usec / 1000);
172}
173
174} // namespace
Adam Stonef0e618d2018-01-17 19:20:41 -0800175
176namespace android {
177
178MediaDrmMetrics::MediaDrmMetrics()
Adam Stone4bea53c2018-01-24 21:44:58 -0800179 : mOpenSessionCounter("drm.mediadrm.open_session", "status"),
180 mCloseSessionCounter("drm.mediadrm.close_session", "status"),
181 mGetKeyRequestTiming("drm.mediadrm.get_key_request", "status"),
182 mProvideKeyResponseTiming("drm.mediadrm.provide_key_response", "status"),
Adam Stone568b3c42018-01-31 12:57:16 -0800183 mGetProvisionRequestCounter("drm.mediadrm.get_provision_request",
184 "status"),
Adam Stonecea91ce2018-01-22 19:23:28 -0800185 mProvideProvisionResponseCounter(
Adam Stone4bea53c2018-01-24 21:44:58 -0800186 "drm.mediadrm.provide_provision_response", "status"),
Adam Stone568b3c42018-01-31 12:57:16 -0800187 mKeyStatusChangeCounter("drm.mediadrm.key_status_change",
188 "key_status_type"),
Adam Stone4bea53c2018-01-24 21:44:58 -0800189 mEventCounter("drm.mediadrm.event", "event_type"),
Adam Stone568b3c42018-01-31 12:57:16 -0800190 mGetDeviceUniqueIdCounter("drm.mediadrm.get_device_unique_id", "status") {
Adam Stonef0e618d2018-01-17 19:20:41 -0800191}
192
Adam Stone568b3c42018-01-31 12:57:16 -0800193void MediaDrmMetrics::SetSessionStart(
194 const android::Vector<uint8_t> &sessionId) {
195 String16 sessionIdHex = String16(ToHexString(sessionId));
196 mSessionLifespans[sessionIdHex] =
197 std::make_pair(getCurrentTimeMs(), (int64_t)0);
Adam Stonef0e618d2018-01-17 19:20:41 -0800198}
199
Adam Stone568b3c42018-01-31 12:57:16 -0800200void MediaDrmMetrics::SetSessionEnd(const android::Vector<uint8_t> &sessionId) {
201 String16 sessionIdHex = String16(ToHexString(sessionId));
202 int64_t endTimeMs = getCurrentTimeMs();
203 if (mSessionLifespans.find(sessionIdHex) != mSessionLifespans.end()) {
204 mSessionLifespans[sessionIdHex] =
205 std::make_pair(mSessionLifespans[sessionIdHex].first, endTimeMs);
206 } else {
207 mSessionLifespans[sessionIdHex] = std::make_pair((int64_t)0, endTimeMs);
208 }
209}
210
211void MediaDrmMetrics::Export(PersistableBundle *metrics) {
212 if (!metrics) {
213 ALOGE("metrics was unexpectedly null.");
214 return;
215 }
216 ExportCounterMetric(mOpenSessionCounter, metrics);
217 ExportCounterMetric(mCloseSessionCounter, metrics);
218 ExportEventMetric(mGetKeyRequestTiming, metrics);
219 ExportEventMetric(mProvideKeyResponseTiming, metrics);
220 ExportCounterMetric(mGetProvisionRequestCounter, metrics);
221 ExportCounterMetric(mProvideProvisionResponseCounter, metrics);
222 ExportCounterMetricWithAttributeNames(mKeyStatusChangeCounter, metrics);
223 ExportCounterMetricWithAttributeNames(mEventCounter, metrics);
224 ExportCounterMetric(mGetDeviceUniqueIdCounter, metrics);
225 ExportSessionLifespans(mSessionLifespans, metrics);
226}
227
228} // namespace android