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 android.media.cts.MediaMetricsTestConstants.LOG_SESSION_ID_KEY; 20 import static android.os.statsd.media.MediaEditingExtensionAtoms.MEDIA_EDITING_ENDED_REPORTED_FIELD_NUMBER; 21 22 import static com.google.common.truth.Truth.assertThat; 23 import static com.google.common.truth.Truth.assertWithMessage; 24 25 import android.cts.statsdatom.lib.AtomTestUtils; 26 import android.cts.statsdatom.lib.ConfigUtils; 27 import android.cts.statsdatom.lib.DeviceUtils; 28 import android.cts.statsdatom.lib.ReportUtils; 29 import android.os.statsd.media.MediaEditingExtensionAtoms; 30 31 import com.android.os.AtomsProto; 32 import com.android.os.StatsLog; 33 import com.android.tradefed.device.DeviceNotAvailableException; 34 import com.android.tradefed.invoker.TestInformation; 35 import com.android.tradefed.log.LogUtil; 36 import com.android.tradefed.metrics.proto.MetricMeasurement; 37 import com.android.tradefed.result.ITestInvocationListener; 38 import com.android.tradefed.result.TestDescription; 39 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 40 import com.android.tradefed.testtype.junit4.AfterClassWithInfo; 41 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 42 import com.android.tradefed.testtype.junit4.BeforeClassWithInfo; 43 import com.android.tradefed.util.RunUtil; 44 45 import com.google.common.truth.Correspondence; 46 import com.google.protobuf.ExtensionRegistry; 47 48 import org.junit.After; 49 import org.junit.Before; 50 import org.junit.Test; 51 import org.junit.runner.RunWith; 52 53 import java.io.FileNotFoundException; 54 import java.util.HashMap; 55 import java.util.List; 56 import java.util.function.Function; 57 import java.util.stream.Collectors; 58 59 import javax.annotation.Nullable; 60 61 @RunWith(DeviceJUnit4ClassRunner.class) 62 public class MediaMetricsAtomTests extends BaseHostJUnit4Test { 63 64 private static final String TEST_RUNNER = "androidx.test.runner.AndroidJUnitRunner"; 65 private static final String TAG = "MediaMetricsAtomTests"; 66 public static final String TEST_APK = "CtsMediaMetricsHostTestApp.apk"; 67 public static final String TEST_PKG = "android.media.metrics.cts"; 68 private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output"; 69 private static final String FEATURE_MICROPHONE = "android.hardware.microphone"; 70 private static final String FEATURE_MIDI = "android.software.midi"; 71 private static final int MAX_BUFFER_CAPACITY = 30 * 1024 * 1024; // 30M 72 73 @BeforeClassWithInfo installApp(TestInformation testInfo)74 public static void installApp(TestInformation testInfo) 75 throws DeviceNotAvailableException, FileNotFoundException { 76 assertThat(testInfo.getBuildInfo()).isNotNull(); 77 DeviceUtils.installTestApp(testInfo.getDevice(), TEST_APK, TEST_PKG, 78 testInfo.getBuildInfo()); 79 } 80 81 @Before setUp()82 public void setUp() throws Exception { 83 ConfigUtils.removeConfig(getDevice()); 84 ReportUtils.clearReports(getDevice()); 85 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 86 } 87 88 @After tearDown()89 public void tearDown() throws Exception { 90 ConfigUtils.removeConfig(getDevice()); 91 ReportUtils.clearReports(getDevice()); 92 } 93 94 @AfterClassWithInfo uninstallApp(TestInformation testInfo)95 public static void uninstallApp(TestInformation testInfo) throws Exception { 96 DeviceUtils.uninstallTestApp(testInfo.getDevice(), TEST_PKG); 97 } 98 99 @Test testPlaybackStateEvent_default()100 public void testPlaybackStateEvent_default() throws Exception { 101 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 102 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); 103 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 104 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 105 "testPlaybackStateEvent_default", 106 new LogSessionIdListener()); 107 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 108 109 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 110 111 assertThat(data.size()).isEqualTo(1); 112 assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); 113 AtomsProto.MediaPlaybackStateChanged result = data.get( 114 0).getAtom().getMediaPlaybackStateChanged(); 115 assertThat(result.getPlaybackState().toString()).isEqualTo("NOT_STARTED"); 116 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); 117 } 118 119 @Test testPlaybackStateEvent()120 public void testPlaybackStateEvent() throws Exception { 121 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 122 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); 123 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 124 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackStateEvent", 125 new LogSessionIdListener()); 126 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 127 128 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 129 130 assertThat(data.size()).isEqualTo(1); 131 assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); 132 AtomsProto.MediaPlaybackStateChanged result = data.get( 133 0).getAtom().getMediaPlaybackStateChanged(); 134 assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); 135 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); 136 } 137 138 // same as testPlaybackStateEvent, but we use the BundleSession transport. 139 @Test testBundleSessionPlaybackStateEvent()140 public void testBundleSessionPlaybackStateEvent() throws Exception { 141 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 142 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); 143 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 144 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 145 "testBundleSessionPlaybackStateEvent", 146 new LogSessionIdListener()); 147 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 148 149 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 150 151 assertThat(data.size()).isEqualTo(1); 152 assertThat(data.get(0).getAtom().hasMediaPlaybackStateChanged()).isTrue(); 153 AtomsProto.MediaPlaybackStateChanged result = data.get( 154 0).getAtom().getMediaPlaybackStateChanged(); 155 assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); 156 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); 157 } 158 159 @Test testPlaybackErrorEvent_default()160 public void testPlaybackErrorEvent_default() throws Exception { 161 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 162 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER); 163 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 164 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 165 "testPlaybackErrorEvent_default", 166 new LogSessionIdListener()); 167 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 168 169 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 170 171 assertThat(data.size()).isEqualTo(1); 172 assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue(); 173 AtomsProto.MediaPlaybackErrorReported result = data.get( 174 0).getAtom().getMediaPlaybackErrorReported(); 175 176 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); 177 assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_UNKNOWN"); 178 assertThat(result.getSubErrorCode()).isEqualTo(0); 179 assertThat(result.getExceptionStack().startsWith( 180 "android.media.metrics.cts.MediaMetricsAtomHostSideTests" 181 + ".testPlaybackErrorEvent")).isTrue(); 182 } 183 184 @Test testPlaybackErrorEvent()185 public void testPlaybackErrorEvent() throws Exception { 186 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 187 AtomsProto.Atom.MEDIA_PLAYBACK_ERROR_REPORTED_FIELD_NUMBER); 188 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 189 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackErrorEvent", 190 new LogSessionIdListener()); 191 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 192 193 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 194 195 assertThat(data.size()).isEqualTo(1); 196 assertThat(data.get(0).getAtom().hasMediaPlaybackErrorReported()).isTrue(); 197 AtomsProto.MediaPlaybackErrorReported result = data.get( 198 0).getAtom().getMediaPlaybackErrorReported(); 199 200 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(17630000L); 201 assertThat(result.getErrorCode().toString()).isEqualTo("ERROR_CODE_RUNTIME"); 202 assertThat(result.getSubErrorCode()).isEqualTo(378); 203 assertThat(result.getExceptionStack().startsWith( 204 "android.media.metrics.cts.MediaMetricsAtomHostSideTests" 205 + ".testPlaybackErrorEvent")).isTrue(); 206 } 207 208 @Test testTrackChangeEvent_default()209 public void testTrackChangeEvent_default() throws Exception { 210 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 211 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); 212 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 213 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 214 "testTrackChangeEvent_default", 215 new LogSessionIdListener()); 216 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 217 218 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 219 220 assertThat(data.size()).isEqualTo(1); 221 assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); 222 AtomsProto.MediaPlaybackTrackChanged result = data.get( 223 0).getAtom().getMediaPlaybackTrackChanged(); 224 225 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); 226 assertThat(result.getState().toString()).isEqualTo("OFF"); 227 assertThat(result.getReason().toString()).isEqualTo("REASON_UNKNOWN"); 228 assertThat(result.getContainerMimeType()).isEqualTo(""); 229 assertThat(result.getSampleMimeType()).isEqualTo(""); 230 assertThat(result.getCodecName()).isEqualTo(""); 231 assertThat(result.getBitrate()).isEqualTo(-1); 232 assertThat(result.getType().toString()).isEqualTo("AUDIO"); 233 assertThat(result.getLanguage()).isEqualTo(""); 234 assertThat(result.getLanguageRegion()).isEqualTo(""); 235 assertThat(result.getSampleRate()).isEqualTo(-1); 236 assertThat(result.getChannelCount()).isEqualTo(-1); 237 } 238 239 @Test testTrackChangeEvent_text()240 public void testTrackChangeEvent_text() throws Exception { 241 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 242 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); 243 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 244 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 245 "testTrackChangeEvent_text", 246 new LogSessionIdListener()); 247 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 248 249 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 250 251 assertThat(data.size()).isEqualTo(1); 252 assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); 253 AtomsProto.MediaPlaybackTrackChanged result = data.get( 254 0).getAtom().getMediaPlaybackTrackChanged(); 255 256 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); 257 assertThat(result.getState().toString()).isEqualTo("ON"); 258 assertThat(result.getReason().toString()).isEqualTo("REASON_MANUAL"); 259 assertThat(result.getContainerMimeType()).isEqualTo("text/foo"); 260 assertThat(result.getSampleMimeType()).isEqualTo("text/plain"); 261 assertThat(result.getCodecName()).isEqualTo("codec_1"); 262 assertThat(result.getBitrate()).isEqualTo(1024); 263 assertThat(result.getType().toString()).isEqualTo("TEXT"); 264 assertThat(result.getLanguage()).isEqualTo("EN"); 265 assertThat(result.getLanguageRegion()).isEqualTo("US"); 266 } 267 268 @Test testTrackChangeEvent_audio()269 public void testTrackChangeEvent_audio() throws Exception { 270 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 271 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); 272 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 273 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 274 "testTrackChangeEvent_audio", 275 new LogSessionIdListener()); 276 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 277 278 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 279 280 assertThat(data.size()).isEqualTo(1); 281 assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); 282 AtomsProto.MediaPlaybackTrackChanged result = data.get( 283 0).getAtom().getMediaPlaybackTrackChanged(); 284 285 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); 286 assertThat(result.getState().toString()).isEqualTo("OFF"); 287 assertThat(result.getReason().toString()).isEqualTo("REASON_INITIAL"); 288 assertThat(result.getContainerMimeType()).isEqualTo("audio/foo"); 289 assertThat(result.getSampleMimeType()).isEqualTo("audio/avc"); 290 assertThat(result.getCodecName()).isEqualTo("codec_2"); 291 assertThat(result.getBitrate()).isEqualTo(1025); 292 assertThat(result.getType().toString()).isEqualTo("AUDIO"); 293 assertThat(result.getLanguage()).isEqualTo("EN"); 294 assertThat(result.getLanguageRegion()).isEqualTo("US"); 295 assertThat(result.getSampleRate()).isEqualTo(89); 296 assertThat(result.getChannelCount()).isEqualTo(3); 297 } 298 299 @Test testTrackChangeEvent_video()300 public void testTrackChangeEvent_video() throws Exception { 301 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 302 AtomsProto.Atom.MEDIA_PLAYBACK_TRACK_CHANGED_FIELD_NUMBER); 303 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 304 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 305 "testTrackChangeEvent_video", 306 new LogSessionIdListener()); 307 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 308 309 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 310 311 assertThat(data.size()).isEqualTo(1); 312 assertThat(data.get(0).getAtom().hasMediaPlaybackTrackChanged()).isTrue(); 313 AtomsProto.MediaPlaybackTrackChanged result = data.get( 314 0).getAtom().getMediaPlaybackTrackChanged(); 315 316 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(37278L); 317 assertThat(result.getState().toString()).isEqualTo("OFF"); 318 assertThat(result.getReason().toString()).isEqualTo("REASON_INITIAL"); 319 assertThat(result.getContainerMimeType()).isEqualTo("video/foo"); 320 assertThat(result.getSampleMimeType()).isEqualTo("video/mpeg"); 321 assertThat(result.getCodecName()).isEqualTo("codec_3"); 322 assertThat(result.getBitrate()).isEqualTo(1025); 323 assertThat(result.getType().toString()).isEqualTo("VIDEO"); 324 assertThat(result.getLanguage()).isEqualTo("EN"); 325 assertThat(result.getLanguageRegion()).isEqualTo("US"); 326 assertThat(result.getHeight()).isEqualTo(1080); 327 assertThat(result.getWidth()).isEqualTo(1440); 328 assertThat(result.getVideoFrameRate()).isEqualTo(60); 329 } 330 331 @Test testNetworkEvent_default()332 public void testNetworkEvent_default() throws Exception { 333 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 334 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER); 335 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 336 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 337 "testNetworkEvent_default", 338 new LogSessionIdListener()); 339 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 340 341 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 342 343 assertThat(data.size()).isEqualTo(1); 344 assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue(); 345 AtomsProto.MediaNetworkInfoChanged result = data.get( 346 0).getAtom().getMediaNetworkInfoChanged(); 347 348 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(-1L); 349 assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_UNKNOWN"); 350 } 351 352 @Test testNetworkEvent()353 public void testNetworkEvent() throws Exception { 354 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 355 AtomsProto.Atom.MEDIA_NETWORK_INFO_CHANGED_FIELD_NUMBER); 356 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 357 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testNetworkEvent", 358 new LogSessionIdListener()); 359 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 360 361 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 362 363 assertThat(data.size()).isEqualTo(1); 364 assertThat(data.get(0).getAtom().hasMediaNetworkInfoChanged()).isTrue(); 365 AtomsProto.MediaNetworkInfoChanged result = data.get( 366 0).getAtom().getMediaNetworkInfoChanged(); 367 368 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(3032L); 369 assertThat(result.getType().toString()).isEqualTo("NETWORK_TYPE_WIFI"); 370 } 371 372 @Test testPlaybackMetrics_default()373 public void testPlaybackMetrics_default() throws Exception { 374 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 375 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 376 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 377 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 378 "testPlaybackMetrics_default", 379 new LogSessionIdListener()); 380 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 381 382 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 383 int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG); 384 385 assertThat(data.size()).isEqualTo(1); 386 assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); 387 AtomsProto.MediametricsPlaybackReported result = data.get( 388 0).getAtom().getMediametricsPlaybackReported(); 389 390 assertThat(result.getUid()).isEqualTo(appUid); 391 assertThat(result.getMediaDurationMillis()).isEqualTo(-1L); 392 assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_UNKNOWN"); 393 assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_UNKNOWN"); 394 assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_UNKNOWN"); 395 assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_NONE"); 396 assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_UNKNOWN"); 397 assertThat(result.getPlayerName()).isEqualTo(""); 398 assertThat(result.getPlayerVersion()).isEqualTo(""); 399 assertThat(result.getVideoFramesPlayed()).isEqualTo(-1); 400 assertThat(result.getVideoFramesDropped()).isEqualTo(-1); 401 assertThat(result.getAudioUnderrunCount()).isEqualTo(-1); 402 assertThat(result.getNetworkBytesRead()).isEqualTo(-1); 403 assertThat(result.getLocalBytesRead()).isEqualTo(-1); 404 assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(-1); 405 assertThat(result.getExperimentIds().getExperimentsList().size()).isEqualTo(0); 406 assertThat(result.getDrmSessionId().length()).isEqualTo(0); 407 } 408 409 @Test testPlaybackMetrics()410 public void testPlaybackMetrics() throws Exception { 411 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 412 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 413 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 414 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testPlaybackMetrics", 415 new LogSessionIdListener()); 416 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 417 418 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 419 int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG); 420 421 assertThat(data.size()).isEqualTo(1); 422 assertThat(data.get(0).getAtom().hasMediametricsPlaybackReported()).isTrue(); 423 AtomsProto.MediametricsPlaybackReported result = data.get( 424 0).getAtom().getMediametricsPlaybackReported(); 425 426 assertThat(result.getUid()).isEqualTo(appUid); 427 assertThat(result.getMediaDurationMillis()).isEqualTo(233L); 428 assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK"); 429 assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER"); 430 assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE"); 431 assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1"); 432 assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN"); 433 assertThat(result.getPlayerName()).isEqualTo("ExoPlayer"); 434 assertThat(result.getPlayerVersion()).isEqualTo("1.01x"); 435 assertThat(result.getVideoFramesPlayed()).isEqualTo(1024); 436 assertThat(result.getVideoFramesDropped()).isEqualTo(32); 437 assertThat(result.getAudioUnderrunCount()).isEqualTo(22); 438 assertThat(result.getNetworkBytesRead()).isEqualTo(102400); 439 assertThat(result.getLocalBytesRead()).isEqualTo(2000); 440 assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000); 441 // TODO: fix missing experiment ID impl 442 assertThat(result.getExperimentIds()).isNotEqualTo(null); 443 // TODO: needs Base64 decoders to verify the data 444 assertThat(result.getDrmSessionId()).isNotEqualTo(null); 445 } 446 447 @Test testEditingEndedEvent_default()448 public void testEditingEndedEvent_default() throws Exception { 449 ConfigUtils.uploadConfigForPushedAtom( 450 getDevice(), TEST_PKG, MEDIA_EDITING_ENDED_REPORTED_FIELD_NUMBER); 451 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 452 MediaEditingExtensionAtoms.registerAllExtensions(registry); 453 454 DeviceUtils.runDeviceTests( 455 getDevice(), 456 TEST_PKG, 457 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 458 "testEditingEndedEvent_default", 459 new LogSessionIdListener()); 460 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 461 462 List<StatsLog.EventMetricData> data = 463 ReportUtils.getEventMetricDataList(getDevice(), registry); 464 assertThat(data).hasSize(1); 465 MediaEditingExtensionAtoms.MediaEditingEndedReported atom = 466 data.get(0) 467 .getAtom() 468 .getExtension(MediaEditingExtensionAtoms.mediaEditingEndedReported); 469 assertThat(atom.getFinalProgressPercent()).isEqualTo(-1f); 470 assertThat(atom.getTimeSinceEditingCreatedMillis()).isEqualTo(-1L); 471 assertThat(atom.getExporterName()).isEqualTo(""); 472 assertThat(atom.getMuxerName()).isEqualTo(""); 473 assertThat(atom.getFinalState().toString()).isEqualTo("FINAL_STATE_SUCCEEDED"); 474 assertThat(atom.getErrorCode().toString()).isEqualTo("ERROR_CODE_NONE"); 475 } 476 477 @Test testEditingEndedEvent_error()478 public void testEditingEndedEvent_error() throws Exception { 479 ConfigUtils.uploadConfigForPushedAtom( 480 getDevice(), TEST_PKG, MEDIA_EDITING_ENDED_REPORTED_FIELD_NUMBER); 481 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 482 MediaEditingExtensionAtoms.registerAllExtensions(registry); 483 484 DeviceUtils.runDeviceTests( 485 getDevice(), 486 TEST_PKG, 487 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 488 "testEditingEndedEvent_error", 489 new LogSessionIdListener()); 490 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 491 492 List<StatsLog.EventMetricData> data = 493 ReportUtils.getEventMetricDataList(getDevice(), registry); 494 assertThat(data).hasSize(1); 495 MediaEditingExtensionAtoms.MediaEditingEndedReported atom = 496 data.get(0) 497 .getAtom() 498 .getExtension(MediaEditingExtensionAtoms.mediaEditingEndedReported); 499 assertThat(atom.getTimeSinceEditingCreatedMillis()).isEqualTo(17630000L); 500 assertThat(atom.getExporterName()).isEqualTo(""); 501 assertThat(atom.getMuxerName()).isEqualTo("androidx.media3:media3-muxer:1.2.1"); 502 assertThat(atom.getFinalState().toString()).isEqualTo("FINAL_STATE_ERROR"); 503 assertThat(atom.getFinalProgressPercent()).isEqualTo(10f); 504 assertThat(atom.getErrorCode().toString()).isEqualTo("ERROR_CODE_FAILED_RUNTIME_CHECK"); 505 assertThat(atom.getOperationTypeVideoTranscode()).isFalse(); 506 assertThat(atom.getOperationTypeAudioTranscode()).isFalse(); 507 assertThat(atom.getOperationTypeVideoEdit()).isTrue(); 508 assertThat(atom.getOperationTypeAudioEdit()).isFalse(); 509 assertThat(atom.getOperationTypeVideoTransmux()).isFalse(); 510 assertThat(atom.getOperationTypeAudioTransmux()).isTrue(); 511 assertThat(atom.getOperationTypeWasPaused()).isFalse(); 512 assertThat(atom.getOperationTypeWasResumed()).isFalse(); 513 } 514 515 @Test testEditingEndedEvent_transcodeAndClip()516 public void testEditingEndedEvent_transcodeAndClip() throws Exception { 517 ConfigUtils.uploadConfigForPushedAtom( 518 getDevice(), TEST_PKG, MEDIA_EDITING_ENDED_REPORTED_FIELD_NUMBER); 519 ExtensionRegistry registry = ExtensionRegistry.newInstance(); 520 MediaEditingExtensionAtoms.registerAllExtensions(registry); 521 522 DeviceUtils.runDeviceTests( 523 getDevice(), 524 TEST_PKG, 525 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 526 "testEditingEndedEvent_transcodeAndClip", 527 new LogSessionIdListener()); 528 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 529 530 List<StatsLog.EventMetricData> data = 531 ReportUtils.getEventMetricDataList(getDevice(), registry); 532 assertThat(data).hasSize(1); 533 MediaEditingExtensionAtoms.MediaEditingEndedReported atom = 534 data.get(0) 535 .getAtom() 536 .getExtension(MediaEditingExtensionAtoms.mediaEditingEndedReported); 537 assertThat(atom.getTimeSinceEditingCreatedMillis()).isEqualTo(2_000L); 538 assertThat(atom.getExporterName()) 539 .isEqualTo("androidx.media3:media3-transformer:1.3.0-beta01"); 540 assertThat(atom.getMuxerName()).isEqualTo("androidx.media3:media3-muxer:1.3.0-beta01"); 541 assertThat(atom.getFinalState().toString()).isEqualTo("FINAL_STATE_SUCCEEDED"); 542 assertThat(atom.getFinalProgressPercent()).isEqualTo(100f); 543 assertThat(atom.getErrorCode().toString()).isEqualTo("ERROR_CODE_NONE"); 544 assertThat(atom.getInputMediaItemCount()).isEqualTo(1); 545 assertThat(atom.getInputMediaItem1SourceType().toString()).isEqualTo("SOURCE_TYPE_CAMERA"); 546 assertThat(atom.getInputMediaItem1HasDataTypeImage()).isFalse(); 547 assertThat(atom.getInputMediaItem1HasDataTypeVideo()).isTrue(); 548 assertThat(atom.getInputMediaItem1HasDataTypeAudio()).isTrue(); 549 assertThat(atom.getInputMediaItem1HasDataTypeMetadata()).isFalse(); 550 assertThat(atom.getInputMediaItem1HasDataTypeDepth()).isFalse(); 551 assertThat(atom.getInputMediaItem1HasDataTypeGainMap()).isFalse(); 552 assertThat(atom.getInputMediaItem1HasDataTypeHighFrameRate()).isFalse(); 553 assertThat(atom.getInputMediaItem1HasDataTypeCuePoints()).isFalse(); 554 assertThat(atom.getInputMediaItem1HasDataTypeGapless()).isFalse(); 555 assertThat(atom.getInputMediaItem1HasDataTypeSpatialAudio()).isFalse(); 556 assertThat(atom.getInputMediaItem1HasDataTypeHighDynamicRangeVideo()).isTrue(); 557 assertThat(atom.getInputMediaItem1DurationMillis()).isEqualTo(3_750L); 558 assertThat(atom.getInputMediaItem1ClipDurationMillis()).isEqualTo(1_875L); 559 assertThat(atom.getInputMediaItem1ContainerMimeType()).isEqualTo("video/mp4"); 560 assertThat(atom.getInputMediaItem1AudioSampleMimeType()).isEqualTo("audio/mp4a-latm"); 561 assertThat(atom.getInputMediaItem1VideoSampleMimeType()).isEqualTo("video/hevc"); 562 assertThat(atom.getInputMediaItem1CommonVideoCodec().toString()).isEqualTo("CODEC_HEVC"); 563 assertThat(atom.getInputMediaItem1CodecName1()).isEqualTo("c2.android.hevc.decoder"); 564 assertThat(atom.getInputMediaItem1CodecName2()).isEqualTo("c2.android.aac.decoder"); 565 assertThat(atom.getInputMediaItem1AudioSampleRateHz()).isEqualTo(44100); 566 assertThat(atom.getInputMediaItem1AudioChannelCount()).isEqualTo(2); 567 assertThat(atom.getInputMediaItem1AudioSampleCount()).isEqualTo(10_000L); 568 assertThat(atom.getInputMediaItem1VideoRawWidthPixels()).isEqualTo(1080); 569 assertThat(atom.getInputMediaItem1VideoRawHeightPixels()).isEqualTo(1920); 570 assertThat(atom.getInputMediaItem1VideoResolution().toString()) 571 .isEqualTo("RESOLUTION_1080P_FHD"); 572 assertThat(atom.getInputMediaItem1VideoResolutionAspectRatio().toString()) 573 .isEqualTo("RESOLUTION_ASPECT_RATIO_PORTRAIT"); 574 assertThat(atom.getInputMediaItem1VideoDataSpace()) 575 .isEqualTo(/* BT2020 | HLG | FULL */ 0b1010000001100000000000000000); 576 assertThat(atom.getInputMediaItem1VideoFrameRate()).isEqualTo(25); 577 assertThat(atom.getThroughputFps()).isEqualTo(50); 578 assertThat(atom.getOutputMediaItemHasDataTypeImage()).isFalse(); 579 assertThat(atom.getOutputMediaItemHasDataTypeVideo()).isTrue(); 580 assertThat(atom.getOutputMediaItemHasDataTypeAudio()).isTrue(); 581 assertThat(atom.getOutputMediaItemHasDataTypeMetadata()).isFalse(); 582 assertThat(atom.getOutputMediaItemHasDataTypeDepth()).isFalse(); 583 assertThat(atom.getOutputMediaItemHasDataTypeGainMap()).isFalse(); 584 assertThat(atom.getOutputMediaItemHasDataTypeHighFrameRate()).isFalse(); 585 assertThat(atom.getOutputMediaItemHasDataTypeCuePoints()).isFalse(); 586 assertThat(atom.getOutputMediaItemHasDataTypeGapless()).isFalse(); 587 assertThat(atom.getOutputMediaItemHasDataTypeSpatialAudio()).isFalse(); 588 assertThat(atom.getOutputMediaItemHasDataTypeHighDynamicRangeVideo()).isFalse(); 589 assertThat(atom.getOutputMediaItemDurationMillis()).isEqualTo(1_875L); 590 assertThat(atom.getOutputMediaItemContainerMimeType()).isEqualTo("video/mp4"); 591 assertThat(atom.getOutputMediaItemAudioSampleMimeType()).isEqualTo("audio/mp4a-latm"); 592 assertThat(atom.getOutputMediaItemVideoSampleMimeType()).isEqualTo("video/avc"); 593 assertThat(atom.getOutputMediaItemCommonVideoCodec().toString()).isEqualTo("CODEC_AVC"); 594 assertThat(atom.getOutputMediaItemCodecName1()).isEqualTo("c2.android.avc.encoder"); 595 assertThat(atom.getOutputMediaItemCodecName2()).isEqualTo("c2.android.aac.encoder"); 596 assertThat(atom.getOutputMediaItemAudioSampleRateHz()).isEqualTo(44100); 597 assertThat(atom.getOutputMediaItemAudioChannelCount()).isEqualTo(2); 598 assertThat(atom.getOutputMediaItemAudioSampleCount()).isEqualTo(10_000L); 599 assertThat(atom.getOutputMediaItemVideoRawWidthPixels()).isEqualTo(720); 600 assertThat(atom.getOutputMediaItemVideoRawHeightPixels()).isEqualTo(1280); 601 assertThat(atom.getOutputMediaItemVideoResolution().toString()) 602 .isEqualTo("RESOLUTION_720P_HD"); 603 assertThat(atom.getOutputMediaItemVideoResolutionAspectRatio().toString()) 604 .isEqualTo("RESOLUTION_ASPECT_RATIO_PORTRAIT"); 605 assertThat(atom.getOutputMediaItemVideoDataSpace()) 606 .isEqualTo(/* BT709 | LINEAR | FULL */ 0b1000010000010000000000000000); 607 assertThat(atom.getOutputMediaItemVideoFrameRate()).isEqualTo(25); 608 } 609 610 @Test testSessionId()611 public void testSessionId() throws Exception { 612 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 613 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 614 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 615 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testSessionId", 616 new LogSessionIdListener()); 617 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 618 619 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 620 assertThat(data).isEmpty(); 621 } 622 623 @Test testRecordingSession()624 public void testRecordingSession() throws Exception { 625 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 626 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 627 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 628 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testRecordingSession", 629 new LogSessionIdListener()); 630 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 631 632 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 633 assertThat(data).isEmpty(); 634 } 635 636 @Test testEditingSession()637 public void testEditingSession() throws Exception { 638 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 639 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 640 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 641 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testEditingSession", 642 new LogSessionIdListener()); 643 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 644 645 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 646 assertThat(data).isEmpty(); 647 } 648 649 @Test testTranscodingSession()650 public void testTranscodingSession() throws Exception { 651 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 652 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 653 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 654 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testTranscodingSession", 655 new LogSessionIdListener()); 656 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 657 658 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 659 assertThat(data).isEmpty(); 660 } 661 662 @Test testBundleSession()663 public void testBundleSession() throws Exception { 664 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 665 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 666 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 667 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testBundleSession", 668 new LogSessionIdListener()); 669 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 670 671 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 672 assertThat(data).isEmpty(); 673 } 674 675 @Test testAppBlocklist()676 public void testAppBlocklist() throws Exception { 677 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 678 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); 679 LogSessionIdListener listener = new LogSessionIdListener(); 680 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 681 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppBlocklist", 682 listener); 683 String logSessionId = listener.getLogSessionId(); 684 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 685 686 assertWithMessage("log session id").that(logSessionId).isNotEmpty(); 687 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 688 List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, 689 AtomsProto.Atom::getMediametricsPlaybackReported); 690 assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( 691 AtomsProto.MediametricsPlaybackReported::getLogSessionId, 692 "getLogSessionId")).doesNotContain(logSessionId); 693 } 694 695 @Test testAttributionBlocklist()696 public void testAttributionBlocklist() throws Exception { 697 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 698 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 699 LogSessionIdListener listener = new LogSessionIdListener(); 700 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 701 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 702 "testAttributionBlocklist", 703 listener); 704 String logSessionId = listener.getLogSessionId(); 705 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 706 707 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 708 assertWithMessage("log session id").that(logSessionId).isNotEmpty(); 709 List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, 710 AtomsProto.Atom::getMediametricsPlaybackReported); 711 assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( 712 AtomsProto.MediametricsPlaybackReported::getLogSessionId, 713 "getLogSessionId")).contains(logSessionId); 714 715 AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter( 716 a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); 717 718 assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0. 719 assertThat(result.getMediaDurationMillis()).isEqualTo(233L); 720 assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK"); 721 assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER"); 722 assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE"); 723 assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1"); 724 assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN"); 725 assertThat(result.getPlayerName()).isEqualTo("ExoPlayer"); 726 assertThat(result.getPlayerVersion()).isEqualTo("1.01x"); 727 assertThat(result.getVideoFramesPlayed()).isEqualTo(1024); 728 assertThat(result.getVideoFramesDropped()).isEqualTo(32); 729 assertThat(result.getAudioUnderrunCount()).isEqualTo(22); 730 assertThat(result.getNetworkBytesRead()).isEqualTo(102400); 731 assertThat(result.getLocalBytesRead()).isEqualTo(2000); 732 assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000); 733 } 734 735 @Test testAppAllowlist()736 public void testAppAllowlist() throws Exception { 737 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 738 AtomsProto.Atom.MEDIA_PLAYBACK_STATE_CHANGED_FIELD_NUMBER); 739 LogSessionIdListener listener = new LogSessionIdListener(); 740 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 741 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testAppAllowlist", 742 listener); 743 String logSessionId = listener.getLogSessionId(); 744 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 745 746 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 747 assertWithMessage("log session id").that(logSessionId).isNotEmpty(); 748 List<AtomsProto.MediaPlaybackStateChanged> stateChangedList = toMyAtoms(data, 749 AtomsProto.Atom::getMediaPlaybackStateChanged); 750 assertThat(stateChangedList).comparingElementsUsing( 751 Correspondence.transforming(AtomsProto.MediaPlaybackStateChanged::getLogSessionId, 752 "getLogSessionId")).contains(logSessionId); 753 754 AtomsProto.MediaPlaybackStateChanged result = stateChangedList.stream().filter( 755 a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); 756 assertThat(result.getPlaybackState().toString()).isEqualTo("JOINING_FOREGROUND"); 757 assertThat(result.getTimeSincePlaybackCreatedMillis()).isEqualTo(1763L); 758 } 759 760 @Test testAttributionAllowlist()761 public void testAttributionAllowlist() throws Exception { 762 ConfigUtils.uploadConfigForPushedAtom(getDevice(), TEST_PKG, 763 AtomsProto.Atom.MEDIAMETRICS_PLAYBACK_REPORTED_FIELD_NUMBER); 764 LogSessionIdListener listener = new LogSessionIdListener(); 765 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 766 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", 767 "testAttributionAllowlist", 768 listener); 769 String logSessionId = listener.getLogSessionId(); 770 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 771 772 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 773 assertWithMessage("log session id").that(logSessionId).isNotEmpty(); 774 List<AtomsProto.MediametricsPlaybackReported> playbackReportedList = toMyAtoms(data, 775 AtomsProto.Atom::getMediametricsPlaybackReported); 776 assertThat(playbackReportedList).comparingElementsUsing(Correspondence.transforming( 777 AtomsProto.MediametricsPlaybackReported::getLogSessionId, 778 "getLogSessionId")).contains(logSessionId); 779 780 AtomsProto.MediametricsPlaybackReported result = playbackReportedList.stream().filter( 781 a -> a.getLogSessionId().equals(logSessionId)).findFirst().orElseThrow(); 782 783 assertThat(result.getUid()).isEqualTo(0); // UID is not logged. Should be 0. 784 assertThat(result.getMediaDurationMillis()).isEqualTo(233L); 785 assertThat(result.getStreamSource().toString()).isEqualTo("STREAM_SOURCE_NETWORK"); 786 assertThat(result.getStreamType().toString()).isEqualTo("STREAM_TYPE_OTHER"); 787 assertThat(result.getPlaybackType().toString()).isEqualTo("PLAYBACK_TYPE_LIVE"); 788 assertThat(result.getDrmType().toString()).isEqualTo("DRM_TYPE_WV_L1"); 789 assertThat(result.getContentType().toString()).isEqualTo("CONTENT_TYPE_MAIN"); 790 assertThat(result.getPlayerName()).isEqualTo("ExoPlayer"); 791 assertThat(result.getPlayerVersion()).isEqualTo("1.01x"); 792 assertThat(result.getVideoFramesPlayed()).isEqualTo(1024); 793 assertThat(result.getVideoFramesDropped()).isEqualTo(32); 794 assertThat(result.getAudioUnderrunCount()).isEqualTo(22); 795 assertThat(result.getNetworkBytesRead()).isEqualTo(102400); 796 assertThat(result.getLocalBytesRead()).isEqualTo(2000); 797 assertThat(result.getNetworkTransferDurationMillis()).isEqualTo(6000); 798 } 799 validateAAudioStreamAtom(String direction)800 private void validateAAudioStreamAtom(String direction) throws Exception { 801 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 802 803 assertThat(data).isNotEmpty(); 804 805 int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG); 806 807 for (StatsLog.EventMetricData event : data) { 808 AtomsProto.MediametricsAAudioStreamReported atom = 809 event.getAtom().getMediametricsAaudiostreamReported(); 810 assertThat(atom.getBufferCapacity()).isGreaterThan(0); 811 assertThat(atom.getBufferCapacity()).isLessThan(MAX_BUFFER_CAPACITY); 812 assertThat(atom.getBufferSize()).isGreaterThan(0); 813 assertThat(atom.getBufferSize()).isAtMost(atom.getBufferCapacity()); 814 assertThat(atom.getFramesPerBurst()).isGreaterThan(0); 815 assertThat(atom.getFramesPerBurst()).isLessThan(atom.getBufferCapacity()); 816 assertThat(atom.getUid()).isEqualTo(appUid); 817 assertThat(atom.getDirection().toString()).isEqualTo(direction); 818 assertThat(atom.getChannelCountHardware()).isGreaterThan(0); 819 assertThat(atom.getSampleRateHardware()).isGreaterThan(0); 820 assertThat(atom.getFormatHardware()).isNotEqualTo(0); 821 assertThat(atom.getTotalFramesTransferred()).isGreaterThan(0); 822 assertThat(atom.getXrunCount()).isEqualTo(0); 823 } 824 } 825 runAAudioTestAndValidate(String requiredFeature, String direction, String testFunctionName)826 private void runAAudioTestAndValidate(String requiredFeature, String direction, 827 String testFunctionName) throws Exception { 828 if (!DeviceUtils.hasFeature(getDevice(), requiredFeature)) { 829 return; 830 } 831 ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, 832 AtomsProto.Atom.MEDIAMETRICS_AAUDIOSTREAM_REPORTED_FIELD_NUMBER); 833 834 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 835 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", testFunctionName, 836 new LogSessionIdListener()); 837 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 838 839 validateAAudioStreamAtom(direction); 840 } 841 842 /** 843 * The test try to create and then close aaudio input stream with low latency via media metrics 844 * atom host side test app on the DUT. 845 * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify 846 * the data is collected correctly. 847 */ 848 @Test testAAudioLowLatencyInputStream()849 public void testAAudioLowLatencyInputStream() throws Exception { 850 runAAudioTestAndValidate(FEATURE_MICROPHONE, 851 "DIRECTION_INPUT", 852 "testAAudioLowLatencyInputStream"); 853 } 854 855 /** 856 * The test try to create and then close aaudio output stream with low latency via media metrics 857 * atom host side test app on the DUT. 858 * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify 859 * the data is collected correctly. 860 */ 861 @Test testAAudioLowLatencyOutputStream()862 public void testAAudioLowLatencyOutputStream() throws Exception { 863 runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT, 864 "DIRECTION_OUTPUT", 865 "testAAudioLowLatencyOutputStream"); 866 } 867 868 /** 869 * The test try to create and then close aaudio input stream with legacy path via media metrics 870 * atom host side test app on the DUT. 871 * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify 872 * the data is collected correctly. 873 */ 874 @Test testAAudioLegacyInputStream()875 public void testAAudioLegacyInputStream() throws Exception { 876 runAAudioTestAndValidate(FEATURE_MICROPHONE, 877 "DIRECTION_INPUT", 878 "testAAudioLegacyInputStream"); 879 } 880 881 /** 882 * The test try to create and then close aaudio output stream with legacy path via media metrics 883 * atom host side test app on the DUT. 884 * After that, the event metric data for MediametricsAAudioStreamReported is pushed to verify 885 * the data is collected correctly. 886 */ 887 @Test testAAudioLegacyOutputStream()888 public void testAAudioLegacyOutputStream() throws Exception { 889 runAAudioTestAndValidate(FEATURE_AUDIO_OUTPUT, 890 "DIRECTION_OUTPUT", 891 "testAAudioLegacyOutputStream"); 892 } 893 894 /** 895 * The test try to create and then close a midi stream via media metrics 896 * atom host side test app on the DUT. 897 * After that, the event metric data for MediametricsMidiDeviceCloseReported is pushed to verify 898 * the data is collected correctly. 899 */ 900 @Test testMidiMetrics()901 public void testMidiMetrics() throws Exception { 902 if (!DeviceUtils.hasFeature(getDevice(), FEATURE_MIDI)) { 903 return; 904 } 905 ConfigUtils.uploadConfigForPushedAtom(getDevice(), DeviceUtils.STATSD_ATOM_TEST_PKG, 906 AtomsProto.Atom.MEDIAMETRICS_MIDI_DEVICE_CLOSE_REPORTED_FIELD_NUMBER); 907 908 DeviceUtils.runDeviceTests(getDevice(), TEST_PKG, 909 "android.media.metrics.cts.MediaMetricsAtomHostSideTests", "testMidiMetrics", 910 new LogSessionIdListener()); 911 RunUtil.getDefault().sleep(AtomTestUtils.WAIT_TIME_LONG); 912 913 List<StatsLog.EventMetricData> data = ReportUtils.getEventMetricDataList(getDevice()); 914 List<AtomsProto.MediametricsMidiDeviceCloseReported> eventList = toMyAtoms(data, 915 AtomsProto.Atom::getMediametricsMidiDeviceCloseReported); 916 917 assertThat(eventList).isNotEmpty(); 918 919 int appUid = DeviceUtils.getAppUid(getDevice(), TEST_PKG); 920 AtomsProto.MediametricsMidiDeviceCloseReported result = eventList.get(0); 921 922 assertThat(result.getUid()).isEqualTo(appUid); 923 assertThat(result.getMidiDeviceId()).isGreaterThan(0); 924 assertThat(result.getInputPortCount()).isEqualTo(1); 925 assertThat(result.getOutputPortCount()).isEqualTo(1); 926 assertThat(result.getDeviceType().toString()).isEqualTo("MIDI_DEVICE_INFO_TYPE_VIRTUAL"); 927 assertThat(result.getIsShared()).isTrue(); 928 assertThat(result.getSupportsUmp()).isFalse(); 929 assertThat(result.getUsingAlsa()).isFalse(); 930 assertThat(result.getDurationNs()).isGreaterThan(0); 931 assertThat(result.getOpenedCount()).isGreaterThan(0); 932 assertThat(result.getClosedCount()).isGreaterThan(0); 933 assertThat(result.getDeviceDisconnected()).isFalse(); 934 assertThat(result.getTotalInputBytes()).isGreaterThan(0); 935 assertThat(result.getTotalOutputBytes()).isGreaterThan(0); 936 } 937 toMyAtoms(List<StatsLog.EventMetricData> data, Function<AtomsProto.Atom, T> mapper)938 private static <T> List<T> toMyAtoms(List<StatsLog.EventMetricData> data, 939 Function<AtomsProto.Atom, T> mapper) { 940 return data.stream().map(StatsLog.EventMetricData::getAtom).map(mapper).collect( 941 Collectors.toUnmodifiableList()); 942 } 943 944 private static final class LogSessionIdListener implements ITestInvocationListener { 945 946 @Nullable 947 private String mLogSessionId; 948 949 @Nullable getLogSessionId()950 public String getLogSessionId() { 951 return mLogSessionId; 952 } 953 954 @Override testEnded(TestDescription test, long endTime, HashMap<String, MetricMeasurement.Metric> testMetrics)955 public void testEnded(TestDescription test, long endTime, 956 HashMap<String, MetricMeasurement.Metric> testMetrics) { 957 LogUtil.CLog.i("testEnded MetricMeasurement.Metric " + testMetrics); 958 MetricMeasurement.Metric metric = testMetrics.get(LOG_SESSION_ID_KEY); 959 mLogSessionId = metric == null ? null : metric.getMeasurements().getSingleString(); 960 } 961 } 962 }