1 /*
2  * Copyright (C) 2019 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.ActivationType;
27 import com.android.internal.os.StatsdConfigProto.AtomMatcher;
28 import com.android.internal.os.StatsdConfigProto.EventActivation;
29 import com.android.internal.os.StatsdConfigProto.EventMetric;
30 import com.android.internal.os.StatsdConfigProto.MetricActivation;
31 import com.android.internal.os.StatsdConfigProto.StatsdConfig;
32 import com.android.os.AtomsProto.AppBreadcrumbReported;
33 import com.android.os.StatsLog.ConfigMetricsReport;
34 import com.android.os.StatsLog.ConfigMetricsReportList;
35 import com.android.os.StatsLog.EventMetricData;
36 import com.android.os.StatsLog.StatsLogReport;
37 import com.android.tradefed.log.LogUtil;
38 import com.android.tradefed.testtype.DeviceTestCase;
39 import com.android.tradefed.util.RunUtil;
40 
41 import com.google.protobuf.ExtensionRegistry;
42 
43 import java.util.ArrayList;
44 import java.util.Comparator;
45 import java.util.List;
46 import java.util.stream.Collectors;
47 
48 /**
49  * Test Statsd Metric activations and deactivations
50  */
51 public class MetricActivationTests extends DeviceTestCase {
52     private final long metric1Id = 1L;
53     private final int metric1MatcherId = 1;
54 
55     private final long metric2Id = 2L;
56     private final int metric2MatcherId = 2;
57 
58     private final long metric3Id = 3L;
59     private final int metric3MatcherId = 3;
60 
61     private final int act1MatcherId = 10;
62     private final int act1CancelMatcherId = -10;
63 
64     private final int act2MatcherId = 20;
65     private final int act2CancelMatcherId = -20;
66 
67     @Override
setUp()68     protected void setUp() throws Exception {
69         super.setUp();
70         ConfigUtils.removeConfig(getDevice());
71         ReportUtils.clearReports(getDevice());
72         RunUtil.getDefault().sleep(1000);
73     }
74 
75     @Override
tearDown()76     protected void tearDown() throws Exception {
77         ConfigUtils.removeConfig(getDevice());
78         ReportUtils.clearReports(getDevice());
79         super.tearDown();
80     }
81 
createConfig(final int act1TtlSecs, final int act2TtlSecs)82     private StatsdConfig.Builder createConfig(final int act1TtlSecs, final int act2TtlSecs) {
83         AtomMatcher metric1Matcher =
84                 MetricsUtils.simpleAtomMatcher(metric1MatcherId, metric1MatcherId);
85         AtomMatcher metric2Matcher =
86                 MetricsUtils.simpleAtomMatcher(metric2MatcherId, metric2MatcherId);
87         AtomMatcher metric3Matcher =
88                 MetricsUtils.simpleAtomMatcher(metric3MatcherId, metric3MatcherId);
89         AtomMatcher act1Matcher = MetricsUtils.simpleAtomMatcher(act1MatcherId, act1MatcherId);
90         AtomMatcher act1CancelMatcher =
91                 MetricsUtils.simpleAtomMatcher(act1CancelMatcherId, act1CancelMatcherId);
92         AtomMatcher act2Matcher = MetricsUtils.simpleAtomMatcher(act2MatcherId, act2MatcherId);
93         AtomMatcher act2CancelMatcher =
94                 MetricsUtils.simpleAtomMatcher(act2CancelMatcherId, act2CancelMatcherId);
95 
96         EventMetric metric1 =
97                 EventMetric.newBuilder().setId(metric1Id).setWhat(metric1MatcherId).build();
98 
99         EventMetric metric2 =
100                 EventMetric.newBuilder().setId(metric2Id).setWhat(metric2MatcherId).build();
101 
102         EventMetric metric3 =
103                 EventMetric.newBuilder().setId(metric3Id).setWhat(metric3MatcherId).build();
104 
105         EventActivation metric1Act1 =
106                 MetricsUtils.createEventActivation(act1TtlSecs, act1MatcherId, act1CancelMatcherId)
107                         .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
108                         .build();
109 
110         EventActivation metric1Act2 =
111                 MetricsUtils.createEventActivation(act2TtlSecs, act2MatcherId, act2CancelMatcherId)
112                         .setActivationType(ActivationType.ACTIVATE_ON_BOOT)
113                         .build();
114 
115         EventActivation metric2Act1 =
116                 MetricsUtils.createEventActivation(act1TtlSecs, act1MatcherId, act1CancelMatcherId)
117                         .setActivationType(ActivationType.ACTIVATE_ON_BOOT)
118                         .build();
119 
120         EventActivation metric2Act2 =
121                 MetricsUtils.createEventActivation(act2TtlSecs, act2MatcherId, act2CancelMatcherId)
122                         .setActivationType(ActivationType.ACTIVATE_IMMEDIATELY)
123                         .build();
124 
125         MetricActivation metric1Activation = MetricActivation.newBuilder()
126                 .setMetricId(metric1Id)
127                 .addEventActivation(metric1Act1)
128                 .addEventActivation(metric1Act2)
129                 .build();
130 
131         MetricActivation metric2Activation = MetricActivation.newBuilder()
132                 .setMetricId(metric2Id)
133                 .addEventActivation(metric2Act1)
134                 .addEventActivation(metric2Act2)
135                 .build();
136 
137 
138         return ConfigUtils.createConfigBuilder(MetricsUtils.DEVICE_SIDE_TEST_PACKAGE)
139                 .addAtomMatcher(metric1Matcher)
140                 .addAtomMatcher(metric2Matcher)
141                 .addAtomMatcher(metric3Matcher)
142                 .addAtomMatcher(act1Matcher)
143                 .addAtomMatcher(act1CancelMatcher)
144                 .addAtomMatcher(act2Matcher)
145                 .addAtomMatcher(act2CancelMatcher)
146                 .addEventMetric(metric1)
147                 .addEventMetric(metric2)
148                 .addEventMetric(metric3)
149                 .addMetricActivation(metric1Activation)
150                 .addMetricActivation(metric2Activation);
151     }
152 
153     /**
154      * Metric 1:
155      * Activation 1:
156      * - Ttl: 5 seconds
157      * - Type: IMMEDIATE
158      * Activation 2:
159      * - Ttl: 8 seconds
160      * - Type: ON_BOOT
161      *
162      * Metric 2:
163      * Activation 1:
164      * - Ttl: 5 seconds
165      * - Type: ON_BOOT
166      * Activation 2:
167      * - Ttl: 8 seconds
168      * - Type: IMMEDIATE
169      *
170      * Metric 3: No activations; always active
171      **/
testCancellation()172     public void testCancellation() throws Exception {
173         final int act1TtlSecs = 5;
174         final int act2TtlSecs = 8;
175         ConfigUtils.uploadConfig(getDevice(), createConfig(act1TtlSecs, act2TtlSecs));
176 
177         // Ignored, metric not active.
178         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
179                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
180         RunUtil.getDefault().sleep(10L);
181 
182         // Trigger cancel for already inactive event activation 1.
183         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
184                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1CancelMatcherId);
185         RunUtil.getDefault().sleep(10L);
186 
187         // Trigger event activation 1.
188         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
189                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
190         RunUtil.getDefault().sleep(10L);
191 
192         // First logged event.
193         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
194                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
195         RunUtil.getDefault().sleep(10L);
196 
197         // Second logged event.
198         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
199                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
200         RunUtil.getDefault().sleep(10L);
201 
202         // Cancel event activation 1.
203         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
204                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1CancelMatcherId);
205         RunUtil.getDefault().sleep(10L);
206 
207         // Ignored, metric not active.
208         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
209                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
210         RunUtil.getDefault().sleep(10L);
211 
212         // Trigger event activation 1.
213         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
214                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
215         RunUtil.getDefault().sleep(10L);
216 
217         // Trigger event activation 2.
218         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
219                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act2MatcherId);
220         RunUtil.getDefault().sleep(10L);
221 
222         // Third logged event.
223         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
224                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
225         RunUtil.getDefault().sleep(10L);
226 
227         // Cancel event activation 2.
228         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
229                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act2CancelMatcherId);
230         RunUtil.getDefault().sleep(10L);
231 
232         // Fourth logged event.
233         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
234                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
235         RunUtil.getDefault().sleep(10L);
236 
237         // Expire event activation 1
238         RunUtil.getDefault().sleep(act1TtlSecs * 1000);
239 
240         // Ignored, metric 1 not active. Activation 1 expired and Activation 2 was cancelled.
241         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
242                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
243         RunUtil.getDefault().sleep(10L);
244 
245         // Trigger event activation 2.
246         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
247                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act2MatcherId);
248         RunUtil.getDefault().sleep(10L);
249 
250         // Metric 1 log ignored, Activation 1 expired and Activation 2 needs reboot to activate.
251         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
252                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
253         RunUtil.getDefault().sleep(10L);
254 
255         // First logged event for Metric 3.
256         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
257                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric3MatcherId);
258         RunUtil.getDefault().sleep(10L);
259 
260         ConfigMetricsReportList reportList = ReportUtils.getReportList(getDevice(),
261                 ExtensionRegistry.getEmptyRegistry());
262         List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
263         ConfigMetricsReport report = reports.get(0);
264         verifyMetrics(report, 4, 0, 1);
265     }
266 
267     /**
268      * Metric 1:
269      * Activation 1:
270      * - Ttl: 100 seconds
271      * - Type: IMMEDIATE
272      * Activation 2:
273      * - Ttl: 200 seconds
274      * - Type: ON_BOOT
275      *
276      * Metric 2:
277      * Activation 1:
278      * - Ttl: 100 seconds
279      * - Type: ON_BOOT
280      * Activation 2:
281      * - Ttl: 200 seconds
282      * - Type: IMMEDIATE
283      *
284      * Metric 3: No activations; always active
285      **/
testRestart()286     public void testRestart() throws Exception {
287         final int act1TtlSecs = 200;
288         final int act2TtlSecs = 400;
289         ConfigUtils.uploadConfig(getDevice(), createConfig(act1TtlSecs, act2TtlSecs));
290 
291         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
292         // Time remaining:
293         // Metric 1 Activation 1: 200 seconds
294         // Metric 1 Activation 2: 0 seconds
295         // Metric 2 Activation 1: 0 seconds (will activate after boot)
296         // Metric 2 Activation 2: 0 seconds
297         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
298                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
299         RunUtil.getDefault().sleep(10L);
300 
301         // First logged event for Metric 1.
302         // Metric 2 event ignored, will activate after boot.
303         // First logged event for Metric 3.
304         logAllMetrics();
305 
306         // Time remaining:
307         // Metric 1 Activation 1: 200 seconds
308         // Metric 1 Activation 2: 0 seconds
309         // Metric 2 Activation 1: 200 seconds
310         // Metric 2 Activation 2: 0 seconds
311         DeviceUtils.rebootDeviceAndWaitUntilReady(getDevice());
312 
313         // Second logged event for Metric 1.
314         // First logged event for Metric 2.
315         // Second logged event for Metric 3.
316         logAllMetrics();
317 
318         // Time remaining:
319         // Metric 1 Activation 1: 0 seconds
320         // Metric 1 Activation 2: 0 seconds
321         // Metric 2 Activation 1: 0 seconds
322         // Metric 2 Activation 2: 0 seconds
323         RunUtil.getDefault().sleep(act1TtlSecs * 1000L);
324 
325         // Metric 1 event ignored, Activation 1 expired.
326         // Metric 2 event ignored, Activation 1 expired.
327         // Third logged event for Metric 3.
328         logAllMetrics();
329 
330         // Trigger Metric 1 Activation 2 and Metric 2 Activation 2.
331         // Time remaining:
332         // Metric 1 Activation 1: 0 seconds
333         // Metric 1 Activation 2: 0 seconds (will activate after boot)
334         // Metric 2 Activation 1: 0 seconds
335         // Metric 2 Activation 2: 400 seconds
336         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
337                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act2MatcherId);
338         RunUtil.getDefault().sleep(10L);
339 
340         // Metric 1 event ignored, will activate after boot.
341         // Second logged event for Metric 2.
342         // Fourth logged event for Metric 3.
343         logAllMetrics();
344 
345         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
346         // Time remaining:
347         // Metric 1 Activation 1: 200 seconds
348         // Metric 1 Activation 2: 0 seconds (will activate after boot)
349         // Metric 2 Activation 1: 0 seconds (will activate after boot)
350         // Metric 2 Activation 2: 400 seconds
351         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
352                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
353         RunUtil.getDefault().sleep(10L);
354 
355         // Third logged event for Metric 1.
356         // Third logged event for Metric 2.
357         // Fifth logged event for Metric 3.
358         logAllMetrics();
359 
360         // Time remaining:
361         // Metric 1 Activation 1: 100 seconds
362         // Metric 1 Activation 2: 0 seconds (will activate after boot)
363         // Metric 2 Activation 1: 0 seconds (will activate after boot)
364         // Metric 2 Activation 2: 300 seconds
365         RunUtil.getDefault().sleep(act1TtlSecs * 1000L / 2);
366 
367         // Time remaining:
368         // Metric 1 Activation 1: 100 seconds
369         // Metric 1 Activation 2: 400 seconds
370         // Metric 2 Activation 1: 200 seconds
371         // Metric 2 Activation 2: 300 seconds
372         DeviceUtils.rebootDeviceAndWaitUntilReady(getDevice());
373 
374         // Fourth logged event for Metric 1.
375         // Fourth logged event for Metric 2.
376         // Sixth logged event for Metric 3.
377         logAllMetrics();
378 
379         // Expire Metric 1 Activation 1.
380         // Time remaining:
381         // Metric 1 Activation 1: 0 seconds
382         // Metric 1 Activation 2: 300 seconds
383         // Metric 2 Activation 1: 100 seconds
384         // Metric 2 Activation 2: 200 seconds
385         RunUtil.getDefault().sleep(act1TtlSecs * 1000L / 2);
386 
387         // Fifth logged event for Metric 1.
388         // Fifth logged event for Metric 2.
389         // Seventh logged event for Metric 3.
390         logAllMetrics();
391 
392         // Expire all activations.
393         // Time remaining:
394         // Metric 1 Activation 1: 0 seconds
395         // Metric 1 Activation 2: 0 seconds
396         // Metric 2 Activation 1: 0 seconds
397         // Metric 2 Activation 2: 0 seconds
398         RunUtil.getDefault().sleep(act2TtlSecs * 1000L);
399 
400         // Metric 1 event ignored.
401         // Metric 2 event ignored.
402         // Eighth logged event for Metric 3.
403         logAllMetrics();
404 
405         ConfigMetricsReportList reportList = ReportUtils.getReportList(getDevice(),
406                 ExtensionRegistry.getEmptyRegistry());
407         List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
408         assertThat(reports).hasSize(3);
409 
410         // Report before restart.
411         ConfigMetricsReport report = reports.get(0);
412         verifyMetrics(report, 1, 0, 1);
413 
414         // Report after first restart.
415         report = reports.get(1);
416         verifyMetrics(report, 2, 3, 4);
417 
418         // Report after second restart.
419         report = reports.get(2);
420         verifyMetrics(report, 2, 2, 3);
421     }
422 
423     /**
424      * Metric 1:
425      * Activation 1:
426      * - Ttl: 100 seconds
427      * - Type: IMMEDIATE
428      * Activation 2:
429      * - Ttl: 200 seconds
430      * - Type: ON_BOOT
431      *
432      * Metric 2:
433      * Activation 1:
434      * - Ttl: 100 seconds
435      * - Type: ON_BOOT
436      * Activation 2:
437      * - Ttl: 200 seconds
438      * - Type: IMMEDIATE
439      *
440      * Metric 3: No activations; always active
441      **/
testMultipleActivations()442     public void testMultipleActivations() throws Exception {
443         final int act1TtlSecs = 200;
444         final int act2TtlSecs = 400;
445         ConfigUtils.uploadConfig(getDevice(), createConfig(act1TtlSecs, act2TtlSecs));
446 
447         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
448         // Time remaining:
449         // Metric 1 Activation 1: 200 seconds
450         // Metric 1 Activation 2: 0 seconds
451         // Metric 2 Activation 1: 0 seconds (will activate after boot)
452         // Metric 2 Activation 2: 0 seconds
453         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
454                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
455         RunUtil.getDefault().sleep(10L);
456 
457         // First logged event for Metric 1.
458         // Metric 2 event ignored, will activate after boot.
459         // First logged event for Metric 3.
460         logAllMetrics();
461 
462         // Time remaining:
463         // Metric 1 Activation 1: 100 seconds
464         // Metric 1 Activation 2: 0 seconds
465         // Metric 2 Activation 1: 0 seconds (will activate after boot)
466         // Metric 2 Activation 2: 0 seconds
467         RunUtil.getDefault().sleep(act1TtlSecs * 1000L / 2);
468 
469         // Second logged event for Metric 1.
470         // Metric 2 event ignored, will activate after boot.
471         // Second logged event for Metric 3.
472         logAllMetrics();
473 
474         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
475         // Time remaining:
476         // Metric 1 Activation 1: 200 seconds
477         // Metric 1 Activation 2: 0 seconds
478         // Metric 2 Activation 1: 0 seconds (will activate after boot)
479         // Metric 2 Activation 2: 0 seconds
480         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
481                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
482         RunUtil.getDefault().sleep(10L);
483 
484         // Third logged event for Metric 1.
485         // Metric 2 event ignored, will activate after boot.
486         // Third logged event for Metric 3.
487         logAllMetrics();
488 
489         // Time remaining:
490         // Metric 1 Activation 1: 200 seconds
491         // Metric 1 Activation 2: 0 seconds
492         // Metric 2 Activation 1: 200 seconds
493         // Metric 2 Activation 2: 0 seconds
494         DeviceUtils.rebootDeviceAndWaitUntilReady(getDevice());
495 
496         // Fourth logged event for Metric 1.
497         // First logged event for Metric 2.
498         // Fourth logged event for Metric 3.
499         logAllMetrics();
500 
501         // Trigger Metric 1 Activation 1 and Metric 2 Activation 1.
502         // Time remaining:
503         // Metric 1 Activation 1: 200 seconds
504         // Metric 1 Activation 2: 0 seconds
505         // Metric 2 Activation 1: 200 seconds
506         // Metric 2 Activation 2: 0 seconds
507         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
508                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), act1MatcherId);
509         RunUtil.getDefault().sleep(10L);
510 
511         // Fifth logged event for Metric 1.
512         // Second logged event for Metric 2.
513         // Fifth logged event for Metric 3.
514         logAllMetrics();
515 
516         // Expire all activations.
517         // Time remaining:
518         // Metric 1 Activation 1: 0 seconds
519         // Metric 1 Activation 2: 0 seconds
520         // Metric 2 Activation 1: 0 seconds
521         // Metric 2 Activation 2: 0 seconds
522         RunUtil.getDefault().sleep(act1TtlSecs * 1000L);
523 
524         // Metric 1 event ignored.
525         // Metric 2 event ignored.
526         // Sixth logged event for Metric 3.
527         logAllMetrics();
528 
529         // Time remaining:
530         // Metric 1 Activation 1: 0 seconds
531         // Metric 1 Activation 2: 0 seconds
532         // Metric 2 Activation 1: 0 seconds
533         // Metric 2 Activation 2: 0 seconds
534         DeviceUtils.rebootDeviceAndWaitUntilReady(getDevice());
535         RunUtil.getDefault().sleep(10_000L);
536 
537         // Metric 1 event ignored.
538         // Metric 2 event ignored.
539         // Seventh logged event for Metric 3.
540         logAllMetrics();
541 
542         ConfigMetricsReportList reportList = ReportUtils.getReportList(getDevice(),
543                 ExtensionRegistry.getEmptyRegistry());
544         List<ConfigMetricsReport> reports = getSortedConfigMetricsReports(reportList);
545         assertThat(reports).hasSize(3);
546 
547         // Report before restart.
548         ConfigMetricsReport report = reports.get(0);
549         verifyMetrics(report, 3, 0, 3);
550 
551         // Report after first restart.
552         report = reports.get(1);
553         verifyMetrics(report, 2, 2, 3);
554 
555         // Report after second restart.
556         report = reports.get(2);
557         verifyMetrics(report, 0, 0, 1);
558     }
559 
560     /**
561      * Gets a List of sorted ConfigMetricsReports from ConfigMetricsReportList.
562      */
getSortedConfigMetricsReports( ConfigMetricsReportList configMetricsReportList)563     private List<ConfigMetricsReport> getSortedConfigMetricsReports(
564             ConfigMetricsReportList configMetricsReportList) {
565         return configMetricsReportList.getReportsList().stream().sorted(
566                 Comparator.comparing(ConfigMetricsReport::getCurrentReportWallClockNanos)).collect(
567                 Collectors.toList());
568     }
569 
logAllMetrics()570     private void logAllMetrics() throws Exception {
571         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
572                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric1MatcherId);
573         RunUtil.getDefault().sleep(10L);
574 
575         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
576                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric2MatcherId);
577         RunUtil.getDefault().sleep(10L);
578 
579         AtomTestUtils.sendAppBreadcrumbReportedAtom(getDevice(),
580                 AppBreadcrumbReported.State.UNSPECIFIED.getNumber(), metric3MatcherId);
581         RunUtil.getDefault().sleep(10L);
582     }
583 
verifyMetrics(ConfigMetricsReport report, int metric1Count, int metric2Count, int metric3Count)584     private void verifyMetrics(ConfigMetricsReport report, int metric1Count, int metric2Count,
585             int metric3Count) throws Exception {
586         assertThat(report.getMetricsCount()).isEqualTo(3);
587 
588         verifyMetric(report.getMetrics(0),   // StatsLogReport
589                 1,                      // Metric Id
590                 1,                      // Metric what atom matcher label
591                 metric1Count            // Data count
592         );
593         verifyMetric(report.getMetrics(1),   // StatsLogReport
594                 2,                      // Metric Id
595                 2,                      // Metric what atom matcher label
596                 metric2Count            // Data count
597         );
598         verifyMetric(report.getMetrics(2),   // StatsLogReport
599                 3,                      // Metric Id
600                 3,                      // Metric what atom matcher label
601                 metric3Count            // Data count
602         );
603     }
604 
verifyMetric(StatsLogReport metricReport, long metricId, int metricMatcherLabel, int dataCount)605     private void verifyMetric(StatsLogReport metricReport, long metricId, int metricMatcherLabel,
606             int dataCount) {
607         LogUtil.CLog.d("Got the following event metric data: " + metricReport.toString());
608         assertThat(metricReport.getMetricId()).isEqualTo(metricId);
609         assertThat(metricReport.hasEventMetrics()).isEqualTo(dataCount > 0);
610 
611         StatsLogReport.EventMetricDataWrapper eventData = metricReport.getEventMetrics();
612         List<EventMetricData> eventMetricDataList = new ArrayList<>();
613         for (EventMetricData eventMetricData : eventData.getDataList()) {
614             eventMetricDataList.addAll(
615                     ReportUtils.backfillAggregatedAtomsInEventMetric(eventMetricData));
616         }
617         assertThat(eventMetricDataList).hasSize(dataCount);
618         for (EventMetricData eventMetricData : eventMetricDataList) {
619             AppBreadcrumbReported atom = eventMetricData.getAtom().getAppBreadcrumbReported();
620             assertThat(atom.getLabel()).isEqualTo(metricMatcherLabel);
621         }
622     }
623 }
624