1 /*
2  * Copyright (C) 2021 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 package android.media.metrics.cts;
18 
19 import static com.google.common.truth.Truth.assertThat;
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.os.AtomsProto;
27 import com.android.os.StatsLog;
28 import com.android.tradefed.build.IBuildInfo;
29 import com.android.tradefed.testtype.DeviceTestCase;
30 import com.android.tradefed.testtype.IBuildReceiver;
31 
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Base64;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Set;
38 
39 public class MediaMetricsAtomTests extends DeviceTestCase implements IBuildReceiver {
40     public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk";
41     public static final String TEST_PKG = "android.media.metrics.cts";
42     private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output";
43     private static final String FEATURE_MICROPHONE = "android.hardware.microphone";
44     private static final int MAX_BUFFER_CAPACITY = 30 * 1024 * 1024; // 30M
45     private IBuildInfo mCtsBuild;
46 
47     @Override
setUp()48     protected void setUp() throws Exception {
49         super.setUp();
50         assertThat(mCtsBuild).isNotNull();
51         DeviceUtils.installTestApp(getDevice(), TEST_APK, TEST_PKG, mCtsBuild);
52         ConfigUtils.removeConfig(getDevice());
53         ReportUtils.clearReports(getDevice());
54         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
55     }
56 
57     @Override
tearDown()58     protected void tearDown() throws Exception {
59         ConfigUtils.removeConfig(getDevice());
60         ReportUtils.clearReports(getDevice());
61         DeviceUtils.uninstallTestApp(getDevice(), TEST_PKG);
62         super.tearDown();
63     }
64 
65     @Override
setBuild(IBuildInfo buildInfo)66     public void setBuild(IBuildInfo buildInfo) {
67         mCtsBuild = buildInfo;
68     }
69 
testPlaybackStateEvent_default()70     public void testPlaybackStateEvent_default() throws Exception {
71         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
72                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
73         DeviceUtils.runDeviceTests(
74                 getDevice(),
75                 TEST_PKG,
76                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
77                 "testPlaybackStateEvent_default");
78         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
79 
80         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
81 
82         assertThat(data.size()).isEqualTo(1);
83         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
84         AtomsProto.MediaPlaybackStateChanged result =
85                 data.get(0).getAtom().getMediaPlaybackStateChanged();
86         assertThat(result.getPlaybackState().toString()).isEqualTo("NOT_STARTED");
87         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
88     }
89 
testPlaybackStateEvent()90     public void testPlaybackStateEvent() throws Exception {
91         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
92                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
93         DeviceUtils.runDeviceTests(
94                 getDevice(),
95                 TEST_PKG,
96                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
97                 "testPlaybackStateEvent");
98         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
99 
100         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
101 
102         assertThat(data.size()).isEqualTo(1);
103         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
104         AtomsProto.MediaPlaybackStateChanged result =
105                 data.get(0).getAtom().getMediaPlaybackStateChanged();
106         assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
107         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
108     }
109 
testPlaybackErrorEvent_default()110     public void testPlaybackErrorEvent_default() throws Exception {
111         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
112                 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
113         DeviceUtils.runDeviceTests(
114                 getDevice(),
115                 TEST_PKG,
116                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
117                 "testPlaybackErrorEvent_default");
118         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
119 
120         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
121 
122         assertThat(data.size()).isEqualTo(1);
123         assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue();
124         AtomsProto.MediaPlaybackErrorReported result =
125                 data.get(0).getAtom().getMediaPlaybackErrorReported();
126 
127         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
128         assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_UNKNOWN");
129         assertThat(result.getSubErrorCode()).isEqualTo(0);
130         assertThat(result.getExceptionStack().startsWith(
131                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent"))
132                         .isTrue();
133     }
134 
testPlaybackErrorEvent()135     public void testPlaybackErrorEvent() throws Exception {
136         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
137                 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER);
138         DeviceUtils.runDeviceTests(
139                 getDevice(),
140                 TEST_PKG,
141                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
142                 "testPlaybackErrorEvent");
143         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
144 
145         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
146 
147         assertThat(data.size()).isEqualTo(1);
148         assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue();
149         AtomsProto.MediaPlaybackErrorReported result =
150                 data.get(0).getAtom().getMediaPlaybackErrorReported();
151 
152         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(17630000L);
153         assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_RUNTIME");
154         assertThat(result.getSubErrorCode()).isEqualTo(378);
155         assertThat(result.getExceptionStack().startsWith(
156                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests.testPlaybackErrorEvent"))
157                         .isTrue();
158     }
159 
testTrackChangeEvent_default()160     public void testTrackChangeEvent_default() throws Exception {
161         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
162                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
163         DeviceUtils.runDeviceTests(
164                 getDevice(),
165                 TEST_PKG,
166                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
167                 "testTrackChangeEvent_default");
168         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
169 
170         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
171 
172         assertThat(data.size()).isEqualTo(1);
173         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
174         AtomsProto.MediaPlaybackTrackChanged result =
175                 data.get(0).getAtom().getMediaPlaybackTrackChanged();
176 
177         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
178         assertThat(result.getState().toString()).isEqualTo("OFF");
179         assertThat(result.getReason().toString()).isEqualTo("REASON_UNKNOWN");
180         assertThat(result.getContainerMimeType()).isEqualTo("");
181         assertThat(result.getSampleMimeType()).isEqualTo("");
182         assertThat(result.getCodecName()).isEqualTo("");
183         assertThat(result.getBitrate()).isEqualTo(-1);
184         assertThat(result.getType().toString()).isEqualTo("AUDIO");
185         assertThat(result.getLanguage()).isEqualTo("");
186         assertThat(result.getLanguageRegion()).isEqualTo("");
187         assertThat(result.getSampleRate()).isEqualTo(-1);
188         assertThat(result.getChannelCount()).isEqualTo(-1);
189     }
190 
testTrackChangeEvent_text()191     public void testTrackChangeEvent_text() throws Exception {
192         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
193                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
194         DeviceUtils.runDeviceTests(
195                 getDevice(),
196                 TEST_PKG,
197                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
198                 "testTrackChangeEvent_text");
199         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
200 
201         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
202 
203         assertThat(data.size()).isEqualTo(1);
204         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
205         AtomsProto.MediaPlaybackTrackChanged result =
206                 data.get(0).getAtom().getMediaPlaybackTrackChanged();
207 
208         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
209         assertThat(result.getState().toString()).isEqualTo("ON");
210         assertThat(result.getReason().toString()).isEqualTo("REASON_MANUAL");
211         assertThat(result.getContainerMimeType()).isEqualTo("text/foo");
212         assertThat(result.getSampleMimeType()).isEqualTo("text/plain");
213         assertThat(result.getCodecName()).isEqualTo("codec_1");
214         assertThat(result.getBitrate()).isEqualTo(1024);
215         assertThat(result.getType().toString()).isEqualTo("TEXT");
216         assertThat(result.getLanguage()).isEqualTo("EN");
217         assertThat(result.getLanguageRegion()).isEqualTo("US");
218     }
219 
testTrackChangeEvent_audio()220     public void testTrackChangeEvent_audio() throws Exception {
221         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
222                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
223         DeviceUtils.runDeviceTests(
224                 getDevice(),
225                 TEST_PKG,
226                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
227                 "testTrackChangeEvent_audio");
228         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
229 
230         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
231 
232         assertThat(data.size()).isEqualTo(1);
233         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
234         AtomsProto.MediaPlaybackTrackChanged result =
235                 data.get(0).getAtom().getMediaPlaybackTrackChanged();
236 
237         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
238         assertThat(result.getState().toString()).isEqualTo("OFF");
239         assertThat(result.getReason().toString()).isEqualTo("REASON_INITIAL");
240         assertThat(result.getContainerMimeType()).isEqualTo("audio/foo");
241         assertThat(result.getSampleMimeType()).isEqualTo("audio/avc");
242         assertThat(result.getCodecName()).isEqualTo("codec_2");
243         assertThat(result.getBitrate()).isEqualTo(1025);
244         assertThat(result.getType().toString()).isEqualTo("AUDIO");
245         assertThat(result.getLanguage()).isEqualTo("EN");
246         assertThat(result.getLanguageRegion()).isEqualTo("US");
247         assertThat(result.getSampleRate()).isEqualTo(89);
248         assertThat(result.getChannelCount()).isEqualTo(3);
249     }
250 
testTrackChangeEvent_video()251     public void testTrackChangeEvent_video() throws Exception {
252         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
253                 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER);
254         DeviceUtils.runDeviceTests(
255                 getDevice(),
256                 TEST_PKG,
257                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
258                 "testTrackChangeEvent_video");
259         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
260 
261         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
262 
263         assertThat(data.size()).isEqualTo(1);
264         assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue();
265         AtomsProto.MediaPlaybackTrackChanged result =
266                 data.get(0).getAtom().getMediaPlaybackTrackChanged();
267 
268         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L);
269         assertThat(result.getState().toString()).isEqualTo("OFF");
270         assertThat(result.getReason().toString()).isEqualTo("REASON_INITIAL");
271         assertThat(result.getContainerMimeType()).isEqualTo("video/foo");
272         assertThat(result.getSampleMimeType()).isEqualTo("video/mpeg");
273         assertThat(result.getCodecName()).isEqualTo("codec_3");
274         assertThat(result.getBitrate()).isEqualTo(1025);
275         assertThat(result.getType().toString()).isEqualTo("VIDEO");
276         assertThat(result.getLanguage()).isEqualTo("EN");
277         assertThat(result.getLanguageRegion()).isEqualTo("US");
278         assertThat(result.getHeight()).isEqualTo(1080);
279         assertThat(result.getWidth()).isEqualTo(1440);
280         assertThat(result.getVideoFrameRate()).isEqualTo(60);
281     }
282 
testNetworkEvent_default()283     public void testNetworkEvent_default() throws Exception {
284         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
285                 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
286         DeviceUtils.runDeviceTests(
287                 getDevice(),
288                 TEST_PKG,
289                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
290                 "testNetworkEvent_default");
291         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
292 
293         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
294 
295         assertThat(data.size()).isEqualTo(1);
296         assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue();
297         AtomsProto.MediaNetworkInfoChanged result =
298                 data.get(0).getAtom().getMediaNetworkInfoChanged();
299 
300         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L);
301         assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN");
302     }
303 
testNetworkEvent()304     public void testNetworkEvent() throws Exception {
305         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
306                 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER);
307         DeviceUtils.runDeviceTests(
308                 getDevice(),
309                 TEST_PKG,
310                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
311                 "testNetworkEvent");
312         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
313 
314         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
315 
316         assertThat(data.size()).isEqualTo(1);
317         assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue();
318         AtomsProto.MediaNetworkInfoChanged result =
319                 data.get(0).getAtom().getMediaNetworkInfoChanged();
320 
321         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(3032L);
322         assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI");
323     }
324 
testPlaybackMetrics_default()325     public void testPlaybackMetrics_default() throws Exception {
326         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
327                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
328         DeviceUtils.runDeviceTests(
329                 getDevice(),
330                 TEST_PKG,
331                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
332                 "testPlaybackMetrics_default");
333         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
334 
335         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
336         int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG);
337 
338         assertThat(data.size()).isEqualTo(1);
339         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
340         AtomsProto.MediametricsPlaybackReported result =
341                 data.get(0).getAtom().getMediametricsPlaybackReported();
342 
343         assertThat(result.getUid()).isEqualTo(appUid);
344         assertThat(result.getMediaDurationMillis()).isEqualTo(-1L);
345         assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_UNKNOWN");
346         assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_UNKNOWN");
347         assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_UNKNOWN");
348         assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_NONE");
349         assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_UNKNOWN");
350         assertThat(result.getPlayerName()).isEqualTo("");
351         assertThat(result.getPlayerVersion()).isEqualTo("");
352         assertThat(result.getVideoFramesPlayed()).isEqualTo(-1);
353         assertThat(result.getVideoFramesDropped()).isEqualTo(-1);
354         assertThat(result.getAudioUnderrunCount()).isEqualTo(-1);
355         assertThat(result.getNetworkBytesRead()).isEqualTo(-1);
356         assertThat(result.getLocalBytesRead()).isEqualTo(-1);
357         assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(-1);
358         assertThat(result.getExperimentIds().getExperimentsList().size()).isEqualTo(0);
359         assertThat(result.getDrmSessionId().length()).isEqualTo(0);
360     }
361 
testPlaybackMetrics()362     public void testPlaybackMetrics() throws Exception {
363         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
364                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
365         DeviceUtils.runDeviceTests(
366                 getDevice(),
367                 TEST_PKG,
368                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
369                 "testPlaybackMetrics");
370         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
371 
372         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
373         int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG);
374 
375         assertThat(data.size()).isEqualTo(1);
376         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
377         AtomsProto.MediametricsPlaybackReported result =
378                 data.get(0).getAtom().getMediametricsPlaybackReported();
379 
380         assertThat(result.getUid()).isEqualTo(appUid);
381         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
382         assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK");
383         assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER");
384         assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE");
385         assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1");
386         assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN");
387         assertThat(result.getPlayerName()).isEqualTo("ExoPlayer");
388         assertThat(result.getPlayerVersion()).isEqualTo("1.01x");
389         assertThat(result.getVideoFramesPlayed()).isEqualTo(1024);
390         assertThat(result.getVideoFramesDropped()).isEqualTo(32);
391         assertThat(result.getAudioUnderrunCount()).isEqualTo(22);
392         assertThat(result.getNetworkBytesRead()).isEqualTo(102400);
393         assertThat(result.getLocalBytesRead()).isEqualTo(2000);
394         assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
395         // TODO: fix missing experiment ID impl
396         assertThat(result.getExperimentIds()).isNotEqualTo(null);
397         // TODO: needs Base64 decoders to verify the data
398         assertThat(result.getDrmSessionId()).isNotEqualTo(null);
399     }
400 
testSessionId()401     public void testSessionId() throws Exception {
402         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
403                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
404         DeviceUtils.runDeviceTests(
405                 getDevice(),
406                 TEST_PKG,
407                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
408                 "testSessionId");
409         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
410 
411         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
412         assertThat(data.size()).isEqualTo(0);
413    }
414 
testRecordingSession()415     public void testRecordingSession() throws Exception {
416         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
417                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
418         DeviceUtils.runDeviceTests(
419                 getDevice(),
420                 TEST_PKG,
421                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
422                 "testRecordingSession");
423         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
424 
425         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
426         assertThat(data.size()).isEqualTo(0);
427    }
428 
testAppBlocklist()429     public void testAppBlocklist() throws Exception {
430         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
431                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
432         DeviceUtils.runDeviceTests(
433                 getDevice(),
434                 TEST_PKG,
435                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
436                 "testAppBlocklist");
437         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
438 
439         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
440 
441         assertThat(data.size()).isEqualTo(0);
442     }
443 
testAttributionBlocklist()444     public void testAttributionBlocklist() throws Exception {
445         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
446                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
447         DeviceUtils.runDeviceTests(
448                 getDevice(),
449                 TEST_PKG,
450                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
451                 "testAttributionBlocklist");
452         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
453 
454         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
455 
456         assertThat(data.size()).isEqualTo(1);
457         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
458         AtomsProto.MediametricsPlaybackReported result =
459                 data.get(0).getAtom().getMediametricsPlaybackReported();
460 
461         assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
462         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
463         assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK");
464         assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER");
465         assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE");
466         assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1");
467         assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN");
468         assertThat(result.getPlayerName()).isEqualTo("ExoPlayer");
469         assertThat(result.getPlayerVersion()).isEqualTo("1.01x");
470         assertThat(result.getVideoFramesPlayed()).isEqualTo(1024);
471         assertThat(result.getVideoFramesDropped()).isEqualTo(32);
472         assertThat(result.getAudioUnderrunCount()).isEqualTo(22);
473         assertThat(result.getNetworkBytesRead()).isEqualTo(102400);
474         assertThat(result.getLocalBytesRead()).isEqualTo(2000);
475         assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
476     }
477 
testAppAllowlist()478     public void testAppAllowlist() throws Exception {
479         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
480                 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER);
481         DeviceUtils.runDeviceTests(
482                 getDevice(),
483                 TEST_PKG,
484                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
485                 "testAppAllowlist");
486         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
487 
488         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
489 
490         assertThat(data.size()).isEqualTo(1);
491         assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue();
492         AtomsProto.MediaPlaybackStateChanged result =
493                 data.get(0).getAtom().getMediaPlaybackStateChanged();
494         assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND");
495         assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L);
496     }
497 
testAttributionAllowlist()498     public void testAttributionAllowlist() throws Exception {
499         ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG,
500                 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER);
501         DeviceUtils.runDeviceTests(
502                 getDevice(),
503                 TEST_PKG,
504                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
505                 "testAttributionAllowlist");
506         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
507 
508         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
509 
510         assertThat(data.size()).isEqualTo(1);
511         assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue();
512         AtomsProto.MediametricsPlaybackReported result =
513                 data.get(0).getAtom().getMediametricsPlaybackReported();
514 
515         assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0.
516         assertThat(result.getMediaDurationMillis()).isEqualTo(233L);
517         assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK");
518         assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER");
519         assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE");
520         assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1");
521         assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN");
522         assertThat(result.getPlayerName()).isEqualTo("ExoPlayer");
523         assertThat(result.getPlayerVersion()).isEqualTo("1.01x");
524         assertThat(result.getVideoFramesPlayed()).isEqualTo(1024);
525         assertThat(result.getVideoFramesDropped()).isEqualTo(32);
526         assertThat(result.getAudioUnderrunCount()).isEqualTo(22);
527         assertThat(result.getNetworkBytesRead()).isEqualTo(102400);
528         assertThat(result.getLocalBytesRead()).isEqualTo(2000);
529         assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000);
530     }
531 
validateAAudioStreamAtom(int direction)532     private void validateAAudioStreamAtom(int direction) throws Exception {
533         Set<Integer> directionSet = new HashSet<>(Arrays.asList(direction));
534         List<Set<Integer>> directionList = Arrays.asList(directionSet);
535 
536         List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice());
537         AtomTestUtils.assertStatesOccurred(directionList, data, 0,
538                 atom -> atom.getMediametricsAaudiostreamReported().getDirection().getNumber());
539 
540         for (StatsLog.EventMetricData event : data) {
541             AtomsProto.MediametricsAAudioStreamReported atom =
542                     event.getAtom().getMediametricsAaudiostreamReported();
543             assertThat(atom.getBufferCapacity()).isGreaterThan(0);
544             assertThat(atom.getBufferCapacity()).isLessThan(MAX_BUFFER_CAPACITY);
545             assertThat(atom.getBufferSize()).isGreaterThan(0);
546             assertThat(atom.getBufferSize()).isAtMost(atom.getBufferCapacity());
547             assertThat(atom.getFramesPerBurst()).isGreaterThan(0);
548             assertThat(atom.getFramesPerBurst()).isLessThan(atom.getBufferCapacity());
549         }
550     }
551 
runAAudioTestAndValidate( String requiredFeature, int direction, String testFunctionName)552     private void runAAudioTestAndValidate(
553             String requiredFeature, int direction, String testFunctionName) throws Exception {
554         if (!DeviceUtils.hasFeature(getDevice(), requiredFeature)) {
555             return;
556         }
557         ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG,
558                 AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER);
559 
560         DeviceUtils.runDeviceTests(
561                 getDevice(),
562                 TEST_PKG,
563                 "android.media.metrics.cts.MediaMetricsAtomHostSideTests",
564                 testFunctionName);
565         Thread.sleep(AtomTestUtils.WAIT_TIME_LONG);
566 
567         validateAAudioStreamAtom(direction);
568     }
569 
570     /**
571      * The test try to create and then close aaudio input stream with mmap path via media metrics
572      * atom host side test app on the DUT.
573      * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
574      * the data is collected correctly.
575      */
testAAudioMmapInputStream()576     public void testAAudioMmapInputStream() throws Exception {
577         runAAudioTestAndValidate(
578                 FEATURE_MICROPHONE,
579                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
580                 "testAAudioMmapInputStream");
581     }
582 
583     /**
584      * The test try to create and then close aaudio output stream with mmap path via media metrics
585      * atom host side test app on the DUT.
586      * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
587      * the data is collected correctly.
588      */
testAAudioMmapOutputStream()589     public void testAAudioMmapOutputStream() throws Exception {
590         runAAudioTestAndValidate(
591                 FEATURE_AUDIO_OUTPUT,
592                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
593                 "testAAudioMmapOutputStream");
594     }
595 
596     /**
597      * The test try to create and then close aaudio input stream with legacy path via media metrics
598      * atom host side test app on the DUT.
599      * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
600      * the data is collected correctly.
601      */
testAAudioLegacyInputStream()602     public void testAAudioLegacyInputStream() throws Exception {
603         runAAudioTestAndValidate(
604                 FEATURE_MICROPHONE,
605                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_INPUT_VALUE,
606                 "testAAudioLegacyInputStream");
607     }
608 
609     /**
610      * The test try to create and then close aaudio output stream with legacy path via media metrics
611      * atom host side test app on the DUT.
612      * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify
613      * the data is collected correctly.
614      */
testAAudioLegacyOutputStream()615     public void testAAudioLegacyOutputStream() throws Exception {
616         runAAudioTestAndValidate(
617                 FEATURE_AUDIO_OUTPUT,
618                 AtomsProto.MediametricsAAudioStreamReported.Direction.DIRECTION_OUTPUT_VALUE,
619                 "testAAudioLegacyOutputStream");
620     }
621 }
622