• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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