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