1 /* 2 * Copyright (C) 2009 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 android.os.cts; 18 19 import static android.os.Flags.batterySaverSupportedCheckApi; 20 21 import static com.android.compatibility.common.util.TestUtils.waitUntil; 22 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.os.Flags; 28 import android.os.PowerManager; 29 import android.os.PowerManager.WakeLock; 30 import android.platform.test.annotations.AppModeFull; 31 import android.provider.Settings.Global; 32 import android.test.AndroidTestCase; 33 34 import androidx.test.filters.LargeTest; 35 36 import com.android.compatibility.common.util.BatteryUtils; 37 import com.android.compatibility.common.util.CallbackAsserter; 38 import com.android.compatibility.common.util.SystemUtil; 39 40 import org.junit.After; 41 import org.junit.Before; 42 43 import java.time.Duration; 44 45 @AppModeFull(reason = "Instant Apps don't have the WRITE_SECURE_SETTINGS permission " 46 + "required in tearDown for Global#putInt") 47 public class PowerManagerTest extends AndroidTestCase { 48 private static final String TAG = "PowerManagerTest"; 49 public static final long TIME = 3000; 50 public static final int MORE_TIME = 300; 51 private static final int BROADCAST_TIMEOUT_SECONDS = 70; 52 private static final Duration LONG_DISCHARGE_DURATION = Duration.ofMillis(2000); 53 private static final Duration SHORT_DISCHARGE_DURATION = Duration.ofMillis(1000); 54 55 private int mInitialPowerSaverMode; 56 private int mInitialDynamicPowerSavingsEnabled; 57 private int mInitialThreshold; 58 59 /** 60 * test points: 61 * 1 Get a wake lock at the level of the flags parameter 62 * 2 Force the device to go to sleep 63 * 3 User activity happened 64 */ testPowerManager()65 public void testPowerManager() throws InterruptedException { 66 PowerManager pm = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE); 67 68 WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, TAG); 69 wl.acquire(TIME); 70 assertTrue(wl.isHeld()); 71 Thread.sleep(TIME + MORE_TIME); 72 assertFalse(wl.isHeld()); 73 74 try { 75 pm.reboot("Testing"); 76 fail("reboot should throw SecurityException"); 77 } catch (SecurityException e) { 78 // expected 79 } 80 } 81 82 @Before setUp()83 public void setUp() { 84 // store the current value so we can restore it 85 ContentResolver resolver = getContext().getContentResolver(); 86 mInitialPowerSaverMode = Global.getInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, 0); 87 mInitialDynamicPowerSavingsEnabled = 88 Global.getInt(resolver, Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0); 89 mInitialThreshold = 90 Global.getInt(resolver, Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 0); 91 92 } 93 94 @After tearDown()95 public void tearDown() { 96 SystemUtil.runWithShellPermissionIdentity(() -> { 97 ContentResolver resolver = getContext().getContentResolver(); 98 99 // Verify we can change it to dynamic. 100 Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, mInitialPowerSaverMode); 101 Global.putInt(resolver, 102 Global.DYNAMIC_POWER_SAVINGS_ENABLED, mInitialDynamicPowerSavingsEnabled); 103 Global.putInt(resolver, 104 Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, mInitialThreshold); 105 }); 106 } 107 testPowerManager_getPowerSaveMode()108 public void testPowerManager_getPowerSaveMode() { 109 PowerManager manager = BatteryUtils.getPowerManager(); 110 if (batterySaverSupportedCheckApi() && !manager.isBatterySaverSupported()) { 111 return; 112 } 113 114 SystemUtil.runWithShellPermissionIdentity(() -> { 115 ContentResolver resolver = getContext().getContentResolver(); 116 117 // Verify we can change it to percentage. 118 Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, 0); 119 assertEquals( 120 PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE, 121 manager.getPowerSaveModeTrigger()); 122 123 // Verify we can change it to dynamic. 124 Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, 1); 125 assertEquals( 126 PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC, 127 manager.getPowerSaveModeTrigger()); 128 }); 129 } 130 testPowerManager_setDynamicPowerSavings()131 public void testPowerManager_setDynamicPowerSavings() { 132 PowerManager manager = BatteryUtils.getPowerManager(); 133 if (batterySaverSupportedCheckApi() && !manager.isBatterySaverSupported()) { 134 return; 135 } 136 137 SystemUtil.runWithShellPermissionIdentity(() -> { 138 ContentResolver resolver = getContext().getContentResolver(); 139 140 // Verify settings are actually updated. 141 manager.setDynamicPowerSaveHint(true, 80); 142 assertEquals(1, Global.getInt(resolver, Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0)); 143 assertEquals(80, Global.getInt(resolver, 144 Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 0)); 145 146 manager.setDynamicPowerSaveHint(false, 20); 147 assertEquals(0, Global.getInt(resolver, Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1)); 148 assertEquals(20, Global.getInt(resolver, 149 Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 0)); 150 }); 151 } 152 153 @LargeTest testPowerManager_batteryDischargePrediction()154 public void testPowerManager_batteryDischargePrediction() throws Exception { 155 final PowerManager manager = BatteryUtils.getPowerManager(); 156 if (batterySaverSupportedCheckApi() && !manager.isBatterySaverSupported()) { 157 return; 158 } 159 160 if (!BatteryUtils.hasBattery()) { 161 assertNull(manager.getBatteryDischargePrediction()); 162 return; 163 } 164 165 // Unplug to ensure the plugged in broadcast is sent. 166 BatteryUtils.runDumpsysBatteryUnplug(); 167 168 // Plugged in. No prediction should be given. 169 final CallbackAsserter pluggedBroadcastAsserter = CallbackAsserter.forBroadcast( 170 new IntentFilter(Intent.ACTION_POWER_CONNECTED)); 171 BatteryUtils.runDumpsysBatterySetPluggedIn(true); 172 pluggedBroadcastAsserter.assertCalled("Didn't get power connected broadcast", 173 BROADCAST_TIMEOUT_SECONDS); 174 // PowerManagerService may get the BATTERY_CHANGED broadcast after we get our broadcast, 175 // so we have to have a little wait. 176 waitUntil("PowerManager doesn't think the device has connected power", 177 () -> manager.getBatteryDischargePrediction() == null); 178 179 // Not plugged in. At the very least, the basic discharge estimation should be returned. 180 final CallbackAsserter unpluggedBroadcastAsserter = CallbackAsserter.forBroadcast( 181 new IntentFilter(Intent.ACTION_POWER_DISCONNECTED)); 182 BatteryUtils.runDumpsysBatteryUnplug(); 183 unpluggedBroadcastAsserter.assertCalled("Didn't get power disconnected broadcast", 184 BROADCAST_TIMEOUT_SECONDS); 185 // PowerManagerService may get the BATTERY_CHANGED broadcast after we get our broadcast, 186 // so we have to have a little wait. 187 waitUntil("PowerManager still thinks the device has connected power", 188 () -> manager.getBatteryDischargePrediction() != null); 189 190 CallbackAsserter predictionChangedBroadcastAsserter = CallbackAsserter.forBroadcast( 191 new IntentFilter(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)); 192 setDischargePrediction(LONG_DISCHARGE_DURATION, true); 193 assertDischargePrediction(LONG_DISCHARGE_DURATION, true); 194 predictionChangedBroadcastAsserter.assertCalled("Prediction changed broadcast not received", 195 BROADCAST_TIMEOUT_SECONDS); 196 197 198 predictionChangedBroadcastAsserter = CallbackAsserter.forBroadcast( 199 new IntentFilter(PowerManager.ACTION_ENHANCED_DISCHARGE_PREDICTION_CHANGED)); 200 setDischargePrediction(SHORT_DISCHARGE_DURATION, false); 201 assertDischargePrediction(SHORT_DISCHARGE_DURATION, false); 202 predictionChangedBroadcastAsserter.assertCalled("Prediction changed broadcast not received", 203 BROADCAST_TIMEOUT_SECONDS); 204 } 205 setDischargePrediction(Duration d, boolean isPersonalized)206 private void setDischargePrediction(Duration d, boolean isPersonalized) { 207 final PowerManager manager = BatteryUtils.getPowerManager(); 208 SystemUtil.runWithShellPermissionIdentity( 209 () -> manager.setBatteryDischargePrediction(d, isPersonalized), 210 android.Manifest.permission.BATTERY_PREDICTION); 211 } 212 assertDischargePrediction(Duration d, boolean isPersonalized)213 private void assertDischargePrediction(Duration d, boolean isPersonalized) { 214 final PowerManager manager = BatteryUtils.getPowerManager(); 215 // We can't pause time so must use >= because the time remaining should decrease as 216 // time goes on. 217 Duration prediction = manager.getBatteryDischargePrediction(); 218 assertTrue("Prediction is greater than " + d.toMillis() + "ms: " 219 + prediction, d.toMillis() >= prediction.toMillis()); 220 assertEquals(isPersonalized, manager.isBatteryDischargePredictionPersonalized()); 221 } 222 } 223