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