xref: /aosp_15_r20/frameworks/av/drm/libmediadrm/DrmMetricsConsumer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 "DrmMetricsConsumer"
17*ec779b8eSAndroid Build Coastguard Worker 
18*ec779b8eSAndroid Build Coastguard Worker #include <android-base/macros.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <mediadrm/DrmMetricsConsumer.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <mediadrm/DrmMetrics.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <utils/String8.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <utils/String16.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker using ::android::String16;
25*ec779b8eSAndroid Build Coastguard Worker using ::android::String8;
26*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::hidl_string;
27*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::hidl_vec;
28*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_0::EventType;
29*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_2::KeyStatusType;
30*ec779b8eSAndroid Build Coastguard Worker using ::android::hardware::drm::V1_1::DrmMetricGroup;
31*ec779b8eSAndroid Build Coastguard Worker using ::android::os::PersistableBundle;
32*ec779b8eSAndroid Build Coastguard Worker 
33*ec779b8eSAndroid Build Coastguard Worker namespace {
34*ec779b8eSAndroid Build Coastguard Worker 
GetAttributeName(const std::string & typeName,uint32_t attribute)35*ec779b8eSAndroid Build Coastguard Worker std::string GetAttributeName(const std::string &typeName, uint32_t attribute) {
36*ec779b8eSAndroid Build Coastguard Worker     if (typeName == "KeyStatusChange") {
37*ec779b8eSAndroid Build Coastguard Worker         static const char *type_names[] = {"USABLE", "EXPIRED",
38*ec779b8eSAndroid Build Coastguard Worker                                        "OUTPUT_NOT_ALLOWED", "STATUS_PENDING",
39*ec779b8eSAndroid Build Coastguard Worker                                        "INTERNAL_ERROR", "USABLE_IN_FUTURE"};
40*ec779b8eSAndroid Build Coastguard Worker         if (attribute >= arraysize(type_names)) {
41*ec779b8eSAndroid Build Coastguard Worker             return "UNKNOWN_TYPE";
42*ec779b8eSAndroid Build Coastguard Worker         }
43*ec779b8eSAndroid Build Coastguard Worker         return type_names[attribute];
44*ec779b8eSAndroid Build Coastguard Worker     }
45*ec779b8eSAndroid Build Coastguard Worker 
46*ec779b8eSAndroid Build Coastguard Worker     static const char *type_names[] = {"PROVISION_REQUIRED", "KEY_NEEDED",
47*ec779b8eSAndroid Build Coastguard Worker                                        "KEY_EXPIRED", "VENDOR_DEFINED",
48*ec779b8eSAndroid Build Coastguard Worker                                        "SESSION_RECLAIMED"};
49*ec779b8eSAndroid Build Coastguard Worker     if (attribute >= arraysize(type_names)) {
50*ec779b8eSAndroid Build Coastguard Worker         return "UNKNOWN_TYPE";
51*ec779b8eSAndroid Build Coastguard Worker     }
52*ec779b8eSAndroid Build Coastguard Worker     return type_names[attribute];
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker 
55*ec779b8eSAndroid Build Coastguard Worker template <typename T>
ExportCounterMetric(const android::CounterMetric<T> & counter,PersistableBundle * metrics)56*ec779b8eSAndroid Build Coastguard Worker void ExportCounterMetric(const android::CounterMetric<T> &counter,
57*ec779b8eSAndroid Build Coastguard Worker                          PersistableBundle *metrics) {
58*ec779b8eSAndroid Build Coastguard Worker     if (!metrics) {
59*ec779b8eSAndroid Build Coastguard Worker         ALOGE("metrics was unexpectedly null.");
60*ec779b8eSAndroid Build Coastguard Worker         return;
61*ec779b8eSAndroid Build Coastguard Worker     }
62*ec779b8eSAndroid Build Coastguard Worker     std::string success_count_name = counter.metric_name() + ".ok.count";
63*ec779b8eSAndroid Build Coastguard Worker     std::string error_count_name = counter.metric_name() + ".error.count";
64*ec779b8eSAndroid Build Coastguard Worker     std::vector<int64_t> status_values;
65*ec779b8eSAndroid Build Coastguard Worker     counter.ExportValues(
66*ec779b8eSAndroid Build Coastguard Worker         [&](const android::status_t status, const int64_t value) {
67*ec779b8eSAndroid Build Coastguard Worker             if (status == android::OK) {
68*ec779b8eSAndroid Build Coastguard Worker                 metrics->putLong(android::String16(success_count_name.c_str()),
69*ec779b8eSAndroid Build Coastguard Worker                                  value);
70*ec779b8eSAndroid Build Coastguard Worker             } else {
71*ec779b8eSAndroid Build Coastguard Worker                 int64_t total_errors(0);
72*ec779b8eSAndroid Build Coastguard Worker                 metrics->getLong(android::String16(error_count_name.c_str()),
73*ec779b8eSAndroid Build Coastguard Worker                                  &total_errors);
74*ec779b8eSAndroid Build Coastguard Worker                 metrics->putLong(android::String16(error_count_name.c_str()),
75*ec779b8eSAndroid Build Coastguard Worker                                  total_errors + value);
76*ec779b8eSAndroid Build Coastguard Worker                 status_values.push_back(status);
77*ec779b8eSAndroid Build Coastguard Worker             }
78*ec779b8eSAndroid Build Coastguard Worker         });
79*ec779b8eSAndroid Build Coastguard Worker     if (!status_values.empty()) {
80*ec779b8eSAndroid Build Coastguard Worker         std::string error_list_name = counter.metric_name() + ".error.list";
81*ec779b8eSAndroid Build Coastguard Worker         metrics->putLongVector(android::String16(error_list_name.c_str()),
82*ec779b8eSAndroid Build Coastguard Worker                                status_values);
83*ec779b8eSAndroid Build Coastguard Worker     }
84*ec779b8eSAndroid Build Coastguard Worker }
85*ec779b8eSAndroid Build Coastguard Worker 
86*ec779b8eSAndroid Build Coastguard Worker template <typename T>
ExportCounterMetricWithAttributeNames(const android::CounterMetric<T> & counter,const std::string & typeName,PersistableBundle * metrics)87*ec779b8eSAndroid Build Coastguard Worker void ExportCounterMetricWithAttributeNames(
88*ec779b8eSAndroid Build Coastguard Worker     const android::CounterMetric<T> &counter, const std::string &typeName, PersistableBundle *metrics) {
89*ec779b8eSAndroid Build Coastguard Worker     if (!metrics) {
90*ec779b8eSAndroid Build Coastguard Worker         ALOGE("metrics was unexpectedly null.");
91*ec779b8eSAndroid Build Coastguard Worker         return;
92*ec779b8eSAndroid Build Coastguard Worker     }
93*ec779b8eSAndroid Build Coastguard Worker     counter.ExportValues([&](const uint32_t attribute, const int64_t value) {
94*ec779b8eSAndroid Build Coastguard Worker         std::string name = counter.metric_name() + "." +
95*ec779b8eSAndroid Build Coastguard Worker                            GetAttributeName(typeName, attribute) + ".count";
96*ec779b8eSAndroid Build Coastguard Worker         metrics->putLong(android::String16(name.c_str()), value);
97*ec779b8eSAndroid Build Coastguard Worker     });
98*ec779b8eSAndroid Build Coastguard Worker }
99*ec779b8eSAndroid Build Coastguard Worker 
100*ec779b8eSAndroid Build Coastguard Worker template <typename T>
ExportEventMetric(const android::EventMetric<T> & event,PersistableBundle * metrics)101*ec779b8eSAndroid Build Coastguard Worker void ExportEventMetric(const android::EventMetric<T> &event,
102*ec779b8eSAndroid Build Coastguard Worker                        PersistableBundle *metrics) {
103*ec779b8eSAndroid Build Coastguard Worker     if (!metrics) {
104*ec779b8eSAndroid Build Coastguard Worker         ALOGE("metrics was unexpectedly null.");
105*ec779b8eSAndroid Build Coastguard Worker         return;
106*ec779b8eSAndroid Build Coastguard Worker     }
107*ec779b8eSAndroid Build Coastguard Worker     std::string success_count_name = event.metric_name() + ".ok.count";
108*ec779b8eSAndroid Build Coastguard Worker     std::string error_count_name = event.metric_name() + ".error.count";
109*ec779b8eSAndroid Build Coastguard Worker     std::string timing_name = event.metric_name() + ".ok.average_time_micros";
110*ec779b8eSAndroid Build Coastguard Worker     std::vector<int64_t> status_values;
111*ec779b8eSAndroid Build Coastguard Worker     event.ExportValues([&](const android::status_t &status,
112*ec779b8eSAndroid Build Coastguard Worker                            const android::EventStatistics &value) {
113*ec779b8eSAndroid Build Coastguard Worker         if (status == android::OK) {
114*ec779b8eSAndroid Build Coastguard Worker             metrics->putLong(android::String16(success_count_name.c_str()),
115*ec779b8eSAndroid Build Coastguard Worker                              value.count);
116*ec779b8eSAndroid Build Coastguard Worker             metrics->putLong(android::String16(timing_name.c_str()),
117*ec779b8eSAndroid Build Coastguard Worker                              value.mean);
118*ec779b8eSAndroid Build Coastguard Worker         } else {
119*ec779b8eSAndroid Build Coastguard Worker             int64_t total_errors(0);
120*ec779b8eSAndroid Build Coastguard Worker             metrics->getLong(android::String16(error_count_name.c_str()),
121*ec779b8eSAndroid Build Coastguard Worker                              &total_errors);
122*ec779b8eSAndroid Build Coastguard Worker             metrics->putLong(android::String16(error_count_name.c_str()),
123*ec779b8eSAndroid Build Coastguard Worker                              total_errors + value.count);
124*ec779b8eSAndroid Build Coastguard Worker             status_values.push_back(status);
125*ec779b8eSAndroid Build Coastguard Worker         }
126*ec779b8eSAndroid Build Coastguard Worker     });
127*ec779b8eSAndroid Build Coastguard Worker     if (!status_values.empty()) {
128*ec779b8eSAndroid Build Coastguard Worker         std::string error_list_name = event.metric_name() + ".error.list";
129*ec779b8eSAndroid Build Coastguard Worker         metrics->putLongVector(android::String16(error_list_name.c_str()),
130*ec779b8eSAndroid Build Coastguard Worker                                status_values);
131*ec779b8eSAndroid Build Coastguard Worker     }
132*ec779b8eSAndroid Build Coastguard Worker }
133*ec779b8eSAndroid Build Coastguard Worker 
ExportSessionLifespans(const std::map<std::string,std::pair<int64_t,int64_t>> & sessionLifespans,PersistableBundle * metrics)134*ec779b8eSAndroid Build Coastguard Worker void ExportSessionLifespans(
135*ec779b8eSAndroid Build Coastguard Worker     const std::map<std::string, std::pair<int64_t, int64_t>> &sessionLifespans,
136*ec779b8eSAndroid Build Coastguard Worker     PersistableBundle *metrics) {
137*ec779b8eSAndroid Build Coastguard Worker     if (!metrics) {
138*ec779b8eSAndroid Build Coastguard Worker         ALOGE("metrics was unexpectedly null.");
139*ec779b8eSAndroid Build Coastguard Worker         return;
140*ec779b8eSAndroid Build Coastguard Worker     }
141*ec779b8eSAndroid Build Coastguard Worker 
142*ec779b8eSAndroid Build Coastguard Worker     if (sessionLifespans.empty()) {
143*ec779b8eSAndroid Build Coastguard Worker         return;
144*ec779b8eSAndroid Build Coastguard Worker     }
145*ec779b8eSAndroid Build Coastguard Worker 
146*ec779b8eSAndroid Build Coastguard Worker     PersistableBundle startTimesBundle;
147*ec779b8eSAndroid Build Coastguard Worker     PersistableBundle endTimesBundle;
148*ec779b8eSAndroid Build Coastguard Worker     for (auto it = sessionLifespans.begin(); it != sessionLifespans.end();
149*ec779b8eSAndroid Build Coastguard Worker          it++) {
150*ec779b8eSAndroid Build Coastguard Worker         String16 key(it->first.c_str(), it->first.size());
151*ec779b8eSAndroid Build Coastguard Worker         startTimesBundle.putLong(key, it->second.first);
152*ec779b8eSAndroid Build Coastguard Worker         endTimesBundle.putLong(key, it->second.second);
153*ec779b8eSAndroid Build Coastguard Worker     }
154*ec779b8eSAndroid Build Coastguard Worker     metrics->putPersistableBundle(
155*ec779b8eSAndroid Build Coastguard Worker         android::String16("drm.mediadrm.session_start_times_ms"),
156*ec779b8eSAndroid Build Coastguard Worker         startTimesBundle);
157*ec779b8eSAndroid Build Coastguard Worker     metrics->putPersistableBundle(
158*ec779b8eSAndroid Build Coastguard Worker         android::String16("drm.mediadrm.session_end_times_ms"), endTimesBundle);
159*ec779b8eSAndroid Build Coastguard Worker }
160*ec779b8eSAndroid Build Coastguard Worker 
161*ec779b8eSAndroid Build Coastguard Worker template <typename CT>
SetValue(const String16 & name,DrmMetricGroup::ValueType type,const CT & value,PersistableBundle * bundle)162*ec779b8eSAndroid Build Coastguard Worker void SetValue(const String16 &name, DrmMetricGroup::ValueType type,
163*ec779b8eSAndroid Build Coastguard Worker               const CT &value, PersistableBundle *bundle) {
164*ec779b8eSAndroid Build Coastguard Worker     switch (type) {
165*ec779b8eSAndroid Build Coastguard Worker     case DrmMetricGroup::ValueType::INT64_TYPE:
166*ec779b8eSAndroid Build Coastguard Worker         bundle->putLong(name, value.int64Value);
167*ec779b8eSAndroid Build Coastguard Worker         break;
168*ec779b8eSAndroid Build Coastguard Worker     case DrmMetricGroup::ValueType::DOUBLE_TYPE:
169*ec779b8eSAndroid Build Coastguard Worker         bundle->putDouble(name, value.doubleValue);
170*ec779b8eSAndroid Build Coastguard Worker         break;
171*ec779b8eSAndroid Build Coastguard Worker     case DrmMetricGroup::ValueType::STRING_TYPE:
172*ec779b8eSAndroid Build Coastguard Worker         bundle->putString(name, String16(value.stringValue.c_str()));
173*ec779b8eSAndroid Build Coastguard Worker         break;
174*ec779b8eSAndroid Build Coastguard Worker     default:
175*ec779b8eSAndroid Build Coastguard Worker         ALOGE("Unexpected value type: %hhu", type);
176*ec779b8eSAndroid Build Coastguard Worker     }
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker 
MakeIndexString(unsigned int index)179*ec779b8eSAndroid Build Coastguard Worker inline String16 MakeIndexString(unsigned int index) {
180*ec779b8eSAndroid Build Coastguard Worker   std::string str("[");
181*ec779b8eSAndroid Build Coastguard Worker   str.append(std::to_string(index));
182*ec779b8eSAndroid Build Coastguard Worker   str.append("]");
183*ec779b8eSAndroid Build Coastguard Worker   return String16(str.c_str());
184*ec779b8eSAndroid Build Coastguard Worker }
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker } // namespace
187*ec779b8eSAndroid Build Coastguard Worker 
188*ec779b8eSAndroid Build Coastguard Worker namespace android {
189*ec779b8eSAndroid Build Coastguard Worker 
consumeFrameworkMetrics(const MediaDrmMetrics & metrics)190*ec779b8eSAndroid Build Coastguard Worker status_t DrmMetricsConsumer::consumeFrameworkMetrics(const MediaDrmMetrics &metrics) {
191*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetric(metrics.mOpenSessionCounter, mBundle);
192*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetric(metrics.mCloseSessionCounter, mBundle);
193*ec779b8eSAndroid Build Coastguard Worker     ExportEventMetric(metrics.mGetKeyRequestTimeUs, mBundle);
194*ec779b8eSAndroid Build Coastguard Worker     ExportEventMetric(metrics.mProvideKeyResponseTimeUs, mBundle);
195*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetric(metrics.mGetProvisionRequestCounter, mBundle);
196*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetric(metrics.mProvideProvisionResponseCounter, mBundle);
197*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetricWithAttributeNames(metrics.mKeyStatusChangeCounter, "KeyStatusChange", mBundle);
198*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetricWithAttributeNames(metrics.mEventCounter, "Event", mBundle);
199*ec779b8eSAndroid Build Coastguard Worker     ExportCounterMetric(metrics.mGetDeviceUniqueIdCounter, mBundle);
200*ec779b8eSAndroid Build Coastguard Worker     ExportSessionLifespans(metrics.GetSessionLifespans(), mBundle);
201*ec779b8eSAndroid Build Coastguard Worker     return android::OK;
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker 
consumeHidlMetrics(const String8 & vendor,const hidl_vec<DrmMetricGroup> & pluginMetrics)204*ec779b8eSAndroid Build Coastguard Worker status_t DrmMetricsConsumer::consumeHidlMetrics(
205*ec779b8eSAndroid Build Coastguard Worker         const String8 &vendor,
206*ec779b8eSAndroid Build Coastguard Worker         const hidl_vec<DrmMetricGroup> &pluginMetrics) {
207*ec779b8eSAndroid Build Coastguard Worker     PersistableBundle pluginBundle;
208*ec779b8eSAndroid Build Coastguard Worker     if (DrmMetricsConsumer::HidlMetricsToBundle(
209*ec779b8eSAndroid Build Coastguard Worker             pluginMetrics, &pluginBundle) == OK) {
210*ec779b8eSAndroid Build Coastguard Worker         mBundle->putPersistableBundle(String16(vendor), pluginBundle);
211*ec779b8eSAndroid Build Coastguard Worker     }
212*ec779b8eSAndroid Build Coastguard Worker     return android::OK;
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker 
HidlMetricsToBundle(const hidl_vec<DrmMetricGroup> & hidlMetricGroups,PersistableBundle * bundleMetricGroups)215*ec779b8eSAndroid Build Coastguard Worker status_t DrmMetricsConsumer::HidlMetricsToBundle(
216*ec779b8eSAndroid Build Coastguard Worker     const hidl_vec<DrmMetricGroup> &hidlMetricGroups,
217*ec779b8eSAndroid Build Coastguard Worker     PersistableBundle *bundleMetricGroups) {
218*ec779b8eSAndroid Build Coastguard Worker     if (bundleMetricGroups == nullptr) {
219*ec779b8eSAndroid Build Coastguard Worker         return UNEXPECTED_NULL;
220*ec779b8eSAndroid Build Coastguard Worker     }
221*ec779b8eSAndroid Build Coastguard Worker     if (hidlMetricGroups.size() == 0) {
222*ec779b8eSAndroid Build Coastguard Worker         return OK;
223*ec779b8eSAndroid Build Coastguard Worker     }
224*ec779b8eSAndroid Build Coastguard Worker 
225*ec779b8eSAndroid Build Coastguard Worker     int groupIndex = 0;
226*ec779b8eSAndroid Build Coastguard Worker     std::map<String16, int> indexMap;
227*ec779b8eSAndroid Build Coastguard Worker     for (const auto &hidlMetricGroup : hidlMetricGroups) {
228*ec779b8eSAndroid Build Coastguard Worker         PersistableBundle bundleMetricGroup;
229*ec779b8eSAndroid Build Coastguard Worker         for (const auto &hidlMetric : hidlMetricGroup.metrics) {
230*ec779b8eSAndroid Build Coastguard Worker             String16 metricName(hidlMetric.name.c_str());
231*ec779b8eSAndroid Build Coastguard Worker             PersistableBundle bundleMetric;
232*ec779b8eSAndroid Build Coastguard Worker             // Add metric component values.
233*ec779b8eSAndroid Build Coastguard Worker             for (const auto &value : hidlMetric.values) {
234*ec779b8eSAndroid Build Coastguard Worker                 SetValue(String16(value.componentName.c_str()), value.type,
235*ec779b8eSAndroid Build Coastguard Worker                          value, &bundleMetric);
236*ec779b8eSAndroid Build Coastguard Worker             }
237*ec779b8eSAndroid Build Coastguard Worker             // Set metric attributes.
238*ec779b8eSAndroid Build Coastguard Worker             PersistableBundle bundleMetricAttributes;
239*ec779b8eSAndroid Build Coastguard Worker             for (const auto &attribute : hidlMetric.attributes) {
240*ec779b8eSAndroid Build Coastguard Worker                 SetValue(String16(attribute.name.c_str()), attribute.type,
241*ec779b8eSAndroid Build Coastguard Worker                          attribute, &bundleMetricAttributes);
242*ec779b8eSAndroid Build Coastguard Worker             }
243*ec779b8eSAndroid Build Coastguard Worker             // Add attributes to the bundle metric.
244*ec779b8eSAndroid Build Coastguard Worker             bundleMetric.putPersistableBundle(String16("attributes"),
245*ec779b8eSAndroid Build Coastguard Worker                                               bundleMetricAttributes);
246*ec779b8eSAndroid Build Coastguard Worker             // Add one layer of indirection, allowing for repeated metric names.
247*ec779b8eSAndroid Build Coastguard Worker             PersistableBundle repeatedMetrics;
248*ec779b8eSAndroid Build Coastguard Worker             bundleMetricGroup.getPersistableBundle(metricName,
249*ec779b8eSAndroid Build Coastguard Worker                                                    &repeatedMetrics);
250*ec779b8eSAndroid Build Coastguard Worker             int index = indexMap[metricName];
251*ec779b8eSAndroid Build Coastguard Worker             repeatedMetrics.putPersistableBundle(MakeIndexString(index),
252*ec779b8eSAndroid Build Coastguard Worker                                                  bundleMetric);
253*ec779b8eSAndroid Build Coastguard Worker             indexMap[metricName] = ++index;
254*ec779b8eSAndroid Build Coastguard Worker 
255*ec779b8eSAndroid Build Coastguard Worker             // Add the bundle metric to the group of metrics.
256*ec779b8eSAndroid Build Coastguard Worker             bundleMetricGroup.putPersistableBundle(metricName,
257*ec779b8eSAndroid Build Coastguard Worker                                                    repeatedMetrics);
258*ec779b8eSAndroid Build Coastguard Worker         }
259*ec779b8eSAndroid Build Coastguard Worker         // Add the bundle metric group to the collection of groups.
260*ec779b8eSAndroid Build Coastguard Worker         bundleMetricGroups->putPersistableBundle(MakeIndexString(groupIndex++),
261*ec779b8eSAndroid Build Coastguard Worker                                                  bundleMetricGroup);
262*ec779b8eSAndroid Build Coastguard Worker     }
263*ec779b8eSAndroid Build Coastguard Worker 
264*ec779b8eSAndroid Build Coastguard Worker     return OK;
265*ec779b8eSAndroid Build Coastguard Worker }
266*ec779b8eSAndroid Build Coastguard Worker 
267*ec779b8eSAndroid Build Coastguard Worker } // namespace android
268*ec779b8eSAndroid Build Coastguard Worker 
269