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 17 package com.android.server.cts.device.statsd; 18 19 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 20 import static com.google.common.truth.Truth.assertWithMessage; 21 22 import android.accounts.Account; 23 import android.accounts.AccountManager; 24 import android.app.ActivityManager; 25 import android.app.ActivityManager.RunningServiceInfo; 26 import android.app.AlarmManager; 27 import android.app.PendingIntent; 28 import android.app.blob.BlobStoreManager; 29 import android.app.job.JobInfo; 30 import android.app.job.JobScheduler; 31 import android.bluetooth.BluetoothAdapter; 32 import android.bluetooth.le.BluetoothLeScanner; 33 import android.bluetooth.le.ScanCallback; 34 import android.bluetooth.le.ScanFilter; 35 import android.bluetooth.le.ScanResult; 36 import android.bluetooth.le.ScanSettings; 37 import android.content.BroadcastReceiver; 38 import android.content.ComponentName; 39 import android.content.ContentResolver; 40 import android.content.Context; 41 import android.content.Intent; 42 import android.content.IntentFilter; 43 import android.content.pm.ApplicationInfo; 44 import android.hardware.camera2.CameraCharacteristics; 45 import android.hardware.camera2.CameraDevice; 46 import android.hardware.camera2.CameraManager; 47 import android.location.GnssStatus; 48 import android.location.Location; 49 import android.location.LocationListener; 50 import android.location.LocationManager; 51 import android.media.MediaPlayer; 52 import android.net.ConnectivityManager; 53 import android.net.Network; 54 import android.net.NetworkCapabilities; 55 import android.net.NetworkRequest; 56 import android.net.cts.util.CtsNetUtils; 57 import android.net.wifi.WifiManager; 58 import android.os.AsyncTask; 59 import android.os.Bundle; 60 import android.os.Handler; 61 import android.os.HandlerThread; 62 import android.os.Looper; 63 import android.os.ParcelFileDescriptor; 64 import android.os.PowerManager; 65 import android.os.Process; 66 import android.os.SystemClock; 67 import android.os.VibrationEffect; 68 import android.os.Vibrator; 69 import android.provider.Settings; 70 import android.text.TextUtils; 71 import android.util.ArrayMap; 72 import android.util.Log; 73 import android.util.StatsEvent; 74 import android.util.StatsLog; 75 import androidx.annotation.NonNull; 76 import androidx.test.InstrumentationRegistry; 77 import com.android.compatibility.common.util.ShellIdentityUtils; 78 import com.google.common.io.BaseEncoding; 79 import java.net.HttpURLConnection; 80 import java.net.URL; 81 import java.util.Arrays; 82 import java.util.List; 83 import java.util.Map; 84 import java.util.concurrent.CompletableFuture; 85 import java.util.concurrent.CountDownLatch; 86 import java.util.concurrent.TimeUnit; 87 import java.util.function.BiConsumer; 88 import org.junit.Test; 89 90 public class AtomTests { 91 private static final String TAG = AtomTests.class.getSimpleName(); 92 93 private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsd"; 94 95 @Test testAudioState()96 public void testAudioState() { 97 // TODO: This should surely be getTargetContext(), here and everywhere, but test first. 98 Context context = InstrumentationRegistry.getContext(); 99 MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.good); 100 mediaPlayer.start(); 101 sleep(2_000); 102 mediaPlayer.stop(); 103 } 104 105 @Test testBleScanOpportunistic()106 public void testBleScanOpportunistic() { 107 ScanSettings scanSettings = new ScanSettings.Builder() 108 .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build(); 109 performBleScan(scanSettings, null,false); 110 } 111 112 @Test testBleScanUnoptimized()113 public void testBleScanUnoptimized() { 114 ScanSettings scanSettings = new ScanSettings.Builder() 115 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 116 performBleScan(scanSettings, null, false); 117 } 118 119 @Test testBleScanResult()120 public void testBleScanResult() { 121 ScanSettings scanSettings = new ScanSettings.Builder() 122 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 123 ScanFilter.Builder scanFilter = new ScanFilter.Builder(); 124 performBleScan(scanSettings, Arrays.asList(scanFilter.build()), true); 125 } 126 127 @Test testBleScanInterrupted()128 public void testBleScanInterrupted() throws Exception { 129 performBleAction((bluetoothAdapter, bleScanner) -> { 130 ScanSettings scanSettings = new ScanSettings.Builder() 131 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 132 ScanCallback scanCallback = new ScanCallback() { 133 @Override 134 public void onScanResult(int callbackType, ScanResult result) { 135 Log.v(TAG, "called onScanResult"); 136 } 137 @Override 138 public void onScanFailed(int errorCode) { 139 Log.v(TAG, "called onScanFailed"); 140 } 141 @Override 142 public void onBatchScanResults(List<ScanResult> results) { 143 Log.v(TAG, "called onBatchScanResults"); 144 } 145 }; 146 147 int uid = Process.myUid(); 148 int whatAtomId = 9_999; 149 150 // Get the current setting for bluetooth background scanning. 151 // Set to 0 if the setting is not found or an error occurs. 152 int initialBleScanGlobalSetting = Settings.Global.getInt( 153 InstrumentationRegistry.getTargetContext().getContentResolver(), 154 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0); 155 156 // Turn off bluetooth background scanning. 157 Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(), 158 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0); 159 160 // Change state to State.ON. 161 bleScanner.startScan(null, scanSettings, scanCallback); 162 sleep(6_000); 163 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 164 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 165 166 bluetoothAdapter.disable(); 167 sleep(6_000); 168 169 // Trigger State.RESET so that new state is State.OFF. 170 if (!bluetoothAdapter.enable()) { 171 Log.e(TAG, "Could not enable bluetooth to trigger state reset"); 172 return; 173 } 174 sleep(6_000); // Wait for Bluetooth to fully turn on. 175 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 176 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 177 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 178 179 // Set bluetooth background scanning to original setting. 180 Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(), 181 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, initialBleScanGlobalSetting); 182 }); 183 } 184 writeSliceByBleScanStateChangedAtom(int atomId, int firstUid, boolean field2, boolean field3, boolean field4)185 private static void writeSliceByBleScanStateChangedAtom(int atomId, int firstUid, 186 boolean field2, boolean field3, 187 boolean field4) { 188 final StatsEvent.Builder builder = StatsEvent.newBuilder() 189 .setAtomId(atomId) 190 .writeAttributionChain(new int[] {firstUid}, new String[] {"tag1"}) 191 .writeBoolean(field2) 192 .writeBoolean(field3) 193 .writeBoolean(field4) 194 .usePooledBuffer(); 195 196 StatsLog.write(builder.build()); 197 } 198 199 /** 200 * Set up BluetoothLeScanner and perform the action in the callback. 201 * Restore Bluetooth to original state afterwards. 202 **/ performBleAction(BiConsumer<BluetoothAdapter, BluetoothLeScanner> actions)203 private static void performBleAction(BiConsumer<BluetoothAdapter, BluetoothLeScanner> actions) { 204 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 205 if (bluetoothAdapter == null) { 206 Log.e(TAG, "Device does not support Bluetooth"); 207 return; 208 } 209 boolean bluetoothEnabledByTest = false; 210 if (!bluetoothAdapter.isEnabled()) { 211 if (!bluetoothAdapter.enable()) { 212 Log.e(TAG, "Bluetooth is not enabled"); 213 return; 214 } 215 sleep(2_000); // Wait for Bluetooth to fully turn on. 216 bluetoothEnabledByTest = true; 217 } 218 BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner(); 219 if (bleScanner == null) { 220 Log.e(TAG, "Cannot access BLE scanner"); 221 return; 222 } 223 224 actions.accept(bluetoothAdapter, bleScanner); 225 226 // Restore adapter state 227 if (bluetoothEnabledByTest) { 228 bluetoothAdapter.disable(); 229 } 230 } 231 232 performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult)233 private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult) { 234 performBleAction((bluetoothAdapter, bleScanner) -> { 235 CountDownLatch resultsLatch = new CountDownLatch(1); 236 ScanCallback scanCallback = new ScanCallback() { 237 @Override 238 public void onScanResult(int callbackType, ScanResult result) { 239 Log.v(TAG, "called onScanResult"); 240 resultsLatch.countDown(); 241 } 242 @Override 243 public void onScanFailed(int errorCode) { 244 Log.v(TAG, "called onScanFailed"); 245 } 246 @Override 247 public void onBatchScanResults(List<ScanResult> results) { 248 Log.v(TAG, "called onBatchScanResults"); 249 resultsLatch.countDown(); 250 } 251 }; 252 253 bleScanner.startScan(scanFilters, scanSettings, scanCallback); 254 if (waitForResult) { 255 waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null); 256 } else { 257 sleep(2_000); 258 } 259 bleScanner.stopScan(scanCallback); 260 }); 261 } 262 263 @Test testCameraState()264 public void testCameraState() throws Exception { 265 Context context = InstrumentationRegistry.getContext(); 266 CameraManager cam = context.getSystemService(CameraManager.class); 267 String[] cameraIds = cam.getCameraIdList(); 268 if (cameraIds.length == 0) { 269 Log.e(TAG, "No camera found on device"); 270 return; 271 } 272 273 CountDownLatch latch = new CountDownLatch(1); 274 final CameraDevice.StateCallback cb = new CameraDevice.StateCallback() { 275 @Override 276 public void onOpened(CameraDevice cd) { 277 Log.i(TAG, "CameraDevice " + cd.getId() + " opened"); 278 sleep(2_000); 279 cd.close(); 280 } 281 @Override 282 public void onClosed(CameraDevice cd) { 283 latch.countDown(); 284 Log.i(TAG, "CameraDevice " + cd.getId() + " closed"); 285 } 286 @Override 287 public void onDisconnected(CameraDevice cd) { 288 Log.w(TAG, "CameraDevice " + cd.getId() + " disconnected"); 289 } 290 @Override 291 public void onError(CameraDevice cd, int error) { 292 Log.e(TAG, "CameraDevice " + cd.getId() + "had error " + error); 293 } 294 }; 295 296 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 297 handlerThread.start(); 298 Looper looper = handlerThread.getLooper(); 299 Handler handler = new Handler(looper); 300 301 cam.openCamera(cameraIds[0], cb, handler); 302 waitForReceiver(context, 10_000, latch, null); 303 } 304 305 @Test testFlashlight()306 public void testFlashlight() throws Exception { 307 Context context = InstrumentationRegistry.getContext(); 308 CameraManager cam = context.getSystemService(CameraManager.class); 309 String[] cameraIds = cam.getCameraIdList(); 310 boolean foundFlash = false; 311 for (int i = 0; i < cameraIds.length; i++) { 312 String id = cameraIds[i]; 313 if(cam.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) { 314 cam.setTorchMode(id, true); 315 sleep(500); 316 cam.setTorchMode(id, false); 317 foundFlash = true; 318 break; 319 } 320 } 321 if(!foundFlash) { 322 Log.e(TAG, "No flashlight found on device"); 323 } 324 } 325 326 @Test testForegroundService()327 public void testForegroundService() throws Exception { 328 Context context = InstrumentationRegistry.getContext(); 329 // The service goes into foreground and exits shortly 330 Intent intent = new Intent(context, StatsdCtsForegroundService.class); 331 context.startService(intent); 332 sleep(500); 333 context.stopService(intent); 334 } 335 336 /** Check if service is running. */ checkIfServiceRunning(Context context, String serviceName)337 public boolean checkIfServiceRunning(Context context, String serviceName) { 338 ActivityManager manager = context.getSystemService(ActivityManager.class); 339 for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 340 if (serviceName.equals(service.service.getClassName()) && service.foreground) { 341 return true; 342 } 343 } 344 return false; 345 } 346 347 @Test testGpsScan()348 public void testGpsScan() { 349 Context context = InstrumentationRegistry.getContext(); 350 final LocationManager locManager = context.getSystemService(LocationManager.class); 351 if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 352 Log.e(TAG, "GPS provider is not enabled"); 353 return; 354 } 355 CountDownLatch latch = new CountDownLatch(1); 356 357 final LocationListener locListener = new LocationListener() { 358 public void onLocationChanged(Location location) { 359 Log.v(TAG, "onLocationChanged: location has been obtained"); 360 } 361 public void onProviderDisabled(String provider) { 362 Log.w(TAG, "onProviderDisabled " + provider); 363 } 364 public void onProviderEnabled(String provider) { 365 Log.w(TAG, "onProviderEnabled " + provider); 366 } 367 public void onStatusChanged(String provider, int status, Bundle extras) { 368 Log.w(TAG, "onStatusChanged " + provider + " " + status); 369 } 370 }; 371 372 new AsyncTask<Void, Void, Void>() { 373 @Override 374 protected Void doInBackground(Void... params) { 375 Looper.prepare(); 376 locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 990, 0, 377 locListener); 378 sleep(1_000); 379 locManager.removeUpdates(locListener); 380 latch.countDown(); 381 return null; 382 } 383 }.execute(); 384 385 waitForReceiver(context, 59_000, latch, null); 386 } 387 388 @Test testGpsStatus()389 public void testGpsStatus() { 390 Context context = InstrumentationRegistry.getContext(); 391 final LocationManager locManager = context.getSystemService(LocationManager.class); 392 393 if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 394 Log.e(TAG, "GPS provider is not enabled"); 395 return; 396 } 397 398 // Time out set to 85 seconds (5 seconds for sleep and a possible 85 seconds if TTFF takes 399 // max time which would be around 90 seconds. 400 // This is based on similar location cts test timeout values. 401 final int TIMEOUT_IN_MSEC = 85_000; 402 final int SLEEP_TIME_IN_MSEC = 5_000; 403 404 final CountDownLatch mLatchNetwork = new CountDownLatch(1); 405 406 final LocationListener locListener = location -> { 407 Log.v(TAG, "onLocationChanged: location has been obtained"); 408 mLatchNetwork.countDown(); 409 }; 410 411 // fetch the networklocation first to make sure the ttff is not flaky 412 if (locManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { 413 Log.i(TAG, "Request Network Location updates."); 414 locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 415 0 /* minTime*/, 416 0 /* minDistance */, 417 locListener, 418 Looper.getMainLooper()); 419 } 420 waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchNetwork, null); 421 422 // TTFF could take up to 90 seconds, thus we need to wait till TTFF does occur if it does 423 // not occur in the first SLEEP_TIME_IN_MSEC 424 final CountDownLatch mLatchTtff = new CountDownLatch(1); 425 426 GnssStatus.Callback gnssStatusCallback = new GnssStatus.Callback() { 427 @Override 428 public void onStarted() { 429 Log.v(TAG, "Gnss Status Listener Started"); 430 } 431 432 @Override 433 public void onStopped() { 434 Log.v(TAG, "Gnss Status Listener Stopped"); 435 } 436 437 @Override 438 public void onFirstFix(int ttffMillis) { 439 Log.v(TAG, "Gnss Status Listener Received TTFF"); 440 mLatchTtff.countDown(); 441 } 442 443 @Override 444 public void onSatelliteStatusChanged(GnssStatus status) { 445 Log.v(TAG, "Gnss Status Listener Received Status Update"); 446 } 447 }; 448 449 boolean gnssStatusCallbackAdded = locManager.registerGnssStatusCallback( 450 gnssStatusCallback, new Handler(Looper.getMainLooper())); 451 if (!gnssStatusCallbackAdded) { 452 // Registration of GnssMeasurements listener has failed, this indicates a platform bug. 453 Log.e(TAG, "Failed to start gnss status callback"); 454 } 455 456 locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 457 0, 458 0 /* minDistance */, 459 locListener, 460 Looper.getMainLooper()); 461 sleep(SLEEP_TIME_IN_MSEC); 462 waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchTtff, null); 463 locManager.removeUpdates(locListener); 464 locManager.unregisterGnssStatusCallback(gnssStatusCallback); 465 } 466 467 @Test testSyncState()468 public void testSyncState() throws Exception { 469 470 Context context = InstrumentationRegistry.getContext(); 471 StatsdAuthenticator.removeAllAccounts(context); 472 AccountManager am = context.getSystemService(AccountManager.class); 473 CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch(); 474 475 Account account = StatsdAuthenticator.getTestAccount(); 476 StatsdAuthenticator.ensureTestAccount(context); 477 sleep(500); 478 479 // Just force set is syncable. 480 ContentResolver.setMasterSyncAutomatically(true); 481 sleep(500); 482 ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1); 483 // Wait for the first (automatic) sync to finish 484 waitForReceiver(context, 120_000, latch, null); 485 486 //Sleep for 500ms, since we assert each start/stop to be ~500ms apart. 487 sleep(500); 488 489 // Request and wait for the second sync to finish 490 latch = StatsdSyncAdapter.resetCountDownLatch(); 491 StatsdSyncAdapter.requestSync(account); 492 waitForReceiver(context, 120_000, latch, null); 493 StatsdAuthenticator.removeAllAccounts(context); 494 } 495 496 @Test testScheduledJob()497 public void testScheduledJob() throws Exception { 498 final ComponentName name = new ComponentName(MY_PACKAGE_NAME, 499 StatsdJobService.class.getName()); 500 501 Context context = InstrumentationRegistry.getContext(); 502 JobScheduler js = context.getSystemService(JobScheduler.class); 503 assertWithMessage("JobScheduler service not available").that(js).isNotNull(); 504 505 JobInfo.Builder builder = new JobInfo.Builder(1, name); 506 builder.setOverrideDeadline(0); 507 JobInfo job = builder.build(); 508 509 long startTime = System.currentTimeMillis(); 510 CountDownLatch latch = StatsdJobService.resetCountDownLatch(); 511 js.schedule(job); 512 waitForReceiver(context, 5_000, latch, null); 513 } 514 515 @Test testVibratorState()516 public void testVibratorState() { 517 Context context = InstrumentationRegistry.getContext(); 518 Vibrator vib = context.getSystemService(Vibrator.class); 519 if (vib.hasVibrator()) { 520 vib.vibrate(VibrationEffect.createOneShot( 521 500 /* ms */, VibrationEffect.DEFAULT_AMPLITUDE)); 522 } 523 } 524 525 @Test testWakelockState()526 public void testWakelockState() { 527 Context context = InstrumentationRegistry.getContext(); 528 PowerManager pm = context.getSystemService(PowerManager.class); 529 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 530 "StatsdPartialWakelock"); 531 wl.acquire(); 532 sleep(500); 533 wl.release(); 534 } 535 536 @Test testSliceByWakelockState()537 public void testSliceByWakelockState() { 538 int uid = Process.myUid(); 539 int whatAtomId = 9_998; 540 int wakelockType = PowerManager.PARTIAL_WAKE_LOCK; 541 String tag = "StatsdPartialWakelock"; 542 543 Context context = InstrumentationRegistry.getContext(); 544 PowerManager pm = context.getSystemService(PowerManager.class); 545 PowerManager.WakeLock wl = pm.newWakeLock(wakelockType, tag); 546 547 wl.acquire(); 548 sleep(500); 549 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 550 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 551 wl.acquire(); 552 sleep(500); 553 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 554 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 555 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 556 wl.release(); 557 sleep(500); 558 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 559 wl.release(); 560 sleep(500); 561 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 562 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 563 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 564 } 565 writeSliceByWakelockStateChangedAtom(int atomId, int firstUid, int field2, String field3)566 private static void writeSliceByWakelockStateChangedAtom(int atomId, int firstUid, 567 int field2, String field3) { 568 final StatsEvent.Builder builder = StatsEvent.newBuilder() 569 .setAtomId(atomId) 570 .writeAttributionChain(new int[] {firstUid}, new String[] {"tag1"}) 571 .writeInt(field2) 572 .writeString(field3) 573 .usePooledBuffer(); 574 575 StatsLog.write(builder.build()); 576 } 577 578 579 @Test testWakelockLoad()580 public void testWakelockLoad() { 581 final int NUM_THREADS = 16; 582 CountDownLatch latch = new CountDownLatch(NUM_THREADS); 583 for (int i = 0; i < NUM_THREADS; i++) { 584 Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch)); 585 t.start(); 586 } 587 waitForReceiver(null, 120_000, latch, null); 588 } 589 590 @Test testWakeupAlarm()591 public void testWakeupAlarm() { 592 Context context = InstrumentationRegistry.getContext(); 593 String name = "android.cts.statsd.testWakeupAlarm"; 594 CountDownLatch onReceiveLatch = new CountDownLatch(1); 595 BroadcastReceiver receiver = 596 registerReceiver(context, onReceiveLatch, new IntentFilter(name)); 597 AlarmManager manager = (AlarmManager) (context.getSystemService(AlarmManager.class)); 598 PendingIntent pintent = PendingIntent.getBroadcast(context, 0, new Intent(name), 0); 599 manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 600 SystemClock.elapsedRealtime() + 2_000, pintent); 601 waitForReceiver(context, 10_000, onReceiveLatch, receiver); 602 } 603 604 @Test testWifiLockHighPerf()605 public void testWifiLockHighPerf() { 606 Context context = InstrumentationRegistry.getContext(); 607 WifiManager wm = context.getSystemService(WifiManager.class); 608 WifiManager.WifiLock lock = 609 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "StatsdCTSWifiLock"); 610 lock.acquire(); 611 sleep(500); 612 lock.release(); 613 } 614 615 @Test testWifiLockLowLatency()616 public void testWifiLockLowLatency() { 617 Context context = InstrumentationRegistry.getContext(); 618 WifiManager wm = context.getSystemService(WifiManager.class); 619 WifiManager.WifiLock lock = 620 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "StatsdCTSWifiLock"); 621 lock.acquire(); 622 sleep(500); 623 lock.release(); 624 } 625 626 @Test testWifiMulticastLock()627 public void testWifiMulticastLock() { 628 Context context = InstrumentationRegistry.getContext(); 629 WifiManager wm = context.getSystemService(WifiManager.class); 630 WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock"); 631 lock.acquire(); 632 sleep(500); 633 lock.release(); 634 } 635 636 @Test 637 /** Does two wifi scans. */ 638 // TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results. testWifiScan()639 public void testWifiScan() { 640 Context context = InstrumentationRegistry.getContext(); 641 IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 642 // Sometimes a scan was already running (from a different uid), so the first scan doesn't 643 // start when requested. Therefore, additionally wait for whatever scan is currently running 644 // to finish, then request a scan again - at least one of these two scans should be 645 // attributed to this app. 646 for (int i = 0; i < 2; i++) { 647 CountDownLatch onReceiveLatch = new CountDownLatch(1); 648 BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter); 649 context.getSystemService(WifiManager.class).startScan(); 650 waitForReceiver(context, 60_000, onReceiveLatch, receiver); 651 } 652 } 653 654 @Test testSimpleCpu()655 public void testSimpleCpu() { 656 long timestamp = System.currentTimeMillis(); 657 for (int i = 0; i < 10000; i ++) { 658 timestamp += i; 659 } 660 Log.i(TAG, "The answer is " + timestamp); 661 } 662 663 /** 664 * Bring up and generate some traffic on cellular data connection. 665 */ 666 @Test testGenerateMobileTraffic()667 public void testGenerateMobileTraffic() throws Exception { 668 final Context context = InstrumentationRegistry.getContext(); 669 doGenerateNetworkTraffic(context, NetworkCapabilities.TRANSPORT_CELLULAR); 670 } 671 672 // Constants which are locally used by doGenerateNetworkTraffic. 673 private static final int NETWORK_TIMEOUT_MILLIS = 15000; 674 private static final String HTTPS_HOST_URL = 675 "https://connectivitycheck.gstatic.com/generate_204"; 676 doGenerateNetworkTraffic(@onNull Context context, int transport)677 private void doGenerateNetworkTraffic(@NonNull Context context, int transport) 678 throws InterruptedException { 679 final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); 680 final NetworkRequest request = new NetworkRequest.Builder().addCapability( 681 NetworkCapabilities.NET_CAPABILITY_INTERNET).addTransportType(transport).build(); 682 final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback(); 683 684 // Request network, and make http query when the network is available. 685 cm.requestNetwork(request, callback); 686 687 // If network is not available, throws IllegalStateException. 688 final Network network = callback.waitForAvailable(); 689 if (network == null) { 690 throw new IllegalStateException("network " + request + " is not available."); 691 } 692 693 final long startTime = SystemClock.elapsedRealtime(); 694 try { 695 exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL)); 696 Log.i(TAG, "exerciseRemoteHost successful in " + (SystemClock.elapsedRealtime() 697 - startTime) + " ms"); 698 } catch (Exception e) { 699 Log.e(TAG, "exerciseRemoteHost failed in " + (SystemClock.elapsedRealtime() 700 - startTime) + " ms: " + e); 701 } finally { 702 cm.unregisterNetworkCallback(callback); 703 } 704 } 705 706 /** 707 * Generate traffic on specified network. 708 */ exerciseRemoteHost(@onNull ConnectivityManager cm, @NonNull Network network, @NonNull URL url)709 private void exerciseRemoteHost(@NonNull ConnectivityManager cm, @NonNull Network network, 710 @NonNull URL url) throws Exception { 711 cm.bindProcessToNetwork(network); 712 HttpURLConnection urlc = null; 713 try { 714 urlc = (HttpURLConnection) network.openConnection(url); 715 urlc.setConnectTimeout(NETWORK_TIMEOUT_MILLIS); 716 urlc.setUseCaches(false); 717 urlc.connect(); 718 } finally { 719 if (urlc != null) { 720 urlc.disconnect(); 721 } 722 } 723 } 724 725 // Constants for testBlobStore 726 private static final long BLOB_COMMIT_CALLBACK_TIMEOUT_SEC = 5; 727 private static final long BLOB_EXPIRY_DURATION_MS = 24 * 60 * 60 * 1000; 728 private static final long BLOB_FILE_SIZE_BYTES = 23 * 1024L; 729 private static final long BLOB_LEASE_EXPIRY_DURATION_MS = 60 * 60 * 1000; 730 private static final byte[] FAKE_PKG_CERT_SHA256 = BaseEncoding.base16().decode( 731 "187E3D3172F2177D6FEC2EA53785BF1E25DFF7B2E5F6E59807E365A7A837E6C3"); 732 733 // ------- Helper methods 734 735 /** Puts the current thread to sleep. */ sleep(int millis)736 static void sleep(int millis) { 737 try { 738 Thread.sleep(millis); 739 } catch (InterruptedException e) { 740 Log.e(TAG, "Interrupted exception while sleeping", e); 741 } 742 } 743 744 /** Register receiver to determine when given action is complete. */ registerReceiver( Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter)745 private static BroadcastReceiver registerReceiver( 746 Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) { 747 BroadcastReceiver receiver = new BroadcastReceiver() { 748 @Override 749 public void onReceive(Context context, Intent intent) { 750 Log.d(TAG, "Received broadcast."); 751 onReceiveLatch.countDown(); 752 } 753 }; 754 // Run Broadcast receiver in a different thread since the main thread will wait. 755 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 756 handlerThread.start(); 757 Looper looper = handlerThread.getLooper(); 758 Handler handler = new Handler(looper); 759 ctx.registerReceiver(receiver, intentFilter, null, handler); 760 return receiver; 761 } 762 763 /** 764 * Uses the receiver to wait until the action is complete. ctx and receiver may be null if no 765 * receiver is needed to be unregistered. 766 */ waitForReceiver(Context ctx, int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver)767 private static void waitForReceiver(Context ctx, 768 int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) { 769 try { 770 boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS); 771 if (didFinish) { 772 Log.v(TAG, "Finished performing action"); 773 } else { 774 // This is not necessarily a problem. If we just want to make sure a count was 775 // recorded for the request, it doesn't matter if the action actually finished. 776 Log.w(TAG, "Did not finish in specified time."); 777 } 778 } catch (InterruptedException e) { 779 Log.e(TAG, "Interrupted exception while awaiting action to finish", e); 780 } 781 if (ctx != null && receiver != null) { 782 ctx.unregisterReceiver(receiver); 783 } 784 } 785 setScreenBrightness(int brightness)786 private static void setScreenBrightness(int brightness) { 787 runShellCommand("settings put system screen_brightness " + brightness); 788 } 789 } 790