blob: 719dcb71b955638799afe56f0654df608e8c4cbf [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.cts.device.statsd;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Activity;
import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.media.MediaPlayer;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.util.Log;
import android.util.StatsLog;
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class AtomTests {
private static final String TAG = AtomTests.class.getSimpleName();
@Test
public void testAudioState() {
// TODO: This should surely be getTargetContext(), here and everywhere, but test first.
Context context = InstrumentationRegistry.getContext();
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.good);
mediaPlayer.start();
sleep(2_000);
mediaPlayer.stop();
}
@Test
public void testBleScanOpportunistic() {
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_OPPORTUNISTIC).build();
performBleScan(scanSettings, null,false);
}
@Test
public void testBleScanUnoptimized() {
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
performBleScan(scanSettings, null, false);
}
@Test
public void testBleScanResult() {
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
ScanFilter.Builder scanFilter = new ScanFilter.Builder();
performBleScan(scanSettings, Arrays.asList(scanFilter.build()), true);
}
private static void performBleScan(ScanSettings scanSettings, List<ScanFilter> scanFilters, boolean waitForResult) {
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
Log.e(TAG, "Device does not support Bluetooth");
return;
}
boolean bluetoothEnabledByTest = false;
if (!bluetoothAdapter.isEnabled()) {
if (!bluetoothAdapter.enable()) {
Log.e(TAG, "Bluetooth is not enabled");
return;
}
sleep(8_000);
bluetoothEnabledByTest = true;
}
BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bleScanner == null) {
Log.e(TAG, "Cannot access BLE scanner");
return;
}
CountDownLatch resultsLatch = new CountDownLatch(1);
ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.v(TAG, "called onScanResult");
resultsLatch.countDown();
}
@Override
public void onScanFailed(int errorCode) {
Log.v(TAG, "called onScanFailed");
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
Log.v(TAG, "called onBatchScanResults");
resultsLatch.countDown();
}
};
bleScanner.startScan(scanFilters, scanSettings, scanCallback);
if (waitForResult) {
waitForReceiver(InstrumentationRegistry.getContext(), 59_000, resultsLatch, null);
} else {
sleep(2_000);
}
bleScanner.stopScan(scanCallback);
// Restore adapter state at end of test
if (bluetoothEnabledByTest) {
bluetoothAdapter.disable();
}
}
@Test
public void testCameraState() throws Exception {
Context context = InstrumentationRegistry.getContext();
CameraManager cam = context.getSystemService(CameraManager.class);
String[] cameraIds = cam.getCameraIdList();
if (cameraIds.length == 0) {
Log.e(TAG, "No camera found on device");
return;
}
CountDownLatch latch = new CountDownLatch(1);
final CameraDevice.StateCallback cb = new CameraDevice.StateCallback() {
@Override
public void onOpened(CameraDevice cd) {
Log.i(TAG, "CameraDevice " + cd.getId() + " opened");
sleep(2_000);
cd.close();
}
@Override
public void onClosed(CameraDevice cd) {
latch.countDown();
Log.i(TAG, "CameraDevice " + cd.getId() + " closed");
}
@Override
public void onDisconnected(CameraDevice cd) {
Log.w(TAG, "CameraDevice " + cd.getId() + " disconnected");
}
@Override
public void onError(CameraDevice cd, int error) {
Log.e(TAG, "CameraDevice " + cd.getId() + "had error " + error);
}
};
HandlerThread handlerThread = new HandlerThread("br_handler_thread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
cam.openCamera(cameraIds[0], cb, handler);
waitForReceiver(context, 10_000, latch, null);
}
@Test
public void testFlashlight() throws Exception {
Context context = InstrumentationRegistry.getContext();
CameraManager cam = context.getSystemService(CameraManager.class);
String[] cameraIds = cam.getCameraIdList();
boolean foundFlash = false;
for (int i = 0; i < cameraIds.length; i++) {
String id = cameraIds[i];
if(cam.getCameraCharacteristics(id).get(CameraCharacteristics.FLASH_INFO_AVAILABLE)) {
cam.setTorchMode(id, true);
sleep(500);
cam.setTorchMode(id, false);
foundFlash = true;
break;
}
}
if(!foundFlash) {
Log.e(TAG, "No flashlight found on device");
}
}
@Test
public void testForegroundService() throws Exception {
Context context = InstrumentationRegistry.getContext();
// The service goes into foreground and exits shortly
Intent intent = new Intent(context, StatsdCtsForegroundService.class);
context.startService(intent);
sleep(500);
context.stopService(intent);
}
@Test
public void testGpsScan() {
Context context = InstrumentationRegistry.getContext();
final LocationManager locManager = context.getSystemService(LocationManager.class);
if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
Log.e(TAG, "GPS provider is not enabled");
return;
}
CountDownLatch latch = new CountDownLatch(1);
final LocationListener locListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.v(TAG, "onLocationChanged: location has been obtained");
}
public void onProviderDisabled(String provider) {
Log.w(TAG, "onProviderDisabled " + provider);
}
public void onProviderEnabled(String provider) {
Log.w(TAG, "onProviderEnabled " + provider);
}
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.w(TAG, "onStatusChanged " + provider + " " + status);
}
};
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
Looper.prepare();
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 990, 0,
locListener);
sleep(1_000);
locManager.removeUpdates(locListener);
latch.countDown();
return null;
}
}.execute();
waitForReceiver(context, 59_000, latch, null);
}
@Test
public void testScreenBrightness() {
Context context = InstrumentationRegistry.getContext();
PowerManager pm = context.getSystemService(PowerManager.class);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP, "StatsdBrightnessTest");
wl.acquire();
sleep(500);
setScreenBrightness(47);
sleep(500);
setScreenBrightness(100);
sleep(500);
setScreenBrightness(198);
sleep(500);
wl.release();
}
@Test
public void testSyncState() throws Exception {
Context context = InstrumentationRegistry.getContext();
StatsdAuthenticator.removeAllAccounts(context);
AccountManager am = context.getSystemService(AccountManager.class);
CountDownLatch latch = StatsdSyncAdapter.resetCountDownLatch();
Account account = StatsdAuthenticator.getTestAccount();
StatsdAuthenticator.ensureTestAccount(context);
sleep(500);
// Just force set is syncable.
ContentResolver.setMasterSyncAutomatically(true);
sleep(500);
ContentResolver.setIsSyncable(account, StatsdProvider.AUTHORITY, 1);
// Wait for the first (automatic) sync to finish
waitForReceiver(context, 120_000, latch, null);
//Sleep for 500ms, since we assert each start/stop to be ~500ms apart.
sleep(500);
// Request and wait for the second sync to finish
latch = StatsdSyncAdapter.resetCountDownLatch();
StatsdSyncAdapter.requestSync(account);
waitForReceiver(context, 120_000, latch, null);
StatsdAuthenticator.removeAllAccounts(context);
}
@Test
public void testScheduledJob() throws Exception {
final ComponentName name = new ComponentName("com.android.server.cts.device.statsd",
StatsdJobService.class.getName());
Context context = InstrumentationRegistry.getContext();
JobScheduler js = context.getSystemService(JobScheduler.class);
assertTrue("JobScheduler service not available", js != null);
JobInfo.Builder builder = new JobInfo.Builder(1, name);
builder.setOverrideDeadline(0);
JobInfo job = builder.build();
long startTime = System.currentTimeMillis();
CountDownLatch latch = StatsdJobService.resetCountDownLatch();
js.schedule(job);
waitForReceiver(context, 2_500, latch, null);
}
@Test
public void testWakelockState() {
Context context = InstrumentationRegistry.getContext();
PowerManager pm = context.getSystemService(PowerManager.class);
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"StatsdPartialWakelock");
wl.acquire();
sleep(500);
wl.release();
}
@Test
public void testWakelockLoad() {
final int NUM_THREADS = 16;
CountDownLatch latch = new CountDownLatch(NUM_THREADS);
for (int i = 0; i < NUM_THREADS; i++) {
Thread t = new Thread(new WakelockLoadTestRunnable("StatsdPartialWakelock" + i, latch));
t.start();
}
waitForReceiver(null, 120_000, latch, null);
}
@Test
public void testWakeupAlarm() {
Context context = InstrumentationRegistry.getContext();
String name = "android.cts.statsd.testWakeupAlarm";
CountDownLatch onReceiveLatch = new CountDownLatch(1);
BroadcastReceiver receiver =
registerReceiver(context, onReceiveLatch, new IntentFilter(name));
AlarmManager manager = (AlarmManager) (context.getSystemService(AlarmManager.class));
PendingIntent pintent = PendingIntent.getBroadcast(context, 0, new Intent(name), 0);
manager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 2_000, pintent);
waitForReceiver(context, 10_000, onReceiveLatch, receiver);
}
@Test
public void testWifiLock() {
Context context = InstrumentationRegistry.getContext();
WifiManager wm = context.getSystemService(WifiManager.class);
WifiManager.WifiLock lock = wm.createWifiLock("StatsdCTSWifiLock");
lock.acquire();
sleep(500);
lock.release();
}
@Test
public void testWifiMulticastLock() {
Context context = InstrumentationRegistry.getContext();
WifiManager wm = context.getSystemService(WifiManager.class);
WifiManager.MulticastLock lock = wm.createMulticastLock("StatsdCTSMulticastLock");
lock.acquire();
sleep(500);
lock.release();
}
@Test
/** Does two wifi scans. */
// TODO: Copied this from BatterystatsValidation but we probably don't need to wait for results.
public void testWifiScan() {
Context context = InstrumentationRegistry.getContext();
IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
// Sometimes a scan was already running (from a different uid), so the first scan doesn't
// start when requested. Therefore, additionally wait for whatever scan is currently running
// to finish, then request a scan again - at least one of these two scans should be
// attributed to this app.
for (int i = 0; i < 2; i++) {
CountDownLatch onReceiveLatch = new CountDownLatch(1);
BroadcastReceiver receiver = registerReceiver(context, onReceiveLatch, intentFilter);
context.getSystemService(WifiManager.class).startScan();
waitForReceiver(context, 60_000, onReceiveLatch, receiver);
}
}
@Test
public void testSimpleCpu() {
long timestamp = System.currentTimeMillis();
for (int i = 0; i < 10000; i ++) {
timestamp += i;
}
Log.i(TAG, "The answer is " + timestamp);
}
// ------- Helper methods
/** Puts the current thread to sleep. */
static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted exception while sleeping", e);
}
}
/** Register receiver to determine when given action is complete. */
private static BroadcastReceiver registerReceiver(
Context ctx, CountDownLatch onReceiveLatch, IntentFilter intentFilter) {
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Received broadcast.");
onReceiveLatch.countDown();
}
};
// Run Broadcast receiver in a different thread since the main thread will wait.
HandlerThread handlerThread = new HandlerThread("br_handler_thread");
handlerThread.start();
Looper looper = handlerThread.getLooper();
Handler handler = new Handler(looper);
ctx.registerReceiver(receiver, intentFilter, null, handler);
return receiver;
}
/**
* Uses the receiver to wait until the action is complete. ctx and receiver may be null if no
* receiver is needed to be unregistered.
*/
private static void waitForReceiver(Context ctx,
int maxWaitTimeMs, CountDownLatch latch, BroadcastReceiver receiver) {
try {
boolean didFinish = latch.await(maxWaitTimeMs, TimeUnit.MILLISECONDS);
if (didFinish) {
Log.v(TAG, "Finished performing action");
} else {
// This is not necessarily a problem. If we just want to make sure a count was
// recorded for the request, it doesn't matter if the action actually finished.
Log.w(TAG, "Did not finish in specified time.");
}
} catch (InterruptedException e) {
Log.e(TAG, "Interrupted exception while awaiting action to finish", e);
}
if (ctx != null && receiver != null) {
ctx.unregisterReceiver(receiver);
}
}
private static void setScreenBrightness(int brightness) {
runShellCommand("settings put system screen_brightness " + brightness);
}
}