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.statsdatom; 18 19 import static com.android.compatibility.common.util.SystemUtil.runShellCommand; 20 21 import static com.google.common.truth.Truth.assertThat; 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import static org.junit.Assert.assertNotNull; 25 import static org.junit.Assume.assumeNotNull; 26 27 import android.accounts.Account; 28 import android.accounts.AccountManager; 29 import android.app.ActivityManager; 30 import android.app.ActivityManager.RunningServiceInfo; 31 import android.app.AppOpsManager; 32 import android.app.GameManager; 33 import android.app.GameModeConfiguration; 34 import android.app.GameState; 35 import android.app.job.JobInfo; 36 import android.app.job.JobScheduler; 37 import android.app.usage.NetworkStatsManager; 38 import android.bluetooth.le.BluetoothLeScanner; 39 import android.bluetooth.le.ScanCallback; 40 import android.bluetooth.le.ScanFilter; 41 import android.bluetooth.le.ScanResult; 42 import android.bluetooth.le.ScanSettings; 43 import android.bluetooth.test_utils.BlockingBluetoothAdapter; 44 import android.bluetooth.test_utils.EnableBluetoothRule; 45 import android.content.BroadcastReceiver; 46 import android.content.ComponentName; 47 import android.content.ContentResolver; 48 import android.content.Context; 49 import android.content.Intent; 50 import android.content.IntentFilter; 51 import android.content.pm.PackageManager; 52 import android.hardware.camera2.CameraCharacteristics; 53 import android.hardware.camera2.CameraDevice; 54 import android.hardware.camera2.CameraManager; 55 import android.location.GnssStatus; 56 import android.location.Location; 57 import android.location.LocationListener; 58 import android.location.LocationManager; 59 import android.media.MediaDrm; 60 import android.media.MediaPlayer; 61 import android.net.ConnectivityManager; 62 import android.net.Network; 63 import android.net.NetworkCapabilities; 64 import android.net.NetworkRequest; 65 import android.net.cts.util.CtsNetUtils; 66 import android.net.wifi.WifiManager; 67 import android.os.AsyncTask; 68 import android.os.Bundle; 69 import android.os.Handler; 70 import android.os.HandlerThread; 71 import android.os.Looper; 72 import android.os.PowerManager; 73 import android.os.Process; 74 import android.os.RemoteException; 75 import android.os.SystemClock; 76 import android.os.VibrationEffect; 77 import android.os.Vibrator; 78 import android.provider.Settings; 79 import android.text.TextUtils; 80 import android.util.Log; 81 import android.util.StatsEvent; 82 import android.util.StatsLog; 83 84 import androidx.annotation.NonNull; 85 import androidx.test.InstrumentationRegistry; 86 import androidx.test.ext.junit.runners.AndroidJUnit4; 87 88 import com.android.compatibility.common.util.PollingCheck; 89 import com.android.compatibility.common.util.ShellIdentityUtils; 90 91 import libcore.javax.net.ssl.TestSSLContext; 92 import libcore.javax.net.ssl.TestSSLSocketPair; 93 94 import org.junit.Assert; 95 import org.junit.ClassRule; 96 import org.junit.Test; 97 import org.junit.runner.RunWith; 98 99 import java.net.HttpURLConnection; 100 import java.net.URL; 101 import java.util.Arrays; 102 import java.util.List; 103 import java.util.UUID; 104 import java.util.concurrent.CountDownLatch; 105 import java.util.concurrent.TimeUnit; 106 107 import javax.net.ssl.SSLSocket; 108 109 @RunWith(AndroidJUnit4.class) 110 public class AtomTests { 111 @ClassRule 112 public static final EnableBluetoothRule sEnableBluetoothRule = new EnableBluetoothRule(); 113 114 private static final String TAG = AtomTests.class.getSimpleName(); 115 116 private static final String MY_PACKAGE_NAME = "com.android.server.cts.device.statsdatom"; 117 118 @Test testTlsHandshake()119 public void testTlsHandshake() throws Exception { 120 TestSSLContext context = TestSSLContext.create(); 121 SSLSocket[] sockets = TestSSLSocketPair.connect(context, null, null); 122 123 if (sockets.length < 2) { 124 return; 125 } 126 sockets[0].getOutputStream().write(42); 127 Assert.assertEquals(42, sockets[1].getInputStream().read()); 128 sockets[0].close(); 129 sockets[1].close(); 130 } 131 132 @Test 133 // Start the isolated service, which logs an AppBreadcrumbReported atom, and then exit. testIsolatedProcessService()134 public void testIsolatedProcessService() throws Exception { 135 Context context = InstrumentationRegistry.getContext(); 136 Intent intent = new Intent(context, IsolatedProcessService.class); 137 context.startService(intent); 138 sleep(2_000); 139 context.stopService(intent); 140 } 141 142 @Test testAudioState()143 public void testAudioState() { 144 // TODO: This should surely be getTargetContext(), here and everywhere, but test first. 145 Context context = InstrumentationRegistry.getContext(); 146 MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.good); 147 mediaPlayer.start(); 148 sleep(2_000); 149 mediaPlayer.stop(); 150 } 151 152 @Test testBleScanOpportunistic()153 public void testBleScanOpportunistic() { 154 ScanSettings scanSettings = new ScanSettings.Builder() 155 .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build(); 156 performBleScan(scanSettings, null, false); 157 } 158 159 @Test testBleScanUnoptimized()160 public void testBleScanUnoptimized() { 161 ScanSettings scanSettings = new ScanSettings.Builder() 162 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 163 performBleScan(scanSettings, null, false); 164 } 165 166 @Test testBleScanResult()167 public void testBleScanResult() { 168 ScanSettings scanSettings = new ScanSettings.Builder() 169 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 170 ScanFilter.Builder scanFilter = new ScanFilter.Builder(); 171 performBleScan(scanSettings, Arrays.asList(scanFilter.build()), true); 172 } 173 174 @Test testBleScanInterrupted()175 public void testBleScanInterrupted() throws Exception { 176 BluetoothLeScanner bleScanner = sEnableBluetoothRule.mAdapter.getBluetoothLeScanner(); 177 assertThat(bleScanner).isNotNull(); 178 ScanSettings scanSettings = new ScanSettings.Builder() 179 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 180 ScanCallback scanCallback = new ScanCallback() { 181 @Override 182 public void onScanResult(int callbackType, ScanResult result) { 183 Log.v(TAG, "called onScanResult"); 184 } 185 186 @Override 187 public void onScanFailed(int errorCode) { 188 Log.v(TAG, "called onScanFailed"); 189 } 190 191 @Override 192 public void onBatchScanResults(List<ScanResult> results) { 193 Log.v(TAG, "called onBatchScanResults"); 194 } 195 }; 196 197 int uid = Process.myUid(); 198 int whatAtomId = 9_999; 199 200 // Get the current setting for bluetooth background scanning. 201 // Set to 0 if the setting is not found or an error occurs. 202 int initialBleScanGlobalSetting = Settings.Global.getInt( 203 InstrumentationRegistry.getTargetContext().getContentResolver(), 204 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0); 205 206 // Turn off bluetooth background scanning. 207 Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(), 208 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, 0); 209 210 // Change state to State.ON. 211 bleScanner.startScan(null, scanSettings, scanCallback); 212 sleep(6_000); 213 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 214 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 215 216 assertThat(BlockingBluetoothAdapter.disable(true)).isTrue(); 217 assertThat(BlockingBluetoothAdapter.enable()).isTrue(); 218 219 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 220 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 221 writeSliceByBleScanStateChangedAtom(whatAtomId, uid, false, false, false); 222 223 // Set bluetooth background scanning to original setting. 224 Settings.Global.putInt(InstrumentationRegistry.getTargetContext().getContentResolver(), 225 Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE, initialBleScanGlobalSetting); 226 } 227 writeSliceByBleScanStateChangedAtom(int atomId, int firstUid, boolean field2, boolean field3, boolean field4)228 private static void writeSliceByBleScanStateChangedAtom(int atomId, int firstUid, 229 boolean field2, boolean field3, 230 boolean field4) { 231 final StatsEvent.Builder builder = StatsEvent.newBuilder() 232 .setAtomId(atomId) 233 .writeAttributionChain(new int[]{firstUid}, new String[]{"tag1"}) 234 .writeBoolean(field2) 235 .writeBoolean(field3) 236 .writeBoolean(field4) 237 .usePooledBuffer(); 238 239 StatsLog.write(builder.build()); 240 } 241 performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult)242 private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, 243 boolean waitForResult) { 244 BluetoothLeScanner bleScanner = sEnableBluetoothRule.mAdapter.getBluetoothLeScanner(); 245 assertThat(bleScanner).isNotNull(); 246 CountDownLatch resultsLatch = new CountDownLatch(1); 247 ScanCallback scanCallback = new ScanCallback() { 248 @Override 249 public void onScanResult(int callbackType, ScanResult result) { 250 Log.v(TAG, "called onScanResult"); 251 resultsLatch.countDown(); 252 } 253 254 @Override 255 public void onScanFailed(int errorCode) { 256 Log.v(TAG, "called onScanFailed"); 257 } 258 259 @Override 260 public void onBatchScanResults(List<ScanResult> results) { 261 Log.v(TAG, "called onBatchScanResults"); 262 resultsLatch.countDown(); 263 } 264 }; 265 266 bleScanner.startScan(scanFilters, scanSettings, scanCallback); 267 if (waitForResult) { 268 waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null); 269 } else { 270 sleep(2_000); 271 } 272 bleScanner.stopScan(scanCallback); 273 } 274 275 @Test testCameraState()276 public void testCameraState() throws Exception { 277 Context context = InstrumentationRegistry.getContext(); 278 CameraManager cam = context.getSystemService(CameraManager.class); 279 String[] cameraIds = cam.getCameraIdList(); 280 if (cameraIds.length == 0) { 281 Log.e(TAG, "No camera found on device"); 282 return; 283 } 284 285 CountDownLatch latch = new CountDownLatch(1); 286 final CameraDevice.StateCallback cb = new CameraDevice.StateCallback() { 287 @Override 288 public void onOpened(CameraDevice cd) { 289 Log.i(TAG, "CameraDevice " + cd.getId() + " opened"); 290 sleep(2_000); 291 cd.close(); 292 } 293 294 @Override 295 public void onClosed(CameraDevice cd) { 296 latch.countDown(); 297 Log.i(TAG, "CameraDevice " + cd.getId() + " closed"); 298 } 299 300 @Override 301 public void onDisconnected(CameraDevice cd) { 302 Log.w(TAG, "CameraDevice " + cd.getId() + " disconnected"); 303 } 304 305 @Override 306 public void onError(CameraDevice cd, int error) { 307 Log.e(TAG, "CameraDevice " + cd.getId() + "had error " + error); 308 } 309 }; 310 311 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 312 handlerThread.start(); 313 Looper looper = handlerThread.getLooper(); 314 Handler handler = new Handler(looper); 315 316 cam.openCamera(cameraIds[0], cb, handler); 317 waitForReceiver(context, 10_000, latch, null); 318 } 319 320 @Test testFlashlight()321 public void testFlashlight() throws Exception { 322 Context context = InstrumentationRegistry.getContext(); 323 CameraManager cam = context.getSystemService(CameraManager.class); 324 String[] cameraIds = cam.getCameraIdList(); 325 boolean foundFlash = false; 326 for (int i = 0; i < cameraIds.length; i++) { 327 String id = cameraIds[i]; 328 if (cam.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) { 329 cam.setTorchMode(id, true); 330 sleep(500); 331 cam.setTorchMode(id, false); 332 foundFlash = true; 333 break; 334 } 335 } 336 if (!foundFlash) { 337 Log.e(TAG, "No flashlight found on device"); 338 } 339 } 340 341 @Test testForegroundService()342 public void testForegroundService() throws Exception { 343 Context context = InstrumentationRegistry.getContext(); 344 // The service goes into foreground and exits shortly 345 Intent intent = new Intent(context, StatsdCtsForegroundService.class); 346 context.startService(intent); 347 sleep(500); 348 context.stopService(intent); 349 } 350 351 @Test testForegroundServiceAccessAppOp()352 public void testForegroundServiceAccessAppOp() throws Exception { 353 Context context = InstrumentationRegistry.getContext(); 354 Intent fgsIntent = new Intent(context, StatsdCtsForegroundService.class); 355 AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 356 357 // No foreground service session 358 noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION); 359 sleep(500); 360 361 // Foreground service session 1 362 context.startService(fgsIntent); 363 while (!checkIfServiceRunning(context, StatsdCtsForegroundService.class.getName())) { 364 sleep(50); 365 } 366 noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA); 367 noteAppOp(appOpsManager, AppOpsManager.OPSTR_FINE_LOCATION); 368 noteAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA); 369 startAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO); 370 noteAppOp(appOpsManager, AppOpsManager.OPSTR_RECORD_AUDIO); 371 startAppOp(appOpsManager, AppOpsManager.OPSTR_CAMERA); 372 sleep(500); 373 context.stopService(fgsIntent); 374 375 // No foreground service session 376 noteAppOp(appOpsManager, AppOpsManager.OPSTR_COARSE_LOCATION); 377 sleep(500); 378 379 // TODO(b/149098800): Start fgs a second time and log OPSTR_CAMERA again 380 } 381 382 @Test testAppOps()383 public void testAppOps() throws Exception { 384 Context context = InstrumentationRegistry.getContext(); 385 AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class); 386 String[] opsList = AppOpsManager.getOpStrs(); 387 388 for (int i = 0; i < opsList.length; i++) { 389 String op = opsList[i]; 390 if (TextUtils.isEmpty(op) || op.startsWith("android:deprecated")) { 391 // Operation removed/deprecated 392 continue; 393 } 394 try { 395 noteAppOp(appOpsManager, opsList[i]); 396 } catch (SecurityException e) { 397 } 398 } 399 } 400 noteAppOp(AppOpsManager aom, String opStr)401 private void noteAppOp(AppOpsManager aom, String opStr) { 402 aom.noteOp(opStr, android.os.Process.myUid(), MY_PACKAGE_NAME, null, "statsdTest"); 403 } 404 startAppOp(AppOpsManager aom, String opStr)405 private void startAppOp(AppOpsManager aom, String opStr) { 406 aom.startOp(opStr, android.os.Process.myUid(), MY_PACKAGE_NAME, null, "statsdTest"); 407 } 408 409 /** Check if service is running. */ checkIfServiceRunning(Context context, String serviceName)410 public boolean checkIfServiceRunning(Context context, String serviceName) { 411 ActivityManager manager = context.getSystemService(ActivityManager.class); 412 for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { 413 if (serviceName.equals(service.service.getClassName()) && service.foreground) { 414 return true; 415 } 416 } 417 return false; 418 } 419 420 @Test testGpsScan()421 public void testGpsScan() { 422 Context context = InstrumentationRegistry.getContext(); 423 final LocationManager locManager = context.getSystemService(LocationManager.class); 424 if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 425 Log.e(TAG, "GPS provider is not enabled"); 426 return; 427 } 428 CountDownLatch latch = new CountDownLatch(1); 429 430 final LocationListener locListener = new LocationListener() { 431 public void onLocationChanged(Location location) { 432 Log.v(TAG, "onLocationChanged: location has been obtained"); 433 } 434 435 public void onProviderDisabled(String provider) { 436 Log.w(TAG, "onProviderDisabled " + provider); 437 } 438 439 public void onProviderEnabled(String provider) { 440 Log.w(TAG, "onProviderEnabled " + provider); 441 } 442 443 public void onStatusChanged(String provider, int status, Bundle extras) { 444 Log.w(TAG, "onStatusChanged " + provider + " " + status); 445 } 446 }; 447 448 new AsyncTask<Void, Void, Void>() { 449 @Override 450 protected Void doInBackground(Void... params) { 451 Looper.prepare(); 452 locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 990, 0, 453 locListener); 454 sleep(1_000); 455 locManager.removeUpdates(locListener); 456 latch.countDown(); 457 return null; 458 } 459 }.execute(); 460 461 waitForReceiver(context, 59_000, latch, null); 462 } 463 464 @Test testGpsStatus()465 public void testGpsStatus() { 466 Context context = InstrumentationRegistry.getContext(); 467 final LocationManager locManager = context.getSystemService(LocationManager.class); 468 469 if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 470 Log.e(TAG, "GPS provider is not enabled"); 471 return; 472 } 473 474 // Time out set to 85 seconds (5 seconds for sleep and a possible 85 seconds if TTFF takes 475 // max time which would be around 90 seconds. 476 // This is based on similar location cts test timeout values. 477 final int TIMEOUT_IN_MSEC = 85_000; 478 final int SLEEP_TIME_IN_MSEC = 5_000; 479 480 final CountDownLatch mLatchNetwork = new CountDownLatch(1); 481 482 final LocationListener locListener = location -> { 483 Log.v(TAG, "onLocationChanged: location has been obtained"); 484 mLatchNetwork.countDown(); 485 }; 486 487 // fetch the networklocation first to make sure the ttff is not flaky 488 if (locManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { 489 Log.i(TAG, "Request Network Location updates."); 490 locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 491 0 /* minTime*/, 492 0 /* minDistance */, 493 locListener, 494 Looper.getMainLooper()); 495 } 496 waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchNetwork, null); 497 498 // TTFF could take up to 90 seconds, thus we need to wait till TTFF does occur if it does 499 // not occur in the first SLEEP_TIME_IN_MSEC 500 final CountDownLatch mLatchTtff = new CountDownLatch(1); 501 502 GnssStatus.Callback gnssStatusCallback = new GnssStatus.Callback() { 503 @Override 504 public void onStarted() { 505 Log.v(TAG, "Gnss Status Listener Started"); 506 } 507 508 @Override 509 public void onStopped() { 510 Log.v(TAG, "Gnss Status Listener Stopped"); 511 } 512 513 @Override 514 public void onFirstFix(int ttffMillis) { 515 Log.v(TAG, "Gnss Status Listener Received TTFF"); 516 mLatchTtff.countDown(); 517 } 518 519 @Override 520 public void onSatelliteStatusChanged(GnssStatus status) { 521 Log.v(TAG, "Gnss Status Listener Received Status Update"); 522 } 523 }; 524 525 boolean gnssStatusCallbackAdded = locManager.registerGnssStatusCallback( 526 gnssStatusCallback, new Handler(Looper.getMainLooper())); 527 if (!gnssStatusCallbackAdded) { 528 // Registration of GnssMeasurements listener has failed, this indicates a platform bug. 529 Log.e(TAG, "Failed to start gnss status callback"); 530 } 531 532 locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 533 0, 534 0 /* minDistance */, 535 locListener, 536 Looper.getMainLooper()); 537 sleep(SLEEP_TIME_IN_MSEC); 538 waitForReceiver(context, TIMEOUT_IN_MSEC, mLatchTtff, null); 539 locManager.removeUpdates(locListener); 540 locManager.unregisterGnssStatusCallback(gnssStatusCallback); 541 } 542 543 @Test testScreenBrightness()544 public void testScreenBrightness() { 545 Context context = InstrumentationRegistry.getContext(); 546 PowerManager pm = context.getSystemService(PowerManager.class); 547 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | 548 PowerManager.ACQUIRE_CAUSES_WAKEUP, "StatsdBrightnessTest"); 549 wl.acquire(); 550 sleep(500); 551 552 setScreenBrightness(47); 553 sleep(500); 554 setScreenBrightness(70); 555 sleep(500); 556 557 558 wl.release(); 559 } 560 561 @Test testSyncState()562 public void testSyncState() throws Exception { 563 564 Context context = InstrumentationRegistry.getContext(); 565 StatsdAuthenticator.removeAllAccounts(context); 566 AccountManager am = context.getSystemService(AccountManager.class); 567 CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch(); 568 569 Account account = StatsdAuthenticator.getTestAccount(); 570 StatsdAuthenticator.ensureTestAccount(context); 571 sleep(500); 572 573 // Just force set is syncable. 574 ContentResolver.setMasterSyncAutomatically(true); 575 sleep(500); 576 ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1); 577 // Wait for the first (automatic) sync to finish 578 waitForReceiver(context, 120_000, latch, null); 579 580 //Sleep for 500ms, since we assert each start/stop to be ~500ms apart. 581 sleep(500); 582 583 // Request and wait for the second sync to finish 584 latch = StatsdSyncAdapter.resetCountDownLatch(); 585 StatsdSyncAdapter.requestSync(account); 586 waitForReceiver(context, 120_000, latch, null); 587 StatsdAuthenticator.removeAllAccounts(context); 588 } 589 590 @Test testScheduledJob()591 public void testScheduledJob() throws Exception { 592 final ComponentName name = new ComponentName(MY_PACKAGE_NAME, 593 StatsdJobService.class.getName()); 594 595 Context context = InstrumentationRegistry.getContext(); 596 JobScheduler js = context.getSystemService(JobScheduler.class); 597 assertWithMessage("JobScheduler service not available").that(js).isNotNull(); 598 599 JobInfo.Builder builder = new JobInfo.Builder(1, name); 600 builder.setOverrideDeadline(0); 601 JobInfo job = builder.build(); 602 603 CountDownLatch latch = StatsdJobService.resetCountDownLatch(); 604 js.schedule(job); 605 waitForReceiver(context, 5_000, latch, null); 606 } 607 608 @Test testScheduledJob_CancelledJob()609 public void testScheduledJob_CancelledJob() throws Exception { 610 final ComponentName name = new ComponentName(MY_PACKAGE_NAME, 611 StatsdJobService.class.getName()); 612 613 Context context = InstrumentationRegistry.getContext(); 614 JobScheduler js = context.getSystemService(JobScheduler.class); 615 assertWithMessage("JobScheduler service not available").that(js).isNotNull(); 616 617 JobInfo.Builder builder = new JobInfo.Builder(1, name); 618 builder.setMinimumLatency(60_000L); 619 JobInfo job = builder.build(); 620 621 js.schedule(job); 622 js.cancel(1); 623 } 624 625 @Test testScheduledJobPriority()626 public void testScheduledJobPriority() throws Exception { 627 final ComponentName name = 628 new ComponentName(MY_PACKAGE_NAME, StatsdJobService.class.getName()); 629 630 Context context = InstrumentationRegistry.getContext(); 631 JobScheduler js = context.getSystemService(JobScheduler.class); 632 assertWithMessage("JobScheduler service not available").that(js).isNotNull(); 633 634 final int[] priorities = { 635 JobInfo.PRIORITY_HIGH, JobInfo.PRIORITY_DEFAULT, 636 JobInfo.PRIORITY_LOW, JobInfo.PRIORITY_MIN}; 637 for (int priority : priorities) { 638 JobInfo job = new JobInfo.Builder(priority, name) 639 .setOverrideDeadline(0) 640 .setPriority(priority) 641 .build(); 642 643 CountDownLatch latch = StatsdJobService.resetCountDownLatch(); 644 js.schedule(job); 645 waitForReceiver(context, 5_000, latch, null); 646 } 647 } 648 649 @Test testVibratorState()650 public void testVibratorState() { 651 Context context = InstrumentationRegistry.getContext(); 652 Vibrator vib = context.getSystemService(Vibrator.class); 653 if (vib.hasVibrator()) { 654 vib.vibrate(VibrationEffect.createOneShot( 655 500 /* ms */, VibrationEffect.DEFAULT_AMPLITUDE)); 656 } 657 // Sleep so that the app does not get killed. 658 sleep(1000); 659 } 660 661 @Test testWakelockState()662 public void testWakelockState() { 663 Context context = InstrumentationRegistry.getContext(); 664 PowerManager pm = context.getSystemService(PowerManager.class); 665 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 666 "StatsdPartialWakelock"); 667 wl.acquire(); 668 sleep(500); 669 wl.release(); 670 } 671 672 @Test testSliceByWakelockState()673 public void testSliceByWakelockState() { 674 int uid = Process.myUid(); 675 int whatAtomId = 9_998; 676 int wakelockType = PowerManager.PARTIAL_WAKE_LOCK; 677 String tag = "StatsdPartialWakelock"; 678 679 Context context = InstrumentationRegistry.getContext(); 680 PowerManager pm = context.getSystemService(PowerManager.class); 681 PowerManager.WakeLock wl = pm.newWakeLock(wakelockType, tag); 682 683 wl.acquire(); 684 sleep(500); 685 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 686 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 687 wl.acquire(); 688 sleep(500); 689 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 690 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 691 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 692 wl.release(); 693 sleep(500); 694 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 695 wl.release(); 696 sleep(500); 697 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 698 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 699 writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag); 700 } 701 writeSliceByWakelockStateChangedAtom(int atomId, int firstUid, int field2, String field3)702 private static void writeSliceByWakelockStateChangedAtom(int atomId, int firstUid, 703 int field2, String field3) { 704 final StatsEvent.Builder builder = StatsEvent.newBuilder() 705 .setAtomId(atomId) 706 .writeAttributionChain(new int[]{firstUid}, new String[]{"tag1"}) 707 .writeInt(field2) 708 .writeString(field3) 709 .usePooledBuffer(); 710 711 StatsLog.write(builder.build()); 712 } 713 714 @Test testWakelockLoad()715 public void testWakelockLoad() { 716 final int NUM_THREADS = 16; 717 CountDownLatch latch = new CountDownLatch(NUM_THREADS); 718 for (int i = 0; i < NUM_THREADS; i++) { 719 Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch)); 720 t.start(); 721 } 722 waitForReceiver(null, 120_000, latch, null); 723 } 724 725 @Test testWifiLockHighPerf()726 public void testWifiLockHighPerf() throws Exception { 727 Context context = InstrumentationRegistry.getContext(); 728 boolean wifiConnected = isWifiConnected(context); 729 Assert.assertTrue( 730 "Wifi is not connected. The test expects Wifi to be connected before the run", 731 wifiConnected); 732 733 WifiManager wm = context.getSystemService(WifiManager.class); 734 WifiManager.WifiLock lock = 735 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "StatsdCTSWifiLock"); 736 lock.acquire(); 737 sleep(500); 738 lock.release(); 739 } 740 741 @Test testWifiConnected()742 public void testWifiConnected() throws Exception { 743 Context context = InstrumentationRegistry.getContext(); 744 boolean wifiConnected = isWifiConnected(context); 745 Assert.assertTrue( 746 "Wifi is not connected. The test expects Wifi to be connected before the run", 747 wifiConnected); 748 } 749 750 @Test testWifiMulticastLock()751 public void testWifiMulticastLock() { 752 Context context = InstrumentationRegistry.getContext(); 753 WifiManager wm = context.getSystemService(WifiManager.class); 754 WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock"); 755 lock.acquire(); 756 sleep(500); 757 lock.release(); 758 } 759 760 @Test 761 /** Does two wifi scans. */ 762 // TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results. testWifiScan()763 public void testWifiScan() { 764 Context context = InstrumentationRegistry.getContext(); 765 IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 766 // Sometimes a scan was already running (from a different uid), so the first scan doesn't 767 // start when requested. Therefore, additionally wait for whatever scan is currently running 768 // to finish, then request a scan again - at least one of these two scans should be 769 // attributed to this app. 770 for (int i = 0; i < 2; i++) { 771 CountDownLatch onReceiveLatch = new CountDownLatch(1); 772 BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter); 773 context.getSystemService(WifiManager.class).startScan(); 774 waitForReceiver(context, 60_000, onReceiveLatch, receiver); 775 } 776 } 777 778 @Test testWifiReconnect()779 public void testWifiReconnect() throws Exception { 780 Context context = InstrumentationRegistry.getContext(); 781 boolean wifiConnected = isWifiConnected(context); 782 Assert.assertTrue( 783 "Wifi is not connected. The test expects Wifi to be connected before the run", 784 wifiConnected); 785 786 wifiDisconnect(context); 787 sleep(500); 788 wifiReconnect(context); 789 sleep(500); 790 } 791 792 @Test testSimpleCpu()793 public void testSimpleCpu() { 794 long timestamp = System.currentTimeMillis(); 795 for (int i = 0; i < 10000; i++) { 796 timestamp += i; 797 } 798 Log.i(TAG, "The answer is " + timestamp); 799 } 800 801 /** 802 * Bring up and generate some traffic on cellular data connection. 803 */ 804 @Test testGenerateMobileTraffic()805 public void testGenerateMobileTraffic() throws Exception { 806 final Context context = InstrumentationRegistry.getContext(); 807 doGenerateNetworkTraffic(context, NetworkCapabilities.TRANSPORT_CELLULAR); 808 } 809 810 /** 811 * Force poll NetworkStatsService to get most updated network stats from lower layer. 812 */ 813 @Test testForcePollNetworkStats()814 public void testForcePollNetworkStats() throws Exception { 815 final Context context = InstrumentationRegistry.getContext(); 816 final NetworkStatsManager nsm = context.getSystemService(NetworkStatsManager.class); 817 try { 818 nsm.setPollForce(true); 819 // This query is for triggering force poll NetworkStatsService. 820 nsm.querySummaryForUser(ConnectivityManager.TYPE_WIFI, null, Long.MIN_VALUE, 821 Long.MAX_VALUE); 822 } catch (RemoteException e) { 823 Log.e(TAG, "doPollNetworkStats failed with " + e); 824 } 825 } 826 827 // Constants which are locally used by doGenerateNetworkTraffic. 828 private static final int NETWORK_TIMEOUT_MILLIS = 15000; 829 private static final String HTTPS_HOST_URL = 830 "https://connectivitycheck.gstatic.com/generate_204"; 831 doGenerateNetworkTraffic(@onNull Context context, int transport)832 private void doGenerateNetworkTraffic(@NonNull Context context, int transport) 833 throws InterruptedException { 834 final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class); 835 final NetworkRequest request = new NetworkRequest.Builder().addCapability( 836 NetworkCapabilities.NET_CAPABILITY_INTERNET).addTransportType(transport).build(); 837 final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback(); 838 839 // Request network, and make http query when the network is available. 840 cm.requestNetwork(request, callback); 841 842 // If network is not available, throws IllegalStateException. 843 final Network network = callback.waitForAvailable(); 844 if (network == null) { 845 throw new IllegalStateException("network with transport " + transport 846 + " is not available."); 847 } 848 849 final long startTime = SystemClock.elapsedRealtime(); 850 try { 851 exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL)); 852 Log.i(TAG, "exerciseRemoteHost successful in " + (SystemClock.elapsedRealtime() 853 - startTime) + " ms"); 854 } catch (Exception e) { 855 Log.e(TAG, "exerciseRemoteHost failed in " + (SystemClock.elapsedRealtime() 856 - startTime) + " ms: " + e); 857 } finally { 858 cm.unregisterNetworkCallback(callback); 859 } 860 } 861 862 /** 863 * Generate traffic on specified network. 864 */ exerciseRemoteHost(@onNull ConnectivityManager cm, @NonNull Network network, @NonNull URL url)865 private void exerciseRemoteHost(@NonNull ConnectivityManager cm, @NonNull Network network, 866 @NonNull URL url) throws Exception { 867 cm.bindProcessToNetwork(network); 868 HttpURLConnection urlc = null; 869 try { 870 urlc = (HttpURLConnection) network.openConnection(url); 871 urlc.setConnectTimeout(NETWORK_TIMEOUT_MILLIS); 872 urlc.setUseCaches(false); 873 urlc.connect(); 874 } finally { 875 if (urlc != null) { 876 urlc.disconnect(); 877 } 878 } 879 } 880 881 // ------- Helper methods 882 883 /** Puts the current thread to sleep. */ sleep(int millis)884 static void sleep(int millis) { 885 try { 886 Thread.sleep(millis); 887 } catch (InterruptedException e) { 888 Log.e(TAG, "Interrupted exception while sleeping", e); 889 } 890 } 891 892 /** Register receiver to determine when given action is complete. */ registerReceiver( Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter)893 private static BroadcastReceiver registerReceiver( 894 Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) { 895 BroadcastReceiver receiver = new BroadcastReceiver() { 896 @Override 897 public void onReceive(Context context, Intent intent) { 898 Log.d(TAG, "Received broadcast."); 899 onReceiveLatch.countDown(); 900 } 901 }; 902 // Run Broadcast receiver in a different thread since the main thread will wait. 903 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 904 handlerThread.start(); 905 Looper looper = handlerThread.getLooper(); 906 Handler handler = new Handler(looper); 907 ctx.registerReceiver(receiver, intentFilter, null, handler); 908 return receiver; 909 } 910 911 /** 912 * Uses the receiver to wait until the action is complete. ctx and receiver may be null if no 913 * receiver is needed to be unregistered. 914 */ waitForReceiver(Context ctx, int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver)915 private static void waitForReceiver(Context ctx, 916 int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) { 917 try { 918 boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS); 919 if (didFinish) { 920 Log.v(TAG, "Finished performing action"); 921 } else { 922 // This is not necessarily a problem. If we just want to make sure a count was 923 // recorded for the request, it doesn't matter if the action actually finished. 924 Log.w(TAG, "Did not finish in specified time."); 925 } 926 } catch (InterruptedException e) { 927 Log.e(TAG, "Interrupted exception while awaiting action to finish", e); 928 } 929 if (ctx != null && receiver != null) { 930 ctx.unregisterReceiver(receiver); 931 } 932 } 933 setScreenBrightness(int brightness)934 private static void setScreenBrightness(int brightness) { 935 runShellCommand("settings put system screen_brightness " + brightness); 936 } 937 938 private static final int WIFI_CONNECT_TIMEOUT_MILLIS = 30_000; 939 wifiDisconnect(Context context)940 public void wifiDisconnect(Context context) throws Exception { 941 WifiManager wifiManager = context.getSystemService(WifiManager.class); 942 ShellIdentityUtils.invokeWithShellPermissions(() -> wifiManager.disconnect()); 943 944 PollingCheck.check( 945 "Timed out waiting for Wifi to become disconnected", 946 WIFI_CONNECT_TIMEOUT_MILLIS, 947 () -> !isWifiConnected(context)); 948 } 949 wifiReconnect(Context context)950 public void wifiReconnect(Context context) throws Exception { 951 WifiManager wifiManager = context.getSystemService(WifiManager.class); 952 ShellIdentityUtils.invokeWithShellPermissions(() -> wifiManager.reconnect()); 953 954 PollingCheck.check( 955 "Timed out waiting for Wifi to become connected", 956 WIFI_CONNECT_TIMEOUT_MILLIS, 957 () -> isWifiConnected(context)); 958 } 959 isWifiConnected(Context context)960 private boolean isWifiConnected(Context context) throws Exception { 961 ConnectivityManager connManager = context.getSystemService(ConnectivityManager.class); 962 if (connManager == null) { 963 return false; 964 } 965 966 Network[] networks = connManager.getAllNetworks(); 967 for (Network network : networks) { 968 if (network == null) { 969 continue; 970 } 971 972 NetworkCapabilities caps = connManager.getNetworkCapabilities(network); 973 if (caps == null) { 974 continue; 975 } 976 977 if (caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) { 978 return true; 979 } 980 } 981 982 return false; 983 } 984 985 @Test testGameState()986 public void testGameState() throws Exception { 987 Context context = InstrumentationRegistry.getContext(); 988 GameManager gameManager = context.getSystemService(GameManager.class); 989 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 990 assumeNotNull(gameManager); 991 } 992 gameManager.setGameState(new GameState(true, GameState.MODE_CONTENT, 1, 2)); 993 } 994 995 @Test testSetGameMode()996 public void testSetGameMode() throws Exception { 997 Context context = InstrumentationRegistry.getContext(); 998 GameManager gameManager = context.getSystemService(GameManager.class); 999 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 1000 assumeNotNull(gameManager); 1001 } else { 1002 assertNotNull(gameManager); 1003 } 1004 assertNotNull(context.getPackageName()); 1005 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(gameManager, 1006 (gm) -> gm.setGameMode(context.getPackageName(), 1007 GameManager.GAME_MODE_PERFORMANCE), "android.permission.MANAGE_GAME_MODE"); 1008 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(gameManager, 1009 (gm) -> gm.setGameMode(context.getPackageName(), 1010 GameManager.GAME_MODE_BATTERY), "android.permission.MANAGE_GAME_MODE"); 1011 } 1012 1013 @Test testUpdateCustomGameModeConfiguration()1014 public void testUpdateCustomGameModeConfiguration() throws Exception { 1015 Context context = InstrumentationRegistry.getContext(); 1016 GameManager gameManager = context.getSystemService(GameManager.class); 1017 if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) { 1018 assumeNotNull(gameManager); 1019 } else { 1020 assertNotNull(gameManager); 1021 } 1022 assertNotNull(context.getPackageName()); 1023 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(gameManager, 1024 (gm) -> gm.updateCustomGameModeConfiguration(context.getPackageName(), 1025 new GameModeConfiguration.Builder() 1026 .setScalingFactor(0.5f) 1027 .setFpsOverride(30).build())); 1028 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(gameManager, 1029 (gm) -> gm.updateCustomGameModeConfiguration(context.getPackageName(), 1030 new GameModeConfiguration.Builder() 1031 .setScalingFactor(0.9f) 1032 .setFpsOverride(60).build())); 1033 } 1034 1035 @Test testMediaDrmAtoms()1036 public void testMediaDrmAtoms() throws Exception { 1037 UUID clearKeyUuid = new UUID(0xe2719d58a985b3c9L, 0x781ab030af78d30eL); 1038 byte[] sid = null; 1039 final int OEM_ERROR = 123; 1040 final int ERROR_CONTEXT = 456; 1041 final int ANDROID_U = 14; 1042 try (MediaDrm drm = new MediaDrm(clearKeyUuid)) { 1043 if (getClearkeyVersionInt(drm) >= ANDROID_U) { 1044 drm.setPropertyString("oemError", Integer.toString(OEM_ERROR)); 1045 drm.setPropertyString("errorContext", Integer.toString(ERROR_CONTEXT)); 1046 } 1047 for (int i = 0; i < 2; i++) { 1048 // Mock error is set per-session 1049 drm.setPropertyString("drmErrorTest", "lostState"); 1050 sid = drm.openSession(); 1051 Assert.assertNotNull("null session id", sid); 1052 try { 1053 drm.closeSession(sid); 1054 } catch (MediaDrm.MediaDrmStateException e) { 1055 Log.d(TAG, "expected for lost state"); 1056 } 1057 } 1058 } 1059 } 1060 getClearkeyVersionInt(MediaDrm drm)1061 private int getClearkeyVersionInt(MediaDrm drm) { 1062 try { 1063 return Integer.parseInt(drm.getPropertyString("version")); 1064 } catch (Exception e) { 1065 return Integer.MIN_VALUE; 1066 } 1067 } 1068 } 1069