• 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
testScreenBrightness()468     public void testScreenBrightness() {
469         Context context = InstrumentationRegistry.getContext();
470         PowerManager pm = context.getSystemService(PowerManager.class);
471         PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
472                 PowerManager.ACQUIRE_CAUSES_WAKEUP, "StatsdBrightnessTest");
473         wl.acquire();
474         sleep(500);
475 
476         setScreenBrightness(47);
477         sleep(500);
478         setScreenBrightness(100);
479         sleep(500);
480         setScreenBrightness(198);
481         sleep(500);
482 
483 
484         wl.release();
485     }
486 
487     @Test
testSyncState()488     public void testSyncState() throws Exception {
489 
490         Context context = InstrumentationRegistry.getContext();
491         StatsdAuthenticator.removeAllAccounts(context);
492         AccountManager am = context.getSystemService(AccountManager.class);
493         CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch();
494 
495         Account account = StatsdAuthenticator.getTestAccount();
496         StatsdAuthenticator.ensureTestAccount(context);
497         sleep(500);
498 
499         // Just force set is syncable.
500         ContentResolver.setMasterSyncAutomatically(true);
501         sleep(500);
502         ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1);
503         // Wait for the first (automatic) sync to finish
504         waitForReceiver(context, 120_000, latch, null);
505 
506         //Sleep for 500ms, since we assert each start/stop to be ~500ms apart.
507         sleep(500);
508 
509         // Request and wait for the second sync to finish
510         latch = StatsdSyncAdapter.resetCountDownLatch();
511         StatsdSyncAdapter.requestSync(account);
512         waitForReceiver(context, 120_000, latch, null);
513         StatsdAuthenticator.removeAllAccounts(context);
514     }
515 
516     @Test
testScheduledJob()517     public void testScheduledJob() throws Exception {
518         final ComponentName name = new ComponentName(MY_PACKAGE_NAME,
519                 StatsdJobService.class.getName());
520 
521         Context context = InstrumentationRegistry.getContext();
522         JobScheduler js = context.getSystemService(JobScheduler.class);
523         assertWithMessage("JobScheduler service not available").that(js).isNotNull();
524 
525         JobInfo.Builder builder = new JobInfo.Builder(1, name);
526         builder.setOverrideDeadline(0);
527         JobInfo job = builder.build();
528 
529         long startTime = System.currentTimeMillis();
530         CountDownLatch latch = StatsdJobService.resetCountDownLatch();
531         js.schedule(job);
532         waitForReceiver(context, 5_000, latch, null);
533     }
534 
535     @Test
testVibratorState()536     public void testVibratorState() {
537         Context context = InstrumentationRegistry.getContext();
538         Vibrator vib = context.getSystemService(Vibrator.class);
539         if (vib.hasVibrator()) {
540             vib.vibrate(VibrationEffect.createOneShot(
541                     500 /* ms */, VibrationEffect.DEFAULT_AMPLITUDE));
542         }
543     }
544 
545     @Test
testWakelockState()546     public void testWakelockState() {
547         Context context = InstrumentationRegistry.getContext();
548         PowerManager pm = context.getSystemService(PowerManager.class);
549         PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
550                 "StatsdPartialWakelock");
551         wl.acquire();
552         sleep(500);
553         wl.release();
554     }
555 
556     @Test
testSliceByWakelockState()557     public void testSliceByWakelockState() {
558         int uid = Process.myUid();
559         int whatAtomId = 9_998;
560         int wakelockType = PowerManager.PARTIAL_WAKE_LOCK;
561         String tag = "StatsdPartialWakelock";
562 
563         Context context = InstrumentationRegistry.getContext();
564         PowerManager pm = context.getSystemService(PowerManager.class);
565         PowerManager.WakeLock wl = pm.newWakeLock(wakelockType, tag);
566 
567         wl.acquire();
568         sleep(500);
569         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
570         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
571         wl.acquire();
572         sleep(500);
573         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
574         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
575         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
576         wl.release();
577         sleep(500);
578         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
579         wl.release();
580         sleep(500);
581         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
582         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
583         writeSliceByWakelockStateChangedAtom(whatAtomId, uid, wakelockType, tag);
584     }
585 
writeSliceByWakelockStateChangedAtom(int atomId, int firstUid, int field2, String field3)586     private static void writeSliceByWakelockStateChangedAtom(int atomId, int firstUid,
587                                                             int field2, String field3) {
588         final StatsEvent.Builder builder = StatsEvent.newBuilder()
589                 .setAtomId(atomId)
590                 .writeAttributionChain(new int[] {firstUid}, new String[] {"tag1"})
591                 .writeInt(field2)
592                 .writeString(field3)
593                 .usePooledBuffer();
594 
595         StatsLog.write(builder.build());
596     }
597 
598 
599     @Test
testWakelockLoad()600     public void testWakelockLoad() {
601         final int NUM_THREADS = 16;
602         CountDownLatch latch = new CountDownLatch(NUM_THREADS);
603         for (int i = 0; i < NUM_THREADS; i++) {
604             Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch));
605             t.start();
606         }
607         waitForReceiver(null, 120_000, latch, null);
608     }
609 
610     @Test
testWakeupAlarm()611     public void testWakeupAlarm() {
612         Context context = InstrumentationRegistry.getContext();
613         String name = "android.cts.statsd.testWakeupAlarm";
614         CountDownLatch onReceiveLatch = new CountDownLatch(1);
615         BroadcastReceiver receiver =
616                 registerReceiver(context, onReceiveLatch, new IntentFilter(name));
617         AlarmManager manager = (AlarmManager) (context.getSystemService(AlarmManager.class));
618         PendingIntent pintent = PendingIntent.getBroadcast(context, 0, new Intent(name), 0);
619         manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
620             SystemClock.elapsedRealtime() + 2_000, pintent);
621         waitForReceiver(context, 10_000, onReceiveLatch, receiver);
622     }
623 
624     @Test
testWifiLockHighPerf()625     public void testWifiLockHighPerf() {
626         Context context = InstrumentationRegistry.getContext();
627         WifiManager wm = context.getSystemService(WifiManager.class);
628         WifiManager.WifiLock lock =
629                 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, "StatsdCTSWifiLock");
630         lock.acquire();
631         sleep(500);
632         lock.release();
633     }
634 
635     @Test
testWifiLockLowLatency()636     public void testWifiLockLowLatency() {
637         Context context = InstrumentationRegistry.getContext();
638         WifiManager wm = context.getSystemService(WifiManager.class);
639         WifiManager.WifiLock lock =
640                 wm.createWifiLock(WifiManager.WIFI_MODE_FULL_LOW_LATENCY, "StatsdCTSWifiLock");
641         lock.acquire();
642         sleep(500);
643         lock.release();
644     }
645 
646     @Test
testWifiMulticastLock()647     public void testWifiMulticastLock() {
648         Context context = InstrumentationRegistry.getContext();
649         WifiManager wm = context.getSystemService(WifiManager.class);
650         WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock");
651         lock.acquire();
652         sleep(500);
653         lock.release();
654     }
655 
656     @Test
657     /** Does two wifi scans. */
658     // TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results.
testWifiScan()659     public void testWifiScan() {
660         Context context = InstrumentationRegistry.getContext();
661         IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
662         // Sometimes a scan was already running (from a different uid), so the first scan doesn't
663         // start when requested. Therefore, additionally wait for whatever scan is currently running
664         // to finish, then request a scan again - at least one of these two scans should be
665         // attributed to this app.
666         for (int i = 0; i < 2; i++) {
667             CountDownLatch onReceiveLatch = new CountDownLatch(1);
668             BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter);
669             context.getSystemService(WifiManager.class).startScan();
670             waitForReceiver(context, 60_000, onReceiveLatch, receiver);
671         }
672     }
673 
674     @Test
testSimpleCpu()675     public void testSimpleCpu() {
676         long timestamp = System.currentTimeMillis();
677         for (int i = 0; i < 10000; i ++) {
678             timestamp += i;
679         }
680         Log.i(TAG, "The answer is " + timestamp);
681     }
682 
683     @Test
testWriteRawTestAtom()684     public void testWriteRawTestAtom() throws Exception {
685         Context context = InstrumentationRegistry.getTargetContext();
686         ApplicationInfo appInfo = context.getPackageManager()
687                 .getApplicationInfo(context.getPackageName(), 0);
688         int[] uids = {1234, appInfo.uid};
689         String[] tags = {"tag1", "tag2"};
690         byte[] experimentIds = {8, 1, 8, 2, 8, 3}; // Corresponds to 1, 2, 3.
691         StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids, tags, 42,
692                 Long.MAX_VALUE, 3.14f, "This is a basic test!", false,
693                 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, experimentIds);
694 
695         // All nulls. Should get dropped since cts app is not in the attribution chain.
696         StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, null, null, 0, 0,
697                 0f, null, false, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__ON, null);
698 
699         // Null tag in attribution chain.
700         int[] uids2 = {9999, appInfo.uid};
701         String[] tags2 = {"tag9999", null};
702         StatsLogStatsdCts.write(StatsLogStatsdCts.TEST_ATOM_REPORTED, uids2, tags2, 100,
703                 Long.MIN_VALUE, -2.5f, "Test null uid", true,
704                 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__UNKNOWN, experimentIds);
705 
706         // Non chained non-null
707         StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED,
708                 appInfo.uid, "tag1", -256, -1234567890L, 42.01f, "Test non chained", true,
709                 StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, experimentIds);
710 
711         // Non chained all null
712         StatsLogStatsdCts.write_non_chained(StatsLogStatsdCts.TEST_ATOM_REPORTED, appInfo.uid, null,
713                 0, 0, 0f, null, true, StatsLogStatsdCts.TEST_ATOM_REPORTED__STATE__OFF, null);
714 
715     }
716 
717     /**
718      * Bring up and generate some traffic on cellular data connection.
719      */
720     @Test
testGenerateMobileTraffic()721     public void testGenerateMobileTraffic() throws Exception {
722         final Context context = InstrumentationRegistry.getContext();
723         doGenerateNetworkTraffic(context, NetworkCapabilities.TRANSPORT_CELLULAR);
724     }
725 
726     // Constants which are locally used by doGenerateNetworkTraffic.
727     private static final int NETWORK_TIMEOUT_MILLIS = 15000;
728     private static final String HTTPS_HOST_URL =
729             "https://connectivitycheck.gstatic.com/generate_204";
730 
doGenerateNetworkTraffic(@onNull Context context, int transport)731     private void doGenerateNetworkTraffic(@NonNull Context context, int transport)
732             throws InterruptedException {
733         final ConnectivityManager cm = context.getSystemService(ConnectivityManager.class);
734         final NetworkRequest request = new NetworkRequest.Builder().addCapability(
735                 NetworkCapabilities.NET_CAPABILITY_INTERNET).addTransportType(transport).build();
736         final CtsNetUtils.TestNetworkCallback callback = new CtsNetUtils.TestNetworkCallback();
737 
738         // Request network, and make http query when the network is available.
739         cm.requestNetwork(request, callback);
740 
741         // If network is not available, throws IllegalStateException.
742         final Network network = callback.waitForAvailable();
743         if (network == null) {
744             throw new IllegalStateException("network " + request + " is not available.");
745         }
746 
747         final long startTime = SystemClock.elapsedRealtime();
748         try {
749             exerciseRemoteHost(cm, network, new URL(HTTPS_HOST_URL));
750             Log.i(TAG, "exerciseRemoteHost successful in " + (SystemClock.elapsedRealtime()
751                     - startTime) + " ms");
752         } catch (Exception e) {
753             Log.e(TAG, "exerciseRemoteHost failed in " + (SystemClock.elapsedRealtime()
754                     - startTime) + " ms: " + e);
755         } finally {
756             cm.unregisterNetworkCallback(callback);
757         }
758     }
759 
760     /**
761      * Generate traffic on specified network.
762      */
exerciseRemoteHost(@onNull ConnectivityManager cm, @NonNull Network network, @NonNull URL url)763     private void exerciseRemoteHost(@NonNull ConnectivityManager cm, @NonNull Network network,
764             @NonNull URL url) throws Exception {
765         cm.bindProcessToNetwork(network);
766         HttpURLConnection urlc = null;
767         try {
768             urlc = (HttpURLConnection) network.openConnection(url);
769             urlc.setConnectTimeout(NETWORK_TIMEOUT_MILLIS);
770             urlc.setUseCaches(false);
771             urlc.connect();
772         } finally {
773             if (urlc != null) {
774                 urlc.disconnect();
775             }
776         }
777     }
778 
779     // Constants for testBlobStore
780     private static final long BLOB_COMMIT_CALLBACK_TIMEOUT_SEC = 5;
781     private static final long BLOB_EXPIRY_DURATION_MS = 24 * 60 * 60 * 1000;
782     private static final long BLOB_FILE_SIZE_BYTES = 23 * 1024L;
783     private static final long BLOB_LEASE_EXPIRY_DURATION_MS = 60 * 60 * 1000;
784     private static final byte[] FAKE_PKG_CERT_SHA256 = BaseEncoding.base16().decode(
785             "187E3D3172F2177D6FEC2EA53785BF1E25DFF7B2E5F6E59807E365A7A837E6C3");
786 
787     // ------- Helper methods
788 
789     /** Puts the current thread to sleep. */
sleep(int millis)790     static void sleep(int millis) {
791         try {
792             Thread.sleep(millis);
793         } catch (InterruptedException e) {
794             Log.e(TAG, "Interrupted exception while sleeping", e);
795         }
796     }
797 
798     /** Register receiver to determine when given action is complete. */
registerReceiver( Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter)799     private static BroadcastReceiver registerReceiver(
800             Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) {
801         BroadcastReceiver receiver = new BroadcastReceiver() {
802             @Override
803             public void onReceive(Context context, Intent intent) {
804                 Log.d(TAG, "Received broadcast.");
805                 onReceiveLatch.countDown();
806             }
807         };
808         // Run Broadcast receiver in a different thread since the main thread will wait.
809         HandlerThread handlerThread = new HandlerThread("br_handler_thread");
810         handlerThread.start();
811         Looper looper = handlerThread.getLooper();
812         Handler handler = new Handler(looper);
813         ctx.registerReceiver(receiver, intentFilter, null, handler);
814         return receiver;
815     }
816 
817     /**
818      * Uses the receiver to wait until the action is complete. ctx and receiver may be null if no
819      * receiver is needed to be unregistered.
820      */
waitForReceiver(Context ctx, int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver)821     private static void waitForReceiver(Context ctx,
822             int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) {
823         try {
824             boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS);
825             if (didFinish) {
826                 Log.v(TAG, "Finished performing action");
827             } else {
828                 // This is not necessarily a problem. If we just want to make sure a count was
829                 // recorded for the request, it doesn't matter if the action actually finished.
830                 Log.w(TAG, "Did not finish in specified time.");
831             }
832         } catch (InterruptedException e) {
833             Log.e(TAG, "Interrupted exception while awaiting action to finish", e);
834         }
835         if (ctx != null && receiver != null) {
836             ctx.unregisterReceiver(receiver);
837         }
838     }
839 
setScreenBrightness(int brightness)840     private static void setScreenBrightness(int brightness) {
841         runShellCommand("settings put system screen_brightness " + brightness);
842     }
843 }
844