fix: 引入Settings的Module

This commit is contained in:
2024-12-10 14:57:24 +08:00
parent ad8fc8731d
commit df105485bd
6934 changed files with 896168 additions and 2 deletions

View File

@@ -0,0 +1,133 @@
/*
* 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.settings.anomaly.tester;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.ResultReceiver;
import android.provider.Settings;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.android.settings.anomaly.tester.service.AnomalyService;
import com.android.settings.anomaly.tester.utils.AnomalyActions;
import com.android.settings.anomaly.tester.utils.AnomalyPolicyBuilder;
/**
* Main activity to control and start anomaly
*/
public class AnomalyActivity extends Activity {
private static final String TAG = AnomalyActivity.class.getSimpleName();
public static final String KEY_TARGET_BUTTON = "target_button";
private AnomalyResultReceiver mResultReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mResultReceiver = new AnomalyResultReceiver(new Handler());
}
public void startBluetoothAnomaly(View view) {
try {
// Enable anomaly detection and change the threshold
final String config = new AnomalyPolicyBuilder()
.addPolicy(AnomalyPolicyBuilder.KEY_ANOMALY_DETECTION_ENABLED, true)
.addPolicy(AnomalyPolicyBuilder.KEY_BLUETOOTH_SCAN_DETECTION_ENABLED, true)
.addPolicy(AnomalyPolicyBuilder.KEY_BLUETOOTH_SCAN_THRESHOLD,
getValueFromEditText(R.id.bluetooth_threshold))
.build();
Settings.Global.putString(getContentResolver(),
Settings.Global.ANOMALY_DETECTION_CONSTANTS, config);
// Start the anomaly service
Intent intent = new Intent(this, AnomalyService.class);
intent.putExtra(AnomalyActions.KEY_ACTION, AnomalyActions.ACTION_BLE_SCAN_UNOPTIMIZED);
intent.putExtra(AnomalyActions.KEY_DURATION_MS,
getValueFromEditText(R.id.bluetooth_run_time));
intent.putExtra(AnomalyActions.KEY_RESULT_RECEIVER, mResultReceiver);
intent.putExtra(KEY_TARGET_BUTTON, view.getId());
startService(intent);
view.setEnabled(false);
} catch (NumberFormatException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
public void startWakelockAnomaly(View view) {
try {
// Enable anomaly detection and change the threshold
final String config = new AnomalyPolicyBuilder()
.addPolicy(AnomalyPolicyBuilder.KEY_ANOMALY_DETECTION_ENABLED, true)
.addPolicy(AnomalyPolicyBuilder.KEY_WAKELOCK_DETECTION_ENABLED, true)
.addPolicy(AnomalyPolicyBuilder.KEY_WAKELOCK_THRESHOLD,
getValueFromEditText(R.id.wakelock_threshold))
.build();
Settings.Global.putString(getContentResolver(),
Settings.Global.ANOMALY_DETECTION_CONSTANTS,
config);
// Start the anomaly service
Intent intent = new Intent(this, AnomalyService.class);
intent.putExtra(AnomalyActions.KEY_ACTION, AnomalyActions.ACTION_WAKE_LOCK);
intent.putExtra(AnomalyActions.KEY_DURATION_MS,
getValueFromEditText(R.id.wakelock_run_time));
intent.putExtra(AnomalyActions.KEY_RESULT_RECEIVER, mResultReceiver);
intent.putExtra(KEY_TARGET_BUTTON, view.getId());
startService(intent);
view.setEnabled(false);
} catch (NumberFormatException e) {
Toast.makeText(getApplicationContext(), e.toString(), Toast.LENGTH_SHORT).show();
}
}
private long getValueFromEditText(final int id) throws NumberFormatException {
final EditText editText = findViewById(id);
if (editText != null) {
final long value = Long.parseLong(editText.getText().toString());
if (value > 0) {
return value;
}
}
throw new NumberFormatException("Number should be positive");
}
private class AnomalyResultReceiver extends ResultReceiver {
public AnomalyResultReceiver(Handler handler) {
super(handler);
}
@Override
protected void onReceiveResult(int resultCode, Bundle resultData) {
super.onReceiveResult(resultCode, resultData);
final Button button = findViewById(resultData.getInt(KEY_TARGET_BUTTON));
if (button != null) {
button.setEnabled(true);
}
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* 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.settings.anomaly.tester.service;
import android.annotation.Nullable;
import android.app.IntentService;
import android.content.Intent;
import android.os.ResultReceiver;
import com.android.settings.anomaly.tester.utils.AnomalyActions;
/**
* Service to run the anomaly action
*/
public class AnomalyService extends IntentService {
private static final String TAG = AnomalyService.class.getSimpleName();
public AnomalyService() {
super(AnomalyService.class.getSimpleName());
}
@Override
protected void onHandleIntent(@Nullable Intent intent) {
final String action = intent.getStringExtra(AnomalyActions.KEY_ACTION);
final long durationMs = intent.getLongExtra(AnomalyActions.KEY_DURATION_MS, 0);
final ResultReceiver resultReceiver = intent.getParcelableExtra(
AnomalyActions.KEY_RESULT_RECEIVER);
AnomalyActions.doAction(this, action, durationMs);
if (resultReceiver != null) {
resultReceiver.send(0 /* resultCode */, intent.getExtras());
}
}
}

View File

@@ -0,0 +1,113 @@
/*
* 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.settings.anomaly.tester.utils;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.Context;
import android.os.PowerManager;
import android.util.Log;
import java.util.List;
/**
* Actions to generate anomaly.
*/
public class AnomalyActions {
private static final String TAG = AnomalyActions.class.getSimpleName();
public static final String KEY_ACTION = "action";
public static final String KEY_DURATION_MS = "duration_ms";
public static final String KEY_RESULT_RECEIVER = "result_receiver";
public static final String ACTION_BLE_SCAN_UNOPTIMIZED = "action.ble_scan_unoptimized";
public static final String ACTION_WAKE_LOCK = "action.wake_lock";
public static void doAction(Context ctx, String actionCode, long durationMs) {
if (actionCode == null) {
Log.e(TAG, "Intent was missing action.");
return;
}
switch (actionCode) {
case ACTION_BLE_SCAN_UNOPTIMIZED:
doUnoptimizedBleScan(ctx, durationMs);
break;
case ACTION_WAKE_LOCK:
doHoldWakelock(ctx, durationMs);
default:
Log.e(TAG, "Intent had invalid action");
}
}
private static void doUnoptimizedBleScan(Context ctx, long durationMs) {
ScanSettings scanSettings = new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
// perform ble scanning
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled() ) {
Log.e(TAG, "Device does not support Bluetooth or Bluetooth not enabled");
return;
}
BluetoothLeScanner bleScanner = bluetoothAdapter.getBluetoothLeScanner();
if (bleScanner == null) {
Log.e(TAG, "Cannot access BLE scanner");
return;
}
ScanCallback scanCallback = new ScanCallback() {
@Override
public void onScanResult(int callbackType, ScanResult result) {
Log.v(TAG, "called onScanResult");
}
@Override
public void onScanFailed(int errorCode) {
Log.v(TAG, "called onScanFailed");
}
@Override
public void onBatchScanResults(List<ScanResult> results) {
Log.v(TAG, "called onBatchScanResults");
}
};
bleScanner.startScan(null, scanSettings, scanCallback);
try {
Thread.sleep(durationMs);
} catch (InterruptedException e) {
Log.e(TAG, "Thread couldn't sleep for " + durationMs, e);
}
bleScanner.stopScan(scanCallback);
}
private static void doHoldWakelock(Context ctx, long durationMs) {
PowerManager powerManager = ctx.getSystemService(PowerManager.class);
PowerManager.WakeLock wl = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"AnomalyWakeLock");
wl.acquire();
try {
Thread.sleep(durationMs);
} catch (InterruptedException e) {
Log.e(TAG, "Thread couldn't sleep for " + durationMs, e);
}
wl.release();
}
}

View File

@@ -0,0 +1,72 @@
/*
* 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.settings.anomaly.tester.utils;
import java.util.HashMap;
import java.util.Map;
/**
* Builder to build the anomaly policy string, used in {@link android.provider.Settings.Global}
*
* @see android.provider.Settings.Global#ANOMALY_DETECTION_CONSTANTS
*/
public class AnomalyPolicyBuilder {
public static final String KEY_ANOMALY_DETECTION_ENABLED = "anomaly_detection_enabled";
public static final String KEY_WAKELOCK_DETECTION_ENABLED = "wakelock_enabled";
public static final String KEY_WAKEUP_ALARM_DETECTION_ENABLED = "wakeup_alarm_enabled";
public static final String KEY_BLUETOOTH_SCAN_DETECTION_ENABLED = "bluetooth_scan_enabled";
public static final String KEY_WAKELOCK_THRESHOLD = "wakelock_threshold";
public static final String KEY_WAKEUP_ALARM_THRESHOLD = "wakeup_alarm_threshold";
public static final String KEY_BLUETOOTH_SCAN_THRESHOLD = "bluetooth_scan_threshold";
public static final String DELIM = ",";
private Map<String, String> mValues;
public AnomalyPolicyBuilder() {
mValues = new HashMap<>();
}
public AnomalyPolicyBuilder addPolicy(String key, String value) {
mValues.put(key, value);
return this;
}
public AnomalyPolicyBuilder addPolicy(String key, long value) {
mValues.put(key, Long.toString(value));
return this;
}
public AnomalyPolicyBuilder addPolicy(String key, boolean value) {
mValues.put(key, value ? "true" : "false");
return this;
}
public String build() {
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : mValues.entrySet()) {
sb.append(entry.getKey() + "=" + entry.getValue() + DELIM);
}
if (sb.length() != 0) {
return sb.substring(0, sb.length() - 1);
} else {
return "";
}
}
}

View File

@@ -0,0 +1,109 @@
/*
* 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.settings.anomaly.tests;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.text.format.DateUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Functional test for bluetooth unoptimized scanning anomaly detector
*
* @see com.android.settings.fuelgauge.anomaly.checker.BluetoothScanAnomalyDetector
*/
@RunWith(AndroidJUnit4.class)
public class BluetoothAnomalyTest {
private static final String BATTERY_INTENT = "android.intent.action.POWER_USAGE_SUMMARY";
private static final String RES_BT_EDITTEXT =
"com.android.settings.anomaly.tester:id/bluetooth_run_time";
private static final String RES_BT_BUTTON =
"com.android.settings.anomaly.tester:id/bluetooth_button";
private static final long TIME_OUT = 3000;
private UiDevice mDevice;
@Before
public void setUp() {
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
final Context context = instrumentation.getContext();
mDevice = UiDevice.getInstance(instrumentation);
// setup environment
TestUtils.setUp(instrumentation);
// start anomaly-tester app
TestUtils.startAnomalyApp(context, mDevice);
}
@After
public void tearDown() {
TestUtils.tearDown(InstrumentationRegistry.getInstrumentation());
}
@Test
public void testBluetoothAnomaly_longScanningTime_reportAnomaly() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS * 15;
TestUtils.setEditTextWithValue(mDevice, RES_BT_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_BT_BUTTON);
// Wait for its running
mDevice.pressHome();
TestUtils.wait(mDevice, durationMs);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Doesn't have bluetooth anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNotNull();
}
@Test
public void testBluetoothAnomaly_shortScanningTime_notReport() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS;
TestUtils.setEditTextWithValue(mDevice, RES_BT_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_BT_BUTTON);
// Wait for its running
mDevice.pressHome();
TestUtils.wait(mDevice, durationMs);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Shouldn't have bluetooth anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNull();
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.settings.anomaly.tests;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.Context;
import android.content.Intent;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.UiObject2;
import androidx.test.uiautomator.Until;
public class TestUtils {
private static final String PACKAGE_NAME = "com.android.settings.anomaly.tester";
private static final long TIME_OUT = 3000;
/**
* This method set up the environment for anomaly test
*
* @param instrumentation to execute command
*/
public static void setUp(Instrumentation instrumentation) {
final UiAutomation uiAutomation = instrumentation.getUiAutomation();
// pretend unplug and screen off, also reset the battery stats
uiAutomation.executeShellCommand("dumpsys battery unplug");
uiAutomation.executeShellCommand("dumpsys batterystats enable pretend-screen-off");
uiAutomation.executeShellCommand("dumpsys batterystats --reset");
}
/**
* This method cleans up all the commands in {@link #setUp(Instrumentation)}
*
* @param instrumentation to execute command
*/
public static void tearDown(Instrumentation instrumentation) {
final UiAutomation uiAutomation = instrumentation.getUiAutomation();
// reset unplug and screen-off
uiAutomation.executeShellCommand("dumpsys battery reset");
uiAutomation.executeShellCommand("dumpsys batterystats disable pretend-screen-off");
}
public static void startAnomalyApp(Context context, UiDevice uiDevice) {
final Intent intent = context.getPackageManager().getLaunchIntentForPackage(PACKAGE_NAME);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
context.startActivity(intent);
uiDevice.wait(Until.hasObject(By.pkg(PACKAGE_NAME).depth(0)), TIME_OUT);
}
/**
* Find {@link android.widget.EditText} with {@code res} and set its {@code value}
*/
public static void setEditTextWithValue(UiDevice uiDevice, String res, long value) {
final UiObject2 editText = uiDevice.findObject(By.res(res));
assertWithMessage("Cannot find editText with res: " + res).that(editText).isNotNull();
editText.setText(String.valueOf(value));
}
/**
* Find {@link android.widget.Button} with {@code res} and click it
*/
public static void clickButton(UiDevice uiDevice, String res) {
final UiObject2 button = uiDevice.findObject(By.res(res));
assertWithMessage("Cannot find button with res: " + res).that(button).isNotNull();
button.click();
}
/**
* Make {@link UiDevice} wait for {@code timeMs}
*
* @see Thread#sleep(long)
*/
public static void wait(UiDevice uiDevice, long timeMs) throws InterruptedException {
uiDevice.waitForIdle();
Thread.sleep(timeMs);
}
}

View File

@@ -0,0 +1,133 @@
/*
* 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.settings.anomaly.tests;
import static com.google.common.truth.Truth.assertWithMessage;
import android.app.Instrumentation;
import android.content.Context;
import android.content.Intent;
import android.text.format.DateUtils;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
/**
* Functional test for bluetooth unoptimized scanning anomaly detector
*
* @see com.android.settings.fuelgauge.anomaly.checker.BluetoothScanAnomalyDetector
*/
@RunWith(AndroidJUnit4.class)
public class WakelockAnomalyTest {
private static final String BATTERY_INTENT = "android.intent.action.POWER_USAGE_SUMMARY";
private static final String RES_WAKELOCK_EDITTEXT =
"com.android.settings.anomaly.tester:id/wakelock_run_time";
private static final String RES_WAKELOCK_BUTTON =
"com.android.settings.anomaly.tester:id/wakelock_button";
private static final long TIME_OUT = 3000;
private UiDevice mDevice;
@Before
public void setUp() {
final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
final Context context = instrumentation.getContext();
mDevice = UiDevice.getInstance(instrumentation);
// setup environment
TestUtils.setUp(instrumentation);
// start anomaly-tester app
TestUtils.startAnomalyApp(context, mDevice);
}
@After
public void tearDown() {
TestUtils.tearDown(InstrumentationRegistry.getInstrumentation());
}
@Test
public void testWakelockAnomaly_longTimeWhileRunning_report() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS * 15;
TestUtils.setEditTextWithValue(mDevice, RES_WAKELOCK_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_WAKELOCK_BUTTON);
// Wait for its running
mDevice.pressHome();
// Sleeping time less than running time, so the app still holding wakelock when we check
TestUtils.wait(mDevice, durationMs - TIME_OUT);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Doesn't have wakelock anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNotNull();
}
@Test
public void testWakelockAnomaly_shortTime_notReport() throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS;
TestUtils.setEditTextWithValue(mDevice, RES_WAKELOCK_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_WAKELOCK_BUTTON);
// Wait for its running
mDevice.pressHome();
TestUtils.wait(mDevice, durationMs);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Shouldn't have wakelock anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNull();
}
@Test
public void testWakelockAnomaly_longTimeWhileNotRunning_notReport()
throws InterruptedException {
// Set running time
final long durationMs = DateUtils.SECOND_IN_MILLIS * 10;
TestUtils.setEditTextWithValue(mDevice, RES_WAKELOCK_EDITTEXT, durationMs);
// Click start button
TestUtils.clickButton(mDevice, RES_WAKELOCK_BUTTON);
// Wait for its running
mDevice.pressHome();
// Wait more time for releasing the wakelock
TestUtils.wait(mDevice, durationMs + TIME_OUT);
// Check it in battery main page
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
instrumentation.startActivitySync(new Intent(BATTERY_INTENT));
assertWithMessage("Shouldn't have wakelock anomaly").that(
mDevice.wait(Until.findObject(By.text("AnomalyTester draining battery")),
TIME_OUT)).isNull();
}
}