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