1 /* 2 * Copyright (C) 2017 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.atom; 17 18 import static org.junit.Assert.assertEquals; 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 22 import android.os.WakeLockLevelEnum; 23 import android.platform.test.annotations.RestrictedBuildTest; 24 25 import com.android.internal.os.StatsdConfigProto.FieldMatcher; 26 import com.android.internal.os.StatsdConfigProto.StatsdConfig; 27 import com.android.os.AtomsProto.AppCrashOccurred; 28 import com.android.os.AtomsProto.AppStartOccurred; 29 import com.android.os.AtomsProto.Atom; 30 import com.android.os.AtomsProto.AudioStateChanged; 31 import com.android.os.AtomsProto.BleScanResultReceived; 32 import com.android.os.AtomsProto.BleScanStateChanged; 33 import com.android.os.AtomsProto.CameraStateChanged; 34 import com.android.os.AtomsProto.CpuActiveTime; 35 import com.android.os.AtomsProto.CpuTimePerUid; 36 import com.android.os.AtomsProto.FlashlightStateChanged; 37 import com.android.os.AtomsProto.ForegroundServiceStateChanged; 38 import com.android.os.AtomsProto.GpsScanStateChanged; 39 import com.android.os.AtomsProto.MediaCodecStateChanged; 40 import com.android.os.AtomsProto.OverlayStateChanged; 41 import com.android.os.AtomsProto.PictureInPictureStateChanged; 42 import com.android.os.AtomsProto.ScheduledJobStateChanged; 43 import com.android.os.AtomsProto.SyncStateChanged; 44 import com.android.os.AtomsProto.WakelockStateChanged; 45 import com.android.os.AtomsProto.WifiLockStateChanged; 46 import com.android.os.AtomsProto.WifiMulticastLockStateChanged; 47 import com.android.os.AtomsProto.WifiScanStateChanged; 48 import com.android.os.StatsLog.EventMetricData; 49 50 import java.util.Arrays; 51 import java.util.HashSet; 52 import java.util.List; 53 import java.util.Set; 54 55 /** 56 * Statsd atom tests that are done via app, for atoms that report a uid. 57 */ 58 public class UidAtomTests extends DeviceAtomTestCase { 59 60 private static final String TAG = "Statsd.UidAtomTests"; 61 62 // These constants are those in PackageManager. 63 private static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le"; 64 private static final String FEATURE_LOCATION_GPS = "android.hardware.location.gps"; 65 private static final String FEATURE_WIFI = "android.hardware.wifi"; 66 private static final String FEATURE_CAMERA_FLASH = "android.hardware.camera.flash"; 67 private static final String FEATURE_CAMERA = "android.hardware.camera"; 68 private static final String FEATURE_CAMERA_FRONT = "android.hardware.camera.front"; 69 private static final String FEATURE_AUDIO_OUTPUT = "android.hardware.audio.output"; 70 private static final String FEATURE_WATCH = "android.hardware.type.watch"; 71 private static final String FEATURE_PICTURE_IN_PICTURE = "android.software.picture_in_picture"; 72 73 private static final boolean DAVEY_ENABLED = false; 74 75 @Override setUp()76 protected void setUp() throws Exception { 77 super.setUp(); 78 } 79 testAppStartOccurred()80 public void testAppStartOccurred() throws Exception { 81 if (statsdDisabled()) { 82 return; 83 } 84 final int atomTag = Atom.APP_START_OCCURRED_FIELD_NUMBER; 85 86 createAndUploadConfig(atomTag, false); 87 Thread.sleep(WAIT_TIME_SHORT); 88 89 runActivity("StatsdCtsForegroundActivity", "action", "action.sleep_top"); 90 91 // Sorted list of events in order in which they occurred. 92 List<EventMetricData> data = getEventMetricDataList(); 93 94 AppStartOccurred atom = data.get(0).getAtom().getAppStartOccurred(); 95 assertEquals("com.android.server.cts.device.statsd", atom.getPkgName()); 96 assertEquals("com.android.server.cts.device.statsd.StatsdCtsForegroundActivity", 97 atom.getActivityName()); 98 assertFalse(atom.getIsInstantApp()); 99 assertTrue(atom.getActivityStartMillis() > 0); 100 assertTrue(atom.getTransitionDelayMillis() > 0); 101 } 102 testBleScan()103 public void testBleScan() throws Exception { 104 if (statsdDisabled()) { 105 return; 106 } 107 if (!hasFeature(FEATURE_BLUETOOTH_LE, true)) return; 108 109 final int atom = Atom.BLE_SCAN_STATE_CHANGED_FIELD_NUMBER; 110 final int field = BleScanStateChanged.STATE_FIELD_NUMBER; 111 final int stateOn = BleScanStateChanged.State.ON_VALUE; 112 final int stateOff = BleScanStateChanged.State.OFF_VALUE; 113 final int minTimeDiffMillis = 1_500; 114 final int maxTimeDiffMillis = 3_000; 115 116 List<EventMetricData> data = doDeviceMethodOnOff("testBleScanUnoptimized", atom, field, 117 stateOn, stateOff, minTimeDiffMillis, maxTimeDiffMillis, true); 118 119 BleScanStateChanged a0 = data.get(0).getAtom().getBleScanStateChanged(); 120 BleScanStateChanged a1 = data.get(1).getAtom().getBleScanStateChanged(); 121 assertTrue(a0.getState().getNumber() == stateOn); 122 assertTrue(a1.getState().getNumber() == stateOff); 123 } 124 testBleUnoptimizedScan()125 public void testBleUnoptimizedScan() throws Exception { 126 if (statsdDisabled()) { 127 return; 128 } 129 if (!hasFeature(FEATURE_BLUETOOTH_LE, true)) return; 130 131 final int atom = Atom.BLE_SCAN_STATE_CHANGED_FIELD_NUMBER; 132 final int field = BleScanStateChanged.STATE_FIELD_NUMBER; 133 final int stateOn = BleScanStateChanged.State.ON_VALUE; 134 final int stateOff = BleScanStateChanged.State.OFF_VALUE; 135 final int minTimeDiffMillis = 1_500; 136 final int maxTimeDiffMillis = 3_000; 137 138 List<EventMetricData> data = doDeviceMethodOnOff("testBleScanUnoptimized", atom, field, 139 stateOn, stateOff, minTimeDiffMillis, maxTimeDiffMillis, true); 140 141 BleScanStateChanged a0 = data.get(0).getAtom().getBleScanStateChanged(); 142 assertTrue(a0.getState().getNumber() == stateOn); 143 assertFalse(a0.getIsFiltered()); 144 assertFalse(a0.getIsFirstMatch()); 145 assertFalse(a0.getIsOpportunistic()); 146 BleScanStateChanged a1 = data.get(1).getAtom().getBleScanStateChanged(); 147 assertTrue(a1.getState().getNumber() == stateOff); 148 assertFalse(a1.getIsFiltered()); 149 assertFalse(a1.getIsFirstMatch()); 150 assertFalse(a1.getIsOpportunistic()); 151 152 153 // Now repeat the test for opportunistic scanning and make sure it is reported correctly. 154 data = doDeviceMethodOnOff("testBleScanOpportunistic", atom, field, 155 stateOn, stateOff, minTimeDiffMillis, maxTimeDiffMillis, true); 156 157 a0 = data.get(0).getAtom().getBleScanStateChanged(); 158 assertTrue(a0.getState().getNumber() == stateOn); 159 assertFalse(a0.getIsFiltered()); 160 assertFalse(a0.getIsFirstMatch()); 161 assertTrue(a0.getIsOpportunistic()); // This scan is opportunistic. 162 a1 = data.get(1).getAtom().getBleScanStateChanged(); 163 assertTrue(a1.getState().getNumber() == stateOff); 164 assertFalse(a1.getIsFiltered()); 165 assertFalse(a1.getIsFirstMatch()); 166 assertTrue(a1.getIsOpportunistic()); 167 } 168 testBleScanResult()169 public void testBleScanResult() throws Exception { 170 if (statsdDisabled()) { 171 return; 172 } 173 if (!hasFeature(FEATURE_BLUETOOTH_LE, true)) return; 174 175 final int atom = Atom.BLE_SCAN_RESULT_RECEIVED_FIELD_NUMBER; 176 final int field = BleScanResultReceived.NUM_RESULTS_FIELD_NUMBER; 177 178 StatsdConfig.Builder conf = createConfigBuilder(); 179 addAtomEvent(conf, atom, createFvm(field).setGteInt(0)); 180 List<EventMetricData> data = doDeviceMethod("testBleScanResult", conf); 181 182 assertTrue(data.size() >= 1); 183 BleScanResultReceived a0 = data.get(0).getAtom().getBleScanResultReceived(); 184 assertTrue(a0.getNumResults() >= 1); 185 } 186 testCameraState()187 public void testCameraState() throws Exception { 188 if (statsdDisabled()) { 189 return; 190 } 191 if (!hasFeature(FEATURE_CAMERA, true) && !hasFeature(FEATURE_CAMERA_FRONT, true)) return; 192 193 final int atomTag = Atom.CAMERA_STATE_CHANGED_FIELD_NUMBER; 194 Set<Integer> cameraOn = new HashSet<>(Arrays.asList(CameraStateChanged.State.ON_VALUE)); 195 Set<Integer> cameraOff = new HashSet<>(Arrays.asList(CameraStateChanged.State.OFF_VALUE)); 196 197 // Add state sets to the list in order. 198 List<Set<Integer>> stateSet = Arrays.asList(cameraOn, cameraOff); 199 200 createAndUploadConfig(atomTag, true); // True: uses attribution. 201 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testCameraState"); 202 203 // Sorted list of events in order in which they occurred. 204 List<EventMetricData> data = getEventMetricDataList(); 205 206 // Assert that the events happened in the expected order. 207 assertStatesOccurred(stateSet, data, WAIT_TIME_LONG, 208 atom -> atom.getCameraStateChanged().getState().getNumber()); 209 } 210 testCpuTimePerUid()211 public void testCpuTimePerUid() throws Exception { 212 if (statsdDisabled()) { 213 return; 214 } 215 if (!hasFeature(FEATURE_WATCH, false)) return; 216 StatsdConfig.Builder config = getPulledConfig(); 217 FieldMatcher.Builder dimension = FieldMatcher.newBuilder() 218 .setField(Atom.CPU_TIME_PER_UID_FIELD_NUMBER) 219 .addChild(FieldMatcher.newBuilder() 220 .setField(CpuTimePerUid.UID_FIELD_NUMBER)); 221 addGaugeAtom(config, Atom.CPU_TIME_PER_UID_FIELD_NUMBER, dimension); 222 223 uploadConfig(config); 224 225 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu"); 226 227 turnScreenOff(); 228 Thread.sleep(WAIT_TIME_SHORT); 229 turnScreenOn(); 230 Thread.sleep(WAIT_TIME_SHORT); 231 232 List<Atom> atomList = getGaugeMetricDataList(); 233 234 // TODO: We don't have atom matching on gauge yet. Let's refactor this after that feature is 235 // implemented. 236 boolean found = false; 237 int uid = getUid(); 238 for (Atom atom : atomList) { 239 if (atom.getCpuTimePerUid().getUid() == uid) { 240 found = true; 241 assertTrue(atom.getCpuTimePerUid().getUserTimeMillis() > 0); 242 assertTrue(atom.getCpuTimePerUid().getSysTimeMillis() > 0); 243 } 244 } 245 assertTrue("found uid " + uid, found); 246 } 247 248 @RestrictedBuildTest testCpuActiveTime()249 public void testCpuActiveTime() throws Exception { 250 if (statsdDisabled()) { 251 return; 252 } 253 if (!hasFeature(FEATURE_WATCH, false)) return; 254 StatsdConfig.Builder config = getPulledConfig(); 255 FieldMatcher.Builder dimension = FieldMatcher.newBuilder() 256 .setField(Atom.CPU_ACTIVE_TIME_FIELD_NUMBER) 257 .addChild(FieldMatcher.newBuilder() 258 .setField(CpuActiveTime.UID_FIELD_NUMBER)); 259 addGaugeAtom(config, Atom.CPU_ACTIVE_TIME_FIELD_NUMBER, dimension); 260 261 uploadConfig(config); 262 263 turnScreenOn(); 264 Thread.sleep(WAIT_TIME_SHORT); 265 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSimpleCpu"); 266 Thread.sleep(WAIT_TIME_SHORT); 267 turnScreenOff(); 268 Thread.sleep(WAIT_TIME_SHORT); 269 turnScreenOn(); 270 Thread.sleep(WAIT_TIME_SHORT); 271 272 List<Atom> atomList = getGaugeMetricDataList(); 273 274 boolean found = false; 275 int uid = getUid(); 276 long timeSpent = 0; 277 for (Atom atom : atomList) { 278 if (atom.getCpuActiveTime().getUid() == uid) { 279 found = true; 280 timeSpent += atom.getCpuActiveTime().getTimeMillis(); 281 } 282 } 283 assertTrue(timeSpent > 0); 284 assertTrue("found uid " + uid, found); 285 } 286 testFlashlightState()287 public void testFlashlightState() throws Exception { 288 if (statsdDisabled()) { 289 return; 290 } 291 if (!hasFeature(FEATURE_CAMERA_FLASH, true)) return; 292 293 final int atomTag = Atom.FLASHLIGHT_STATE_CHANGED_FIELD_NUMBER; 294 final String name = "testFlashlight"; 295 296 Set<Integer> flashlightOn = new HashSet<>( 297 Arrays.asList(FlashlightStateChanged.State.ON_VALUE)); 298 Set<Integer> flashlightOff = new HashSet<>( 299 Arrays.asList(FlashlightStateChanged.State.OFF_VALUE)); 300 301 // Add state sets to the list in order. 302 List<Set<Integer>> stateSet = Arrays.asList(flashlightOn, flashlightOff); 303 304 createAndUploadConfig(atomTag, true); // True: uses attribution. 305 Thread.sleep(WAIT_TIME_SHORT); 306 307 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", name); 308 309 // Sorted list of events in order in which they occurred. 310 List<EventMetricData> data = getEventMetricDataList(); 311 312 // Assert that the events happened in the expected order. 313 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 314 atom -> atom.getFlashlightStateChanged().getState().getNumber()); 315 } 316 testForegroundServiceState()317 public void testForegroundServiceState() throws Exception { 318 if (statsdDisabled()) { 319 return; 320 } 321 final int atomTag = Atom.FOREGROUND_SERVICE_STATE_CHANGED_FIELD_NUMBER; 322 final String name = "testForegroundService"; 323 324 Set<Integer> enterForeground = new HashSet<>( 325 Arrays.asList(ForegroundServiceStateChanged.State.ENTER_VALUE)); 326 Set<Integer> exitForeground = new HashSet<>( 327 Arrays.asList(ForegroundServiceStateChanged.State.EXIT_VALUE)); 328 329 // Add state sets to the list in order. 330 List<Set<Integer>> stateSet = Arrays.asList(enterForeground, exitForeground); 331 332 createAndUploadConfig(atomTag, false); 333 Thread.sleep(WAIT_TIME_SHORT); 334 335 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", name); 336 337 // Sorted list of events in order in which they occurred. 338 List<EventMetricData> data = getEventMetricDataList(); 339 340 // Assert that the events happened in the expected order. 341 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 342 atom -> atom.getForegroundServiceStateChanged().getState().getNumber()); 343 } 344 testGpsScan()345 public void testGpsScan() throws Exception { 346 if (statsdDisabled()) { 347 return; 348 } 349 if (!hasFeature(FEATURE_LOCATION_GPS, true)) return; 350 // Whitelist this app against background location request throttling 351 getDevice().executeShellCommand(String.format( 352 "settings put global location_background_throttle_package_whitelist %s", 353 DEVICE_SIDE_TEST_PACKAGE)); 354 355 final int atom = Atom.GPS_SCAN_STATE_CHANGED_FIELD_NUMBER; 356 final int key = GpsScanStateChanged.STATE_FIELD_NUMBER; 357 final int stateOn = GpsScanStateChanged.State.ON_VALUE; 358 final int stateOff = GpsScanStateChanged.State.OFF_VALUE; 359 final int minTimeDiffMillis = 500; 360 final int maxTimeDiffMillis = 60_000; 361 362 List<EventMetricData> data = doDeviceMethodOnOff("testGpsScan", atom, key, 363 stateOn, stateOff, minTimeDiffMillis, maxTimeDiffMillis, true); 364 365 GpsScanStateChanged a0 = data.get(0).getAtom().getGpsScanStateChanged(); 366 GpsScanStateChanged a1 = data.get(1).getAtom().getGpsScanStateChanged(); 367 assertTrue(a0.getState().getNumber() == stateOn); 368 assertTrue(a1.getState().getNumber() == stateOff); 369 } 370 testOverlayState()371 public void testOverlayState() throws Exception { 372 if (statsdDisabled()) { 373 return; 374 } 375 final int atomTag = Atom.OVERLAY_STATE_CHANGED_FIELD_NUMBER; 376 377 Set<Integer> entered = new HashSet<>( 378 Arrays.asList(OverlayStateChanged.State.ENTERED_VALUE)); 379 Set<Integer> exited = new HashSet<>( 380 Arrays.asList(OverlayStateChanged.State.EXITED_VALUE)); 381 382 // Add state sets to the list in order. 383 List<Set<Integer>> stateSet = Arrays.asList(entered, exited); 384 385 createAndUploadConfig(atomTag, false); 386 387 runActivity("StatsdCtsForegroundActivity", "action", "action.show_application_overlay", 388 3_000); 389 390 // Sorted list of events in order in which they occurred. 391 List<EventMetricData> data = getEventMetricDataList(); 392 393 // Assert that the events happened in the expected order. 394 // The overlay box should appear about 2sec after the app start 395 assertStatesOccurred(stateSet, data, 0, 396 atom -> atom.getOverlayStateChanged().getState().getNumber()); 397 } 398 testDavey()399 public void testDavey() throws Exception { 400 if (statsdDisabled()) { 401 return; 402 } 403 if (!DAVEY_ENABLED ) return; 404 long MAX_DURATION = 2000; 405 long MIN_DURATION = 750; 406 final int atomTag = Atom.DAVEY_OCCURRED_FIELD_NUMBER; 407 createAndUploadConfig(atomTag, false); // UID is logged without attribution node 408 409 runActivity("DaveyActivity", null, null); 410 411 List<EventMetricData> data = getEventMetricDataList(); 412 assertTrue(data.size() == 1); 413 long duration = data.get(0).getAtom().getDaveyOccurred().getJankDurationMillis(); 414 assertTrue("Jank duration of " + duration + "ms was less than " + MIN_DURATION + "ms", 415 duration >= MIN_DURATION); 416 assertTrue("Jank duration of " + duration + "ms was longer than " + MAX_DURATION + "ms", 417 duration <= MAX_DURATION); 418 } 419 testScheduledJobState()420 public void testScheduledJobState() throws Exception { 421 if (statsdDisabled()) { 422 return; 423 } 424 String expectedName = "com.android.server.cts.device.statsd/.StatsdJobService"; 425 final int atomTag = Atom.SCHEDULED_JOB_STATE_CHANGED_FIELD_NUMBER; 426 Set<Integer> jobSchedule = new HashSet<>( 427 Arrays.asList(ScheduledJobStateChanged.State.SCHEDULED_VALUE)); 428 Set<Integer> jobOn = new HashSet<>( 429 Arrays.asList(ScheduledJobStateChanged.State.STARTED_VALUE)); 430 Set<Integer> jobOff = new HashSet<>( 431 Arrays.asList(ScheduledJobStateChanged.State.FINISHED_VALUE)); 432 433 // Add state sets to the list in order. 434 List<Set<Integer>> stateSet = Arrays.asList(jobSchedule, jobOn, jobOff); 435 436 createAndUploadConfig(atomTag, true); // True: uses attribution. 437 allowImmediateSyncs(); 438 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testScheduledJob"); 439 440 // Sorted list of events in order in which they occurred. 441 List<EventMetricData> data = getEventMetricDataList(); 442 443 assertStatesOccurred(stateSet, data, 0, 444 atom -> atom.getScheduledJobStateChanged().getState().getNumber()); 445 446 for (EventMetricData e : data) { 447 assertTrue(e.getAtom().getScheduledJobStateChanged().getJobName().equals(expectedName)); 448 } 449 } 450 451 //Note: this test does not have uid, but must run on the device testScreenBrightness()452 public void testScreenBrightness() throws Exception { 453 if (statsdDisabled()) { 454 return; 455 } 456 int initialBrightness = getScreenBrightness(); 457 boolean isInitialManual = isScreenBrightnessModeManual(); 458 setScreenBrightnessMode(true); 459 setScreenBrightness(200); 460 Thread.sleep(WAIT_TIME_LONG); 461 462 final int atomTag = Atom.SCREEN_BRIGHTNESS_CHANGED_FIELD_NUMBER; 463 464 Set<Integer> screenMin = new HashSet<>(Arrays.asList(47)); 465 Set<Integer> screen100 = new HashSet<>(Arrays.asList(100)); 466 Set<Integer> screen200 = new HashSet<>(Arrays.asList(198)); 467 // Set<Integer> screenMax = new HashSet<>(Arrays.asList(255)); 468 469 // Add state sets to the list in order. 470 List<Set<Integer>> stateSet = Arrays.asList(screenMin, screen100, screen200); 471 472 createAndUploadConfig(atomTag); 473 Thread.sleep(WAIT_TIME_SHORT); 474 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testScreenBrightness"); 475 476 // Sorted list of events in order in which they occurred. 477 List<EventMetricData> data = getEventMetricDataList(); 478 479 // Restore initial screen brightness 480 setScreenBrightness(initialBrightness); 481 setScreenBrightnessMode(isInitialManual); 482 483 popUntilFind(data, screenMin, atom->atom.getScreenBrightnessChanged().getLevel()); 484 popUntilFindFromEnd(data, screen200, atom->atom.getScreenBrightnessChanged().getLevel()); 485 // Assert that the events happened in the expected order. 486 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 487 atom -> atom.getScreenBrightnessChanged().getLevel()); 488 } testSyncState()489 public void testSyncState() throws Exception { 490 if (statsdDisabled()) { 491 return; 492 } 493 final int atomTag = Atom.SYNC_STATE_CHANGED_FIELD_NUMBER; 494 Set<Integer> syncOn = new HashSet<>(Arrays.asList(SyncStateChanged.State.ON_VALUE)); 495 Set<Integer> syncOff = new HashSet<>(Arrays.asList(SyncStateChanged.State.OFF_VALUE)); 496 497 // Add state sets to the list in order. 498 List<Set<Integer>> stateSet = Arrays.asList(syncOn, syncOff, syncOn, syncOff); 499 500 createAndUploadConfig(atomTag, true); 501 allowImmediateSyncs(); 502 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testSyncState"); 503 504 // Sorted list of events in order in which they occurred. 505 List<EventMetricData> data = getEventMetricDataList(); 506 507 // Assert that the events happened in the expected order. 508 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 509 atom -> atom.getSyncStateChanged().getState().getNumber()); 510 } 511 testWakelockState()512 public void testWakelockState() throws Exception { 513 if (statsdDisabled()) { 514 return; 515 } 516 final int atomTag = Atom.WAKELOCK_STATE_CHANGED_FIELD_NUMBER; 517 Set<Integer> wakelockOn = new HashSet<>(Arrays.asList( 518 WakelockStateChanged.State.ACQUIRE_VALUE, 519 WakelockStateChanged.State.CHANGE_ACQUIRE_VALUE)); 520 Set<Integer> wakelockOff = new HashSet<>(Arrays.asList( 521 WakelockStateChanged.State.RELEASE_VALUE, 522 WakelockStateChanged.State.CHANGE_RELEASE_VALUE)); 523 524 final String EXPECTED_TAG = "StatsdPartialWakelock"; 525 final WakeLockLevelEnum EXPECTED_LEVEL = WakeLockLevelEnum.PARTIAL_WAKE_LOCK; 526 527 // Add state sets to the list in order. 528 List<Set<Integer>> stateSet = Arrays.asList(wakelockOn, wakelockOff); 529 530 createAndUploadConfig(atomTag, true); // True: uses attribution. 531 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWakelockState"); 532 533 // Sorted list of events in order in which they occurred. 534 List<EventMetricData> data = getEventMetricDataList(); 535 536 // Assert that the events happened in the expected order. 537 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 538 atom -> atom.getWakelockStateChanged().getState().getNumber()); 539 540 for (EventMetricData event: data) { 541 String tag = event.getAtom().getWakelockStateChanged().getTag(); 542 WakeLockLevelEnum type = event.getAtom().getWakelockStateChanged().getLevel(); 543 assertTrue("Expected tag: " + EXPECTED_TAG + ", but got tag: " + tag, 544 tag.equals(EXPECTED_TAG)); 545 assertTrue("Expected wakelock level: " + EXPECTED_LEVEL + ", but got level: " + type, 546 type == EXPECTED_LEVEL); 547 } 548 } 549 testWakeupAlarm()550 public void testWakeupAlarm() throws Exception { 551 if (statsdDisabled()) { 552 return; 553 } 554 final int atomTag = Atom.WAKEUP_ALARM_OCCURRED_FIELD_NUMBER; 555 556 StatsdConfig.Builder config = createConfigBuilder(); 557 addAtomEvent(config, atomTag, true); // True: uses attribution. 558 559 List<EventMetricData> data = doDeviceMethod("testWakeupAlarm", config); 560 assertTrue(data.size() >= 1); 561 for (int i = 0; i < data.size(); i++) { 562 String tag = data.get(i).getAtom().getWakeupAlarmOccurred().getTag(); 563 assertTrue(tag.equals("*walarm*:android.cts.statsd.testWakeupAlarm")); 564 } 565 } 566 testWifiLock()567 public void testWifiLock() throws Exception { 568 if (statsdDisabled()) { 569 return; 570 } 571 if (!hasFeature(FEATURE_WIFI, true)) return; 572 573 final int atomTag = Atom.WIFI_LOCK_STATE_CHANGED_FIELD_NUMBER; 574 Set<Integer> lockOn = new HashSet<>(Arrays.asList(WifiLockStateChanged.State.ON_VALUE)); 575 Set<Integer> lockOff = new HashSet<>(Arrays.asList(WifiLockStateChanged.State.OFF_VALUE)); 576 577 // Add state sets to the list in order. 578 List<Set<Integer>> stateSet = Arrays.asList(lockOn, lockOff); 579 580 createAndUploadConfig(atomTag, true); // True: uses attribution. 581 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWifiLock"); 582 583 // Sorted list of events in order in which they occurred. 584 List<EventMetricData> data = getEventMetricDataList(); 585 586 // Assert that the events happened in the expected order. 587 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 588 atom -> atom.getWifiLockStateChanged().getState().getNumber()); 589 } 590 testWifiMulticastLock()591 public void testWifiMulticastLock() throws Exception { 592 if (statsdDisabled()) { 593 return; 594 } 595 if (!hasFeature(FEATURE_WIFI, true)) return; 596 597 final int atomTag = Atom.WIFI_MULTICAST_LOCK_STATE_CHANGED_FIELD_NUMBER; 598 Set<Integer> lockOn = new HashSet<>( 599 Arrays.asList(WifiMulticastLockStateChanged.State.ON_VALUE)); 600 Set<Integer> lockOff = new HashSet<>( 601 Arrays.asList(WifiMulticastLockStateChanged.State.OFF_VALUE)); 602 603 // Add state sets to the list in order. 604 List<Set<Integer>> stateSet = Arrays.asList(lockOn, lockOff); 605 606 createAndUploadConfig(atomTag, true); 607 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", "testWifiMulticastLock"); 608 609 // Sorted list of events in order in which they occurred. 610 List<EventMetricData> data = getEventMetricDataList(); 611 612 // Assert that the events happened in the expected order. 613 assertStatesOccurred(stateSet, data, WAIT_TIME_SHORT, 614 atom -> atom.getWifiMulticastLockStateChanged().getState().getNumber()); 615 } 616 testWifiScan()617 public void testWifiScan() throws Exception { 618 if (statsdDisabled()) { 619 return; 620 } 621 if (!hasFeature(FEATURE_WIFI, true)) return; 622 623 final int atom = Atom.WIFI_SCAN_STATE_CHANGED_FIELD_NUMBER; 624 final int key = WifiScanStateChanged.STATE_FIELD_NUMBER; 625 final int stateOn = WifiScanStateChanged.State.ON_VALUE; 626 final int stateOff = WifiScanStateChanged.State.OFF_VALUE; 627 final int minTimeDiffMillis = 250; 628 final int maxTimeDiffMillis = 60_000; 629 final boolean demandExactlyTwo = false; // Two scans are performed, so up to 4 atoms logged. 630 631 List<EventMetricData> data = doDeviceMethodOnOff("testWifiScan", atom, key, 632 stateOn, stateOff, minTimeDiffMillis, maxTimeDiffMillis, demandExactlyTwo); 633 634 assertTrue(data.size() >= 2); 635 assertTrue(data.size() <= 4); 636 WifiScanStateChanged a0 = data.get(0).getAtom().getWifiScanStateChanged(); 637 WifiScanStateChanged a1 = data.get(1).getAtom().getWifiScanStateChanged(); 638 assertTrue(a0.getState().getNumber() == stateOn); 639 assertTrue(a1.getState().getNumber() == stateOff); 640 } 641 testAudioState()642 public void testAudioState() throws Exception { 643 if (statsdDisabled()) { 644 return; 645 } 646 if (!hasFeature(FEATURE_AUDIO_OUTPUT, true)) return; 647 648 final int atomTag = Atom.AUDIO_STATE_CHANGED_FIELD_NUMBER; 649 final String name = "testAudioState"; 650 651 Set<Integer> onState = new HashSet<>( 652 Arrays.asList(AudioStateChanged.State.ON_VALUE)); 653 Set<Integer> offState = new HashSet<>( 654 Arrays.asList(AudioStateChanged.State.OFF_VALUE)); 655 656 // Add state sets to the list in order. 657 List<Set<Integer>> stateSet = Arrays.asList(onState, offState); 658 659 createAndUploadConfig(atomTag, true); // True: uses attribution. 660 Thread.sleep(WAIT_TIME_SHORT); 661 662 runDeviceTests(DEVICE_SIDE_TEST_PACKAGE, ".AtomTests", name); 663 664 Thread.sleep(WAIT_TIME_SHORT); 665 // Sorted list of events in order in which they occurred. 666 List<EventMetricData> data = getEventMetricDataList(); 667 668 // AudioStateChanged timestamp is fuzzed to 5min buckets 669 assertStatesOccurred(stateSet, data, 0, 670 atom -> atom.getAudioStateChanged().getState().getNumber()); 671 } 672 testMediaCodecActivity()673 public void testMediaCodecActivity() throws Exception { 674 if (statsdDisabled()) { 675 return; 676 } 677 if (!hasFeature(FEATURE_WATCH, false)) return; 678 final int atomTag = Atom.MEDIA_CODEC_STATE_CHANGED_FIELD_NUMBER; 679 680 Set<Integer> onState = new HashSet<>( 681 Arrays.asList(MediaCodecStateChanged.State.ON_VALUE)); 682 Set<Integer> offState = new HashSet<>( 683 Arrays.asList(MediaCodecStateChanged.State.OFF_VALUE)); 684 685 // Add state sets to the list in order. 686 List<Set<Integer>> stateSet = Arrays.asList(onState, offState); 687 688 createAndUploadConfig(atomTag, true); // True: uses attribution. 689 Thread.sleep(WAIT_TIME_SHORT); 690 691 runActivity("VideoPlayerActivity", "action", "action.play_video"); 692 693 // Sorted list of events in order in which they occurred. 694 List<EventMetricData> data = getEventMetricDataList(); 695 696 // Assert that the events happened in the expected order. 697 assertStatesOccurred(stateSet, data, WAIT_TIME_LONG, 698 atom -> atom.getMediaCodecStateChanged().getState().getNumber()); 699 } 700 testPictureInPictureState()701 public void testPictureInPictureState() throws Exception { 702 if (statsdDisabled()) { 703 return; 704 } 705 if (!hasFeature(FEATURE_WATCH, false) || 706 !hasFeature(FEATURE_PICTURE_IN_PICTURE, true)) return; 707 final int atomTag = Atom.PICTURE_IN_PICTURE_STATE_CHANGED_FIELD_NUMBER; 708 709 Set<Integer> entered = new HashSet<>( 710 Arrays.asList(PictureInPictureStateChanged.State.ENTERED_VALUE)); 711 712 // Add state sets to the list in order. 713 List<Set<Integer>> stateSet = Arrays.asList(entered); 714 715 createAndUploadConfig(atomTag, false); 716 717 runActivity("VideoPlayerActivity", "action", "action.play_video_picture_in_picture_mode"); 718 719 // Sorted list of events in order in which they occurred. 720 List<EventMetricData> data = getEventMetricDataList(); 721 722 // Assert that the events happened in the expected order. 723 assertStatesOccurred(stateSet, data, WAIT_TIME_LONG, 724 atom -> atom.getPictureInPictureStateChanged().getState().getNumber()); 725 } 726 testAppCrashOccurred()727 public void testAppCrashOccurred() throws Exception { 728 if (statsdDisabled()) { 729 return; 730 } 731 final int atomTag = Atom.APP_CRASH_OCCURRED_FIELD_NUMBER; 732 createAndUploadConfig(atomTag, false); 733 Thread.sleep(WAIT_TIME_SHORT); 734 735 runActivity("StatsdCtsForegroundActivity", "action", "action.crash"); 736 737 Thread.sleep(WAIT_TIME_SHORT); 738 // Sorted list of events in order in which they occurred. 739 List<EventMetricData> data = getEventMetricDataList(); 740 741 AppCrashOccurred atom = data.get(0).getAtom().getAppCrashOccurred(); 742 assertEquals("crash", atom.getEventType()); 743 assertEquals(AppCrashOccurred.InstantApp.FALSE_VALUE, atom.getIsInstantApp().getNumber()); 744 assertEquals(AppCrashOccurred.ForegroundState.FOREGROUND_VALUE, 745 atom.getForegroundState().getNumber()); 746 assertEquals("com.android.server.cts.device.statsd", atom.getPackageName()); 747 } 748 } 749