Merge "Sticky battery saver" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
110a7c20f4
@@ -585,6 +585,7 @@ package android.provider {
|
||||
field public static final java.lang.String HIDDEN_API_BLACKLIST_EXEMPTIONS = "hidden_api_blacklist_exemptions";
|
||||
field public static final java.lang.String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
|
||||
field public static final java.lang.String LOW_POWER_MODE = "low_power";
|
||||
field public static final java.lang.String LOW_POWER_MODE_STICKY = "low_power_sticky";
|
||||
field public static final java.lang.String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
|
||||
}
|
||||
|
||||
|
||||
@@ -11004,12 +11004,20 @@ public final class Settings {
|
||||
public static final String SHOW_PROCESSES = "show_processes";
|
||||
|
||||
/**
|
||||
* If 1 low power mode is enabled.
|
||||
* If 1 low power mode (aka battery saver) is enabled.
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public static final String LOW_POWER_MODE = "low_power";
|
||||
|
||||
/**
|
||||
* If 1, battery saver ({@link #LOW_POWER_MODE}) will be re-activated after the device
|
||||
* is unplugged from a charger or rebooted.
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
|
||||
|
||||
/**
|
||||
* Battery level [1-100] at which low power mode automatically turns on.
|
||||
* If 0, it will not automatically turn on.
|
||||
|
||||
@@ -118,61 +118,60 @@ message PowerManagerServiceDumpProto {
|
||||
// True if the sandman has just been summoned for the first time since entering
|
||||
// the dreaming or dozing state. Indicates whether a new dream should begin.
|
||||
optional bool is_sandman_summoned = 23;
|
||||
// If true, the device is in low power mode.
|
||||
optional bool is_low_power_mode_enabled = 24;
|
||||
// True if the battery level is currently considered low.
|
||||
optional bool is_battery_level_low = 25;
|
||||
optional bool is_battery_level_low = 24;
|
||||
// True if we are currently in light device idle mode.
|
||||
optional bool is_light_device_idle_mode = 26;
|
||||
optional bool is_light_device_idle_mode = 25;
|
||||
// True if we are currently in device idle mode.
|
||||
optional bool is_device_idle_mode = 27;
|
||||
optional bool is_device_idle_mode = 26;
|
||||
// Set of app ids that we will always respect the wake locks for.
|
||||
repeated int32 device_idle_whitelist = 28;
|
||||
repeated int32 device_idle_whitelist = 27;
|
||||
// Set of app ids that are temporarily allowed to acquire wakelocks due to
|
||||
// high-pri message
|
||||
repeated int32 device_idle_temp_whitelist = 29;
|
||||
repeated int32 device_idle_temp_whitelist = 28;
|
||||
// Timestamp of the last time the device was awoken.
|
||||
optional int64 last_wake_time_ms = 30;
|
||||
optional int64 last_wake_time_ms = 29;
|
||||
// Timestamp of the last time the device was put to sleep.
|
||||
optional int64 last_sleep_time_ms = 31;
|
||||
optional int64 last_sleep_time_ms = 30;
|
||||
// Timestamp of the last call to user activity.
|
||||
optional int64 last_user_activity_time_ms = 32;
|
||||
optional int64 last_user_activity_time_no_change_lights_ms = 33;
|
||||
optional int64 last_user_activity_time_ms = 31;
|
||||
optional int64 last_user_activity_time_no_change_lights_ms = 32;
|
||||
// Timestamp of last interactive power hint.
|
||||
optional int64 last_interactive_power_hint_time_ms = 34;
|
||||
optional int64 last_interactive_power_hint_time_ms = 33;
|
||||
// Timestamp of the last screen brightness boost.
|
||||
optional int64 last_screen_brightness_boost_time_ms = 35;
|
||||
optional int64 last_screen_brightness_boost_time_ms = 34;
|
||||
// True if screen brightness boost is in progress.
|
||||
optional bool is_screen_brightness_boost_in_progress = 36;
|
||||
optional bool is_screen_brightness_boost_in_progress = 35;
|
||||
// True if the display power state has been fully applied, which means the
|
||||
// display is actually on or actually off or whatever was requested.
|
||||
optional bool is_display_ready = 37;
|
||||
optional bool is_display_ready = 36;
|
||||
// True if the wake lock suspend blocker has been acquired.
|
||||
optional bool is_holding_wake_lock_suspend_blocker = 38;
|
||||
optional bool is_holding_wake_lock_suspend_blocker = 37;
|
||||
// The suspend blocker used to keep the CPU alive when the display is on, the
|
||||
// display is getting ready or there is user activity (in which case the
|
||||
// display must be on).
|
||||
optional bool is_holding_display_suspend_blocker = 39;
|
||||
optional bool is_holding_display_suspend_blocker = 38;
|
||||
// Settings and configuration
|
||||
optional PowerServiceSettingsAndConfigurationDumpProto settings_and_configuration = 40;
|
||||
optional PowerServiceSettingsAndConfigurationDumpProto settings_and_configuration = 39;
|
||||
// Sleep timeout in ms. This can be -1.
|
||||
optional sint32 sleep_timeout_ms = 41;
|
||||
optional sint32 sleep_timeout_ms = 40;
|
||||
// Screen off timeout in ms
|
||||
optional int32 screen_off_timeout_ms = 42;
|
||||
optional int32 screen_off_timeout_ms = 41;
|
||||
// Screen dim duration in ms
|
||||
optional int32 screen_dim_duration_ms = 43;
|
||||
optional int32 screen_dim_duration_ms = 42;
|
||||
// We are currently in the middle of a batch change of uids.
|
||||
optional bool are_uids_changing = 44;
|
||||
optional bool are_uids_changing = 43;
|
||||
// Some uids have actually changed while mUidsChanging was true.
|
||||
optional bool are_uids_changed = 45;
|
||||
optional bool are_uids_changed = 44;
|
||||
// List of UIDs and their states
|
||||
repeated UidStateProto uid_states = 46;
|
||||
optional .android.os.LooperProto looper = 47;
|
||||
repeated UidStateProto uid_states = 45;
|
||||
optional .android.os.LooperProto looper = 46;
|
||||
// List of all wake locks acquired by applications.
|
||||
repeated WakeLockProto wake_locks = 48;
|
||||
repeated WakeLockProto wake_locks = 47;
|
||||
// List of all suspend blockers.
|
||||
repeated SuspendBlockerProto suspend_blockers = 49;
|
||||
optional WirelessChargerDetectorProto wireless_charger_detector = 50;
|
||||
repeated SuspendBlockerProto suspend_blockers = 48;
|
||||
optional WirelessChargerDetectorProto wireless_charger_detector = 49;
|
||||
optional BatterySaverStateMachineProto battery_saver_state_machine = 50;
|
||||
}
|
||||
|
||||
// A com.android.server.power.PowerManagerService.SuspendBlockerImpl object.
|
||||
@@ -270,51 +269,80 @@ message PowerServiceSettingsAndConfigurationDumpProto {
|
||||
optional bool are_dreams_activate_on_dock_setting = 17;
|
||||
// True if doze should not be started until after the screen off transition.
|
||||
optional bool is_doze_after_screen_off_config = 18;
|
||||
// If true, the device is in low power mode.
|
||||
optional bool is_low_power_mode_setting = 19;
|
||||
// Current state of whether the settings are allowing auto low power mode.
|
||||
optional bool is_auto_low_power_mode_configured = 20;
|
||||
// The user turned off low power mode below the trigger level
|
||||
optional bool is_auto_low_power_mode_snoozing = 21;
|
||||
// The minimum screen off timeout, in milliseconds.
|
||||
optional int32 minimum_screen_off_timeout_config_ms = 22;
|
||||
optional int32 minimum_screen_off_timeout_config_ms = 19;
|
||||
// The screen dim duration, in milliseconds.
|
||||
optional int32 maximum_screen_dim_duration_config_ms = 23;
|
||||
optional int32 maximum_screen_dim_duration_config_ms = 20;
|
||||
// The maximum screen dim time expressed as a ratio relative to the screen off timeout.
|
||||
optional float maximum_screen_dim_ratio_config = 24;
|
||||
optional float maximum_screen_dim_ratio_config = 21;
|
||||
// The screen off timeout setting value in milliseconds.
|
||||
optional int32 screen_off_timeout_setting_ms = 25;
|
||||
optional int32 screen_off_timeout_setting_ms = 22;
|
||||
// The sleep timeout setting value in milliseconds. Default value is -1.
|
||||
optional sint32 sleep_timeout_setting_ms = 26;
|
||||
optional sint32 sleep_timeout_setting_ms = 23;
|
||||
// The maximum allowable screen off timeout according to the device administration policy.
|
||||
optional int32 maximum_screen_off_timeout_from_device_admin_ms = 27;
|
||||
optional bool is_maximum_screen_off_timeout_from_device_admin_enforced_locked = 28;
|
||||
optional int32 maximum_screen_off_timeout_from_device_admin_ms = 24;
|
||||
optional bool is_maximum_screen_off_timeout_from_device_admin_enforced_locked = 25;
|
||||
// The stay on while plugged in setting.
|
||||
// A set of battery conditions under which to make the screen stay on.
|
||||
optional StayOnWhilePluggedInProto stay_on_while_plugged_in = 29;
|
||||
optional StayOnWhilePluggedInProto stay_on_while_plugged_in = 26;
|
||||
// The screen brightness mode.
|
||||
optional .android.providers.settings.SettingsProto.ScreenBrightnessMode screen_brightness_mode_setting = 30;
|
||||
optional .android.providers.settings.SettingsProto.ScreenBrightnessMode screen_brightness_mode_setting = 27;
|
||||
// The screen brightness setting override from the window manager
|
||||
// to allow the current foreground activity to override the brightness.
|
||||
// Use -1 to disable.
|
||||
optional sint32 screen_brightness_override_from_window_manager = 31;
|
||||
optional sint32 screen_brightness_override_from_window_manager = 28;
|
||||
// The user activity timeout override from the window manager
|
||||
// to allow the current foreground activity to override the user activity
|
||||
// timeout. Use -1 to disable.
|
||||
optional sint64 user_activity_timeout_override_from_window_manager_ms = 32;
|
||||
optional sint64 user_activity_timeout_override_from_window_manager_ms = 29;
|
||||
// The window manager has determined the user to be inactive via other means.
|
||||
// Set this to false to disable.
|
||||
optional bool is_user_inactive_override_from_window_manager = 33;
|
||||
optional bool is_user_inactive_override_from_window_manager = 30;
|
||||
// The screen state to use while dozing.
|
||||
optional .android.view.DisplayStateEnum doze_screen_state_override_from_dream_manager = 34;
|
||||
optional .android.view.DisplayStateEnum doze_screen_state_override_from_dream_manager = 31;
|
||||
// The screen brightness to use while dozing.
|
||||
optional float dozed_screen_brightness_override_from_dream_manager = 35;
|
||||
optional float dozed_screen_brightness_override_from_dream_manager = 32;
|
||||
// Screen brightness settings limits.
|
||||
optional ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 36;
|
||||
optional ScreenBrightnessSettingLimitsProto screen_brightness_setting_limits = 33;
|
||||
// True if double tap to wake is enabled
|
||||
optional bool is_double_tap_wake_enabled = 37;
|
||||
optional bool is_double_tap_wake_enabled = 34;
|
||||
// True if we are currently in VR Mode.
|
||||
optional bool is_vr_mode_enabled = 38;
|
||||
optional bool is_vr_mode_enabled = 35;
|
||||
// True if Sidekick is controlling the display and we shouldn't change its power mode.
|
||||
optional bool draw_wake_lock_override_from_sidekick = 39;
|
||||
optional bool draw_wake_lock_override_from_sidekick = 36;
|
||||
}
|
||||
|
||||
message BatterySaverStateMachineProto {
|
||||
// Whether battery saver is enabled.
|
||||
optional bool enabled = 1;
|
||||
|
||||
// Whether system has booted.
|
||||
optional bool boot_completed = 2;
|
||||
|
||||
// Whether settings have been loaded already.
|
||||
optional bool settings_loaded = 3;
|
||||
|
||||
// Whether battery status has been set at least once.
|
||||
optional bool battery_status_set = 4;
|
||||
|
||||
// Whether automatic battery saver has been canceled by the user.
|
||||
optional bool battery_saver_snoozing = 5;
|
||||
|
||||
// Whether the device is connected to any power source.
|
||||
optional bool is_powered = 6;
|
||||
|
||||
// Current battery level in %, 0-100.
|
||||
optional int32 battery_level = 7;
|
||||
|
||||
// Whether battery level is low or not.
|
||||
optional bool is_battery_level_low = 8;
|
||||
|
||||
// The value of Global.LOW_POWER_MODE.
|
||||
optional bool setting_battery_saver_enabled = 9;
|
||||
|
||||
// The value of Global.LOW_POWER_MODE_STICKY.
|
||||
optional bool setting_battery_saver_enabled_sticky = 10;
|
||||
|
||||
// The value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
|
||||
optional int32 setting_battery_saver_trigger_threshold = 11;
|
||||
}
|
||||
@@ -266,6 +266,7 @@ public class SettingsBackupTest {
|
||||
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
|
||||
Settings.Global.LOW_POWER_MODE,
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL_MAX,
|
||||
Settings.Global.LOW_POWER_MODE_STICKY,
|
||||
Settings.Global.LTE_SERVICE_FORCED,
|
||||
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
|
||||
Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
|
||||
|
||||
@@ -64,6 +64,7 @@ import android.os.UserManager;
|
||||
import android.os.WorkSource;
|
||||
import android.os.WorkSource.WorkChain;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.provider.Settings.SettingNotFoundException;
|
||||
import android.service.dreams.DreamManagerInternal;
|
||||
import android.service.vr.IVrManager;
|
||||
@@ -97,6 +98,7 @@ import com.android.server.lights.Light;
|
||||
import com.android.server.lights.LightsManager;
|
||||
import com.android.server.policy.WindowManagerPolicy;
|
||||
import com.android.server.power.batterysaver.BatterySaverController;
|
||||
import com.android.server.power.batterysaver.BatterySaverStateMachine;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -225,6 +227,7 @@ public final class PowerManagerService extends SystemService
|
||||
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
|
||||
private final BatterySaverPolicy mBatterySaverPolicy;
|
||||
private final BatterySaverController mBatterySaverController;
|
||||
private final BatterySaverStateMachine mBatterySaverStateMachine;
|
||||
|
||||
private LightsManager mLightsManager;
|
||||
private BatteryManagerInternal mBatteryManagerInternal;
|
||||
@@ -492,18 +495,6 @@ public final class PowerManagerService extends SystemService
|
||||
// Time when we last logged a warning about calling userActivity() without permission.
|
||||
private long mLastWarningAboutUserActivityPermission = Long.MIN_VALUE;
|
||||
|
||||
// If true, the device is in low power mode.
|
||||
private boolean mLowPowerModeEnabled;
|
||||
|
||||
// Current state of the low power mode setting.
|
||||
private boolean mLowPowerModeSetting;
|
||||
|
||||
// Current state of whether the settings are allowing auto low power mode.
|
||||
private boolean mAutoLowPowerModeConfigured;
|
||||
|
||||
// The user turned off low power mode below the trigger level
|
||||
private boolean mAutoLowPowerModeSnoozing;
|
||||
|
||||
// True if the battery level is currently considered low.
|
||||
private boolean mBatteryLevelLow;
|
||||
|
||||
@@ -667,6 +658,7 @@ public final class PowerManagerService extends SystemService
|
||||
mBatterySaverPolicy = new BatterySaverPolicy(mHandler);
|
||||
mBatterySaverController = new BatterySaverController(mContext,
|
||||
BackgroundThread.get().getLooper(), mBatterySaverPolicy);
|
||||
mBatterySaverStateMachine = new BatterySaverStateMachine(mContext, mBatterySaverController);
|
||||
|
||||
synchronized (mLock) {
|
||||
mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks");
|
||||
@@ -704,6 +696,7 @@ public final class PowerManagerService extends SystemService
|
||||
mBatterySaverPolicy = batterySaverPolicy;
|
||||
mBatterySaverController = new BatterySaverController(context,
|
||||
BackgroundThread.getHandler().getLooper(), batterySaverPolicy);
|
||||
mBatterySaverStateMachine = new BatterySaverStateMachine(mContext, mBatterySaverController);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -725,6 +718,8 @@ public final class PowerManagerService extends SystemService
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
mBootCompleted = true;
|
||||
mDirty |= DIRTY_BOOT_COMPLETED;
|
||||
|
||||
mBatterySaverStateMachine.onBootCompleted();
|
||||
userActivityNoUpdateLocked(
|
||||
now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
|
||||
updatePowerStateLocked();
|
||||
@@ -819,12 +814,6 @@ public final class PowerManagerService extends SystemService
|
||||
resolver.registerContentObserver(Settings.System.getUriFor(
|
||||
Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ),
|
||||
false, mSettingsObserver, UserHandle.USER_ALL);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE),
|
||||
false, mSettingsObserver, UserHandle.USER_ALL);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
|
||||
false, mSettingsObserver, UserHandle.USER_ALL);
|
||||
resolver.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.THEATER_MODE_ON),
|
||||
false, mSettingsObserver, UserHandle.USER_ALL);
|
||||
@@ -953,17 +942,6 @@ public final class PowerManagerService extends SystemService
|
||||
Settings.System.SCREEN_BRIGHTNESS_MODE,
|
||||
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
|
||||
|
||||
final boolean lowPowerModeEnabled = Settings.Global.getInt(resolver,
|
||||
Settings.Global.LOW_POWER_MODE, 0) != 0;
|
||||
final boolean autoLowPowerModeConfigured = Settings.Global.getInt(resolver,
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0) != 0;
|
||||
if (lowPowerModeEnabled != mLowPowerModeSetting
|
||||
|| autoLowPowerModeConfigured != mAutoLowPowerModeConfigured) {
|
||||
mLowPowerModeSetting = lowPowerModeEnabled;
|
||||
mAutoLowPowerModeConfigured = autoLowPowerModeConfigured;
|
||||
updateLowPowerModeLocked();
|
||||
}
|
||||
|
||||
mDirty |= DIRTY_SETTINGS;
|
||||
}
|
||||
|
||||
@@ -977,29 +955,6 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLowPowerModeLocked() {
|
||||
if ((mIsPowered || !mBatteryLevelLow && !mBootCompleted) && mLowPowerModeSetting) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "updateLowPowerModeLocked: powered or booting with sufficient battery,"
|
||||
+ " turning setting off");
|
||||
}
|
||||
// Turn setting off if powered
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE, 0);
|
||||
mLowPowerModeSetting = false;
|
||||
}
|
||||
final boolean autoLowPowerModeEnabled = !mIsPowered && mAutoLowPowerModeConfigured
|
||||
&& !mAutoLowPowerModeSnoozing && mBatteryLevelLow;
|
||||
final boolean lowPowerModeEnabled = mLowPowerModeSetting || autoLowPowerModeEnabled;
|
||||
|
||||
if (mLowPowerModeEnabled != lowPowerModeEnabled) {
|
||||
mLowPowerModeEnabled = lowPowerModeEnabled;
|
||||
|
||||
postAfterBootCompleted(() ->
|
||||
mBatterySaverController.enableBatterySaver(mLowPowerModeEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSettingsChangedLocked() {
|
||||
updateSettingsLocked();
|
||||
updatePowerStateLocked();
|
||||
@@ -1751,15 +1706,7 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
if (wasPowered != mIsPowered || oldLevelLow != mBatteryLevelLow) {
|
||||
if (oldLevelLow != mBatteryLevelLow && !mBatteryLevelLow) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "updateIsPoweredLocked: resetting low power snooze");
|
||||
}
|
||||
mAutoLowPowerModeSnoozing = false;
|
||||
}
|
||||
updateLowPowerModeLocked();
|
||||
}
|
||||
mBatterySaverStateMachine.setBatteryStatus(mIsPowered, mBatteryLevel, mBatteryLevelLow);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2733,36 +2680,20 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
|
||||
private boolean isLowPowerModeInternal() {
|
||||
synchronized (mLock) {
|
||||
return mLowPowerModeEnabled;
|
||||
}
|
||||
return mBatterySaverController.isEnabled();
|
||||
}
|
||||
|
||||
private boolean setLowPowerModeInternal(boolean mode) {
|
||||
private boolean setLowPowerModeInternal(boolean enabled) {
|
||||
synchronized (mLock) {
|
||||
if (DEBUG) Slog.d(TAG, "setLowPowerModeInternal " + mode + " mIsPowered=" + mIsPowered);
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setLowPowerModeInternal " + enabled + " mIsPowered=" + mIsPowered);
|
||||
}
|
||||
if (mIsPowered) {
|
||||
return false;
|
||||
}
|
||||
Settings.Global.putInt(mContext.getContentResolver(),
|
||||
Settings.Global.LOW_POWER_MODE, mode ? 1 : 0);
|
||||
mLowPowerModeSetting = mode;
|
||||
|
||||
if (mAutoLowPowerModeConfigured && mBatteryLevelLow) {
|
||||
if (mode && mAutoLowPowerModeSnoozing) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "setLowPowerModeInternal: clearing low power mode snooze");
|
||||
}
|
||||
mAutoLowPowerModeSnoozing = false;
|
||||
} else if (!mode && !mAutoLowPowerModeSnoozing) {
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "setLowPowerModeInternal: snoozing low power mode");
|
||||
}
|
||||
mAutoLowPowerModeSnoozing = true;
|
||||
}
|
||||
}
|
||||
mBatterySaverStateMachine.setBatterySaverEnabledManually(enabled);
|
||||
|
||||
updateLowPowerModeLocked();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -2848,7 +2779,8 @@ public final class PowerManagerService extends SystemService
|
||||
@VisibleForTesting
|
||||
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
|
||||
PowerSaveState state = mBatterySaverPolicy.
|
||||
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS, mLowPowerModeEnabled);
|
||||
getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS,
|
||||
mBatterySaverController.isEnabled());
|
||||
displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
|
||||
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
|
||||
}
|
||||
@@ -3325,7 +3257,6 @@ public final class PowerManagerService extends SystemService
|
||||
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
|
||||
pw.println(" mSandmanScheduled=" + mSandmanScheduled);
|
||||
pw.println(" mSandmanSummoned=" + mSandmanSummoned);
|
||||
pw.println(" mLowPowerModeEnabled=" + mLowPowerModeEnabled);
|
||||
pw.println(" mBatteryLevelLow=" + mBatteryLevelLow);
|
||||
pw.println(" mLightDeviceIdleMode=" + mLightDeviceIdleMode);
|
||||
pw.println(" mDeviceIdleMode=" + mDeviceIdleMode);
|
||||
@@ -3378,9 +3309,6 @@ public final class PowerManagerService extends SystemService
|
||||
pw.println(" mDreamsActivateOnSleepSetting=" + mDreamsActivateOnSleepSetting);
|
||||
pw.println(" mDreamsActivateOnDockSetting=" + mDreamsActivateOnDockSetting);
|
||||
pw.println(" mDozeAfterScreenOff=" + mDozeAfterScreenOff);
|
||||
pw.println(" mLowPowerModeSetting=" + mLowPowerModeSetting);
|
||||
pw.println(" mAutoLowPowerModeConfigured=" + mAutoLowPowerModeConfigured);
|
||||
pw.println(" mAutoLowPowerModeSnoozing=" + mAutoLowPowerModeSnoozing);
|
||||
pw.println(" mMinimumScreenOffTimeoutConfig=" + mMinimumScreenOffTimeoutConfig);
|
||||
pw.println(" mMaximumScreenDimDurationConfig=" + mMaximumScreenDimDurationConfig);
|
||||
pw.println(" mMaximumScreenDimRatioConfig=" + mMaximumScreenDimRatioConfig);
|
||||
@@ -3456,6 +3384,7 @@ public final class PowerManagerService extends SystemService
|
||||
pw.println("Display Power: " + mDisplayPowerCallbacks);
|
||||
|
||||
mBatterySaverPolicy.dump(pw);
|
||||
mBatterySaverStateMachine.dump(pw);
|
||||
|
||||
pw.println();
|
||||
final int numProfiles = mProfilePowerState.size();
|
||||
@@ -3557,7 +3486,6 @@ public final class PowerManagerService extends SystemService
|
||||
mRequestWaitForNegativeProximity);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SCHEDULED, mSandmanScheduled);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_SANDMAN_SUMMONED, mSandmanSummoned);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_LOW_POWER_MODE_ENABLED, mLowPowerModeEnabled);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_BATTERY_LEVEL_LOW, mBatteryLevelLow);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_LIGHT_DEVICE_IDLE_MODE, mLightDeviceIdleMode);
|
||||
proto.write(PowerManagerServiceDumpProto.IS_DEVICE_IDLE_MODE, mDeviceIdleMode);
|
||||
@@ -3662,15 +3590,6 @@ public final class PowerManagerService extends SystemService
|
||||
proto.write(
|
||||
PowerServiceSettingsAndConfigurationDumpProto.IS_DOZE_AFTER_SCREEN_OFF_CONFIG,
|
||||
mDozeAfterScreenOff);
|
||||
proto.write(
|
||||
PowerServiceSettingsAndConfigurationDumpProto.IS_LOW_POWER_MODE_SETTING,
|
||||
mLowPowerModeSetting);
|
||||
proto.write(
|
||||
PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_CONFIGURED,
|
||||
mAutoLowPowerModeConfigured);
|
||||
proto.write(
|
||||
PowerServiceSettingsAndConfigurationDumpProto.IS_AUTO_LOW_POWER_MODE_SNOOZING,
|
||||
mAutoLowPowerModeSnoozing);
|
||||
proto.write(
|
||||
PowerServiceSettingsAndConfigurationDumpProto
|
||||
.MINIMUM_SCREEN_OFF_TIMEOUT_CONFIG_MS,
|
||||
@@ -3792,6 +3711,9 @@ public final class PowerManagerService extends SystemService
|
||||
proto.end(uIDToken);
|
||||
}
|
||||
|
||||
mBatterySaverStateMachine.dumpProto(proto,
|
||||
PowerManagerServiceDumpProto.BATTERY_SAVER_STATE_MACHINE);
|
||||
|
||||
mHandler.getLooper().writeToProto(proto, PowerManagerServiceDumpProto.LOOPER);
|
||||
|
||||
for (WakeLock wl : mWakeLocks) {
|
||||
@@ -4432,12 +4354,12 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public boolean setPowerSaveMode(boolean mode) {
|
||||
public boolean setPowerSaveMode(boolean enabled) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.DEVICE_POWER, null);
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return setLowPowerModeInternal(mode);
|
||||
return setLowPowerModeInternal(enabled);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(ident);
|
||||
}
|
||||
@@ -4752,7 +4674,8 @@ public final class PowerManagerService extends SystemService
|
||||
@Override
|
||||
public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
|
||||
synchronized (mLock) {
|
||||
return mBatterySaverPolicy.getBatterySaverPolicy(serviceType, mLowPowerModeEnabled);
|
||||
return mBatterySaverPolicy.getBatterySaverPolicy(serviceType,
|
||||
mBatterySaverController.isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* 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 android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.ContentObserver;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
import android.provider.Settings.Global;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.power.BatterySaverPolicy;
|
||||
import com.android.server.power.BatterySaverStateMachineProto;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Decides when to enable / disable battery saver.
|
||||
*
|
||||
* (n.b. This isn't really implemented as a "state machine" though.)
|
||||
*
|
||||
* Test:
|
||||
atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
|
||||
*/
|
||||
public class BatterySaverStateMachine {
|
||||
private static final String TAG = "BatterySaverStateMachine";
|
||||
private final Object mLock = new Object();
|
||||
|
||||
private static final boolean DEBUG = BatterySaverPolicy.DEBUG;
|
||||
|
||||
private final Context mContext;
|
||||
private final BatterySaverController mBatterySaverController;
|
||||
|
||||
/** Whether the system has booted. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mBootCompleted;
|
||||
|
||||
/** Whether global settings have been loaded already. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mSettingsLoaded;
|
||||
|
||||
/** Whether the first battery status has arrived. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mBatteryStatusSet;
|
||||
|
||||
/** Whether the device is connected to any power source. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mIsPowered;
|
||||
|
||||
/** Current battery level in %, 0-100. (Currently only used in dumpsys.) */
|
||||
@GuardedBy("mLock")
|
||||
private int mBatteryLevel;
|
||||
|
||||
/** Whether the battery level is considered to be "low" or not.*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean mIsBatteryLevelLow;
|
||||
|
||||
/** Previously known value of Global.LOW_POWER_MODE. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mSettingBatterySaverEnabled;
|
||||
|
||||
/** Previously known value of Global.LOW_POWER_MODE_STICKY. */
|
||||
@GuardedBy("mLock")
|
||||
private boolean mSettingBatterySaverEnabledSticky;
|
||||
|
||||
/**
|
||||
* Previously known value of Global.LOW_POWER_MODE_TRIGGER_LEVEL.
|
||||
* (Currently only used in dumpsys.)
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private int mSettingBatterySaverTriggerThreshold;
|
||||
|
||||
/**
|
||||
* Whether BS has been manually disabled while the battery level is low, in which case we
|
||||
* shouldn't auto re-enable it until the battery level is not low.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean mBatterySaverSnoozing;
|
||||
|
||||
private final ContentObserver mSettingsObserver = new ContentObserver(null) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
synchronized (mLock) {
|
||||
refreshSettingsLocked();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public BatterySaverStateMachine(
|
||||
Context context, BatterySaverController batterySaverController) {
|
||||
mContext = context;
|
||||
mBatterySaverController = batterySaverController;
|
||||
}
|
||||
|
||||
private boolean isBatterySaverEnabled() {
|
||||
return mBatterySaverController.isEnabled();
|
||||
}
|
||||
|
||||
private boolean isAutoBatterySaverConfigured() {
|
||||
return mSettingBatterySaverTriggerThreshold > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link com.android.server.power.PowerManagerService} calls it when the system is booted.
|
||||
*/
|
||||
public void onBootCompleted() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "onBootCompleted");
|
||||
}
|
||||
synchronized (mLock) {
|
||||
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
cr.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE),
|
||||
false, mSettingsObserver, UserHandle.USER_SYSTEM);
|
||||
cr.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE_STICKY),
|
||||
false, mSettingsObserver, UserHandle.USER_SYSTEM);
|
||||
cr.registerContentObserver(Settings.Global.getUriFor(
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
|
||||
false, mSettingsObserver, UserHandle.USER_SYSTEM);
|
||||
|
||||
mBootCompleted = true;
|
||||
|
||||
refreshSettingsLocked();
|
||||
|
||||
doAutoBatterySaverLocked();
|
||||
}
|
||||
}
|
||||
|
||||
void refreshSettingsLocked() {
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
|
||||
final boolean lowPowerModeEnabled = getGlobalSetting(
|
||||
Settings.Global.LOW_POWER_MODE, 0) != 0;
|
||||
final boolean lowPowerModeEnabledSticky = getGlobalSetting(
|
||||
Settings.Global.LOW_POWER_MODE_STICKY, 0) != 0;
|
||||
final int lowPowerModeTriggerLevel = getGlobalSetting(
|
||||
Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
||||
|
||||
setSettingsLocked(lowPowerModeEnabled, lowPowerModeEnabledSticky,
|
||||
lowPowerModeTriggerLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link com.android.server.power.PowerManagerService} calls it when relevant global settings
|
||||
* have changed.
|
||||
*
|
||||
* Note this will be called before {@link #onBootCompleted} too.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void setSettingsLocked(boolean batterySaverEnabled, boolean batterySaverEnabledSticky,
|
||||
int batterySaverTriggerThreshold) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setSettings: enabled=" + batterySaverEnabled
|
||||
+ " sticky=" + batterySaverEnabledSticky
|
||||
+ " threshold=" + batterySaverTriggerThreshold);
|
||||
}
|
||||
|
||||
mSettingsLoaded = true;
|
||||
|
||||
final boolean enabledChanged = mSettingBatterySaverEnabled != batterySaverEnabled;
|
||||
final boolean stickyChanged =
|
||||
mSettingBatterySaverEnabledSticky != batterySaverEnabledSticky;
|
||||
final boolean thresholdChanged
|
||||
= mSettingBatterySaverTriggerThreshold != batterySaverTriggerThreshold;
|
||||
|
||||
if (!(enabledChanged || stickyChanged || thresholdChanged)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSettingBatterySaverEnabled = batterySaverEnabled;
|
||||
mSettingBatterySaverEnabledSticky = batterySaverEnabledSticky;
|
||||
mSettingBatterySaverTriggerThreshold = batterySaverTriggerThreshold;
|
||||
|
||||
if (enabledChanged) {
|
||||
final String reason = batterySaverEnabled
|
||||
? "Global.low_power changed to 1" : "Global.low_power changed to 0";
|
||||
enableBatterySaverLocked(/*enable=*/ batterySaverEnabled, /*manual=*/ true,
|
||||
reason);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link com.android.server.power.PowerManagerService} calls it when battery state changes.
|
||||
*
|
||||
* Note this may be called before {@link #onBootCompleted} too.
|
||||
*/
|
||||
public void setBatteryStatus(boolean newPowered, int newLevel, boolean newBatteryLevelLow) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setBatteryStatus: powered=" + newPowered + " level=" + newLevel
|
||||
+ " low=" + newBatteryLevelLow);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
mBatteryStatusSet = true;
|
||||
|
||||
final boolean poweredChanged = mIsPowered != newPowered;
|
||||
final boolean levelChanged = mBatteryLevel != newLevel;
|
||||
final boolean lowChanged = mIsBatteryLevelLow != newBatteryLevelLow;
|
||||
|
||||
if (!(poweredChanged || levelChanged || lowChanged)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIsPowered = newPowered;
|
||||
mBatteryLevel = newLevel;
|
||||
mIsBatteryLevelLow = newBatteryLevelLow;
|
||||
|
||||
doAutoBatterySaverLocked();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether to auto-start / stop battery saver.
|
||||
*/
|
||||
private void doAutoBatterySaverLocked() {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "doAutoBatterySaverLocked: mBootCompleted=" + mBootCompleted
|
||||
+ " mSettingsLoaded=" + mSettingsLoaded
|
||||
+ " mBatteryStatusSet=" + mBatteryStatusSet
|
||||
+ " mIsBatteryLevelLow=" + mIsBatteryLevelLow
|
||||
+ " mBatterySaverSnoozing=" + mBatterySaverSnoozing
|
||||
+ " mIsPowered=" + mIsPowered
|
||||
+ " mSettingBatterySaverEnabledSticky=" + mSettingBatterySaverEnabledSticky);
|
||||
}
|
||||
if (!(mBootCompleted && mSettingsLoaded && mBatteryStatusSet)) {
|
||||
return; // Not fully initialized yet.
|
||||
}
|
||||
if (!mIsBatteryLevelLow) {
|
||||
updateSnoozingLocked(false, "Battery not low");
|
||||
}
|
||||
if (mIsPowered) {
|
||||
updateSnoozingLocked(false, "Plugged in");
|
||||
enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false, "Plugged in");
|
||||
|
||||
} else if (mSettingBatterySaverEnabledSticky) {
|
||||
// Re-enable BS.
|
||||
enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ true, "Sticky restore");
|
||||
|
||||
} else if (mIsBatteryLevelLow) {
|
||||
if (!mBatterySaverSnoozing && isAutoBatterySaverConfigured()) {
|
||||
enableBatterySaverLocked(/*enable=*/ true, /*manual=*/ false, "Auto ON");
|
||||
}
|
||||
} else { // Battery not low
|
||||
enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false, "Auto OFF");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link com.android.server.power.PowerManagerService} calls it when
|
||||
* {@link android.os.PowerManager#setPowerSaveMode} is called.
|
||||
*
|
||||
* Note this could? be called before {@link #onBootCompleted} too.
|
||||
*/
|
||||
public void setBatterySaverEnabledManually(boolean enabled) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "setBatterySaverEnabledManually: enabled=" + enabled);
|
||||
}
|
||||
synchronized (mLock) {
|
||||
enableBatterySaverLocked(/*enable=*/ enabled, /*manual=*/ true,
|
||||
(enabled ? "Manual ON" : "Manual OFF"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually enable / disable battery saver. Write the new state to the global settings
|
||||
* and propagate it to {@link #mBatterySaverController}.
|
||||
*/
|
||||
private void enableBatterySaverLocked(boolean enable, boolean manual, String reason) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "enableBatterySaver: enable=" + enable + " manual=" + manual
|
||||
+ " reason=" + reason);
|
||||
}
|
||||
final boolean wasEnabled = mBatterySaverController.isEnabled();
|
||||
|
||||
if (wasEnabled == enable) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Already " + (enable ? "enabled" : "disabled"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (enable && mIsPowered) {
|
||||
if (DEBUG) Slog.d(TAG, "Can't enable: isPowered");
|
||||
return;
|
||||
}
|
||||
|
||||
if (manual) {
|
||||
if (enable) {
|
||||
updateSnoozingLocked(false, "Manual snooze OFF");
|
||||
} else {
|
||||
// When battery saver is disabled manually (while battery saver is enabled)
|
||||
// when the battery level is low, we "snooze" BS -- i.e. disable auto battery saver.
|
||||
// We resume auto-BS once the battery level is not low, or the device is plugged in.
|
||||
if (isBatterySaverEnabled() && mIsBatteryLevelLow) {
|
||||
updateSnoozingLocked(true, "Manual snooze");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mSettingBatterySaverEnabled = enable;
|
||||
putGlobalSetting(Global.LOW_POWER_MODE, enable ? 1 : 0);
|
||||
|
||||
if (manual) {
|
||||
mSettingBatterySaverEnabledSticky = enable;
|
||||
putGlobalSetting(Global.LOW_POWER_MODE_STICKY, enable ? 1 : 0);
|
||||
}
|
||||
mBatterySaverController.enableBatterySaver(enable);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Battery saver: Enabled=" + enable
|
||||
+ " manual=" + manual
|
||||
+ " reason=" + reason);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSnoozingLocked(boolean snoozing, String reason) {
|
||||
if (mBatterySaverSnoozing == snoozing) {
|
||||
return;
|
||||
}
|
||||
if (DEBUG) Slog.d(TAG, "Snooze: " + (snoozing ? "start" : "stop") + " reason=" + reason);
|
||||
mBatterySaverSnoozing = snoozing;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected void putGlobalSetting(String key, int value) {
|
||||
Global.putInt(mContext.getContentResolver(), key, value);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
protected int getGlobalSetting(String key, int defValue) {
|
||||
return Global.getInt(mContext.getContentResolver(), key, defValue);
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
synchronized (mLock) {
|
||||
pw.println();
|
||||
pw.println("Battery saver state machine:");
|
||||
|
||||
pw.print(" Enabled=");
|
||||
pw.println(mBatterySaverController.isEnabled());
|
||||
|
||||
pw.print(" mBootCompleted=");
|
||||
pw.println(mBootCompleted);
|
||||
pw.print(" mSettingsLoaded=");
|
||||
pw.println(mSettingsLoaded);
|
||||
pw.print(" mBatteryStatusSet=");
|
||||
pw.println(mBatteryStatusSet);
|
||||
|
||||
pw.print(" mBatterySaverSnoozing=");
|
||||
pw.println(mBatterySaverSnoozing);
|
||||
|
||||
pw.print(" mIsPowered=");
|
||||
pw.println(mIsPowered);
|
||||
pw.print(" mBatteryLevel=");
|
||||
pw.println(mBatteryLevel);
|
||||
pw.print(" mIsBatteryLevelLow=");
|
||||
pw.println(mIsBatteryLevelLow);
|
||||
|
||||
pw.print(" mSettingBatterySaverEnabled=");
|
||||
pw.println(mSettingBatterySaverEnabled);
|
||||
pw.print(" mSettingBatterySaverEnabledSticky=");
|
||||
pw.println(mSettingBatterySaverEnabledSticky);
|
||||
pw.print(" mSettingBatterySaverTriggerThreshold=");
|
||||
pw.println(mSettingBatterySaverTriggerThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpProto(ProtoOutputStream proto, long tag) {
|
||||
synchronized (mLock) {
|
||||
final long token = proto.start(tag);
|
||||
|
||||
proto.write(BatterySaverStateMachineProto.ENABLED,
|
||||
mBatterySaverController.isEnabled());
|
||||
|
||||
proto.write(BatterySaverStateMachineProto.BOOT_COMPLETED, mBootCompleted);
|
||||
proto.write(BatterySaverStateMachineProto.SETTINGS_LOADED, mSettingsLoaded);
|
||||
proto.write(BatterySaverStateMachineProto.BATTERY_STATUS_SET, mBatteryStatusSet);
|
||||
|
||||
proto.write(BatterySaverStateMachineProto.BATTERY_SAVER_SNOOZING,
|
||||
mBatterySaverSnoozing);
|
||||
|
||||
proto.write(BatterySaverStateMachineProto.IS_POWERED, mIsPowered);
|
||||
proto.write(BatterySaverStateMachineProto.BATTERY_LEVEL, mBatteryLevel);
|
||||
proto.write(BatterySaverStateMachineProto.IS_BATTERY_LEVEL_LOW, mIsBatteryLevelLow);
|
||||
|
||||
proto.write(BatterySaverStateMachineProto.SETTING_BATTERY_SAVER_ENABLED,
|
||||
mSettingBatterySaverEnabled);
|
||||
proto.write(BatterySaverStateMachineProto.SETTING_BATTERY_SAVER_ENABLED_STICKY,
|
||||
mSettingBatterySaverEnabledSticky);
|
||||
proto.write(BatterySaverStateMachineProto.SETTING_BATTERY_SAVER_TRIGGER_THRESHOLD,
|
||||
mSettingBatterySaverTriggerThreshold);
|
||||
|
||||
proto.end(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
* 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.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.provider.Settings.Global;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.test.mock.MockContext;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class BatterySaverStateMachineTest {
|
||||
|
||||
private MyMockContext mMockContext;
|
||||
private ContentResolver mMockContextResolver;
|
||||
private BatterySaverController mMockBatterySaverController;
|
||||
private Device mDevice;
|
||||
private TestableBatterySaverStateMachine mTarget;
|
||||
|
||||
private class MyMockContext extends MockContext {
|
||||
@Override
|
||||
public ContentResolver getContentResolver() {
|
||||
return mMockContextResolver;
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
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 {
|
||||
public TestableBatterySaverStateMachine() {
|
||||
super(mMockContext, mMockBatterySaverController);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void putGlobalSetting(String key, int value) {
|
||||
if (Objects.equal(mPersistedState.global.get(key), value)) {
|
||||
return;
|
||||
}
|
||||
mDevice.putGlobalSetting(key, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getGlobalSetting(String key, int defValue) {
|
||||
return mDevice.getGlobalSetting(key, defValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mMockContext = new MyMockContext();
|
||||
mMockContextResolver = mock(ContentResolver.class);
|
||||
mMockBatterySaverController = mock(BatterySaverController.class);
|
||||
|
||||
doAnswer((inv) -> mDevice.batterySaverEnabled = inv.getArgument(0))
|
||||
.when(mMockBatterySaverController).enableBatterySaver(anyBoolean());
|
||||
when(mMockBatterySaverController.isEnabled())
|
||||
.thenAnswer((inv) -> mDevice.batterySaverEnabled);
|
||||
|
||||
mPersistedState = new DevicePersistedState();
|
||||
initDevice();
|
||||
}
|
||||
|
||||
private void initDevice() {
|
||||
mDevice = new Device();
|
||||
|
||||
mTarget = new TestableBatterySaverStateMachine();
|
||||
|
||||
mDevice.pushBatteryStatus();
|
||||
mDevice.pushGlobalSettings();
|
||||
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);
|
||||
|
||||
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() {
|
||||
mDevice.putGlobalSetting(Global.LOW_POWER_MODE_TRIGGER_LEVEL, 50);
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user