| /* |
| * Copyright (C) 2018 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.server.power.batterysaver; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.mockito.ArgumentMatchers.anyBoolean; |
| import static org.mockito.ArgumentMatchers.anyInt; |
| import static org.mockito.Mockito.doAnswer; |
| import static org.mockito.Mockito.doReturn; |
| import static org.mockito.Mockito.mock; |
| import static org.mockito.Mockito.when; |
| |
| import android.app.NotificationManager; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.provider.Settings.Global; |
| |
| import androidx.test.filters.SmallTest; |
| import androidx.test.runner.AndroidJUnit4; |
| |
| import org.junit.Before; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.HashMap; |
| import java.util.Objects; |
| |
| /** |
| * atest com.android.server.power.batterysaver.BatterySaverStateMachineTest |
| */ |
| @SmallTest |
| @RunWith(AndroidJUnit4.class) |
| public class BatterySaverStateMachineTest { |
| |
| private Context mMockContext; |
| private ContentResolver mMockContextResolver; |
| private BatterySaverController mMockBatterySaverController; |
| private NotificationManager mMockNotificationManager; |
| private Device mDevice; |
| private TestableBatterySaverStateMachine mTarget; |
| private Resources mMockResources; |
| |
| private DevicePersistedState mPersistedState; |
| |
| private class DevicePersistedState { |
| // Current battery level. |
| public int batteryLevel = 100; |
| |
| // Whether battery level is currently low or not. |
| public boolean batteryLow = false; |
| |
| // Whether the device is plugged in or not. |
| public boolean powered = false; |
| |
| // Global settings. |
| public final HashMap<String, Integer> global = new HashMap<>(); |
| } |
| |
| /** |
| * This class simulates a device's volatile status that will be reset by {@link #initDevice()}. |
| */ |
| private class Device { |
| public boolean batterySaverEnabled = false; |
| |
| public int getLowPowerModeTriggerLevel() { |
| return mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0); |
| } |
| |
| public void setBatteryLevel(int level) { |
| mPersistedState.batteryLevel = level; |
| if (mPersistedState.batteryLevel <= Math.max(15, getLowPowerModeTriggerLevel())) { |
| mPersistedState.batteryLow = true; |
| } else if (mPersistedState.batteryLow |
| && (mPersistedState.batteryLevel >= (getLowPowerModeTriggerLevel() + 5))) { |
| mPersistedState.batteryLow = false; |
| } |
| pushBatteryStatus(); |
| } |
| |
| public void setPowered(boolean newPowered) { |
| mPersistedState.powered = newPowered; |
| pushBatteryStatus(); |
| } |
| |
| public void pushBatteryStatus() { |
| mTarget.setBatteryStatus(mPersistedState.powered, mPersistedState.batteryLevel, |
| mPersistedState.batteryLow); |
| } |
| |
| public void pushGlobalSettings() { |
| mTarget.setSettingsLocked( |
| mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE, 0) != 0, |
| mPersistedState.global.getOrDefault(Global.LOW_POWER_MODE_STICKY, 0) != 0, |
| mDevice.getLowPowerModeTriggerLevel(), |
| mPersistedState.global.getOrDefault( |
| Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 0) != 0, |
| mPersistedState.global.getOrDefault( |
| Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90), |
| mPersistedState.global.getOrDefault(Global.AUTOMATIC_POWER_SAVER_MODE, 0), |
| mPersistedState.global.getOrDefault( |
| Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0) != 0, |
| mPersistedState.global.getOrDefault( |
| Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 100)); |
| } |
| |
| public void putGlobalSetting(String key, int value) { |
| mPersistedState.global.put(key, value); |
| pushGlobalSettings(); |
| } |
| |
| public int getGlobalSetting(String key, int defValue) { |
| return mPersistedState.global.getOrDefault(key, defValue); |
| } |
| } |
| |
| /** |
| * Test target class. |
| */ |
| private class TestableBatterySaverStateMachine extends BatterySaverStateMachine { |
| TestableBatterySaverStateMachine() { |
| super(new Object(), mMockContext, mMockBatterySaverController); |
| } |
| |
| @Override |
| protected void putGlobalSetting(String key, int value) { |
| if (Objects.equals(mPersistedState.global.get(key), value)) { |
| return; |
| } |
| mDevice.putGlobalSetting(key, value); |
| } |
| |
| @Override |
| protected int getGlobalSetting(String key, int defValue) { |
| return mDevice.getGlobalSetting(key, defValue); |
| } |
| |
| @Override |
| void runOnBgThread(Runnable r) { |
| r.run(); |
| } |
| |
| @Override |
| void runOnBgThreadLazy(Runnable r, int delayMillis) { |
| r.run(); |
| } |
| |
| @Override |
| void triggerDynamicModeNotification() { |
| // Do nothing |
| } |
| } |
| |
| @Before |
| public void setUp() { |
| mMockContext = mock(Context.class); |
| mMockContextResolver = mock(ContentResolver.class); |
| mMockBatterySaverController = mock(BatterySaverController.class); |
| mMockNotificationManager = mock(NotificationManager.class); |
| mMockResources = mock(Resources.class); |
| |
| doReturn(mMockContextResolver).when(mMockContext).getContentResolver(); |
| doReturn(mMockResources).when(mMockContext).getResources(); |
| doReturn(mMockNotificationManager).when(mMockContext) |
| .getSystemService(NotificationManager.class); |
| doAnswer((inv) -> mDevice.batterySaverEnabled = inv.getArgument(0)) |
| .when(mMockBatterySaverController).enableBatterySaver(anyBoolean(), anyInt()); |
| when(mMockBatterySaverController.isEnabled()) |
| .thenAnswer((inv) -> mDevice.batterySaverEnabled); |
| when(mMockResources.getBoolean( |
| com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled)) |
| .thenReturn(false); |
| when(mMockResources.getInteger( |
| com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold)) |
| .thenReturn(80); |
| |
| mPersistedState = new DevicePersistedState(); |
| initDevice(); |
| } |
| |
| private void initDevice() { |
| mDevice = new Device(); |
| |
| mTarget = new TestableBatterySaverStateMachine(); |
| |
| mDevice.pushBatteryStatus(); |
| mTarget.onBootCompleted(); |
| } |
| |
| @Test |
| public void testNoAutoBatterySaver() { |
| assertEquals(0, mDevice.getLowPowerModeTriggerLevel()); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(16); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(16, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // When LOW_POWER_MODE_TRIGGER_LEVEL is 0, 15% will still trigger low-battery, but |
| // BS wont be enabled. |
| mDevice.setBatteryLevel(15); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(15, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(10); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(10, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // Manually enable BS. |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(10, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Start charging. It'll disable BS. |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(60); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Unplug. |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(10); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(10, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(80); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Reboot the device. |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Sticky. |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Still sticky. |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mTarget.setBatterySaverEnabledManually(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); // reboot. |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testAutoBatterySaver() { |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50); |
| mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(51); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(51, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Hit the threshold. BS should be enabled. |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // Battery goes up, but until it hits 55%, we still keep BS on. |
| mDevice.setBatteryLevel(54); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(54, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // 50% + 5%, now BS will be off. |
| mDevice.setBatteryLevel(55); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(55, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(40); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze. |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // Plug in and out, snooze will reset. |
| mDevice.setPowered(true); |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(60); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(70); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Bump ump the threshold. |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 70); |
| mDevice.setBatteryLevel(mPersistedState.batteryLevel); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // Then down. |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 60); |
| mDevice.setBatteryLevel(mPersistedState.batteryLevel); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Reboot in low state -> automatically enable BS. |
| mDevice.setPowered(false); |
| mDevice.setBatteryLevel(30); |
| mTarget.setBatterySaverEnabledManually(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testAutoBatterySaver_withSticky_withAutoOffDisabled() { |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 0); |
| |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(80); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Still enabled. |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Restores BS. |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mTarget.setBatterySaverEnabledManually(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testAutoBatterySaver_withSticky_withAutoOffEnabled() { |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 90); |
| |
| // Scenario 1: User turns BS on manually above the threshold, it shouldn't turn off even |
| // with battery level change above threshold. |
| mDevice.setBatteryLevel(100); |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(95); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Stays on. |
| assertEquals(95, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 2: User turns BS on manually above the threshold then charges device. BS |
| // shouldn't turn back on. |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(95, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(97); |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled. |
| assertEquals(97, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 3: User turns BS on manually above the threshold. Device drains below |
| // threshold and then charged to below threshold. Sticky BS should activate. |
| mTarget.setBatterySaverEnabledManually(true); |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(80); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Still enabled. |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| // Scenario 4: User turns BS on manually above the threshold. Device drains below |
| // threshold and is eventually charged to above threshold. Sticky BS should turn off. |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); // Sticky BS no longer enabled. |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 5: User turns BS on manually below threshold and charges to below threshold. |
| // Sticky BS should activate. |
| mDevice.setBatteryLevel(70); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(80); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Sticky BS still on. |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 6: User turns BS on manually below threshold and eventually charges to above |
| // threshold. Sticky BS should turn off. |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(95); |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(95, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 7: User turns BS on above threshold and then reboots device. Sticky BS |
| // shouldn't activate. |
| mTarget.setBatterySaverEnabledManually(true); |
| mPersistedState.batteryLevel = 93; |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(93, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 8: User turns BS on below threshold and then reboots device without charging. |
| // Sticky BS should activate. |
| mDevice.setBatteryLevel(75); |
| mTarget.setBatterySaverEnabledManually(true); |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(75, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(75, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 9: User turns BS on below threshold and then reboots device after charging |
| // above threshold. Sticky BS shouldn't activate. |
| mDevice.setBatteryLevel(80); |
| mTarget.setBatterySaverEnabledManually(true); |
| mPersistedState.batteryLevel = 100; |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Scenario 10: Somehow autoDisableLevel is set to a value below lowPowerModeTriggerLevel |
| // and then user enables manually above both thresholds, discharges below |
| // autoDisableLevel and then charges up to between autoDisableLevel and |
| // lowPowerModeTriggerLevel. Sticky BS shouldn't activate, but BS should still be on |
| // because the level is below lowPowerModeTriggerLevel. |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 75); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_ENABLED, 1); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL, 60); |
| initDevice(); |
| |
| mDevice.setBatteryLevel(90); |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(65); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(65, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(65, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testAutoBatterySaver_withStickyDisabled() { |
| when(mMockResources.getBoolean( |
| com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled)) |
| .thenReturn(true); |
| initDevice(); |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50); |
| mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 0); |
| |
| mTarget.setBatterySaverEnabledManually(true); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(80); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); // Not sticky. |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(80, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); // Restores BS. |
| assertEquals(30, mPersistedState.batteryLevel); |
| assertEquals(true, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mTarget.setBatterySaverEnabledManually(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| initDevice(); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testNoAutoBatterySaver_fromAdb() { |
| assertEquals(0, mDevice.getLowPowerModeTriggerLevel()); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Enable |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE, 1); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Disable |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE, 0); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Enable again |
| mDevice.putGlobalSetting(Global.LOW_POWER_MODE, 1); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| |
| // Reboot -- setting BS from adb is also sticky. |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| assertEquals(false, mPersistedState.batteryLow); |
| } |
| |
| @Test |
| public void testAutoBatterySaver_smartBatterySaverEnabled() { |
| mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 50); |
| mDevice.putGlobalSetting(Global.AUTOMATIC_POWER_SAVER_MODE, 1); |
| mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 0); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(100, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(90); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(90, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(51); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(51, mPersistedState.batteryLevel); |
| |
| // Hit the threshold. BS should be disabled since dynamic power savings still off |
| mDevice.setBatteryLevel(50); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(50, mPersistedState.batteryLevel); |
| |
| // dynamic power savings comes on, battery saver should turn on |
| mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_ENABLED, 1); |
| mDevice.setBatteryLevel(40); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| |
| mDevice.setPowered(true); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| |
| mTarget.setBatterySaverEnabledManually(false); // Manually disable -> snooze. |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(30); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| |
| // Plug in and out, snooze will reset. |
| mDevice.setPowered(true); |
| mDevice.setPowered(false); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| |
| mDevice.setPowered(true); |
| mDevice.setBatteryLevel(60); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| |
| mDevice.setPowered(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(60, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(40); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(40, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(70); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| |
| // Bump up the threshold. |
| mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 71); |
| mDevice.setBatteryLevel(mPersistedState.batteryLevel); |
| |
| // changes are only registered if some battery level changed |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(70, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(69); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(69, mPersistedState.batteryLevel); |
| |
| // Then down. |
| mDevice.putGlobalSetting(Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, 60); |
| mDevice.setBatteryLevel(mPersistedState.batteryLevel); |
| |
| // changes are only registered if battery level changed |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(69, mPersistedState.batteryLevel); |
| |
| mDevice.setBatteryLevel(68); |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(68, mPersistedState.batteryLevel); |
| |
| // Reboot in low state -> automatically enable BS. |
| mDevice.setPowered(false); |
| mDevice.setBatteryLevel(30); |
| mTarget.setBatterySaverEnabledManually(false); |
| |
| assertEquals(false, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| |
| initDevice(); |
| |
| assertEquals(true, mDevice.batterySaverEnabled); |
| assertEquals(30, mPersistedState.batteryLevel); |
| } |
| } |