• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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 
17 #define LOG_TAG "DrmMetricsTest"
18 #include "mediadrm/DrmMetrics.h"
19 #include "mediadrm/DrmMetricsConsumer.h"
20 
21 #include <android/hardware/drm/1.0/types.h>
22 #include <android/hardware/drm/1.1/types.h>
23 #include <binder/PersistableBundle.h>
24 #include <google/protobuf/text_format.h>
25 #include <google/protobuf/util/message_differencer.h>
26 #include <gtest/gtest.h>
27 #include <utils/Log.h>
28 
29 #include "protos/metrics.pb.h"
30 
31 using ::android::drm_metrics::DrmFrameworkMetrics;
32 using ::android::hardware::hidl_vec;
33 using ::android::hardware::drm::V1_0::EventType;
34 using ::android::hardware::drm::V1_2::KeyStatusType;
35 using ::android::hardware::drm::V1_0::Status;
36 using ::android::hardware::drm::V1_1::DrmMetricGroup;
37 using ::android::os::PersistableBundle;
38 using ::google::protobuf::util::MessageDifferencer;
39 using ::google::protobuf::TextFormat;
40 
41 namespace android {
42 
43 /**
44  * Unit tests for the MediaDrmMetrics class.
45  */
46 class MediaDrmMetricsTest : public ::testing::Test {};
47 
48 /**
49  * This derived class mocks the clock for testing purposes.
50  */
51 class FakeMediaDrmMetrics : public MediaDrmMetrics {
52  public:
FakeMediaDrmMetrics()53   FakeMediaDrmMetrics() : MediaDrmMetrics(), time_(0) {};
54 
GetCurrentTimeMs()55   int64_t GetCurrentTimeMs() { return time_++; }
56   int64_t time_;
57 };
58 
TEST_F(MediaDrmMetricsTest,EmptySuccess)59 TEST_F(MediaDrmMetricsTest, EmptySuccess) {
60   MediaDrmMetrics metrics;
61   PersistableBundle bundle;
62   DrmMetricsConsumer consumer(&bundle);
63 
64   consumer.consumeFrameworkMetrics(metrics);
65   EXPECT_TRUE(bundle.empty());
66 }
67 
TEST_F(MediaDrmMetricsTest,AllValuesSuccessCounts)68 TEST_F(MediaDrmMetricsTest, AllValuesSuccessCounts) {
69   MediaDrmMetrics metrics;
70 
71   metrics.mOpenSessionCounter.Increment(OK);
72   metrics.mCloseSessionCounter.Increment(OK);
73 
74   {
75     EventTimer<status_t> get_key_request_timer(&metrics.mGetKeyRequestTimeUs);
76     EventTimer<status_t> provide_key_response_timer(
77         &metrics.mProvideKeyResponseTimeUs);
78     get_key_request_timer.SetAttribute(OK);
79     provide_key_response_timer.SetAttribute(OK);
80   }
81 
82   metrics.mGetProvisionRequestCounter.Increment(OK);
83   metrics.mProvideProvisionResponseCounter.Increment(OK);
84   metrics.mGetDeviceUniqueIdCounter.Increment(OK);
85 
86   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
87   metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
88 
89   PersistableBundle bundle;
90   DrmMetricsConsumer consumer(&bundle);
91 
92   consumer.consumeFrameworkMetrics(metrics);
93   EXPECT_EQ(11U, bundle.size());
94 
95   // Verify the list of pairs of int64 metrics.
96   std::vector<std::pair<std::string, int64_t>> expected_values = {
97       { "drm.mediadrm.open_session.ok.count", 1 },
98       { "drm.mediadrm.close_session.ok.count", 1 },
99       { "drm.mediadrm.get_key_request.ok.count", 1 },
100       { "drm.mediadrm.provide_key_response.ok.count", 1 },
101       { "drm.mediadrm.get_provision_request.ok.count", 1 },
102       { "drm.mediadrm.provide_provision_response.ok.count", 1 },
103       { "drm.mediadrm.key_status_change.USABLE.count", 1 },
104       { "drm.mediadrm.event.PROVISION_REQUIRED.count", 1 },
105       { "drm.mediadrm.get_device_unique_id.ok.count", 1 }};
106   for (const auto& expected_pair : expected_values) {
107     String16 key(expected_pair.first.c_str());
108     int64_t value = -1;
109     EXPECT_TRUE(bundle.getLong(key, &value))
110         << "Unexpected error retrieviing key: " << key;
111     EXPECT_EQ(expected_pair.second, value)
112         << "Unexpected value for " << expected_pair.first << ". " << value;
113   }
114 
115   // Validate timing values exist.
116   String16 get_key_request_key(
117       "drm.mediadrm.get_key_request.ok.average_time_micros");
118   String16 provide_key_response_key(
119       "drm.mediadrm.provide_key_response.ok.average_time_micros");
120   int64_t value = -1;
121   EXPECT_TRUE(bundle.getLong(get_key_request_key, &value));
122   EXPECT_GE(value, 0);
123   value = -1;
124   EXPECT_TRUE(bundle.getLong(provide_key_response_key, &value));
125   EXPECT_GE(value, 0);
126 }
127 
TEST_F(MediaDrmMetricsTest,AllValuesFull)128 TEST_F(MediaDrmMetricsTest, AllValuesFull) {
129   MediaDrmMetrics metrics;
130 
131   metrics.mOpenSessionCounter.Increment(OK);
132   metrics.mOpenSessionCounter.Increment(UNEXPECTED_NULL);
133 
134   metrics.mCloseSessionCounter.Increment(OK);
135   metrics.mCloseSessionCounter.Increment(UNEXPECTED_NULL);
136 
137   for (status_t s : {OK, UNEXPECTED_NULL}) {
138     {
139       EventTimer<status_t> get_key_request_timer(&metrics.mGetKeyRequestTimeUs);
140       EventTimer<status_t> provide_key_response_timer(
141           &metrics.mProvideKeyResponseTimeUs);
142       get_key_request_timer.SetAttribute(s);
143       provide_key_response_timer.SetAttribute(s);
144     }
145   }
146 
147   metrics.mGetProvisionRequestCounter.Increment(OK);
148   metrics.mGetProvisionRequestCounter.Increment(UNEXPECTED_NULL);
149   metrics.mProvideProvisionResponseCounter.Increment(OK);
150   metrics.mProvideProvisionResponseCounter.Increment(UNEXPECTED_NULL);
151   metrics.mGetDeviceUniqueIdCounter.Increment(OK);
152   metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
153 
154   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
155   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
156   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
157   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
158   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
159   metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
160   metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
161   metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
162   metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
163   metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
164 
165   android::Vector<uint8_t> sessionId1;
166   sessionId1.push_back(1);
167   sessionId1.push_back(2);
168   android::Vector<uint8_t> sessionId2;
169   sessionId2.push_back(3);
170   sessionId2.push_back(4);
171   String16 hexSessionId1("0102");
172   String16 hexSessionId2("0304");
173 
174   metrics.SetSessionStart(sessionId1);
175   metrics.SetSessionStart(sessionId2);
176   metrics.SetSessionEnd(sessionId2);
177   metrics.SetSessionEnd(sessionId1);
178 
179   PersistableBundle bundle;
180   DrmMetricsConsumer consumer(&bundle);
181   consumer.consumeFrameworkMetrics(metrics);
182   EXPECT_EQ(35U, bundle.size());
183 
184   // Verify the list of pairs of int64 metrics.
185   std::vector<std::pair<std::string, int64_t>> expected_values = {
186       { "drm.mediadrm.open_session.ok.count", 1 },
187       { "drm.mediadrm.close_session.ok.count", 1 },
188       { "drm.mediadrm.get_key_request.ok.count", 1 },
189       { "drm.mediadrm.provide_key_response.ok.count", 1 },
190       { "drm.mediadrm.get_provision_request.ok.count", 1 },
191       { "drm.mediadrm.provide_provision_response.ok.count", 1 },
192       { "drm.mediadrm.get_device_unique_id.ok.count", 1 },
193       { "drm.mediadrm.open_session.error.count", 1 },
194       { "drm.mediadrm.close_session.error.count", 1 },
195       { "drm.mediadrm.get_key_request.error.count", 1 },
196       { "drm.mediadrm.provide_key_response.error.count", 1 },
197       { "drm.mediadrm.get_provision_request.error.count", 1 },
198       { "drm.mediadrm.provide_provision_response.error.count", 1 },
199       { "drm.mediadrm.get_device_unique_id.error.count", 1 },
200       { "drm.mediadrm.key_status_change.USABLE.count", 1 },
201       { "drm.mediadrm.key_status_change.EXPIRED.count", 1 },
202       { "drm.mediadrm.key_status_change.OUTPUT_NOT_ALLOWED.count", 1 },
203       { "drm.mediadrm.key_status_change.STATUS_PENDING.count", 1 },
204       { "drm.mediadrm.key_status_change.INTERNAL_ERROR.count", 1 },
205       { "drm.mediadrm.event.PROVISION_REQUIRED.count", 1 },
206       { "drm.mediadrm.event.KEY_NEEDED.count", 1 },
207       { "drm.mediadrm.event.KEY_EXPIRED.count", 1 },
208       { "drm.mediadrm.event.VENDOR_DEFINED.count", 1 },
209       { "drm.mediadrm.event.SESSION_RECLAIMED.count", 1 }};
210   for (const auto& expected_pair : expected_values) {
211     String16 key(expected_pair.first.c_str());
212     int64_t value = -1;
213     EXPECT_TRUE(bundle.getLong(key, &value))
214         << "Unexpected error retrieviing key: " << key;
215     EXPECT_EQ(expected_pair.second, value)
216         << "Unexpected value for " << expected_pair.first << ". " << value;
217   }
218 
219   // Verify the error lists
220   std::vector<std::pair<std::string, std::vector<int64_t>>> expected_vector_values = {
221       { "drm.mediadrm.close_session.error.list", { UNEXPECTED_NULL } },
222       { "drm.mediadrm.get_device_unique_id.error.list", { UNEXPECTED_NULL } },
223       { "drm.mediadrm.get_key_request.error.list", { UNEXPECTED_NULL } },
224       { "drm.mediadrm.get_provision_request.error.list", { UNEXPECTED_NULL } },
225       { "drm.mediadrm.open_session.error.list", { UNEXPECTED_NULL } },
226       { "drm.mediadrm.provide_key_response.error.list", { UNEXPECTED_NULL } },
227       { "drm.mediadrm.provide_provision_response.error.list", { UNEXPECTED_NULL } }};
228   for (const auto& expected_pair : expected_vector_values) {
229     String16 key(expected_pair.first.c_str());
230     std::vector<int64_t> values;
231     EXPECT_TRUE(bundle.getLongVector(key, &values))
232         << "Unexpected error retrieviing key: " << key;
233     for (auto expected : expected_pair.second) {
234       EXPECT_TRUE(std::find(values.begin(), values.end(), expected) != values.end())
235           << "Could not find " << expected << " for key " << expected_pair.first;
236     }
237   }
238 
239   // Verify the lifespans
240   PersistableBundle start_times;
241   PersistableBundle end_times;
242   String16 start_time_key("drm.mediadrm.session_start_times_ms");
243   String16 end_time_key("drm.mediadrm.session_end_times_ms");
244   ASSERT_TRUE(bundle.getPersistableBundle(start_time_key, &start_times));
245   ASSERT_TRUE(bundle.getPersistableBundle(end_time_key, &end_times));
246   EXPECT_EQ(2U, start_times.size());
247   EXPECT_EQ(2U, end_times.size());
248   int64_t start_time, end_time;
249   for (const auto& sid : { hexSessionId1, hexSessionId2 }) {
250     start_time = -1;
251     end_time = -1;
252     EXPECT_TRUE(start_times.getLong(sid, &start_time));
253     EXPECT_TRUE(end_times.getLong(sid, &end_time));
254     EXPECT_GT(start_time, 0);
255     EXPECT_GE(end_time, start_time);
256   }
257 
258   // Validate timing values exist.
259   String16 get_key_request_key(
260       "drm.mediadrm.get_key_request.ok.average_time_micros");
261   String16 provide_key_response_key(
262       "drm.mediadrm.provide_key_response.ok.average_time_micros");
263   int64_t value = -1;
264   EXPECT_TRUE(bundle.getLong(get_key_request_key, &value));
265   EXPECT_GE(value, 0);
266   value = -1;
267   EXPECT_TRUE(bundle.getLong(provide_key_response_key, &value));
268   EXPECT_GE(value, 0);
269 }
270 
271 
TEST_F(MediaDrmMetricsTest,CounterValuesProtoSerialization)272 TEST_F(MediaDrmMetricsTest, CounterValuesProtoSerialization) {
273   MediaDrmMetrics metrics;
274 
275   metrics.mOpenSessionCounter.Increment(OK);
276   metrics.mOpenSessionCounter.Increment(UNEXPECTED_NULL);
277   metrics.mCloseSessionCounter.Increment(OK);
278   metrics.mCloseSessionCounter.Increment(UNEXPECTED_NULL);
279 
280   metrics.mGetProvisionRequestCounter.Increment(OK);
281   metrics.mGetProvisionRequestCounter.Increment(UNEXPECTED_NULL);
282   metrics.mProvideProvisionResponseCounter.Increment(OK);
283   metrics.mProvideProvisionResponseCounter.Increment(UNEXPECTED_NULL);
284   metrics.mGetDeviceUniqueIdCounter.Increment(OK);
285   metrics.mGetDeviceUniqueIdCounter.Increment(UNEXPECTED_NULL);
286 
287   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::USABLE);
288   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::EXPIRED);
289   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::OUTPUTNOTALLOWED);
290   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::STATUSPENDING);
291   metrics.mKeyStatusChangeCounter.Increment((uint32_t)KeyStatusType::INTERNALERROR);
292   metrics.mEventCounter.Increment((uint32_t)EventType::PROVISION_REQUIRED);
293   metrics.mEventCounter.Increment((uint32_t)EventType::KEY_NEEDED);
294   metrics.mEventCounter.Increment((uint32_t)EventType::KEY_EXPIRED);
295   metrics.mEventCounter.Increment((uint32_t)EventType::VENDOR_DEFINED);
296   metrics.mEventCounter.Increment((uint32_t)EventType::SESSION_RECLAIMED);
297 
298   std::string serializedMetrics;
299   ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
300 
301   DrmFrameworkMetrics metricsProto;
302   ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
303 
304   std::string expectedMetrics =
305       "open_session_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
306       "open_session_counter { count: 1 attributes { error_code: 0 } } "
307       "close_session_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
308       "close_session_counter { count: 1 attributes { error_code: 0 } } "
309       "get_provisioning_request_counter { count: 1 attributes { error_code: -0x7FFFFFF8 } } "
310       "get_provisioning_request_counter { count: 1 attributes { error_code: 0 } } "
311       "provide_provisioning_response_counter { count: 1 attributes { error_code: -0x7ffffff8 } } "
312       "provide_provisioning_response_counter { count: 1 attributes { error_code: 0 } } "
313       "get_device_unique_id_counter { count: 1 attributes { error_code: -0x7ffffff8 } } "
314       "get_device_unique_id_counter { count: 1 attributes { error_code: 0 } } "
315       "key_status_change_counter { count: 1 attributes { key_status_type: 0 } } "
316       "key_status_change_counter { count: 1 attributes { key_status_type: 1 } } "
317       "key_status_change_counter { count: 1 attributes { key_status_type: 2 } } "
318       "key_status_change_counter { count: 1 attributes { key_status_type: 3 } } "
319       "key_status_change_counter { count: 1 attributes { key_status_type: 4 } } "
320       "event_callback_counter { count: 1 attributes { event_type: 0 } } "
321       "event_callback_counter { count: 1 attributes { event_type: 1 } } "
322       "event_callback_counter { count: 1 attributes { event_type: 2 } } "
323       "event_callback_counter { count: 1 attributes { event_type: 3 } } "
324       "event_callback_counter { count: 1 attributes { event_type: 4 } } ";
325 
326   DrmFrameworkMetrics expectedMetricsProto;
327   ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
328 
329   std::string diffString;
330   MessageDifferencer differ;
331   differ.ReportDifferencesToString(&diffString);
332   ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
333       << diffString;
334 }
335 
TEST_F(MediaDrmMetricsTest,TimeMetricsProtoSerialization)336 TEST_F(MediaDrmMetricsTest, TimeMetricsProtoSerialization) {
337   MediaDrmMetrics metrics;
338 
339   for (status_t s : {OK, UNEXPECTED_NULL}) {
340     double time = 0;
341     for (int i = 0; i < 5; i++) {
342       time += 1.0;
343       metrics.mGetKeyRequestTimeUs.Record(time, s);
344       metrics.mProvideKeyResponseTimeUs.Record(time, s);
345     }
346   }
347 
348   std::string serializedMetrics;
349   ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
350 
351   DrmFrameworkMetrics metricsProto;
352   ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
353 
354   std::string expectedMetrics =
355       "get_key_request_time_us { "
356       "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
357       "  attributes { error_code: -0x7FFFFFF8 } "
358       "} "
359       "get_key_request_time_us { "
360       "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
361       "  attributes { error_code: 0 } "
362       "} "
363       "provide_key_response_time_us { "
364       "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
365       "  attributes { error_code: -0x7FFFFFF8 } "
366       "} "
367       "provide_key_response_time_us { "
368       "  min: 1 max: 5 mean: 3.5 variance: 1 operation_count: 5 "
369       "  attributes { error_code: 0 } "
370       "} ";
371 
372   DrmFrameworkMetrics expectedMetricsProto;
373   ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
374 
375   std::string diffString;
376   MessageDifferencer differ;
377   differ.ReportDifferencesToString(&diffString);
378   ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
379       << diffString;
380 }
381 
TEST_F(MediaDrmMetricsTest,SessionLifetimeProtoSerialization)382 TEST_F(MediaDrmMetricsTest, SessionLifetimeProtoSerialization) {
383   // Use the fake so the clock is predictable;
384   FakeMediaDrmMetrics metrics;
385 
386   android::Vector<uint8_t> sessionId1;
387   sessionId1.push_back(1);
388   sessionId1.push_back(2);
389   android::Vector<uint8_t> sessionId2;
390   sessionId2.push_back(3);
391   sessionId2.push_back(4);
392 
393   metrics.SetSessionStart(sessionId1);
394   metrics.SetSessionStart(sessionId2);
395   metrics.SetSessionEnd(sessionId2);
396   metrics.SetSessionEnd(sessionId1);
397 
398   std::string serializedMetrics;
399   ASSERT_EQ(OK, metrics.GetSerializedMetrics(&serializedMetrics));
400 
401   DrmFrameworkMetrics metricsProto;
402   ASSERT_TRUE(metricsProto.ParseFromString(serializedMetrics));
403 
404   std::string expectedMetrics =
405       "session_lifetimes: { "
406       "  key: '0102' "
407       "  value { start_time_ms: 0 end_time_ms: 3 } "
408       "} "
409       "session_lifetimes: { "
410       "  key: '0304' "
411       "  value { start_time_ms: 1 end_time_ms: 2 } "
412       "} ";
413 
414   DrmFrameworkMetrics expectedMetricsProto;
415   ASSERT_TRUE(TextFormat::MergeFromString(expectedMetrics, &expectedMetricsProto));
416 
417   std::string diffString;
418   MessageDifferencer differ;
419   differ.ReportDifferencesToString(&diffString);
420   ASSERT_TRUE(differ.Compare(expectedMetricsProto, metricsProto))
421       << diffString;
422 }
423 
TEST_F(MediaDrmMetricsTest,HidlToBundleMetricsEmpty)424 TEST_F(MediaDrmMetricsTest, HidlToBundleMetricsEmpty) {
425   hidl_vec<DrmMetricGroup> hidlMetricGroups;
426   PersistableBundle bundleMetricGroups;
427 
428   ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidlMetricGroups, &bundleMetricGroups));
429   ASSERT_EQ(0U, bundleMetricGroups.size());
430 }
431 
TEST_F(MediaDrmMetricsTest,HidlToBundleMetricsMultiple)432 TEST_F(MediaDrmMetricsTest, HidlToBundleMetricsMultiple) {
433   DrmMetricGroup hidlMetricGroup =
434       { { {
435               "open_session_ok",
436               { { "status", DrmMetricGroup::ValueType::INT64_TYPE,
437                   (int64_t) Status::OK, 0.0, "" } },
438               { { "count", DrmMetricGroup::ValueType::INT64_TYPE, 3, 0.0, "" } }
439           },
440           {
441               "close_session_not_opened",
442               { { "status", DrmMetricGroup::ValueType::INT64_TYPE,
443                   (int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, 0.0, "" } },
444               { { "count", DrmMetricGroup::ValueType::INT64_TYPE, 7, 0.0, "" } }
445           } } };
446 
447   PersistableBundle bundleMetricGroups;
448   ASSERT_EQ(OK, DrmMetricsConsumer::HidlMetricsToBundle(hidl_vec<DrmMetricGroup>({hidlMetricGroup}),
449                                                      &bundleMetricGroups));
450   ASSERT_EQ(1U, bundleMetricGroups.size());
451   PersistableBundle bundleMetricGroup;
452   ASSERT_TRUE(bundleMetricGroups.getPersistableBundle(String16("[0]"), &bundleMetricGroup));
453   ASSERT_EQ(2U, bundleMetricGroup.size());
454 
455   // Verify each metric.
456   PersistableBundle metric;
457   ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("open_session_ok"), &metric));
458   PersistableBundle metricInstance;
459   ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
460   int64_t value = 0;
461   ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
462   ASSERT_EQ(3, value);
463   PersistableBundle attributeBundle;
464   ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
465   ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
466   ASSERT_EQ((int64_t) Status::OK, value);
467 
468   ASSERT_TRUE(bundleMetricGroup.getPersistableBundle(String16("close_session_not_opened"),
469                                                      &metric));
470   ASSERT_TRUE(metric.getPersistableBundle(String16("[0]"), &metricInstance));
471   ASSERT_TRUE(metricInstance.getLong(String16("count"), &value));
472   ASSERT_EQ(7, value);
473   ASSERT_TRUE(metricInstance.getPersistableBundle(String16("attributes"), &attributeBundle));
474   value = 0;
475   ASSERT_TRUE(attributeBundle.getLong(String16("status"), &value));
476   ASSERT_EQ((int64_t) Status::ERROR_DRM_SESSION_NOT_OPENED, value);
477 }
478 
479 }  // namespace android
480