• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 package com.android.compatibility.common.util;
17 
18 import static com.android.compatibility.common.util.TestUtils.waitUntil;
19 
20 import android.content.Intent;
21 import android.content.IntentFilter;
22 import android.content.pm.PackageManager;
23 import android.os.BatteryManager;
24 import android.os.PowerManager;
25 import android.provider.Settings.Global;
26 import android.util.Log;
27 
28 import androidx.test.InstrumentationRegistry;
29 
30 import com.android.compatibility.common.util.UserSettings.Namespace;
31 
32 import org.junit.Assume;
33 
34 public class BatteryUtils {
35     private static final String TAG = "CtsBatteryUtils";
36 
BatteryUtils()37     private BatteryUtils() {
38     }
39 
getBatteryManager()40     public static BatteryManager getBatteryManager() {
41         return InstrumentationRegistry.getContext().getSystemService(BatteryManager.class);
42     }
43 
getPowerManager()44     public static PowerManager getPowerManager() {
45         return InstrumentationRegistry.getContext().getSystemService(PowerManager.class);
46     }
47 
hasBattery()48     public static boolean hasBattery() {
49         final Intent batteryInfo = InstrumentationRegistry.getContext()
50                 .registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
51         return batteryInfo.getBooleanExtra(BatteryManager.EXTRA_PRESENT, true);
52     }
53 
54     /** Make the target device think it's off charger. */
runDumpsysBatteryUnplug()55     public static void runDumpsysBatteryUnplug() throws Exception {
56         SystemUtil.runShellCommandForNoOutput("cmd battery unplug");
57 
58         waitForPlugStatus(false);
59 
60         Log.d(TAG, "Battery UNPLUGGED");
61     }
62 
63     /**
64      * Set the battery level to {@code level} percent. The valid range is [0, 100].
65      */
runDumpsysBatterySetLevel(int level)66     public static void runDumpsysBatterySetLevel(int level) throws Exception {
67         SystemUtil.runShellCommandForNoOutput(("cmd battery set level " + level));
68 
69         Log.d(TAG, "Battery level set to " + level);
70     }
71 
72     /**
73      * Set whether the device is plugged in to a charger or not.
74      */
runDumpsysBatterySetPluggedIn(boolean pluggedIn)75     public static void runDumpsysBatterySetPluggedIn(boolean pluggedIn) throws Exception {
76         SystemUtil.runShellCommandForNoOutput(("cmd battery set ac " + (pluggedIn ? "1" : "0")));
77 
78         waitForPlugStatus(pluggedIn);
79 
80         Log.d(TAG, "Battery AC set to " + pluggedIn);
81     }
82 
waitForPlugStatus(boolean pluggedIn)83     private static void waitForPlugStatus(boolean pluggedIn) throws Exception {
84         if (InstrumentationRegistry.getContext().getPackageManager().isInstantApp()) {
85             // Instant apps are not allowed to query ACTION_BATTERY_CHANGED. Add short sleep as
86             // best-effort wait for status.
87             Thread.sleep(2000);
88             return;
89         }
90         IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
91         waitUntil("Device still " + (pluggedIn ? " not plugged" : " plugged"),
92                 () -> {
93                     Intent batteryStatus =
94                             InstrumentationRegistry.getContext().registerReceiver(null, ifilter);
95                     int chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
96                     return pluggedIn == (chargePlug != 0);
97                 });
98     }
99 
100     /** Reset the effect of all the previous {@code runDumpsysBattery*} call */
runDumpsysBatteryReset()101     public static void runDumpsysBatteryReset() {
102         SystemUtil.runShellCommandForNoOutput(("cmd battery reset"));
103 
104         Log.d(TAG, "Battery RESET");
105     }
106 
enableAdaptiveBatterySaver(boolean enabled)107     public static void enableAdaptiveBatterySaver(boolean enabled) {
108         final String setting = enabled ? "true" : "false";
109         SystemUtil.runShellCommandForNoOutput(
110                 "cmd power set-adaptive-power-saver-enabled " + setting);
111     }
112 
113     /**
114      * Enable / disable battery saver. Note {@link #runDumpsysBatteryUnplug} must have been
115      * executed before enabling BS.
116      */
enableBatterySaver(boolean enabled)117     public static void enableBatterySaver(boolean enabled) throws Exception {
118         UserSettings globalSettings = new UserSettings(Namespace.GLOBAL);
119         if (enabled) {
120             SystemUtil.runShellCommandForNoOutput("cmd power set-mode 1");
121             AmUtils.waitForBroadcastBarrier();
122             globalSettings.set(Global.LOW_POWER_MODE, "1");
123             waitUntil("Battery saver still off", () -> getPowerManager().isPowerSaveMode());
124         } else {
125             SystemUtil.runShellCommandForNoOutput("cmd power set-mode 0");
126             AmUtils.waitForBroadcastBarrier();
127             globalSettings.set(Global.LOW_POWER_MODE, "0");
128             globalSettings.set(Global.LOW_POWER_MODE_STICKY, "0");
129             waitUntil("Battery saver still on", () -> !getPowerManager().isPowerSaveMode());
130         }
131 
132         AmUtils.waitForBroadcastBarrier();
133         Log.d(TAG, "Battery saver turned " + (enabled ? "ON" : "OFF"));
134     }
135 
136     /** Reset battery saver state and take it out of a forced state. */
resetBatterySaver()137     public static void resetBatterySaver() throws Exception {
138         UserSettings globalSettings = new UserSettings(Namespace.GLOBAL);
139         SystemUtil.runShellCommandForNoOutput("cmd power set-mode 0");
140         globalSettings.set(Global.LOW_POWER_MODE, null);
141         globalSettings.set(Global.LOW_POWER_MODE_STICKY, null);
142         waitUntil("Battery saver still on", () -> !getPowerManager().isPowerSaveMode());
143     }
144 
145     /**
146      * Turn on/off screen.
147      */
turnOnScreen(boolean on)148     public static void turnOnScreen(boolean on) throws Exception {
149         if (on) {
150             SystemUtil.runShellCommandForNoOutput("input keyevent KEYCODE_WAKEUP");
151             waitUntil("Device still not interactive", () -> getPowerManager().isInteractive());
152 
153         } else {
154             SystemUtil.runShellCommandForNoOutput("input keyevent KEYCODE_SLEEP");
155             waitUntil("Device still interactive", () -> !getPowerManager().isInteractive());
156         }
157         AmUtils.waitForBroadcastBarrier();
158         Log.d(TAG, "Screen turned " + (on ? "ON" : "OFF"));
159     }
160 
161     /** @return true if the device supports battery saver. */
isBatterySaverSupported()162     public static boolean isBatterySaverSupported() {
163         if (!hasBattery()) {
164             // Devices without a battery don't support battery saver.
165             return false;
166         }
167 
168         final PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
169         return !(pm.hasSystemFeature(PackageManager.FEATURE_WATCH) ||
170             pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
171     }
172 
173     /** "Assume" the current device supports battery saver. */
assumeBatterySaverFeature()174     public static void assumeBatterySaverFeature() {
175         Assume.assumeTrue("Device doesn't support battery saver", isBatterySaverSupported());
176     }
177 }
178