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 21 import static org.junit.Assert.assertTrue; 22 23 import android.accounts.Account; 24 import android.accounts.AccountManager; 25 import android.app.AlarmManager; 26 import android.app.PendingIntent; 27 import android.app.job.JobInfo; 28 import android.app.job.JobScheduler; 29 import android.bluetooth.BluetoothAdapter; 30 import android.bluetooth.le.BluetoothLeScanner; 31 import android.bluetooth.le.ScanCallback; 32 import android.bluetooth.le.ScanFilter; 33 import android.bluetooth.le.ScanResult; 34 import android.bluetooth.le.ScanSettings; 35 import android.content.BroadcastReceiver; 36 import android.content.ComponentName; 37 import android.content.ContentResolver; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.IntentFilter; 41 import android.content.pm.ApplicationInfo; 42 import android.hardware.camera2.CameraCharacteristics; 43 import android.hardware.camera2.CameraDevice; 44 import android.hardware.camera2.CameraManager; 45 import android.location.Location; 46 import android.location.LocationListener; 47 import android.location.LocationManager; 48 import android.media.MediaPlayer; 49 import android.net.wifi.WifiManager; 50 import android.os.AsyncTask; 51 import android.os.Bundle; 52 import android.os.Handler; 53 import android.os.HandlerThread; 54 import android.os.Looper; 55 import android.os.PowerManager; 56 import android.os.SystemClock; 57 import android.os.VibrationEffect; 58 import android.os.Vibrator; 59 import android.util.Log; 60 61 import androidx.test.InstrumentationRegistry; 62 63 import org.junit.Test; 64 65 import java.util.Arrays; 66 import java.util.List; 67 import java.util.concurrent.CountDownLatch; 68 import java.util.concurrent.TimeUnit; 69 70 public class AtomTests { 71 private static final String TAG = AtomTests.class.getSimpleName(); 72 73 @Test testAudioState()74 public void testAudioState() { 75 // TODO: This should surely be getTargetContext(), here and everywhere, but test first. 76 Context context = InstrumentationRegistry.getContext(); 77 MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.good); 78 mediaPlayer.start(); 79 sleep(2_000); 80 mediaPlayer.stop(); 81 } 82 83 @Test testBleScanOpportunistic()84 public void testBleScanOpportunistic() { 85 ScanSettings scanSettings = new ScanSettings.Builder() 86 .setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build(); 87 performBleScan(scanSettings, null,false); 88 } 89 90 @Test testBleScanUnoptimized()91 public void testBleScanUnoptimized() { 92 ScanSettings scanSettings = new ScanSettings.Builder() 93 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 94 performBleScan(scanSettings, null, false); 95 } 96 97 @Test testBleScanResult()98 public void testBleScanResult() { 99 ScanSettings scanSettings = new ScanSettings.Builder() 100 .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(); 101 ScanFilter.Builder scanFilter = new ScanFilter.Builder(); 102 performBleScan(scanSettings, Arrays.asList(scanFilter.build()), true); 103 } 104 performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult)105 private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult) { 106 BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 107 if (bluetoothAdapter == null) { 108 Log.e(TAG, "Device does not support Bluetooth"); 109 return; 110 } 111 boolean bluetoothEnabledByTest = false; 112 if (!bluetoothAdapter.isEnabled()) { 113 if (!bluetoothAdapter.enable()) { 114 Log.e(TAG, "Bluetooth is not enabled"); 115 return; 116 } 117 sleep(8_000); 118 bluetoothEnabledByTest = true; 119 } 120 BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner(); 121 if (bleScanner == null) { 122 Log.e(TAG, "Cannot access BLE scanner"); 123 return; 124 } 125 126 CountDownLatch resultsLatch = new CountDownLatch(1); 127 ScanCallback scanCallback = new ScanCallback() { 128 @Override 129 public void onScanResult(int callbackType, ScanResult result) { 130 Log.v(TAG, "called onScanResult"); 131 resultsLatch.countDown(); 132 } 133 @Override 134 public void onScanFailed(int errorCode) { 135 Log.v(TAG, "called onScanFailed"); 136 } 137 @Override 138 public void onBatchScanResults(List<ScanResult> results) { 139 Log.v(TAG, "called onBatchScanResults"); 140 resultsLatch.countDown(); 141 } 142 }; 143 144 bleScanner.startScan(scanFilters, scanSettings, scanCallback); 145 if (waitForResult) { 146 waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null); 147 } else { 148 sleep(2_000); 149 } 150 bleScanner.stopScan(scanCallback); 151 152 // Restore adapter state at end of test 153 if (bluetoothEnabledByTest) { 154 bluetoothAdapter.disable(); 155 } 156 } 157 158 @Test testCameraState()159 public void testCameraState() throws Exception { 160 Context context = InstrumentationRegistry.getContext(); 161 CameraManager cam = context.getSystemService(CameraManager.class); 162 String[] cameraIds = cam.getCameraIdList(); 163 if (cameraIds.length == 0) { 164 Log.e(TAG, "No camera found on device"); 165 return; 166 } 167 168 CountDownLatch latch = new CountDownLatch(1); 169 final CameraDevice.StateCallback cb = new CameraDevice.StateCallback() { 170 @Override 171 public void onOpened(CameraDevice cd) { 172 Log.i(TAG, "CameraDevice " + cd.getId() + " opened"); 173 sleep(2_000); 174 cd.close(); 175 } 176 @Override 177 public void onClosed(CameraDevice cd) { 178 latch.countDown(); 179 Log.i(TAG, "CameraDevice " + cd.getId() + " closed"); 180 } 181 @Override 182 public void onDisconnected(CameraDevice cd) { 183 Log.w(TAG, "CameraDevice " + cd.getId() + " disconnected"); 184 } 185 @Override 186 public void onError(CameraDevice cd, int error) { 187 Log.e(TAG, "CameraDevice " + cd.getId() + "had error " + error); 188 } 189 }; 190 191 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 192 handlerThread.start(); 193 Looper looper = handlerThread.getLooper(); 194 Handler handler = new Handler(looper); 195 196 cam.openCamera(cameraIds[0], cb, handler); 197 waitForReceiver(context, 10_000, latch, null); 198 } 199 200 @Test testFlashlight()201 public void testFlashlight() throws Exception { 202 Context context = InstrumentationRegistry.getContext(); 203 CameraManager cam = context.getSystemService(CameraManager.class); 204 String[] cameraIds = cam.getCameraIdList(); 205 boolean foundFlash = false; 206 for (int i = 0; i < cameraIds.length; i++) { 207 String id = cameraIds[i]; 208 if(cam.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) { 209 cam.setTorchMode(id, true); 210 sleep(500); 211 cam.setTorchMode(id, false); 212 foundFlash = true; 213 break; 214 } 215 } 216 if(!foundFlash) { 217 Log.e(TAG, "No flashlight found on device"); 218 } 219 } 220 221 @Test testForegroundService()222 public void testForegroundService() throws Exception { 223 Context context = InstrumentationRegistry.getContext(); 224 // The service goes into foreground and exits shortly 225 Intent intent = new Intent(context, StatsdCtsForegroundService.class); 226 context.startService(intent); 227 sleep(500); 228 context.stopService(intent); 229 } 230 231 @Test testGpsScan()232 public void testGpsScan() { 233 Context context = InstrumentationRegistry.getContext(); 234 final LocationManager locManager = context.getSystemService(LocationManager.class); 235 if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { 236 Log.e(TAG, "GPS provider is not enabled"); 237 return; 238 } 239 CountDownLatch latch = new CountDownLatch(1); 240 241 final LocationListener locListener = new LocationListener() { 242 public void onLocationChanged(Location location) { 243 Log.v(TAG, "onLocationChanged: location has been obtained"); 244 } 245 public void onProviderDisabled(String provider) { 246 Log.w(TAG, "onProviderDisabled " + provider); 247 } 248 public void onProviderEnabled(String provider) { 249 Log.w(TAG, "onProviderEnabled " + provider); 250 } 251 public void onStatusChanged(String provider, int status, Bundle extras) { 252 Log.w(TAG, "onStatusChanged " + provider + " " + status); 253 } 254 }; 255 256 new AsyncTask<Void, Void, Void>() { 257 @Override 258 protected Void doInBackground(Void... params) { 259 Looper.prepare(); 260 locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 990, 0, 261 locListener); 262 sleep(1_000); 263 locManager.removeUpdates(locListener); 264 latch.countDown(); 265 return null; 266 } 267 }.execute(); 268 269 waitForReceiver(context, 59_000, latch, null); 270 } 271 272 @Test testScreenBrightness()273 public void testScreenBrightness() { 274 Context context = InstrumentationRegistry.getContext(); 275 PowerManager pm = context.getSystemService(PowerManager.class); 276 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | 277 PowerManager.ACQUIRE_CAUSES_WAKEUP, "StatsdBrightnessTest"); 278 wl.acquire(); 279 sleep(500); 280 281 setScreenBrightness(47); 282 sleep(500); 283 setScreenBrightness(100); 284 sleep(500); 285 setScreenBrightness(198); 286 sleep(500); 287 288 289 wl.release(); 290 } 291 292 @Test testSyncState()293 public void testSyncState() throws Exception { 294 295 Context context = InstrumentationRegistry.getContext(); 296 StatsdAuthenticator.removeAllAccounts(context); 297 AccountManager am = context.getSystemService(AccountManager.class); 298 CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch(); 299 300 Account account = StatsdAuthenticator.getTestAccount(); 301 StatsdAuthenticator.ensureTestAccount(context); 302 sleep(500); 303 304 // Just force set is syncable. 305 ContentResolver.setMasterSyncAutomatically(true); 306 sleep(500); 307 ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1); 308 // Wait for the first (automatic) sync to finish 309 waitForReceiver(context, 120_000, latch, null); 310 311 //Sleep for 500ms, since we assert each start/stop to be ~500ms apart. 312 sleep(500); 313 314 // Request and wait for the second sync to finish 315 latch = StatsdSyncAdapter.resetCountDownLatch(); 316 StatsdSyncAdapter.requestSync(account); 317 waitForReceiver(context, 120_000, latch, null); 318 StatsdAuthenticator.removeAllAccounts(context); 319 } 320 321 @Test testScheduledJob()322 public void testScheduledJob() throws Exception { 323 final ComponentName name = new ComponentName("com.android.server.cts.device.statsd", 324 StatsdJobService.class.getName()); 325 326 Context context = InstrumentationRegistry.getContext(); 327 JobScheduler js = context.getSystemService(JobScheduler.class); 328 assertTrue("JobScheduler service not available", js != null); 329 330 JobInfo.Builder builder = new JobInfo.Builder(1, name); 331 builder.setOverrideDeadline(0); 332 JobInfo job = builder.build(); 333 334 long startTime = System.currentTimeMillis(); 335 CountDownLatch latch = StatsdJobService.resetCountDownLatch(); 336 js.schedule(job); 337 waitForReceiver(context, 2_500, latch, null); 338 } 339 340 @Test testVibratorState()341 public void testVibratorState() { 342 Context context = InstrumentationRegistry.getContext(); 343 Vibrator vib = context.getSystemService(Vibrator.class); 344 if (vib.hasVibrator()) { 345 vib.vibrate(VibrationEffect.createOneShot( 346 500 /* ms */, VibrationEffect.DEFAULT_AMPLITUDE)); 347 } 348 } 349 350 @Test testWakelockState()351 public void testWakelockState() { 352 Context context = InstrumentationRegistry.getContext(); 353 PowerManager pm = context.getSystemService(PowerManager.class); 354 PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 355 "StatsdPartialWakelock"); 356 wl.acquire(); 357 sleep(500); 358 wl.release(); 359 } 360 361 @Test testWakelockLoad()362 public void testWakelockLoad() { 363 final int NUM_THREADS = 16; 364 CountDownLatch latch = new CountDownLatch(NUM_THREADS); 365 for (int i = 0; i < NUM_THREADS; i++) { 366 Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch)); 367 t.start(); 368 } 369 waitForReceiver(null, 120_000, latch, null); 370 } 371 372 @Test testWakeupAlarm()373 public void testWakeupAlarm() { 374 Context context = InstrumentationRegistry.getContext(); 375 String name = "android.cts.statsd.testWakeupAlarm"; 376 CountDownLatch onReceiveLatch = new CountDownLatch(1); 377 BroadcastReceiver receiver = 378 registerReceiver(context, onReceiveLatch, new IntentFilter(name)); 379 AlarmManager manager = (AlarmManager) (context.getSystemService(AlarmManager.class)); 380 PendingIntent pintent = PendingIntent.getBroadcast(context, 0, new Intent(name), 0); 381 manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 382 SystemClock.elapsedRealtime() + 2_000, pintent); 383 waitForReceiver(context, 10_000, onReceiveLatch, receiver); 384 } 385 386 @Test testWifiLockHighPerf()387 public void testWifiLockHighPerf() { 388 Context context = InstrumentationRegistry.getContext(); 389 WifiManager wm = context.getSystemService(WifiManager.class); 390 WifiManager.WifiLock lock = 391 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "StatsdCTSWifiLock"); 392 lock.acquire(); 393 sleep(500); 394 lock.release(); 395 } 396 397 @Test testWifiLockLowLatency()398 public void testWifiLockLowLatency() { 399 Context context = InstrumentationRegistry.getContext(); 400 WifiManager wm = context.getSystemService(WifiManager.class); 401 WifiManager.WifiLock lock = 402 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "StatsdCTSWifiLock"); 403 lock.acquire(); 404 sleep(500); 405 lock.release(); 406 } 407 408 @Test testWifiMulticastLock()409 public void testWifiMulticastLock() { 410 Context context = InstrumentationRegistry.getContext(); 411 WifiManager wm = context.getSystemService(WifiManager.class); 412 WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock"); 413 lock.acquire(); 414 sleep(500); 415 lock.release(); 416 } 417 418 @Test 419 /** Does two wifi scans. */ 420 // TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results. testWifiScan()421 public void testWifiScan() { 422 Context context = InstrumentationRegistry.getContext(); 423 IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 424 // Sometimes a scan was already running (from a different uid), so the first scan doesn't 425 // start when requested. Therefore, additionally wait for whatever scan is currently running 426 // to finish, then request a scan again - at least one of these two scans should be 427 // attributed to this app. 428 for (int i = 0; i < 2; i++) { 429 CountDownLatch onReceiveLatch = new CountDownLatch(1); 430 BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter); 431 context.getSystemService(WifiManager.class).startScan(); 432 waitForReceiver(context, 60_000, onReceiveLatch, receiver); 433 } 434 } 435 436 @Test testSimpleCpu()437 public void testSimpleCpu() { 438 long timestamp = System.currentTimeMillis(); 439 for (int i = 0; i < 10000; i ++) { 440 timestamp += i; 441 } 442 Log.i(TAG, "The answer is " + timestamp); 443 } 444 445 @Test testWriteRawTestAtom()446 public void testWriteRawTestAtom() throws Exception { 447 Context context = InstrumentationRegistry.getTargetContext(); 448 ApplicationInfo appInfo = context.getPackageManager() 449 .getApplicationInfo(context.getPackageName(), 0); 450 int[] uids = {1234, appInfo.uid}; 451 String[] tags = {"tag1", "tag2"}; 452 byte[] experimentIds = {8, 1, 8, 2, 8, 3}; // Corresponds to 1, 2, 3. 453 StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids, tags, 42, 454 Long.MAX_VALUE, 3.14f, "This is a basic test!", false, 455 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, experimentIds); 456 457 // All nulls. Should get dropped since cts app is not in the attribution chain. 458 StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, null, null, 0, 0, 459 0f, null, false, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, null); 460 461 // Null tag in attribution chain. 462 int[] uids2 = {9999, appInfo.uid}; 463 String[] tags2 = {"tag9999", null}; 464 StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids2, tags2, 100, 465 Long.MIN_VALUE, -2.5f, "Test null uid", true, 466 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__UNKNOWN, experimentIds); 467 468 // Non chained non-null 469 StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED, 470 appInfo.uid, "tag1", -256, -1234567890L, 42.01f, "Test non chained", true, 471 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, experimentIds); 472 473 // Non chained all null 474 StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED, appInfo.uid, null, 475 0, 0, 0f, null, true, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, null); 476 477 } 478 479 // ------- Helper methods 480 481 /** Puts the current thread to sleep. */ sleep(int millis)482 static void sleep(int millis) { 483 try { 484 Thread.sleep(millis); 485 } catch (InterruptedException e) { 486 Log.e(TAG, "Interrupted exception while sleeping", e); 487 } 488 } 489 490 /** Register receiver to determine when given action is complete. */ registerReceiver( Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter)491 private static BroadcastReceiver registerReceiver( 492 Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) { 493 BroadcastReceiver receiver = new BroadcastReceiver() { 494 @Override 495 public void onReceive(Context context, Intent intent) { 496 Log.d(TAG, "Received broadcast."); 497 onReceiveLatch.countDown(); 498 } 499 }; 500 // Run Broadcast receiver in a different thread since the main thread will wait. 501 HandlerThread handlerThread = new HandlerThread("br_handler_thread"); 502 handlerThread.start(); 503 Looper looper = handlerThread.getLooper(); 504 Handler handler = new Handler(looper); 505 ctx.registerReceiver(receiver, intentFilter, null, handler); 506 return receiver; 507 } 508 509 /** 510 * Uses the receiver to wait until the action is complete. ctx and receiver may be null if no 511 * receiver is needed to be unregistered. 512 */ waitForReceiver(Context ctx, int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver)513 private static void waitForReceiver(Context ctx, 514 int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) { 515 try { 516 boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS); 517 if (didFinish) { 518 Log.v(TAG, "Finished performing action"); 519 } else { 520 // This is not necessarily a problem. If we just want to make sure a count was 521 // recorded for the request, it doesn't matter if the action actually finished. 522 Log.w(TAG, "Did not finish in specified time."); 523 } 524 } catch (InterruptedException e) { 525 Log.e(TAG, "Interrupted exception while awaiting action to finish", e); 526 } 527 if (ctx != null && receiver != null) { 528 ctx.unregisterReceiver(receiver); 529 } 530 } 531 setScreenBrightness(int brightness)532 private static void setScreenBrightness(int brightness) { 533 runShellCommand("settings put system screen_brightness " + brightness); 534 } 535 } 536