1 /*
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 package android.cts.statsd.metric;
17 
18 import static com.google.common.truth.Truth.assertThat;
19 import static com.google.common.truth.Truth.assertWithMessage;
20 
21 import android.cts.statsdatom.lib.AtomTestUtils;
22 import android.cts.statsdatom.lib.ConfigUtils;
23 import android.cts.statsdatom.lib.DeviceUtils;
24 import android.cts.statsdatom.lib.ReportUtils;
25 
26 import com.android.internal.os.StatsdConfigProto;
27 import com.android.internal.os.StatsdConfigProto.FieldMatcher;
28 import com.android.internal.os.StatsdConfigProto.Position;
29 import com.android.os.AtomsProto.Atom;
30 import com.android.os.AtomsProto.AppBreadcrumbReported;
31 import com.android.os.AtomsProto.WakelockStateChanged;
32 import com.android.os.AttributionNode;
33 import com.android.os.StatsLog.ConfigMetricsReport;
34 import com.android.os.StatsLog.ConfigMetricsReportList;
35 import com.android.os.StatsLog.CountBucketInfo;
36 import com.android.os.StatsLog.CountMetricData;
37 import com.android.os.StatsLog.StatsLogReport;
38 import com.android.tradefed.build.IBuildInfo;
39 import com.android.tradefed.log.LogUtil;
40 import com.android.tradefed.testtype.DeviceTestCase;
41 import com.android.tradefed.testtype.IBuildReceiver;
42 import com.android.tradefed.util.RunUtil;
43 
44 import com.google.protobuf.ExtensionRegistry;
45 
46 import java.util.List;
47 import java.util.stream.Collectors;
48 import java.util.stream.IntStream;
49 
50 public class CountMetricsTests extends DeviceTestCase implements IBuildReceiver {
51 
52     private IBuildInfo mCtsBuild;
53 
54     @Override
setUp()55     protected void setUp() throws Exception {
56         super.setUp();
57         assertThat(mCtsBuild).isNotNull();
58         ConfigUtils.removeConfig(getDevice());
59         ReportUtils.clearReports(getDevice());
60         DeviceUtils.installTestApp(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_APK,
61                 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, mCtsBuild);
62         RunUtil.getDefault().sleep(1000);
63     }
64 
65     @Override
tearDown()66     protected void tearDown() throws Exception {
67         ConfigUtils.removeConfig(getDevice());
68         ReportUtils.clearReports(getDevice());
69         DeviceUtils.uninstallTestApp(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE);
70         super.tearDown();
71     }
72 
73     @Override
setBuild(IBuildInfo buildInfo)74     public void setBuild(IBuildInfo buildInfo) {
75         mCtsBuild = buildInfo;
76     }
77 
testSimpleEventCountMetric()78     public void testSimpleEventCountMetric() throws Exception {
79         int matcherId = 1;
80         StatsdConfigProto.StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder(
81                 MetricsUtils.DEVICE_SIDE_TEST_PACKAGE);
82         builder.addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
83                         .setId(MetricsUtils.COUNT_METRIC_ID)
84                         .setBucket(StatsdConfigProto.TimeUnit.ONE_MINUTE)
85                         .setWhat(matcherId))
86                 .addAtomMatcher(MetricsUtils.simpleAtomMatcher(matcherId));
87         ConfigUtils.uploadConfig(getDevice(), builder);
88 
89         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
90                 AppBreadcrumbReported.State.START.getNumber(), 0);
91         RunUtil.getDefault().sleep(100);
92         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
93                 AppBreadcrumbReported.State.STOP.getNumber(), 0);
94         RunUtil.getDefault().sleep(2000);  // Wait for the metrics to propagate to statsd.
95 
96         StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(),
97                 ExtensionRegistry.getEmptyRegistry());
98         LogUtil.CLog.d("Got the following stats log report: \n" + metricReport.toString());
99         assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
100         assertThat(metricReport.hasCountMetrics()).isTrue();
101 
102         StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
103 
104         assertThat(countData.getDataCount()).isGreaterThan(0);
105         assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(2);
106     }
107 
testEventCountWithCondition()108     public void testEventCountWithCondition() throws Exception {
109         int startMatcherId = 1;
110         int endMatcherId = 2;
111         int whatMatcherId = 3;
112         int conditionId = 4;
113 
114         StatsdConfigProto.AtomMatcher whatMatcher =
115                 MetricsUtils.unspecifiedAtomMatcher(whatMatcherId);
116 
117         StatsdConfigProto.AtomMatcher predicateStartMatcher =
118                 MetricsUtils.startAtomMatcher(startMatcherId);
119 
120         StatsdConfigProto.AtomMatcher predicateEndMatcher =
121                 MetricsUtils.stopAtomMatcher(endMatcherId);
122 
123         StatsdConfigProto.Predicate p = StatsdConfigProto.Predicate.newBuilder()
124                 .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
125                         .setStart(startMatcherId)
126                         .setStop(endMatcherId)
127                         .setCountNesting(false))
128                 .setId(conditionId)
129                 .build();
130 
131         StatsdConfigProto.StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder(
132                         MetricsUtils.DEVICE_SIDE_TEST_PACKAGE)
133                 .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
134                         .setId(MetricsUtils.COUNT_METRIC_ID)
135                         .setBucket(StatsdConfigProto.TimeUnit.CTS)
136                         .setWhat(whatMatcherId)
137                         .setCondition(conditionId))
138                 .addAtomMatcher(whatMatcher)
139                 .addAtomMatcher(predicateStartMatcher)
140                 .addAtomMatcher(predicateEndMatcher)
141                 .addPredicate(p);
142 
143         ConfigUtils.uploadConfig(getDevice(), builder);
144 
145         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
146                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 0);
147         RunUtil.getDefault().sleep(10);
148         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
149                 AppBreadcrumbReported.State.START.getNumber(), 0);
150         RunUtil.getDefault().sleep(10);
151         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
152                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 0);
153         RunUtil.getDefault().sleep(10);
154         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
155                 AppBreadcrumbReported.State.STOP.getNumber(), 0);
156         RunUtil.getDefault().sleep(10);
157         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
158                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), 0);
159         RunUtil.getDefault().sleep(2000);  // Wait for the metrics to propagate to statsd.
160 
161         StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(),
162                 ExtensionRegistry.getEmptyRegistry());
163         assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
164         assertThat(metricReport.hasCountMetrics()).isTrue();
165 
166         StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
167 
168         assertThat(countData.getDataCount()).isGreaterThan(0);
169         assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(1);
170     }
171 
testEventCountWithConditionAndActivation()172     public void testEventCountWithConditionAndActivation() throws Exception {
173         int startMatcherId = 1;
174         int startMatcherLabel = 1;
175         int endMatcherId = 2;
176         int endMatcherLabel = 2;
177         int whatMatcherId = 3;
178         int whatMatcherLabel = 3;
179         int conditionId = 4;
180         int activationMatcherId = 5;
181         int activationMatcherLabel = 5;
182         int ttlSec = 5;
183 
184         StatsdConfigProto.AtomMatcher whatMatcher =
185                 MetricsUtils.appBreadcrumbMatcherWithLabel(whatMatcherId, whatMatcherLabel);
186 
187         StatsdConfigProto.AtomMatcher predicateStartMatcher =
188                 MetricsUtils.startAtomMatcherWithLabel(startMatcherId, startMatcherLabel);
189 
190         StatsdConfigProto.AtomMatcher predicateEndMatcher =
191                 MetricsUtils.stopAtomMatcherWithLabel(endMatcherId, endMatcherLabel);
192 
193         StatsdConfigProto.AtomMatcher activationMatcher =
194                 MetricsUtils.appBreadcrumbMatcherWithLabel(activationMatcherId,
195                         activationMatcherLabel);
196 
197         StatsdConfigProto.Predicate p = StatsdConfigProto.Predicate.newBuilder()
198                 .setSimplePredicate(StatsdConfigProto.SimplePredicate.newBuilder()
199                         .setStart(startMatcherId)
200                         .setStop(endMatcherId)
201                         .setCountNesting(false))
202                 .setId(conditionId)
203                 .build();
204 
205         StatsdConfigProto.StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder(
206                         MetricsUtils.DEVICE_SIDE_TEST_PACKAGE)
207                 .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
208                         .setId(MetricsUtils.COUNT_METRIC_ID)
209                         .setBucket(StatsdConfigProto.TimeUnit.ONE_MINUTE)
210                         .setWhat(whatMatcherId)
211                         .setCondition(conditionId)
212                 )
213                 .addAtomMatcher(whatMatcher)
214                 .addAtomMatcher(predicateStartMatcher)
215                 .addAtomMatcher(predicateEndMatcher)
216                 .addAtomMatcher(activationMatcher)
217                 .addPredicate(p)
218                 .addMetricActivation(StatsdConfigProto.MetricActivation.newBuilder()
219                         .setMetricId(MetricsUtils.COUNT_METRIC_ID)
220                         .setActivationType(StatsdConfigProto.ActivationType.ACTIVATE_IMMEDIATELY)
221                         .addEventActivation(StatsdConfigProto.EventActivation.newBuilder()
222                                 .setAtomMatcherId(activationMatcherId)
223                                 .setTtlSeconds(ttlSec)));
224 
225         ConfigUtils.uploadConfig(getDevice(), builder);
226 
227         // Activate the metric.
228         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
229                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), activationMatcherLabel);
230         RunUtil.getDefault().sleep(10);
231 
232         // Set the condition to true.
233         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
234                 AppBreadcrumbReported.State.START.getNumber(), startMatcherLabel);
235         RunUtil.getDefault().sleep(10);
236 
237         // Log an event that should be counted. Bucket 1 Count 1.
238         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
239                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
240         RunUtil.getDefault().sleep(10);
241 
242         // Log an event that should be counted. Bucket 1 Count 2.
243         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
244                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
245         RunUtil.getDefault().sleep(10);
246 
247         // Set the condition to false.
248         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
249                 AppBreadcrumbReported.State.STOP.getNumber(), endMatcherLabel);
250         RunUtil.getDefault().sleep(10);
251 
252         // Log an event that should not be counted because condition is false.
253         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
254                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
255         RunUtil.getDefault().sleep(10);
256 
257         // Let the metric deactivate.
258         RunUtil.getDefault().sleep(ttlSec * 1000);
259 
260         // Log an event that should not be counted.
261         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
262                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
263         RunUtil.getDefault().sleep(10);
264 
265         // Condition to true again.
266         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
267                 AppBreadcrumbReported.State.START.getNumber(), startMatcherLabel);
268         RunUtil.getDefault().sleep(10);
269 
270         // Event should not be counted, metric is still not active.
271         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
272                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
273         RunUtil.getDefault().sleep(10);
274 
275         // Activate the metric.
276         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
277                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), activationMatcherLabel);
278         RunUtil.getDefault().sleep(10);
279 
280         //  Log an event that should be counted.
281         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
282                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
283         RunUtil.getDefault().sleep(10);
284 
285         // Let the metric deactivate.
286         RunUtil.getDefault().sleep(ttlSec * 1000);
287 
288         // Log an event that should not be counted.
289         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
290                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), whatMatcherLabel);
291         RunUtil.getDefault().sleep(10);
292 
293         // Wait for the metrics to propagate to statsd.
294         RunUtil.getDefault().sleep(2000);
295 
296         StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(),
297                 ExtensionRegistry.getEmptyRegistry());
298         assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
299         LogUtil.CLog.d("Received the following data: " + metricReport.toString());
300         assertThat(metricReport.hasCountMetrics()).isTrue();
301         assertThat(metricReport.getIsActive()).isFalse();
302 
303         StatsLogReport.CountMetricDataWrapper countData = metricReport.getCountMetrics();
304         assertThat(countData.getDataCount()).isEqualTo(1);
305         assertThat(countData.getData(0).getBucketInfoCount()).isEqualTo(2);
306         assertThat(countData.getData(0).getBucketInfo(0).getCount()).isEqualTo(2);
307         assertThat(countData.getData(0).getBucketInfo(1).getCount()).isEqualTo(1);
308     }
309 
testPartialBucketCountMetric()310     public void testPartialBucketCountMetric() throws Exception {
311         int matcherId = 1;
312         StatsdConfigProto.StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder(
313                         MetricsUtils.DEVICE_SIDE_TEST_PACKAGE)
314                 .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
315                         .setId(MetricsUtils.COUNT_METRIC_ID)
316                         .setBucket(StatsdConfigProto.TimeUnit.ONE_DAY) // Ensures partial bucket.
317                         .setWhat(matcherId)
318                         .setSplitBucketForAppUpgrade(true))
319                 .addAtomMatcher(MetricsUtils.simpleAtomMatcher(matcherId));
320         ConfigUtils.uploadConfig(getDevice(), builder);
321 
322         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
323                 AppBreadcrumbReported.State.START.getNumber(), 0);
324 
325         builder.getCountMetricBuilder(0).setBucket(StatsdConfigProto.TimeUnit.CTS);
326         ConfigUtils.uploadConfig(getDevice(), builder);  // The count metric had a partial bucket.
327         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
328                 AppBreadcrumbReported.State.START.getNumber(), 0);
329         RunUtil.getDefault().sleep(10);
330         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
331                 AppBreadcrumbReported.State.START.getNumber(), 0);
332         RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); // Finish the current bucket.
333 
334         ConfigMetricsReportList reports = ReportUtils.getReportList(getDevice(),
335                 ExtensionRegistry.getEmptyRegistry());
336         LogUtil.CLog.d("Got following report list: " + reports.toString());
337 
338         assertThat(reports.getReportsCount()).isEqualTo(2);
339         boolean inOrder = reports.getReports(0).getCurrentReportWallClockNanos() <
340                 reports.getReports(1).getCurrentReportWallClockNanos();
341 
342         // Only 1 metric, so there should only be 1 StatsLogReport.
343         for (ConfigMetricsReport report : reports.getReportsList()) {
344             assertThat(report.getMetricsCount()).isEqualTo(1);
345             assertThat(report.getMetrics(0).getCountMetrics().getDataCount()).isEqualTo(1);
346         }
347         CountMetricData data1 =
348                 reports.getReports(inOrder ? 0 : 1).getMetrics(0).getCountMetrics().getData(0);
349         CountMetricData data2 =
350                 reports.getReports(inOrder ? 1 : 0).getMetrics(0).getCountMetrics().getData(0);
351         // Data1 should have only 1 bucket, and it should be a partial bucket.
352         // The count should be 1.
353         assertThat(data1.getBucketInfoCount()).isEqualTo(1);
354         CountBucketInfo bucketInfo = data1.getBucketInfo(0);
355         assertThat(bucketInfo.getCount()).isEqualTo(1);
356         assertWithMessage("First report's bucket should be less than 1 day")
357                 .that(bucketInfo.getEndBucketElapsedNanos())
358                 .isLessThan(bucketInfo.getStartBucketElapsedNanos() +
359                         1_000_000_000L * 60L * 60L * 24L);
360 
361         //Second report should have a count of 2.
362         assertThat(data2.getBucketInfoCount()).isAtMost(2);
363         int totalCount = 0;
364         for (CountBucketInfo bucket : data2.getBucketInfoList()) {
365             totalCount += bucket.getCount();
366         }
367         assertThat(totalCount).isEqualTo(2);
368     }
369 
370     public void testSlicedStateCountMetricNoReset() throws Exception {
371         int whatMatcherId = 3;
372         int stateId = 4;
373         int onStateGroupId = 5;
374         int offStateGroupId = 6;
375 
376         // Atom 9998 {
377         //     repeated AttributionNode attribution_node = 1;
378         //     optional WakeLockLevelEnum type = 2;
379         //     optional string tag = 3;
380         // }
381         int whatAtomId = 9_998;
382 
383         StatsdConfigProto.AtomMatcher whatMatcher =
384                 MetricsUtils.getAtomMatcher(whatAtomId)
385                         .setId(whatMatcherId)
386                         .build();
387 
388         StatsdConfigProto.State state = StatsdConfigProto.State.newBuilder()
389                 .setId(stateId)
390                 .setAtomId(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
391                 .setMap(StatsdConfigProto.StateMap.newBuilder()
392                         .addGroup(StatsdConfigProto.StateMap.StateGroup.newBuilder()
393                                 .setGroupId(onStateGroupId)
394                                 .addValue(WakelockStateChanged.State.ACQUIRE_VALUE)
395                                 .addValue(WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE)
396                         )
397                         .addGroup(StatsdConfigProto.StateMap.StateGroup.newBuilder()
398                                 .setGroupId(offStateGroupId)
399                                 .addValue(WakelockStateChanged.State.RELEASE_VALUE)
400                                 .addValue(WakelockStateChanged.State.CHANGE_RELEASE_VALUE)
401                         )
402                 )
403                 .build();
404 
405         StatsdConfigProto.MetricStateLink stateLink = StatsdConfigProto.MetricStateLink.newBuilder()
406                 .setStateAtomId(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
407                 .setFieldsInWhat(FieldMatcher.newBuilder()
408                         .setField(whatAtomId)
409                         .addChild(FieldMatcher.newBuilder()
410                                 .setField(1)
411                                 .setPosition(Position.FIRST)
412                                 .addChild(FieldMatcher.newBuilder()
413                                         .setField(AttributionNode.UID_FIELD_NUMBER)
414                                 )
415                         )
416                         .addChild(FieldMatcher.newBuilder()
417                                 .setField(2)
418                         )
419                         .addChild(FieldMatcher.newBuilder()
420                                 .setField(3)
421                         )
422                 )
423                 .setFieldsInState(FieldMatcher.newBuilder()
424                         .setField(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER)
425                         .addChild(FieldMatcher.newBuilder()
426                                 .setField(WakelockStateChanged.ATTRIBUTION_NODE_FIELD_NUMBER)
427                                 .setPosition(Position.FIRST)
428                                 .addChild(FieldMatcher.newBuilder()
429                                         .setField(AttributionNode.UID_FIELD_NUMBER)
430                                 )
431                         )
432                         .addChild(FieldMatcher.newBuilder()
433                                 .setField(WakelockStateChanged.TYPE_FIELD_NUMBER)
434                         )
435                         .addChild(FieldMatcher.newBuilder()
436                                 .setField(WakelockStateChanged.TAG_FIELD_NUMBER)
437                         )
438                 )
439                 .build();
440 
441         StatsdConfigProto.StatsdConfig.Builder builder = ConfigUtils.createConfigBuilder(
442                         MetricsUtils.DEVICE_SIDE_TEST_PACKAGE)
443                 .addCountMetric(StatsdConfigProto.CountMetric.newBuilder()
444                         .setId(MetricsUtils.COUNT_METRIC_ID)
445                         .setBucket(StatsdConfigProto.TimeUnit.CTS)
446                         .setWhat(whatMatcherId)
447                         .addSliceByState(stateId)
448                         .addStateLink(stateLink)
449                         .setDimensionsInWhat(
450                                 FieldMatcher.newBuilder()
451                                         .setField(whatAtomId)
452                                         .addChild(FieldMatcher.newBuilder()
453                                                 .setField(1)
454                                                 .setPosition(Position.FIRST)
455                                                 .addChild(FieldMatcher.newBuilder()
456                                                         .setField(AttributionNode.UID_FIELD_NUMBER)
457                                                 )
458                                         )
459                                         .addChild(FieldMatcher.newBuilder()
460                                                 .setField(2)
461                                         )
462                                         .addChild(FieldMatcher.newBuilder()
463                                                 .setField(3)
464                                         )
465                         )
466                 )
467                 .addAtomMatcher(whatMatcher)
468                 .addState(state);
469         ConfigUtils.uploadConfig(getDevice(), builder);
470 
471         DeviceUtils.runDeviceTests(getDevice(), MetricsUtils.DEVICE_SIDE_TEST_PACKAGE, ".AtomTests",
472                 "testSliceByWakelockState");
473 
474         StatsLogReport metricReport = ReportUtils.getStatsLogReport(getDevice(),
475                 ExtensionRegistry.getEmptyRegistry());
476         LogUtil.CLog.d("Got the following stats log report: \n" + metricReport.toString());
477         assertThat(metricReport.getMetricId()).isEqualTo(MetricsUtils.COUNT_METRIC_ID);
478         assertThat(metricReport.hasCountMetrics()).isTrue();
479 
480         StatsLogReport.CountMetricDataWrapper dataWrapper = metricReport.getCountMetrics();
481         assertThat(dataWrapper.getDataCount()).isEqualTo(2);
482 
483 
484         List<CountMetricData> sortedDataList = IntStream.range(0, dataWrapper.getDataCount())
485                 .mapToObj(i -> {
486                     CountMetricData data = dataWrapper.getData(i);
487                     assertWithMessage("Unexpected SliceByState count for data[%s]", "" + i)
488                             .that(data.getSliceByStateCount()).isEqualTo(1);
489                     return data;
490                 })
491                 .sorted((data1, data2) ->
492                         Long.compare(data1.getSliceByState(0).getGroupId(),
493                                 data2.getSliceByState(0).getGroupId())
494                 )
495                 .collect(Collectors.toList());
496 
497         CountMetricData data = sortedDataList.get(0);
498         assertThat(data.getSliceByState(0).getAtomId())
499                 .isEqualTo(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER);
500         assertThat(data.getSliceByState(0).getGroupId())
501                 .isEqualTo(onStateGroupId);
502         long totalCount = data.getBucketInfoList().stream()
503                 .mapToLong(CountBucketInfo::getCount)
504                 .sum();
505         assertThat(totalCount).isEqualTo(6);
506 
507         data = sortedDataList.get(1);
508         assertThat(data.getSliceByState(0).getAtomId())
509                 .isEqualTo(Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER);
510         assertThat(data.getSliceByState(0).getGroupId())
511                 .isEqualTo(offStateGroupId);
512         totalCount = data.getBucketInfoList().stream()
513                 .mapToLong(CountBucketInfo::getCount)
514                 .sum();
515         assertThat(totalCount).isEqualTo(3);
516     }
517 }
518