Merge "Adding support for adaptive battery saver."
diff --git a/api/system-current.txt b/api/system-current.txt
index 2ffe8e2..de263ca 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4963,6 +4963,53 @@
field public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
}
+ public final class BatterySaverPolicyConfig implements android.os.Parcelable {
+ method public int describeContents();
+ method public float getAdjustBrightnessFactor();
+ method public boolean getAdvertiseIsEnabled();
+ method public boolean getDeferFullBackup();
+ method public boolean getDeferKeyValueBackup();
+ method @NonNull public java.util.Map<java.lang.String,java.lang.String> getDeviceSpecificSettings();
+ method public boolean getDisableAnimation();
+ method public boolean getDisableAod();
+ method public boolean getDisableLaunchBoost();
+ method public boolean getDisableOptionalSensors();
+ method public boolean getDisableSoundTrigger();
+ method public boolean getDisableVibration();
+ method public boolean getEnableAdjustBrightness();
+ method public boolean getEnableDataSaver();
+ method public boolean getEnableFirewall();
+ method public boolean getEnableQuickDoze();
+ method public boolean getForceAllAppsStandby();
+ method public boolean getForceBackgroundCheck();
+ method public int getGpsMode();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.os.BatterySaverPolicyConfig> CREATOR;
+ }
+
+ public static final class BatterySaverPolicyConfig.Builder {
+ ctor public BatterySaverPolicyConfig.Builder();
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder addDeviceSpecificSetting(@NonNull String, @NonNull String);
+ method @NonNull public android.os.BatterySaverPolicyConfig build();
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setAdjustBrightnessFactor(float);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setAdvertiseIsEnabled(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDeferFullBackup(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDeferKeyValueBackup(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableAnimation(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableAod(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableLaunchBoost(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableOptionalSensors(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableSoundTrigger(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setDisableVibration(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableAdjustBrightness(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableDataSaver(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableFirewall(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setEnableQuickDoze(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setForceAllAppsStandby(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setForceBackgroundCheck(boolean);
+ method @NonNull public android.os.BatterySaverPolicyConfig.Builder setGpsMode(int);
+ }
+
public class Binder implements android.os.IBinder {
method public static final long clearCallingWorkSource();
method public static final int getCallingWorkSourceUid();
@@ -5238,6 +5285,8 @@
public final class PowerManager {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveMode();
+ method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSaveEnabled(boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setAdaptivePowerSavePolicy(@NonNull android.os.BatterySaverPolicyConfig);
method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public boolean setDynamicPowerSavings(boolean, int);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.POWER_SAVER}) public boolean setPowerSaveMode(boolean);
method @RequiresPermission(anyOf={android.Manifest.permission.DEVICE_POWER, android.Manifest.permission.USER_ACTIVITY}) public void userActivity(long, int, int);
diff --git a/core/java/android/os/BatterySaverPolicyConfig.aidl b/core/java/android/os/BatterySaverPolicyConfig.aidl
new file mode 100644
index 0000000..37c66d0
--- /dev/null
+++ b/core/java/android/os/BatterySaverPolicyConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 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 android.os;
+
+parcelable BatterySaverPolicyConfig;
diff --git a/core/java/android/os/BatterySaverPolicyConfig.java b/core/java/android/os/BatterySaverPolicyConfig.java
new file mode 100644
index 0000000..b6e2b69
--- /dev/null
+++ b/core/java/android/os/BatterySaverPolicyConfig.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2019 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 android.os;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Config to set Battery Saver policy flags.
+ *
+ * @hide
+ */
+@SystemApi
+public final class BatterySaverPolicyConfig implements Parcelable {
+ private final float mAdjustBrightnessFactor;
+ private final boolean mAdvertiseIsEnabled;
+ private final boolean mDeferFullBackup;
+ private final boolean mDeferKeyValueBackup;
+ @NonNull
+ private final Map<String, String> mDeviceSpecificSettings;
+ private final boolean mDisableAnimation;
+ private final boolean mDisableAod;
+ private final boolean mDisableLaunchBoost;
+ private final boolean mDisableOptionalSensors;
+ private final boolean mDisableSoundTrigger;
+ private final boolean mDisableVibration;
+ private final boolean mEnableAdjustBrightness;
+ private final boolean mEnableDataSaver;
+ private final boolean mEnableFirewall;
+ private final boolean mEnableQuickDoze;
+ private final boolean mForceAllAppsStandby;
+ private final boolean mForceBackgroundCheck;
+ private final int mGpsMode;
+
+ private BatterySaverPolicyConfig(Builder in) {
+ mAdjustBrightnessFactor = Math.max(0, Math.min(in.mAdjustBrightnessFactor, 1f));
+ mAdvertiseIsEnabled = in.mAdvertiseIsEnabled;
+ mDeferFullBackup = in.mDeferFullBackup;
+ mDeferKeyValueBackup = in.mDeferKeyValueBackup;
+ mDeviceSpecificSettings = Collections.unmodifiableMap(in.mDeviceSpecificSettings);
+ mDisableAnimation = in.mDisableAnimation;
+ mDisableAod = in.mDisableAod;
+ mDisableLaunchBoost = in.mDisableLaunchBoost;
+ mDisableOptionalSensors = in.mDisableOptionalSensors;
+ mDisableSoundTrigger = in.mDisableSoundTrigger;
+ mDisableVibration = in.mDisableVibration;
+ mEnableAdjustBrightness = in.mEnableAdjustBrightness;
+ mEnableDataSaver = in.mEnableDataSaver;
+ mEnableFirewall = in.mEnableFirewall;
+ mEnableQuickDoze = in.mEnableQuickDoze;
+ mForceAllAppsStandby = in.mForceAllAppsStandby;
+ mForceBackgroundCheck = in.mForceBackgroundCheck;
+ mGpsMode = Math.max(PowerManager.MIN_LOCATION_MODE,
+ Math.min(in.mGpsMode, PowerManager.MAX_LOCATION_MODE));
+ }
+
+ private BatterySaverPolicyConfig(Parcel in) {
+ mAdjustBrightnessFactor = Math.max(0, Math.min(in.readFloat(), 1f));
+ mAdvertiseIsEnabled = in.readBoolean();
+ mDeferFullBackup = in.readBoolean();
+ mDeferKeyValueBackup = in.readBoolean();
+
+ final int size = in.readInt();
+ Map<String, String> deviceSpecificSettings = new ArrayMap<>(size);
+ for (int i = 0; i < size; ++i) {
+ String key = TextUtils.emptyIfNull(in.readString());
+ String val = TextUtils.emptyIfNull(in.readString());
+ if (key.trim().isEmpty()) {
+ continue;
+ }
+ deviceSpecificSettings.put(key, val);
+ }
+ mDeviceSpecificSettings = Collections.unmodifiableMap(deviceSpecificSettings);
+
+ mDisableAnimation = in.readBoolean();
+ mDisableAod = in.readBoolean();
+ mDisableLaunchBoost = in.readBoolean();
+ mDisableOptionalSensors = in.readBoolean();
+ mDisableSoundTrigger = in.readBoolean();
+ mDisableVibration = in.readBoolean();
+ mEnableAdjustBrightness = in.readBoolean();
+ mEnableDataSaver = in.readBoolean();
+ mEnableFirewall = in.readBoolean();
+ mEnableQuickDoze = in.readBoolean();
+ mForceAllAppsStandby = in.readBoolean();
+ mForceBackgroundCheck = in.readBoolean();
+ mGpsMode = Math.max(PowerManager.MIN_LOCATION_MODE,
+ Math.min(in.readInt(), PowerManager.MAX_LOCATION_MODE));
+ }
+
+ public static final Creator<BatterySaverPolicyConfig> CREATOR =
+ new Creator<BatterySaverPolicyConfig>() {
+ @Override
+ public BatterySaverPolicyConfig createFromParcel(Parcel in) {
+ return new BatterySaverPolicyConfig(in);
+ }
+
+ @Override
+ public BatterySaverPolicyConfig[] newArray(int size) {
+ return new BatterySaverPolicyConfig[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeFloat(mAdjustBrightnessFactor);
+ dest.writeBoolean(mAdvertiseIsEnabled);
+ dest.writeBoolean(mDeferFullBackup);
+ dest.writeBoolean(mDeferKeyValueBackup);
+
+ final Set<Map.Entry<String, String>> entries = mDeviceSpecificSettings.entrySet();
+ final int size = entries.size();
+ dest.writeInt(size);
+ for (Map.Entry<String, String> entry : entries) {
+ dest.writeString(entry.getKey());
+ dest.writeString(entry.getValue());
+ }
+
+ dest.writeBoolean(mDisableAnimation);
+ dest.writeBoolean(mDisableAod);
+ dest.writeBoolean(mDisableLaunchBoost);
+ dest.writeBoolean(mDisableOptionalSensors);
+ dest.writeBoolean(mDisableSoundTrigger);
+ dest.writeBoolean(mDisableVibration);
+ dest.writeBoolean(mEnableAdjustBrightness);
+ dest.writeBoolean(mEnableDataSaver);
+ dest.writeBoolean(mEnableFirewall);
+ dest.writeBoolean(mEnableQuickDoze);
+ dest.writeBoolean(mForceAllAppsStandby);
+ dest.writeBoolean(mForceBackgroundCheck);
+ dest.writeInt(mGpsMode);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ for (Map.Entry<String, String> entry : mDeviceSpecificSettings.entrySet()) {
+ sb.append(entry.getKey()).append("=").append(entry.getValue()).append(",");
+ }
+ return "adjust_brightness_disabled=" + !mEnableAdjustBrightness + ","
+ + "adjust_brightness_factor=" + mAdjustBrightnessFactor + ","
+ + "advertise_is_enabled=" + mAdvertiseIsEnabled + ","
+ + "animation_disabled=" + mDisableAnimation + ","
+ + "aod_disabled=" + mDisableAod + ","
+ + "datasaver_disabled=" + !mEnableDataSaver + ","
+ + "firewall_disabled=" + !mEnableFirewall + ","
+ + "force_all_apps_standby=" + mForceAllAppsStandby + ","
+ + "force_background_check=" + mForceBackgroundCheck + ","
+ + "fullbackup_deferred=" + mDeferFullBackup + ","
+ + "gps_mode=" + mGpsMode + ","
+ + "keyvaluebackup_deferred=" + mDeferKeyValueBackup + ","
+ + "launch_boost_disabled=" + mDisableLaunchBoost + ","
+ + "optional_sensors_disabled=" + mDisableOptionalSensors + ","
+ + "quick_doze_enabled=" + mEnableQuickDoze + ","
+ + "soundtrigger_disabled=" + mDisableSoundTrigger + ","
+ + "vibration_disabled=" + mDisableVibration + ","
+ + sb.toString();
+ }
+
+ /**
+ * How much to adjust the screen brightness while in Battery Saver. This will have no effect
+ * if {@link #getEnableAdjustBrightness()} is {@code false}.
+ */
+ public float getAdjustBrightnessFactor() {
+ return mAdjustBrightnessFactor;
+ }
+
+ /**
+ * Whether or not to tell the system (and other apps) that Battery Saver is currently enabled.
+ */
+ public boolean getAdvertiseIsEnabled() {
+ return mAdvertiseIsEnabled;
+ }
+
+ /** Whether or not to defer full backup while in Battery Saver. */
+ public boolean getDeferFullBackup() {
+ return mDeferFullBackup;
+ }
+
+ /** Whether or not to defer key-value backup while in Battery Saver. */
+ public boolean getDeferKeyValueBackup() {
+ return mDeferKeyValueBackup;
+ }
+
+ /**
+ * Returns the device-specific battery saver constants.
+ */
+ @NonNull
+ public Map<String, String> getDeviceSpecificSettings() {
+ return mDeviceSpecificSettings;
+ }
+
+ /** Whether or not to disable animation while in Battery Saver. */
+ public boolean getDisableAnimation() {
+ return mDisableAnimation;
+ }
+
+ /** Whether or not to disable Always On Display while in Battery Saver. */
+ public boolean getDisableAod() {
+ return mDisableAod;
+ }
+
+ /** Whether or not to disable launch boost while in Battery Saver. */
+ public boolean getDisableLaunchBoost() {
+ return mDisableLaunchBoost;
+ }
+
+ /** Whether or not to disable optional sensors while in Battery Saver. */
+ public boolean getDisableOptionalSensors() {
+ return mDisableOptionalSensors;
+ }
+
+ /** Whether or not to disable sound trigger while in Battery Saver. */
+ public boolean getDisableSoundTrigger() {
+ return mDisableSoundTrigger;
+ }
+
+ /** Whether or not to disable vibration while in Battery Saver. */
+ public boolean getDisableVibration() {
+ return mDisableVibration;
+ }
+
+ /** Whether or not to enable brightness adjustment while in Battery Saver. */
+ public boolean getEnableAdjustBrightness() {
+ return mEnableAdjustBrightness;
+ }
+
+ /** Whether or not to enable Data Saver while in Battery Saver. */
+ public boolean getEnableDataSaver() {
+ return mEnableDataSaver;
+ }
+
+ /** Whether or not to enable the network firewall while in Battery Saver. */
+ public boolean getEnableFirewall() {
+ return mEnableFirewall;
+ }
+
+ /** Whether or not to enable Quick Doze while in Battery Saver. */
+ public boolean getEnableQuickDoze() {
+ return mEnableQuickDoze;
+ }
+
+ /** Whether or not to force all apps to standby mode while in Battery Saver. */
+ public boolean getForceAllAppsStandby() {
+ return mForceAllAppsStandby;
+ }
+
+ /** Whether or not to force background check while in Battery Saver. */
+ public boolean getForceBackgroundCheck() {
+ return mForceBackgroundCheck;
+ }
+
+ /** The GPS mode while in Battery Saver. */
+ public int getGpsMode() {
+ return mGpsMode;
+ }
+
+ /** Builder class for constructing {@link BatterySaverPolicyConfig} objects. */
+ public static final class Builder {
+ private float mAdjustBrightnessFactor = 1f;
+ private boolean mAdvertiseIsEnabled = false;
+ private boolean mDeferFullBackup = false;
+ private boolean mDeferKeyValueBackup = false;
+ @NonNull
+ private final ArrayMap<String, String> mDeviceSpecificSettings = new ArrayMap<>();
+ private boolean mDisableAnimation = false;
+ private boolean mDisableAod = false;
+ private boolean mDisableLaunchBoost = false;
+ private boolean mDisableOptionalSensors = false;
+ private boolean mDisableSoundTrigger = false;
+ private boolean mDisableVibration = false;
+ private boolean mEnableAdjustBrightness = false;
+ private boolean mEnableDataSaver = false;
+ private boolean mEnableFirewall = false;
+ private boolean mEnableQuickDoze = false;
+ private boolean mForceAllAppsStandby = false;
+ private boolean mForceBackgroundCheck = false;
+ private int mGpsMode = PowerManager.LOCATION_MODE_NO_CHANGE;
+
+ public Builder() {
+ }
+
+ /**
+ * Set how much to adjust the screen brightness while in Battery Saver. The value should
+ * be in the [0, 1] range, where 1 will not change the brightness. This will have no
+ * effect if {@link #setEnableAdjustBrightness(boolean)} is not called with {@code true}.
+ */
+ @NonNull
+ public Builder setAdjustBrightnessFactor(float adjustBrightnessFactor) {
+ mAdjustBrightnessFactor = adjustBrightnessFactor;
+ return this;
+ }
+
+ /**
+ * Set whether or not to tell the system (and other apps) that Battery Saver is
+ * currently enabled.
+ */
+ @NonNull
+ public Builder setAdvertiseIsEnabled(boolean advertiseIsEnabled) {
+ mAdvertiseIsEnabled = advertiseIsEnabled;
+ return this;
+ }
+
+ /** Set whether or not to defer full backup while in Battery Saver. */
+ @NonNull
+ public Builder setDeferFullBackup(boolean deferFullBackup) {
+ mDeferFullBackup = deferFullBackup;
+ return this;
+ }
+
+ /** Set whether or not to defer key-value backup while in Battery Saver. */
+ @NonNull
+ public Builder setDeferKeyValueBackup(boolean deferKeyValueBackup) {
+ mDeferKeyValueBackup = deferKeyValueBackup;
+ return this;
+ }
+
+ /**
+ * Adds a key-value pair for device-specific battery saver constants. The supported keys
+ * and values are the same as those in
+ * {@link android.provider.Settings.Global#BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS}.
+ *
+ * @throws IllegalArgumentException if the provided key is invalid (empty, null, or all
+ * whitespace)
+ */
+ @NonNull
+ public Builder addDeviceSpecificSetting(@NonNull String key, @NonNull String value) {
+ if (key == null) {
+ throw new IllegalArgumentException("Key cannot be null");
+ }
+ key = key.trim();
+ if (TextUtils.isEmpty(key)) {
+ throw new IllegalArgumentException("Key cannot be empty");
+ }
+ mDeviceSpecificSettings.put(key, TextUtils.emptyIfNull(value));
+ return this;
+ }
+
+ /** Set whether or not to disable animation while in Battery Saver. */
+ @NonNull
+ public Builder setDisableAnimation(boolean disableAnimation) {
+ mDisableAnimation = disableAnimation;
+ return this;
+ }
+
+ /** Set whether or not to disable Always On Display while in Battery Saver. */
+ @NonNull
+ public Builder setDisableAod(boolean disableAod) {
+ mDisableAod = disableAod;
+ return this;
+ }
+
+ /** Set whether or not to disable launch boost while in Battery Saver. */
+ @NonNull
+ public Builder setDisableLaunchBoost(boolean disableLaunchBoost) {
+ mDisableLaunchBoost = disableLaunchBoost;
+ return this;
+ }
+
+ /** Set whether or not to disable optional sensors while in Battery Saver. */
+ @NonNull
+ public Builder setDisableOptionalSensors(boolean disableOptionalSensors) {
+ mDisableOptionalSensors = disableOptionalSensors;
+ return this;
+ }
+
+ /** Set whether or not to disable sound trigger while in Battery Saver. */
+ @NonNull
+ public Builder setDisableSoundTrigger(boolean disableSoundTrigger) {
+ mDisableSoundTrigger = disableSoundTrigger;
+ return this;
+ }
+
+ /** Set whether or not to disable vibration while in Battery Saver. */
+ @NonNull
+ public Builder setDisableVibration(boolean disableVibration) {
+ mDisableVibration = disableVibration;
+ return this;
+ }
+
+ /** Set whether or not to enable brightness adjustment while in Battery Saver. */
+ @NonNull
+ public Builder setEnableAdjustBrightness(boolean enableAdjustBrightness) {
+ mEnableAdjustBrightness = enableAdjustBrightness;
+ return this;
+ }
+
+ /** Set whether or not to enable Data Saver while in Battery Saver. */
+ @NonNull
+ public Builder setEnableDataSaver(boolean enableDataSaver) {
+ mEnableDataSaver = enableDataSaver;
+ return this;
+ }
+
+ /** Set whether or not to enable the network firewall while in Battery Saver. */
+ @NonNull
+ public Builder setEnableFirewall(boolean enableFirewall) {
+ mEnableFirewall = enableFirewall;
+ return this;
+ }
+
+ /** Set whether or not to enable Quick Doze while in Battery Saver. */
+ @NonNull
+ public Builder setEnableQuickDoze(boolean enableQuickDoze) {
+ mEnableQuickDoze = enableQuickDoze;
+ return this;
+ }
+
+ /** Set whether or not to force all apps to standby mode while in Battery Saver. */
+ @NonNull
+ public Builder setForceAllAppsStandby(boolean forceAllAppsStandby) {
+ mForceAllAppsStandby = forceAllAppsStandby;
+ return this;
+ }
+
+ /** Set whether or not to force background check while in Battery Saver. */
+ @NonNull
+ public Builder setForceBackgroundCheck(boolean forceBackgroundCheck) {
+ mForceBackgroundCheck = forceBackgroundCheck;
+ return this;
+ }
+
+ /** Set the GPS mode while in Battery Saver. */
+ @NonNull
+ public Builder setGpsMode(@PowerManager.LocationPowerSaveMode int gpsMode) {
+ mGpsMode = gpsMode;
+ return this;
+ }
+
+ /**
+ * Build a {@link BatterySaverPolicyConfig} object using the set parameters. This object
+ * is immutable.
+ */
+ @NonNull
+ public BatterySaverPolicyConfig build() {
+ if (!mEnableAdjustBrightness && Float.compare(1f, mAdjustBrightnessFactor) != 0) {
+ throw new IllegalArgumentException("Brightness adjustment factor changed without "
+ + "enabling brightness adjustment");
+ }
+ return new BatterySaverPolicyConfig(this);
+ }
+ }
+}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index ca5b233..093897a 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -17,8 +17,9 @@
package android.os;
-import android.os.WorkSource;
+import android.os.BatterySaverPolicyConfig;
import android.os.PowerSaveState;
+import android.os.WorkSource;
/** @hide */
@@ -49,6 +50,8 @@
PowerSaveState getPowerSaveState(int serviceType);
boolean setPowerSaveMode(boolean mode);
boolean setDynamicPowerSavings(boolean dynamicPowerSavingsEnabled, int disableThreshold);
+ boolean setAdaptivePowerSavePolicy(in BatterySaverPolicyConfig config);
+ boolean setAdaptivePowerSaveEnabled(boolean enabled);
int getPowerSaveMode();
boolean isDeviceIdleMode();
boolean isLightDeviceIdleMode();
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 7f4254e..0441ba2 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -640,6 +640,9 @@
*/
public static final int LOCATION_MODE_FOREGROUND_ONLY = 3;
+ static final int MIN_LOCATION_MODE = LOCATION_MODE_NO_CHANGE;
+ static final int MAX_LOCATION_MODE = LOCATION_MODE_FOREGROUND_ONLY;
+
/**
* @hide
*/
@@ -1272,6 +1275,48 @@
}
/**
+ * Sets the policy for adaptive power save.
+ *
+ * @return true if there was an effectual change. If full battery saver is enabled or the
+ * adaptive policy is not enabled, then this will return false.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.DEVICE_POWER,
+ android.Manifest.permission.POWER_SAVER
+ })
+ public boolean setAdaptivePowerSavePolicy(@NonNull BatterySaverPolicyConfig config) {
+ try {
+ return mService.setAdaptivePowerSavePolicy(config);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Enables or disables adaptive power save.
+ *
+ * @return true if there was an effectual change. If full battery saver is enabled, then this
+ * will return false.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(anyOf = {
+ android.Manifest.permission.DEVICE_POWER,
+ android.Manifest.permission.POWER_SAVER
+ })
+ public boolean setAdaptivePowerSaveEnabled(boolean enabled) {
+ try {
+ return mService.setAdaptivePowerSaveEnabled(enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Indicates automatic battery saver toggling by the system will be based on percentage.
*
* @see PowerManager#getPowerSaveMode()
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dcda8a3..ffa47a9 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11428,6 +11428,9 @@
* The following keys are supported:
*
* <pre>
+ * advertise_is_enabled (boolean)
+ * datasaver_disabled (boolean)
+ * launch_boost_disabled (boolean)
* vibration_disabled (boolean)
* animation_disabled (boolean)
* soundtrigger_disabled (boolean)
@@ -11451,6 +11454,14 @@
/**
* Battery Saver device specific settings
* This is encoded as a key=value list, separated by commas.
+ *
+ * The following keys are supported:
+ *
+ * <pre>
+ * cpufreq-i (list of "core-number:frequency" pairs concatenated with /)
+ * cpufreq-n (list of "core-number:frequency" pairs concatenated with /)
+ * </pre>
+ *
* See {@link com.android.server.power.batterysaver.BatterySaverPolicy} for the details.
*
* @hide
@@ -11459,6 +11470,24 @@
"battery_saver_device_specific_constants";
/**
+ * Settings for adaptive Battery Saver mode. Uses the same flags as
+ * {@link #BATTERY_SAVER_CONSTANTS}.
+ *
+ * @hide
+ */
+ public static final String BATTERY_SAVER_ADAPTIVE_CONSTANTS =
+ "battery_saver_adaptive_constants";
+
+ /**
+ * Device specific settings for adaptive Battery Saver mode. Uses the same flags as
+ * {@link #BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS}.
+ *
+ * @hide
+ */
+ public static final String BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS =
+ "battery_saver_adaptive_device_specific_constants";
+
+ /**
* Battery tip specific settings
* This is encoded as a key=value list, separated by commas. Ex:
*
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index af0a942..8fce94e 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -318,6 +318,16 @@
// Whether battery saver is enabled.
optional bool enabled = 1;
+ // Whether full battery saver is enabled.
+ optional bool is_full_enabled = 14;
+
+ // Whether adaptive battery saver is enabled.
+ optional bool is_adaptive_enabled = 15;
+
+ // Whether the battery saver policy indicates that is_enabled should be
+ // advertised.
+ optional bool should_advertise_is_enabled = 16;
+
// Whether system has booted.
optional bool boot_completed = 2;
@@ -358,4 +368,10 @@
// The value of Global.LOW_POWER_MODE_STICKY_AUTO_DISABLE_LEVEL. This is a cached value, so it
// could be slightly different from what's in GlobalSettingsProto.LowPowerMode.
optional int32 setting_battery_saver_sticky_auto_disable_threshold = 13;
+
+ // The last time adaptive battery saver was changed by an external service,
+ // using elapsed realtime as the timebase.
+ optional int64 last_adaptive_battery_saver_changed_externally_elapsed = 17;
+
+ // Next tag: 18
}
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index f38abd7..f420033 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -137,6 +137,7 @@
Settings.Global.BROADCAST_OFFLOAD_CONSTANTS,
Settings.Global.BATTERY_DISCHARGE_DURATION_THRESHOLD,
Settings.Global.BATTERY_DISCHARGE_THRESHOLD,
+ Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS,
Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS,
Settings.Global.BATTERY_STATS_CONSTANTS,
Settings.Global.BINDER_CALLS_STATS,
@@ -222,6 +223,7 @@
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED,
Settings.Global.DEVICE_DEMO_MODE,
Settings.Global.DEVICE_IDLE_CONSTANTS,
+ Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS,
Settings.Global.BATTERY_SAVER_CONSTANTS,
Settings.Global.BATTERY_TIP_CONSTANTS,
Settings.Global.DEFAULT_SM_DP_PLUS,
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index d869734..0ed5beb 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -33,7 +33,7 @@
# It logs the time remaining before the device would've normally gone to sleep without the request.
2731 power_soft_sleep_requested (savedwaketimems|2)
# Power save state has changed. See BatterySaverController.java for the details.
-2739 battery_saver_mode (prevOffOrOn|1|5),(nowOffOrOn|1|5),(interactive|1|5),(features|3|5),(reason|1|5)
+2739 battery_saver_mode (fullPrevOffOrOn|1|5),(adaptivePrevOffOrOn|1|5),(fullNowOffOrOn|1|5),(adaptiveNowOffOrOn|1|5),(interactive|1|5),(features|3|5),(reason|1|5)
27390 battery_saving_stats (batterySaver|1|5),(interactive|1|5),(doze|1|5),(delta_duration|2|3),(delta_battery_drain|1|1),(delta_battery_drain_percent|1|6),(total_duration|2|3),(total_battery_drain|1|1),(total_battery_drain_percent|1|6)
# Note when the user activity timeout has been overriden by ActivityManagerService
27391 user_activity_timeout_override (override|2|3)
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 3be6480..3ccd234 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -22,6 +22,7 @@
import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.SynchronousUserSwitchObserver;
@@ -42,6 +43,7 @@
import android.net.Uri;
import android.os.BatteryManager;
import android.os.BatteryManagerInternal;
+import android.os.BatterySaverPolicyConfig;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -2875,8 +2877,7 @@
@VisibleForTesting
void updatePowerRequestFromBatterySaverPolicy(DisplayPowerRequest displayPowerRequest) {
PowerSaveState state = mBatterySaverPolicy.
- getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS,
- mBatterySaverController.isEnabled());
+ getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
displayPowerRequest.lowPowerMode = state.batterySaverEnabled;
displayPowerRequest.screenLowPowerBrightnessFactor = state.brightnessFactor;
}
@@ -4451,8 +4452,7 @@
public PowerSaveState getPowerSaveState(@ServiceType int serviceType) {
final long ident = Binder.clearCallingIdentity();
try {
- return mBatterySaverPolicy.getBatterySaverPolicy(
- serviceType, mBatterySaverController.isEnabled());
+ return mBatterySaverPolicy.getBatterySaverPolicy(serviceType);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -4497,6 +4497,36 @@
}
@Override // Binder call
+ public boolean setAdaptivePowerSavePolicy(@NonNull BatterySaverPolicyConfig config) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER)
+ != PackageManager.PERMISSION_GRANTED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, "setAdaptivePowerSavePolicy");
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mBatterySaverStateMachine.setAdaptiveBatterySaverPolicy(config);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
+ public boolean setAdaptivePowerSaveEnabled(boolean enabled) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER)
+ != PackageManager.PERMISSION_GRANTED) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.DEVICE_POWER, "setAdaptivePowerSaveEnabled");
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return mBatterySaverStateMachine.setAdaptiveBatterySaverEnabled(enabled);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public int getPowerSaveMode() {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
final long ident = Binder.clearCallingIdentity();
@@ -4846,8 +4876,7 @@
@Override
public PowerSaveState getLowPowerState(@ServiceType int serviceType) {
- return mBatterySaverPolicy.getBatterySaverPolicy(serviceType,
- mBatterySaverController.isEnabled());
+ return mBatterySaverPolicy.getBatterySaverPolicy(serviceType);
}
@Override
diff --git a/services/core/java/com/android/server/power/PowerManagerShellCommand.java b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
index 46115d8..18b8f0e 100644
--- a/services/core/java/com/android/server/power/PowerManagerShellCommand.java
+++ b/services/core/java/com/android/server/power/PowerManagerShellCommand.java
@@ -41,6 +41,8 @@
final PrintWriter pw = getOutPrintWriter();
try {
switch(cmd) {
+ case "set-adaptive-power-saver-enabled":
+ return runSetAdaptiveEnabled();
case "set-mode":
return runSetMode();
default:
@@ -52,6 +54,11 @@
return -1;
}
+ private int runSetAdaptiveEnabled() throws RemoteException {
+ mInterface.setAdaptivePowerSaveEnabled(Boolean.parseBoolean(getNextArgRequired()));
+ return 0;
+ }
+
private int runSetMode() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
int mode = -1;
@@ -72,6 +79,8 @@
pw.println(" help");
pw.println(" Print this help text.");
pw.println("");
+ pw.println(" set-adaptive-power-saver-enabled [true|false]");
+ pw.println(" enables or disables adaptive power saver.");
pw.println(" set-mode MODE");
pw.println(" sets the power mode of the device to MODE.");
pw.println(" 1 turns low power mode on and 0 turns low power mode off.");
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
index ab2807a..94bb3ea 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverController.java
@@ -23,6 +23,7 @@
import android.content.IntentFilter;
import android.hardware.power.V1_0.PowerHint;
import android.os.BatteryManager;
+import android.os.BatterySaverPolicyConfig;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -42,6 +43,7 @@
import com.android.server.LocalServices;
import com.android.server.power.PowerManagerService;
import com.android.server.power.batterysaver.BatterySaverPolicy.BatterySaverPolicyListener;
+import com.android.server.power.batterysaver.BatterySaverPolicy.Policy;
import com.android.server.power.batterysaver.BatterySavingStats.BatterySaverState;
import com.android.server.power.batterysaver.BatterySavingStats.DozeState;
import com.android.server.power.batterysaver.BatterySavingStats.InteractiveState;
@@ -74,16 +76,25 @@
private final ArrayList<LowPowerModeListener> mListeners = new ArrayList<>();
@GuardedBy("mLock")
- private boolean mEnabled;
+ private boolean mFullEnabled;
+
+ @GuardedBy("mLock")
+ private boolean mAdaptiveEnabled;
@GuardedBy("mLock")
private boolean mIsPluggedIn;
/**
- * Previously enabled or not; only for the event logging. Only use it from
+ * Whether full was previously enabled or not; only for the event logging. Only use it from
* {@link #handleBatterySaverStateChanged}.
*/
- private boolean mPreviouslyEnabled;
+ private boolean mFullPreviouslyEnabled;
+
+ /**
+ * Whether adaptive was previously enabled or not; only for the event logging. Only use it from
+ * {@link #handleBatterySaverStateChanged}.
+ */
+ private boolean mAdaptivePreviouslyEnabled;
@GuardedBy("mLock")
private boolean mIsInteractive;
@@ -104,7 +115,9 @@
public static final int REASON_SETTING_CHANGED = 8;
public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_ON = 9;
public static final int REASON_DYNAMIC_POWER_SAVINGS_AUTOMATIC_OFF = 10;
- public static final int REASON_STICKY_RESTORE_OFF = 13;
+ public static final int REASON_STICKY_RESTORE_OFF = 11;
+ public static final int REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED = 12;
+ public static final int REASON_TIMEOUT = 13;
/**
* Plugin interface. All methods are guaranteed to be called on the same (handler) thread.
@@ -124,7 +137,7 @@
switch (intent.getAction()) {
case Intent.ACTION_SCREEN_ON:
case Intent.ACTION_SCREEN_OFF:
- if (!isEnabled()) {
+ if (!isPolicyEnabled()) {
updateBatterySavingStats();
return; // No need to send it if not enabled.
}
@@ -199,7 +212,7 @@
@Override
public void onBatterySaverPolicyChanged(BatterySaverPolicy policy) {
- if (!isEnabled()) {
+ if (!isPolicyEnabled()) {
return; // No need to send it if not enabled.
}
mHandler.postStateChanged(/*sendBroadcast=*/ true, REASON_POLICY_CHANGED);
@@ -248,22 +261,98 @@
@VisibleForTesting
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
- if (mEnabled == enable) {
+ if (mFullEnabled == enable) {
return;
}
- mEnabled = enable;
+ mFullEnabled = enable;
- mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
+ if (updatePolicyLevelLocked()) {
+ mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
+ }
}
}
- /** @return whether battery saver is enabled or not. */
+ private boolean updatePolicyLevelLocked() {
+ if (mFullEnabled) {
+ return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_FULL);
+ } else if (mAdaptiveEnabled) {
+ return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_ADAPTIVE);
+ } else {
+ return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_OFF);
+ }
+ }
+
+ /**
+ * @return whether battery saver is enabled or not. This takes into
+ * account whether a policy says to advertise isEnabled so this can be propagated externally.
+ */
public boolean isEnabled() {
synchronized (mLock) {
- return mEnabled;
+ return mFullEnabled
+ || (mAdaptiveEnabled && mBatterySaverPolicy.shouldAdvertiseIsEnabled());
}
}
+ /**
+ * @return whether battery saver policy is enabled or not. This does not take into account
+ * whether a policy says to advertise isEnabled, so this shouldn't be propagated externally.
+ */
+ private boolean isPolicyEnabled() {
+ synchronized (mLock) {
+ return mFullEnabled || mAdaptiveEnabled;
+ }
+ }
+
+ boolean isFullEnabled() {
+ synchronized (mLock) {
+ return mFullEnabled;
+ }
+ }
+
+ boolean isAdaptiveEnabled() {
+ synchronized (mLock) {
+ return mAdaptiveEnabled;
+ }
+ }
+
+ boolean setAdaptivePolicyLocked(String settings, String deviceSpecificSettings, int reason) {
+ return setAdaptivePolicyLocked(
+ BatterySaverPolicy.Policy.fromSettings(settings, deviceSpecificSettings),
+ reason);
+ }
+
+ boolean setAdaptivePolicyLocked(BatterySaverPolicyConfig config, int reason) {
+ return setAdaptivePolicyLocked(BatterySaverPolicy.Policy.fromConfig(config), reason);
+ }
+
+ boolean setAdaptivePolicyLocked(Policy policy, int reason) {
+ if (mBatterySaverPolicy.setAdaptivePolicyLocked(policy)) {
+ mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
+ return true;
+ }
+ return false;
+ }
+
+ boolean resetAdaptivePolicyLocked(int reason) {
+ if (mBatterySaverPolicy.resetAdaptivePolicyLocked()) {
+ mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
+ return true;
+ }
+ return false;
+ }
+
+ boolean setAdaptivePolicyEnabledLocked(boolean enabled, int reason) {
+ if (mAdaptiveEnabled == enabled) {
+ return false;
+ }
+ mAdaptiveEnabled = enabled;
+ if (updatePolicyLevelLocked()) {
+ mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
+ return true;
+ }
+ return false;
+ }
+
/** @return whether device is in interactive state. */
public boolean isInteractive() {
synchronized (mLock) {
@@ -280,7 +369,7 @@
* @return true if launch boost should currently be disabled.
*/
public boolean isLaunchBoostDisabled() {
- return isEnabled() && mBatterySaverPolicy.isLaunchBoostDisabled();
+ return isPolicyEnabled() && mBatterySaverPolicy.isLaunchBoostDisabled();
}
/**
@@ -293,6 +382,9 @@
* - When battery saver becomes deactivated.
* - When battery saver is on and the interactive state changes.
* - When battery saver is on and the battery saver policy changes.
+ * - When adaptive battery saver becomes activated.
+ * - When adaptive battery saver becomes deactivated.
+ * - When adaptive battery saver policy changes.
*/
void handleBatterySaverStateChanged(boolean sendBroadcast, int reason) {
final LowPowerModeListener[] listeners;
@@ -302,17 +394,22 @@
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
+ enabled = mFullEnabled || mAdaptiveEnabled;
+
EventLogTags.writeBatterySaverMode(
- mPreviouslyEnabled ? 1 : 0, // Previously off or on.
- mEnabled ? 1 : 0, // Now off or on.
+ mFullPreviouslyEnabled ? 1 : 0, // Previously off or on.
+ mAdaptivePreviouslyEnabled ? 1 : 0, // Previously off or on.
+ mFullEnabled ? 1 : 0, // Now off or on.
+ mAdaptiveEnabled ? 1 : 0, // Now off or on.
isInteractive ? 1 : 0, // Device interactive state.
- mEnabled ? mBatterySaverPolicy.toEventLogString() : "",
+ enabled ? mBatterySaverPolicy.toEventLogString() : "",
reason);
- mPreviouslyEnabled = mEnabled;
+
+ mFullPreviouslyEnabled = mFullEnabled;
+ mAdaptivePreviouslyEnabled = mAdaptiveEnabled;
listeners = mListeners.toArray(new LowPowerModeListener[0]);
- enabled = mEnabled;
mIsInteractive = isInteractive;
if (enabled) {
@@ -324,7 +421,7 @@
final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
if (pmi != null) {
- pmi.powerHint(PowerHint.LOW_POWER, enabled ? 1 : 0);
+ pmi.powerHint(PowerHint.LOW_POWER, isEnabled() ? 1 : 0);
}
updateBatterySavingStats();
@@ -342,13 +439,13 @@
if (sendBroadcast) {
if (DEBUG) {
- Slog.i(TAG, "Sending broadcasts for mode: " + enabled);
+ Slog.i(TAG, "Sending broadcasts for mode: " + isEnabled());
}
// Send the broadcasts and notify the listeners. We only do this when the battery saver
// mode changes, but not when only the screen state changes.
Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)
- .putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, enabled)
+ .putExtra(PowerManager.EXTRA_POWER_SAVE_MODE, isEnabled())
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
@@ -364,8 +461,7 @@
for (LowPowerModeListener listener : listeners) {
final PowerSaveState result =
- mBatterySaverPolicy.getBatterySaverPolicy(
- listener.getServiceType(), enabled);
+ mBatterySaverPolicy.getBatterySaverPolicy(listener.getServiceType());
listener.onLowPowerModeChanged(result);
}
}
@@ -389,7 +485,8 @@
return;
}
mBatterySavingStats.transitionState(
- mEnabled ? BatterySaverState.ON : BatterySaverState.OFF,
+ mFullEnabled ? BatterySaverState.ON :
+ (mAdaptiveEnabled ? BatterySaverState.ADAPTIVE : BatterySaverState.OFF),
isInteractive ? InteractiveState.INTERACTIVE : InteractiveState.NON_INTERACTIVE,
dozeMode);
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
index bd8baeb..a77d133 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverLocationPlugin.java
@@ -53,8 +53,8 @@
private void updateLocationState(BatterySaverController caller) {
final boolean kill =
(caller.getBatterySaverPolicy().getGpsMode()
- == PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF) &&
- caller.isEnabled() && !caller.isInteractive();
+ == PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF)
+ && !caller.isInteractive();
if (DEBUG) {
Slog.d(TAG, "Battery saver " + (kill ? "stopping" : "restoring") + " location.");
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
index 48a041e..8550bc3 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
@@ -15,16 +15,17 @@
*/
package com.android.server.power.batterysaver;
+import android.annotation.IntDef;
import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.net.Uri;
+import android.os.BatterySaverPolicyConfig;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.ServiceType;
import android.os.PowerSaveState;
import android.provider.Settings;
-import android.provider.Settings.Global;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.KeyValueListParser;
@@ -39,8 +40,12 @@
import com.android.server.power.PowerManagerService;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
/**
* Class to decide whether to turn on battery saver mode for specific services.
@@ -48,12 +53,12 @@
* IMPORTANT: This class shares the power manager lock, which is very low in the lock hierarchy.
* Do not call out with the lock held, such as AccessibilityManager. (Settings provider is okay.)
*
- * Test: atest com.android.server.power.batterysaver.BatterySaverPolicyTest.java
+ * Test: atest com.android.server.power.batterysaver.BatterySaverPolicyTest
*/
public class BatterySaverPolicy extends ContentObserver {
private static final String TAG = "BatterySaverPolicy";
- public static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
+ static final boolean DEBUG = false; // DO NOT SUBMIT WITH TRUE.
private static final String KEY_GPS_MODE = "gps_mode";
private static final String KEY_VIBRATION_DISABLED = "vibration_disabled";
@@ -81,6 +86,14 @@
* If set to true, Data Saver WILL NOT be turned on when Battery Saver is turned on.
*/
private static final String KEY_ACTIVATE_DATASAVER_DISABLED = "datasaver_disabled";
+
+ /**
+ * {@code true} if the Policy should advertise to the rest of the system that battery saver
+ * is enabled. This advertising could cause other system components to change their
+ * behavior. This will not affect other policy flags and what they change.
+ */
+ private static final String KEY_ADVERTISE_IS_ENABLED = "advertise_is_enabled";
+
private static final String KEY_LAUNCH_BOOST_DISABLED = "launch_boost_disabled";
private static final String KEY_ADJUST_BRIGHTNESS_FACTOR = "adjust_brightness_factor";
private static final String KEY_FULLBACKUP_DEFERRED = "fullbackup_deferred";
@@ -96,8 +109,35 @@
private static final String KEY_CPU_FREQ_INTERACTIVE = "cpufreq-i";
private static final String KEY_CPU_FREQ_NONINTERACTIVE = "cpufreq-n";
- private static final Policy sDefaultPolicy = new Policy(
+ @VisibleForTesting
+ static final Policy OFF_POLICY = new Policy(
+ 1f, /* adjustBrightnessFactor */
+ false, /* advertiseIsEnabled */
+ false, /* deferFullBackup */
+ false, /* deferKeyValueBackup */
+ false, /* disableAnimation */
+ false, /* disableAod */
+ false, /* disableLaunchBoost */
+ false, /* disableOptionalSensors */
+ false, /* disableSoundTrigger */
+ false, /* disableVibration */
+ false, /* enableAdjustBrightness */
+ false, /* enableDataSaver */
+ false, /* enableFireWall */
+ false, /* enableQuickDoze */
+ new ArrayMap<>(), /* filesForInteractive */
+ new ArrayMap<>(), /* filesForNoninteractive */
+ false, /* forceAllAppsStandby */
+ false, /* forceBackgroundCheck */
+ PowerManager.LOCATION_MODE_NO_CHANGE, /* gpsMode */
+ false /* sendTronLog */
+ );
+
+ private static final Policy DEFAULT_ADAPTIVE_POLICY = OFF_POLICY;
+
+ private static final Policy DEFAULT_FULL_POLICY = new Policy(
0.5f, /* adjustBrightnessFactor */
+ true, /* advertiseIsEnabled */
true, /* deferFullBackup */
true, /* deferKeyValueBackup */
false, /* disableAnimation */
@@ -130,6 +170,12 @@
@GuardedBy("mLock")
private String mDeviceSpecificSettingsSource; // For dump() only.
+ @GuardedBy("mLock")
+ private String mAdaptiveSettings;
+
+ @GuardedBy("mLock")
+ private String mAdaptiveDeviceSpecificSettings;
+
/**
* A short string describing which battery saver is now enabled, which we dump in the eventlog.
*/
@@ -149,8 +195,32 @@
@GuardedBy("mLock")
private boolean mAccessibilityEnabled;
+ /** The current default adaptive policy. */
@GuardedBy("mLock")
- private Policy mCurrPolicy = sDefaultPolicy;
+ private Policy mDefaultAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
+
+ /** The policy that will be used for adaptive battery saver. */
+ @GuardedBy("mLock")
+ private Policy mAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
+
+ /** The policy to be used for full battery saver. */
+ @GuardedBy("mLock")
+ private Policy mFullPolicy = DEFAULT_FULL_POLICY;
+
+ @IntDef(prefix = {"POLICY_LEVEL_"}, value = {
+ POLICY_LEVEL_OFF,
+ POLICY_LEVEL_ADAPTIVE,
+ POLICY_LEVEL_FULL,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface PolicyLevel {}
+
+ static final int POLICY_LEVEL_OFF = 0;
+ static final int POLICY_LEVEL_ADAPTIVE = 1;
+ static final int POLICY_LEVEL_FULL = 2;
+
+ @GuardedBy("mLock")
+ private int mPolicyLevel = POLICY_LEVEL_OFF;
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -181,7 +251,11 @@
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
Settings.Global.BATTERY_SAVER_CONSTANTS), false, this);
mContentResolver.registerContentObserver(Settings.Global.getUriFor(
- Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);
+ Settings.Global.BATTERY_SAVER_DEVICE_SPECIFIC_CONSTANTS), false, this);
+ mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS), false, this);
+ mContentResolver.registerContentObserver(Settings.Global.getUriFor(
+ Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS), false, this);
final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
@@ -241,8 +315,16 @@
mDeviceSpecificSettingsSource = "(overlay)";
}
- // Update.
- updateConstantsLocked(setting, deviceSpecificSetting);
+ final String adaptiveSetting =
+ getGlobalSetting(Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS);
+ final String adaptiveDeviceSpecificSetting = getGlobalSetting(
+ Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS);
+
+ if (!updateConstantsLocked(setting, deviceSpecificSetting,
+ adaptiveSetting, adaptiveDeviceSpecificSetting)) {
+ // Nothing of note changed.
+ return;
+ }
listeners = mListeners.toArray(new BatterySaverPolicyListener[0]);
}
@@ -258,123 +340,94 @@
@GuardedBy("mLock")
@VisibleForTesting
void updateConstantsLocked(final String setting, final String deviceSpecificSetting) {
+ updateConstantsLocked(setting, deviceSpecificSetting, "", "");
+ }
+
+ /** @return true if the currently active policy changed. */
+ private boolean updateConstantsLocked(String setting, String deviceSpecificSetting,
+ String adaptiveSetting, String adaptiveDeviceSpecificSetting) {
+ setting = TextUtils.emptyIfNull(setting);
+ deviceSpecificSetting = TextUtils.emptyIfNull(deviceSpecificSetting);
+ adaptiveSetting = TextUtils.emptyIfNull(adaptiveSetting);
+ adaptiveDeviceSpecificSetting = TextUtils.emptyIfNull(adaptiveDeviceSpecificSetting);
+
+ if (setting.equals(mSettings)
+ && deviceSpecificSetting.equals(mDeviceSpecificSettings)
+ && adaptiveSetting.equals(mAdaptiveSettings)
+ && adaptiveDeviceSpecificSetting.equals(mAdaptiveDeviceSpecificSettings)) {
+ return false;
+ }
+
mSettings = setting;
mDeviceSpecificSettings = deviceSpecificSetting;
+ mAdaptiveSettings = adaptiveSetting;
+ mAdaptiveDeviceSpecificSettings = adaptiveDeviceSpecificSetting;
if (DEBUG) {
Slog.i(TAG, "mSettings=" + mSettings);
Slog.i(TAG, "mDeviceSpecificSettings=" + mDeviceSpecificSettings);
+ Slog.i(TAG, "mAdaptiveSettings=" + mAdaptiveSettings);
+ Slog.i(TAG, "mAdaptiveDeviceSpecificSettings=" + mAdaptiveDeviceSpecificSettings);
}
- final KeyValueListParser parser = new KeyValueListParser(',');
-
- // Device-specific parameters.
- try {
- parser.setString(deviceSpecificSetting);
- } catch (IllegalArgumentException e) {
- Slog.wtf(TAG, "Bad device specific battery saver constants: "
- + deviceSpecificSetting);
+ boolean changed = false;
+ Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting,
+ DEFAULT_FULL_POLICY);
+ if (mPolicyLevel == POLICY_LEVEL_FULL && !mFullPolicy.equals(newFullPolicy)) {
+ changed = true;
}
+ mFullPolicy = newFullPolicy;
- final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
- final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
-
- // Non-device-specific parameters.
- try {
- parser.setString(setting);
- } catch (IllegalArgumentException e) {
- Slog.wtf(TAG, "Bad battery saver constants: " + setting);
+ mDefaultAdaptivePolicy = Policy.fromSettings(adaptiveSetting, adaptiveDeviceSpecificSetting,
+ DEFAULT_ADAPTIVE_POLICY);
+ if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE
+ && !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) {
+ changed = true;
}
+ // This will override any config set by an external source. This should be fine for now.
+ // TODO: make sure it doesn't override what's set externally
+ mAdaptivePolicy = mDefaultAdaptivePolicy;
- float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
- sDefaultPolicy.adjustBrightnessFactor);
- boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED,
- sDefaultPolicy.deferFullBackup);
- boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED,
- sDefaultPolicy.deferKeyValueBackup);
- boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED,
- sDefaultPolicy.disableAnimation);
- boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, sDefaultPolicy.disableAod);
- boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED,
- sDefaultPolicy.disableLaunchBoost);
- boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED,
- sDefaultPolicy.disableOptionalSensors);
- boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED,
- sDefaultPolicy.disableSoundTrigger);
- boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED,
- sDefaultPolicy.disableVibration);
- boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED,
- !sDefaultPolicy.enableAdjustBrightness);
- boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED,
- !sDefaultPolicy.enableDataSaver);
- boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED,
- !sDefaultPolicy.enableFirewall);
- boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED,
- sDefaultPolicy.enableQuickDoze);
- boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
- sDefaultPolicy.forceAllAppsStandby);
- boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
- sDefaultPolicy.forceBackgroundCheck);
- int gpsMode = parser.getInt(KEY_GPS_MODE, sDefaultPolicy.gpsMode);
- boolean sendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, sDefaultPolicy.sendTronLog);
+ updatePolicyDependenciesLocked();
- mCurrPolicy = new Policy(
- adjustBrightnessFactor,
- deferFullBackup,
- deferKeyValueBackup,
- disableAnimation,
- disableAod,
- disableLaunchBoost,
- disableOptionalSensors,
- disableSoundTrigger,
- /* disableVibration */
- disableVibrationConfig,
- enableAdjustBrightness,
- enableDataSaver,
- enableFirewall,
- enableQuickDoze,
- /* filesForInteractive */
- (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
- /* filesForNoninteractive */
- (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
- forceAllAppsStandby,
- forceBackgroundCheck,
- gpsMode,
- sendTronLog
- );
+ return changed;
+ }
- // Update the effective policy.
- mDisableVibrationEffective = mCurrPolicy.disableVibration
+ @GuardedBy("mLock")
+ private void updatePolicyDependenciesLocked() {
+ final Policy currPolicy = getCurrentPolicyLocked();
+ // Update the effective vibration policy.
+ mDisableVibrationEffective = currPolicy.disableVibration
&& !mAccessibilityEnabled; // Don't disable vibration when accessibility is on.
final StringBuilder sb = new StringBuilder();
- if (mCurrPolicy.forceAllAppsStandby) sb.append("A");
- if (mCurrPolicy.forceBackgroundCheck) sb.append("B");
+ if (currPolicy.forceAllAppsStandby) sb.append("A");
+ if (currPolicy.forceBackgroundCheck) sb.append("B");
if (mDisableVibrationEffective) sb.append("v");
- if (mCurrPolicy.disableAnimation) sb.append("a");
- if (mCurrPolicy.disableSoundTrigger) sb.append("s");
- if (mCurrPolicy.deferFullBackup) sb.append("F");
- if (mCurrPolicy.deferKeyValueBackup) sb.append("K");
- if (mCurrPolicy.enableFirewall) sb.append("f");
- if (mCurrPolicy.enableDataSaver) sb.append("d");
- if (mCurrPolicy.enableAdjustBrightness) sb.append("b");
+ if (currPolicy.disableAnimation) sb.append("a");
+ if (currPolicy.disableSoundTrigger) sb.append("s");
+ if (currPolicy.deferFullBackup) sb.append("F");
+ if (currPolicy.deferKeyValueBackup) sb.append("K");
+ if (currPolicy.enableFirewall) sb.append("f");
+ if (currPolicy.enableDataSaver) sb.append("d");
+ if (currPolicy.enableAdjustBrightness) sb.append("b");
- if (mCurrPolicy.disableLaunchBoost) sb.append("l");
- if (mCurrPolicy.disableOptionalSensors) sb.append("S");
- if (mCurrPolicy.disableAod) sb.append("o");
- if (mCurrPolicy.enableQuickDoze) sb.append("q");
- if (mCurrPolicy.sendTronLog) sb.append("t");
+ if (currPolicy.disableLaunchBoost) sb.append("l");
+ if (currPolicy.disableOptionalSensors) sb.append("S");
+ if (currPolicy.disableAod) sb.append("o");
+ if (currPolicy.enableQuickDoze) sb.append("q");
+ if (currPolicy.sendTronLog) sb.append("t");
- sb.append(mCurrPolicy.gpsMode);
+ sb.append(currPolicy.gpsMode);
mEventLogKeys = sb.toString();
- mBatterySavingStats.setSendTronLog(mCurrPolicy.sendTronLog);
+ mBatterySavingStats.setSendTronLog(currPolicy.sendTronLog);
}
- private static class Policy {
+ static class Policy {
/**
* This is the flag to decide the how much to adjust the screen brightness. This is
* the float value from 0 to 1 where 1 means don't change brightness.
@@ -385,6 +438,16 @@
public final float adjustBrightnessFactor;
/**
+ * {@code true} if the Policy should advertise to the rest of the system that battery saver
+ * is enabled. This advertising could cause other system components to change their
+ * behavior. This will not affect other policy flags and what they change.
+ *
+ * @see Settings.Global#BATTERY_SAVER_CONSTANTS
+ * @see #KEY_ADVERTISE_IS_ENABLED
+ */
+ public final boolean advertiseIsEnabled;
+
+ /**
* {@code true} if full backup is deferred in battery saver mode.
*
* @see Settings.Global#BATTERY_SAVER_CONSTANTS
@@ -509,8 +572,11 @@
*/
public final boolean sendTronLog;
+ private final int mHashCode;
+
Policy(
float adjustBrightnessFactor,
+ boolean advertiseIsEnabled,
boolean deferFullBackup,
boolean deferKeyValueBackup,
boolean disableAnimation,
@@ -531,6 +597,7 @@
boolean sendTronLog) {
this.adjustBrightnessFactor = adjustBrightnessFactor;
+ this.advertiseIsEnabled = advertiseIsEnabled;
this.deferFullBackup = deferFullBackup;
this.deferKeyValueBackup = deferKeyValueBackup;
this.disableAnimation = disableAnimation;
@@ -549,94 +616,338 @@
this.forceBackgroundCheck = forceBackgroundCheck;
this.gpsMode = gpsMode;
this.sendTronLog = sendTronLog;
+
+ mHashCode = Objects.hash(
+ adjustBrightnessFactor,
+ advertiseIsEnabled,
+ deferFullBackup,
+ deferKeyValueBackup,
+ disableAnimation,
+ disableAod,
+ disableLaunchBoost,
+ disableOptionalSensors,
+ disableSoundTrigger,
+ disableVibration,
+ enableAdjustBrightness,
+ enableDataSaver,
+ enableFirewall,
+ enableQuickDoze,
+ filesForInteractive,
+ filesForNoninteractive,
+ forceAllAppsStandby,
+ forceBackgroundCheck,
+ gpsMode,
+ sendTronLog);
+ }
+
+ static Policy fromConfig(BatterySaverPolicyConfig config) {
+ if (config == null) {
+ Slog.e(TAG, "Null config passed down to BatterySaverPolicy");
+ return OFF_POLICY;
+ }
+
+ // Device-specific parameters.
+ Map<String, String> deviceSpecificSettings = config.getDeviceSpecificSettings();
+ final String cpuFreqInteractive =
+ deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_INTERACTIVE, "");
+ final String cpuFreqNoninteractive =
+ deviceSpecificSettings.getOrDefault(KEY_CPU_FREQ_NONINTERACTIVE, "");
+
+ return new Policy(
+ config.getAdjustBrightnessFactor(),
+ config.getAdvertiseIsEnabled(),
+ config.getDeferFullBackup(),
+ config.getDeferKeyValueBackup(),
+ config.getDisableAnimation(),
+ config.getDisableAod(),
+ config.getDisableLaunchBoost(),
+ config.getDisableOptionalSensors(),
+ config.getDisableSoundTrigger(),
+ config.getDisableVibration(),
+ config.getEnableAdjustBrightness(),
+ config.getEnableDataSaver(),
+ config.getEnableFirewall(),
+ config.getEnableQuickDoze(),
+ /* filesForInteractive */
+ (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
+ /* filesForNoninteractive */
+ (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
+ config.getForceAllAppsStandby(),
+ config.getForceBackgroundCheck(),
+ config.getGpsMode(),
+ OFF_POLICY.sendTronLog
+ );
+ }
+
+ static Policy fromSettings(String settings, String deviceSpecificSettings) {
+ return fromSettings(settings, deviceSpecificSettings, OFF_POLICY);
+ }
+
+ static Policy fromSettings(String settings, String deviceSpecificSettings,
+ Policy defaultPolicy) {
+ final KeyValueListParser parser = new KeyValueListParser(',');
+
+ // Device-specific parameters.
+ try {
+ parser.setString(deviceSpecificSettings == null ? "" : deviceSpecificSettings);
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Bad device specific battery saver constants: "
+ + deviceSpecificSettings);
+ }
+
+ final String cpuFreqInteractive = parser.getString(KEY_CPU_FREQ_INTERACTIVE, "");
+ final String cpuFreqNoninteractive = parser.getString(KEY_CPU_FREQ_NONINTERACTIVE, "");
+
+ // Non-device-specific parameters.
+ try {
+ parser.setString(settings == null ? "" : settings);
+ } catch (IllegalArgumentException e) {
+ Slog.wtf(TAG, "Bad battery saver constants: " + settings);
+ }
+
+ float adjustBrightnessFactor = parser.getFloat(KEY_ADJUST_BRIGHTNESS_FACTOR,
+ defaultPolicy.adjustBrightnessFactor);
+ boolean advertiseIsEnabled = parser.getBoolean(KEY_ADVERTISE_IS_ENABLED,
+ defaultPolicy.advertiseIsEnabled);
+ boolean deferFullBackup = parser.getBoolean(KEY_FULLBACKUP_DEFERRED,
+ defaultPolicy.deferFullBackup);
+ boolean deferKeyValueBackup = parser.getBoolean(KEY_KEYVALUE_DEFERRED,
+ defaultPolicy.deferKeyValueBackup);
+ boolean disableAnimation = parser.getBoolean(KEY_ANIMATION_DISABLED,
+ defaultPolicy.disableAnimation);
+ boolean disableAod = parser.getBoolean(KEY_AOD_DISABLED, defaultPolicy.disableAod);
+ boolean disableLaunchBoost = parser.getBoolean(KEY_LAUNCH_BOOST_DISABLED,
+ defaultPolicy.disableLaunchBoost);
+ boolean disableOptionalSensors = parser.getBoolean(KEY_OPTIONAL_SENSORS_DISABLED,
+ defaultPolicy.disableOptionalSensors);
+ boolean disableSoundTrigger = parser.getBoolean(KEY_SOUNDTRIGGER_DISABLED,
+ defaultPolicy.disableSoundTrigger);
+ boolean disableVibrationConfig = parser.getBoolean(KEY_VIBRATION_DISABLED,
+ defaultPolicy.disableVibration);
+ boolean enableAdjustBrightness = !parser.getBoolean(KEY_ADJUST_BRIGHTNESS_DISABLED,
+ !defaultPolicy.enableAdjustBrightness);
+ boolean enableDataSaver = !parser.getBoolean(KEY_ACTIVATE_DATASAVER_DISABLED,
+ !defaultPolicy.enableDataSaver);
+ boolean enableFirewall = !parser.getBoolean(KEY_ACTIVATE_FIREWALL_DISABLED,
+ !defaultPolicy.enableFirewall);
+ boolean enableQuickDoze = parser.getBoolean(KEY_QUICK_DOZE_ENABLED,
+ defaultPolicy.enableQuickDoze);
+ boolean forceAllAppsStandby = parser.getBoolean(KEY_FORCE_ALL_APPS_STANDBY,
+ defaultPolicy.forceAllAppsStandby);
+ boolean forceBackgroundCheck = parser.getBoolean(KEY_FORCE_BACKGROUND_CHECK,
+ defaultPolicy.forceBackgroundCheck);
+ int gpsMode = parser.getInt(KEY_GPS_MODE, defaultPolicy.gpsMode);
+ boolean sendTronLog = parser.getBoolean(KEY_SEND_TRON_LOG, defaultPolicy.sendTronLog);
+
+ return new Policy(
+ adjustBrightnessFactor,
+ advertiseIsEnabled,
+ deferFullBackup,
+ deferKeyValueBackup,
+ disableAnimation,
+ disableAod,
+ disableLaunchBoost,
+ disableOptionalSensors,
+ disableSoundTrigger,
+ /* disableVibration */
+ disableVibrationConfig,
+ enableAdjustBrightness,
+ enableDataSaver,
+ enableFirewall,
+ enableQuickDoze,
+ /* filesForInteractive */
+ (new CpuFrequencies()).parseString(cpuFreqInteractive).toSysFileMap(),
+ /* filesForNoninteractive */
+ (new CpuFrequencies()).parseString(cpuFreqNoninteractive).toSysFileMap(),
+ forceAllAppsStandby,
+ forceBackgroundCheck,
+ gpsMode,
+ sendTronLog
+ );
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (!(obj instanceof Policy)) return false;
+ Policy other = (Policy) obj;
+ return Float.compare(other.adjustBrightnessFactor, adjustBrightnessFactor) == 0
+ && advertiseIsEnabled == other.advertiseIsEnabled
+ && deferFullBackup == other.deferFullBackup
+ && deferKeyValueBackup == other.deferKeyValueBackup
+ && disableAnimation == other.disableAnimation
+ && disableAod == other.disableAod
+ && disableLaunchBoost == other.disableLaunchBoost
+ && disableOptionalSensors == other.disableOptionalSensors
+ && disableSoundTrigger == other.disableSoundTrigger
+ && disableVibration == other.disableVibration
+ && enableAdjustBrightness == other.enableAdjustBrightness
+ && enableDataSaver == other.enableDataSaver
+ && enableFirewall == other.enableFirewall
+ && enableQuickDoze == other.enableQuickDoze
+ && forceAllAppsStandby == other.forceAllAppsStandby
+ && forceBackgroundCheck == other.forceBackgroundCheck
+ && gpsMode == other.gpsMode
+ && sendTronLog == other.sendTronLog
+ && filesForInteractive.equals(other.filesForInteractive)
+ && filesForNoninteractive.equals(other.filesForNoninteractive);
+ }
+
+ @Override
+ public int hashCode() {
+ return mHashCode;
}
}
/**
- * Get the {@link PowerSaveState} based on {@paramref type} and {@paramref realMode}.
+ * Get the {@link PowerSaveState} based on the current policy level.
* The result will have {@link PowerSaveState#batterySaverEnabled} and some other
* parameters when necessary.
*
- * @param type type of the service, one of {@link ServiceType}
- * @param realMode whether the battery saver is on by default
+ * @param type type of the service, one of {@link ServiceType}
* @return State data that contains battery saver data
*/
- public PowerSaveState getBatterySaverPolicy(@ServiceType int type, boolean realMode) {
+ public PowerSaveState getBatterySaverPolicy(@ServiceType int type) {
synchronized (mLock) {
+ final Policy currPolicy = getCurrentPolicyLocked();
final PowerSaveState.Builder builder = new PowerSaveState.Builder()
- .setGlobalBatterySaverEnabled(realMode);
- if (!realMode) {
- return builder.setBatterySaverEnabled(realMode)
- .build();
- }
+ .setGlobalBatterySaverEnabled(currPolicy.advertiseIsEnabled);
switch (type) {
case ServiceType.GPS:
- return builder.setBatterySaverEnabled(realMode)
- .setGpsMode(mCurrPolicy.gpsMode)
+ boolean isEnabled = currPolicy.advertiseIsEnabled
+ || currPolicy.gpsMode != PowerManager.LOCATION_MODE_NO_CHANGE;
+ return builder.setBatterySaverEnabled(isEnabled)
+ .setGpsMode(currPolicy.gpsMode)
.build();
case ServiceType.ANIMATION:
- return builder.setBatterySaverEnabled(mCurrPolicy.disableAnimation)
+ return builder.setBatterySaverEnabled(currPolicy.disableAnimation)
.build();
case ServiceType.FULL_BACKUP:
- return builder.setBatterySaverEnabled(mCurrPolicy.deferFullBackup)
+ return builder.setBatterySaverEnabled(currPolicy.deferFullBackup)
.build();
case ServiceType.KEYVALUE_BACKUP:
- return builder.setBatterySaverEnabled(mCurrPolicy.deferKeyValueBackup)
+ return builder.setBatterySaverEnabled(currPolicy.deferKeyValueBackup)
.build();
case ServiceType.NETWORK_FIREWALL:
- return builder.setBatterySaverEnabled(mCurrPolicy.enableFirewall)
+ return builder.setBatterySaverEnabled(currPolicy.enableFirewall)
.build();
case ServiceType.SCREEN_BRIGHTNESS:
- return builder.setBatterySaverEnabled(mCurrPolicy.enableAdjustBrightness)
- .setBrightnessFactor(mCurrPolicy.adjustBrightnessFactor)
+ return builder.setBatterySaverEnabled(currPolicy.enableAdjustBrightness)
+ .setBrightnessFactor(currPolicy.adjustBrightnessFactor)
.build();
case ServiceType.DATA_SAVER:
- return builder.setBatterySaverEnabled(mCurrPolicy.enableDataSaver)
+ return builder.setBatterySaverEnabled(currPolicy.enableDataSaver)
.build();
case ServiceType.SOUND:
- return builder.setBatterySaverEnabled(mCurrPolicy.disableSoundTrigger)
+ return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
.build();
case ServiceType.VIBRATION:
return builder.setBatterySaverEnabled(mDisableVibrationEffective)
.build();
case ServiceType.FORCE_ALL_APPS_STANDBY:
- return builder.setBatterySaverEnabled(mCurrPolicy.forceAllAppsStandby)
+ return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
.build();
case ServiceType.FORCE_BACKGROUND_CHECK:
- return builder.setBatterySaverEnabled(mCurrPolicy.forceBackgroundCheck)
+ return builder.setBatterySaverEnabled(currPolicy.forceBackgroundCheck)
.build();
case ServiceType.OPTIONAL_SENSORS:
- return builder.setBatterySaverEnabled(mCurrPolicy.disableOptionalSensors)
+ return builder.setBatterySaverEnabled(currPolicy.disableOptionalSensors)
.build();
case ServiceType.AOD:
- return builder.setBatterySaverEnabled(mCurrPolicy.disableAod)
+ return builder.setBatterySaverEnabled(currPolicy.disableAod)
.build();
case ServiceType.QUICK_DOZE:
- return builder.setBatterySaverEnabled(mCurrPolicy.enableQuickDoze)
+ return builder.setBatterySaverEnabled(currPolicy.enableQuickDoze)
.build();
default:
- return builder.setBatterySaverEnabled(realMode)
+ return builder.setBatterySaverEnabled(currPolicy.advertiseIsEnabled)
.build();
}
}
}
+ /**
+ * Sets the current policy.
+ *
+ * @return true if the policy level was changed.
+ */
+ boolean setPolicyLevel(@PolicyLevel int level) {
+ synchronized (mLock) {
+ if (mPolicyLevel == level) {
+ return false;
+ }
+ switch (level) {
+ case POLICY_LEVEL_FULL:
+ case POLICY_LEVEL_ADAPTIVE:
+ case POLICY_LEVEL_OFF:
+ mPolicyLevel = level;
+ break;
+ default:
+ Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
+ return false;
+ }
+ updatePolicyDependenciesLocked();
+ return true;
+ }
+ }
+
+ /** @return true if the current policy changed and the policy level is ADAPTIVE. */
+ boolean setAdaptivePolicyLocked(Policy p) {
+ if (p == null) {
+ Slog.wtf(TAG, "setAdaptivePolicy given null policy");
+ return false;
+ }
+ if (mAdaptivePolicy.equals(p)) {
+ return false;
+ }
+
+ mAdaptivePolicy = p;
+ if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) {
+ updatePolicyDependenciesLocked();
+ return true;
+ }
+ return false;
+ }
+
+ /** @return true if the current policy changed and the policy level is ADAPTIVE. */
+ boolean resetAdaptivePolicyLocked() {
+ return setAdaptivePolicyLocked(mDefaultAdaptivePolicy);
+ }
+
+ private Policy getCurrentPolicyLocked() {
+ switch (mPolicyLevel) {
+ case POLICY_LEVEL_FULL:
+ return mFullPolicy;
+ case POLICY_LEVEL_ADAPTIVE:
+ return mAdaptivePolicy;
+ case POLICY_LEVEL_OFF:
+ default:
+ return OFF_POLICY;
+ }
+ }
+
public int getGpsMode() {
synchronized (mLock) {
- return mCurrPolicy.gpsMode;
+ return getCurrentPolicyLocked().gpsMode;
}
}
public ArrayMap<String, String> getFileValues(boolean interactive) {
synchronized (mLock) {
- return interactive ? mCurrPolicy.filesForInteractive
- : mCurrPolicy.filesForNoninteractive;
+ return interactive ? getCurrentPolicyLocked().filesForInteractive
+ : getCurrentPolicyLocked().filesForNoninteractive;
}
}
public boolean isLaunchBoostDisabled() {
synchronized (mLock) {
- return mCurrPolicy.disableLaunchBoost;
+ return getCurrentPolicyLocked().disableLaunchBoost;
+ }
+ }
+
+ boolean shouldAdvertiseIsEnabled() {
+ synchronized (mLock) {
+ return getCurrentPolicyLocked().advertiseIsEnabled;
}
}
@@ -658,40 +969,75 @@
pw.println(" Settings: " + mDeviceSpecificSettingsSource);
pw.println(" value: " + mDeviceSpecificSettings);
- pw.println();
+ pw.println(" Adaptive Settings: " + Settings.Global.BATTERY_SAVER_ADAPTIVE_CONSTANTS);
+ pw.println(" value: " + mAdaptiveSettings);
+ pw.println(" Adaptive Device Specific Settings: "
+ + Settings.Global.BATTERY_SAVER_ADAPTIVE_DEVICE_SPECIFIC_CONSTANTS);
+ pw.println(" value: " + mAdaptiveDeviceSpecificSettings);
+
pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled);
- pw.println(" " + KEY_VIBRATION_DISABLED + ":config=" + mCurrPolicy.disableVibration);
- pw.println(" " + KEY_VIBRATION_DISABLED + ":effective=" + mDisableVibrationEffective);
- pw.println(" " + KEY_ANIMATION_DISABLED + "=" + mCurrPolicy.disableAnimation);
- pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + mCurrPolicy.deferFullBackup);
- pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + mCurrPolicy.deferKeyValueBackup);
- pw.println(" " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !mCurrPolicy.enableFirewall);
- pw.println(" " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !mCurrPolicy.enableDataSaver);
- pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + mCurrPolicy.disableLaunchBoost);
- pw.println(" " + KEY_ADJUST_BRIGHTNESS_DISABLED + "="
- + !mCurrPolicy.enableAdjustBrightness);
- pw.println(
- " " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + mCurrPolicy.adjustBrightnessFactor);
- pw.println(" " + KEY_GPS_MODE + "=" + mCurrPolicy.gpsMode);
- pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + mCurrPolicy.forceAllAppsStandby);
- pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + mCurrPolicy.forceBackgroundCheck);
- pw.println(" " + KEY_OPTIONAL_SENSORS_DISABLED + "="
- + mCurrPolicy.disableOptionalSensors);
- pw.println(" " + KEY_AOD_DISABLED + "=" + mCurrPolicy.disableAod);
- pw.println(" " + KEY_SOUNDTRIGGER_DISABLED + "=" + mCurrPolicy.disableSoundTrigger);
- pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + mCurrPolicy.enableQuickDoze);
- pw.println(" " + KEY_SEND_TRON_LOG + "=" + mCurrPolicy.sendTronLog);
- pw.println();
+ pw.println(" mPolicyLevel=" + mPolicyLevel);
- pw.print(" Interactive File values:\n");
- dumpMap(pw, " ", mCurrPolicy.filesForInteractive);
- pw.println();
-
- pw.print(" Noninteractive File values:\n");
- dumpMap(pw, " ", mCurrPolicy.filesForNoninteractive);
+ dumpPolicyLocked(pw, " ", "full", mFullPolicy);
+ dumpPolicyLocked(pw, " ", "default adaptive", mDefaultAdaptivePolicy);
+ dumpPolicyLocked(pw, " ", "current adaptive", mAdaptivePolicy);
}
}
+ private void dumpPolicyLocked(PrintWriter pw, String indent, String label, Policy p) {
+ pw.println();
+ pw.print(indent);
+ pw.println("Policy '" + label + "'");
+ pw.print(indent);
+ pw.println(" " + KEY_ADVERTISE_IS_ENABLED + "=" + p.advertiseIsEnabled);
+ pw.print(indent);
+ pw.println(" " + KEY_VIBRATION_DISABLED + ":config=" + p.disableVibration);
+ // mDisableVibrationEffective is based on the currently selected policy
+ pw.print(indent);
+ pw.println(" " + KEY_VIBRATION_DISABLED + ":effective=" + (p.disableVibration
+ && !mAccessibilityEnabled));
+ pw.print(indent);
+ pw.println(" " + KEY_ANIMATION_DISABLED + "=" + p.disableAnimation);
+ pw.print(indent);
+ pw.println(" " + KEY_FULLBACKUP_DEFERRED + "=" + p.deferFullBackup);
+ pw.print(indent);
+ pw.println(" " + KEY_KEYVALUE_DEFERRED + "=" + p.deferKeyValueBackup);
+ pw.print(indent);
+ pw.println(" " + KEY_ACTIVATE_FIREWALL_DISABLED + "=" + !p.enableFirewall);
+ pw.print(indent);
+ pw.println(" " + KEY_ACTIVATE_DATASAVER_DISABLED + "=" + !p.enableDataSaver);
+ pw.print(indent);
+ pw.println(" " + KEY_LAUNCH_BOOST_DISABLED + "=" + p.disableLaunchBoost);
+ pw.println(
+ " " + KEY_ADJUST_BRIGHTNESS_DISABLED + "=" + !p.enableAdjustBrightness);
+ pw.print(indent);
+ pw.println(" " + KEY_ADJUST_BRIGHTNESS_FACTOR + "=" + p.adjustBrightnessFactor);
+ pw.print(indent);
+ pw.println(" " + KEY_GPS_MODE + "=" + p.gpsMode);
+ pw.print(indent);
+ pw.println(" " + KEY_FORCE_ALL_APPS_STANDBY + "=" + p.forceAllAppsStandby);
+ pw.print(indent);
+ pw.println(" " + KEY_FORCE_BACKGROUND_CHECK + "=" + p.forceBackgroundCheck);
+ pw.println(
+ " " + KEY_OPTIONAL_SENSORS_DISABLED + "=" + p.disableOptionalSensors);
+ pw.print(indent);
+ pw.println(" " + KEY_AOD_DISABLED + "=" + p.disableAod);
+ pw.print(indent);
+ pw.println(" " + KEY_SOUNDTRIGGER_DISABLED + "=" + p.disableSoundTrigger);
+ pw.print(indent);
+ pw.println(" " + KEY_QUICK_DOZE_ENABLED + "=" + p.enableQuickDoze);
+ pw.print(indent);
+ pw.println(" " + KEY_SEND_TRON_LOG + "=" + p.sendTronLog);
+ pw.println();
+
+ pw.print(" Interactive File values:\n");
+ dumpMap(pw, " ", p.filesForInteractive);
+ pw.println();
+
+ pw.print(" Noninteractive File values:\n");
+ dumpMap(pw, " ", p.filesForNoninteractive);
+ }
+
private void dumpMap(PrintWriter pw, String prefix, ArrayMap<String, String> map) {
if (map == null) {
return;
@@ -710,6 +1056,7 @@
public void setAccessibilityEnabledForTest(boolean enabled) {
synchronized (mLock) {
mAccessibilityEnabled = enabled;
+ updatePolicyDependenciesLocked();
}
}
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index 404e450..e6fa500 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -24,8 +24,10 @@
import android.content.Intent;
import android.content.res.Resources;
import android.database.ContentObserver;
+import android.os.BatterySaverPolicyConfig;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
@@ -46,8 +48,7 @@
* IMPORTANT: This class shares the power manager lock, which is very low in the lock hierarchy.
* Do not call out with the lock held. (Settings provider is okay.)
*
- * Test:
- atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+ * Test: atest com.android.server.power.batterysaver.BatterySaverStateMachineTest
*/
public class BatterySaverStateMachine {
private static final String TAG = "BatterySaverStateMachine";
@@ -57,6 +58,8 @@
private static final boolean DEBUG = BatterySaverPolicy.DEBUG;
+ private static final long ADAPTIVE_CHANGE_TIMEOUT_MS = 24 * 60 * 60 * 1000L;
+
private final Context mContext;
private final BatterySaverController mBatterySaverController;
@@ -157,6 +160,13 @@
@GuardedBy("mLock")
private String mLastChangedStrReason;
+ /**
+ * The last time adaptive battery saver was changed by an external service, using elapsed
+ * realtime as the timebase.
+ */
+ @GuardedBy("mLock")
+ private long mLastAdaptiveBatterySaverChangedExternallyElapsed;
+
private final ContentObserver mSettingsObserver = new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
@@ -178,10 +188,6 @@
com.android.internal.R.integer.config_dynamicPowerSavingsDefaultDisableThreshold);
}
- private boolean isBatterySaverEnabled() {
- return mBatterySaverController.isEnabled();
- }
-
private boolean isAutoBatterySaverConfiguredLocked() {
return mSettingBatterySaverTriggerThreshold > 0;
}
@@ -392,6 +398,36 @@
}
}
+ /**
+ * Enable or disable the current adaptive battery saver policy. This may not change what's in
+ * effect if full battery saver is also enabled.
+ */
+ public boolean setAdaptiveBatterySaverEnabled(boolean enabled) {
+ if (DEBUG) {
+ Slog.d(TAG, "setAdaptiveBatterySaverEnabled: enabled=" + enabled);
+ }
+ synchronized (mLock) {
+ mLastAdaptiveBatterySaverChangedExternallyElapsed = SystemClock.elapsedRealtime();
+ return mBatterySaverController.setAdaptivePolicyEnabledLocked(
+ enabled, BatterySaverController.REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED);
+ }
+ }
+
+ /**
+ * Change the adaptive battery saver policy.
+ */
+ public boolean setAdaptiveBatterySaverPolicy(BatterySaverPolicyConfig config) {
+ if (DEBUG) {
+ Slog.d(TAG, "setAdaptiveBatterySaverPolicy: config=" + config);
+ }
+
+ synchronized (mLock) {
+ mLastAdaptiveBatterySaverChangedExternallyElapsed = SystemClock.elapsedRealtime();
+ return mBatterySaverController.setAdaptivePolicyLocked(config,
+ BatterySaverController.REASON_ADAPTIVE_DYNAMIC_POWER_SAVINGS_CHANGED);
+ }
+ }
+
@GuardedBy("mLock")
private boolean isBatteryLowLocked() {
final boolean percentageLow =
@@ -427,12 +463,26 @@
if (!isBatteryLowLocked()) {
updateSnoozingLocked(false, "Battery not low");
}
+
+ if (SystemClock.elapsedRealtime() - mLastAdaptiveBatterySaverChangedExternallyElapsed
+ > ADAPTIVE_CHANGE_TIMEOUT_MS) {
+ mBatterySaverController.setAdaptivePolicyEnabledLocked(
+ false, BatterySaverController.REASON_TIMEOUT);
+ mBatterySaverController.resetAdaptivePolicyLocked(
+ BatterySaverController.REASON_TIMEOUT);
+ }
+
if (mIsPowered) {
updateSnoozingLocked(false, "Plugged in");
enableBatterySaverLocked(/*enable=*/ false, /*manual=*/ false,
BatterySaverController.REASON_PLUGGED_IN,
"Plugged in");
+ if (mBatteryLevel >= 80 /* Arbitrary level */) {
+ mBatterySaverController.setAdaptivePolicyEnabledLocked(
+ false, BatterySaverController.REASON_PLUGGED_IN);
+ }
+
} else if (mSettingBatterySaverEnabledSticky && !mBatterySaverStickyBehaviourDisabled) {
if (mSettingBatterySaverStickyAutoDisableEnabled
&& mBatteryLevel >= mSettingBatterySaverStickyAutoDisableThreshold) {
@@ -472,7 +522,7 @@
// do nothing if automatic battery saver mode = PERCENTAGE and low warning threshold = 0%
}
- /**
+ /**
* {@link com.android.server.power.PowerManagerService} calls it when
* {@link android.os.PowerManager#setPowerSaveMode} is called.
*
@@ -501,7 +551,7 @@
Slog.d(TAG, "enableBatterySaver: enable=" + enable + " manual=" + manual
+ " reason=" + strReason + "(" + intReason + ")");
}
- final boolean wasEnabled = mBatterySaverController.isEnabled();
+ final boolean wasEnabled = mBatterySaverController.isFullEnabled();
if (wasEnabled == enable) {
if (DEBUG) {
@@ -523,9 +573,10 @@
// 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() && isBatteryLowLocked()) {
+ if (mBatterySaverController.isFullEnabled() && isBatteryLowLocked()) {
updateSnoozingLocked(true, "Manual snooze");
}
+ // TODO: maybe turn off adaptive if it's on and advertiseIsEnabled is true
}
}
@@ -622,6 +673,17 @@
pw.print(" Enabled=");
pw.println(mBatterySaverController.isEnabled());
+ pw.print(" full=");
+ pw.println(mBatterySaverController.isFullEnabled());
+ pw.print(" adaptive=");
+ pw.print(mBatterySaverController.isAdaptiveEnabled());
+ if (mBatterySaverController.isAdaptiveEnabled()) {
+ pw.print(" (advertise=");
+ pw.print(
+ mBatterySaverController.getBatterySaverPolicy().shouldAdvertiseIsEnabled());
+ pw.print(")");
+ }
+ pw.println();
pw.print(" mLastChangedIntReason=");
pw.println(mLastChangedIntReason);
@@ -657,6 +719,9 @@
pw.println(mSettingBatterySaverTriggerThreshold);
pw.print(" mBatterySaverStickyBehaviourDisabled=");
pw.println(mBatterySaverStickyBehaviourDisabled);
+
+ pw.print(" mLastAdaptiveBatterySaverChangedExternallyElapsed=");
+ pw.println(mLastAdaptiveBatterySaverChangedExternallyElapsed);
}
}
@@ -666,6 +731,12 @@
proto.write(BatterySaverStateMachineProto.ENABLED,
mBatterySaverController.isEnabled());
+ proto.write(BatterySaverStateMachineProto.IS_FULL_ENABLED,
+ mBatterySaverController.isFullEnabled());
+ proto.write(BatterySaverStateMachineProto.IS_ADAPTIVE_ENABLED,
+ mBatterySaverController.isAdaptiveEnabled());
+ proto.write(BatterySaverStateMachineProto.SHOULD_ADVERTISE_IS_ENABLED,
+ mBatterySaverController.getBatterySaverPolicy().shouldAdvertiseIsEnabled());
proto.write(BatterySaverStateMachineProto.BOOT_COMPLETED, mBootCompleted);
proto.write(BatterySaverStateMachineProto.SETTINGS_LOADED, mSettingsLoaded);
@@ -692,6 +763,11 @@
.SETTING_BATTERY_SAVER_STICKY_AUTO_DISABLE_THRESHOLD,
mSettingBatterySaverStickyAutoDisableThreshold);
+ proto.write(
+ BatterySaverStateMachineProto
+ .LAST_ADAPTIVE_BATTERY_SAVER_CHANGED_EXTERNALLY_ELAPSED,
+ mLastAdaptiveBatterySaverChangedExternallyElapsed);
+
proto.end(token);
}
}
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
index 79b44eb..1d30a03 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySavingStats.java
@@ -57,9 +57,10 @@
interface BatterySaverState {
int OFF = 0;
int ON = 1;
+ int ADAPTIVE = 2;
int SHIFT = 0;
- int BITS = 1;
+ int BITS = 2;
int MASK = (1 << BITS) - 1;
static int fromIndex(int index) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
index 5009d64..86e8598 100644
--- a/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/power/batterysaver/BatterySaverStateMachineTest.java
@@ -16,6 +16,7 @@
package com.android.server.power.batterysaver;
import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.doAnswer;
@@ -178,8 +179,12 @@
.getSystemService(NotificationManager.class);
doAnswer((inv) -> mDevice.batterySaverEnabled = inv.getArgument(0))
.when(mMockBatterySaverController).enableBatterySaver(anyBoolean(), anyInt());
+ doReturn(true).when(mMockBatterySaverController)
+ .setAdaptivePolicyLocked(any(BatterySaverPolicy.Policy.class), anyInt());
when(mMockBatterySaverController.isEnabled())
.thenAnswer((inv) -> mDevice.batterySaverEnabled);
+ when(mMockBatterySaverController.isFullEnabled())
+ .thenAnswer((inv) -> mDevice.batterySaverEnabled);
when(mMockResources.getBoolean(
com.android.internal.R.bool.config_batterySaverStickyBehaviourDisabled))
.thenReturn(false);
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 0dff03f..bfa0b74 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -86,7 +85,7 @@
.setBrightnessFactor(BRIGHTNESS_FACTOR)
.build();
when(mBatterySaverPolicyMock.getBatterySaverPolicy(
- eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS), anyBoolean()))
+ eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS)))
.thenReturn(mPowerSaveState);
mDisplayPowerRequest = new DisplayPowerRequest();
diff --git a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
index 73eefcf..9cc2b10 100644
--- a/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java
@@ -15,6 +15,10 @@
*/
package com.android.server.power.batterysaver;
+import static com.android.server.power.batterysaver.BatterySaverPolicy.POLICY_LEVEL_ADAPTIVE;
+import static com.android.server.power.batterysaver.BatterySaverPolicy.POLICY_LEVEL_FULL;
+import static com.android.server.power.batterysaver.BatterySaverPolicy.POLICY_LEVEL_OFF;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -31,6 +35,7 @@
import com.android.frameworks.servicestests.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
+import com.android.server.power.batterysaver.BatterySaverPolicy.Policy;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -39,15 +44,15 @@
* Tests for {@link com.android.server.power.batterysaver.BatterySaverPolicy}
*/
public class BatterySaverPolicyTest extends AndroidTestCase {
- private static final boolean BATTERY_SAVER_ON = true;
- private static final boolean BATTERY_SAVER_OFF = false;
+ private static final int MAX_SERVICE_TYPE = 15;
private static final float BRIGHTNESS_FACTOR = 0.7f;
private static final float DEFAULT_BRIGHTNESS_FACTOR = 0.5f;
private static final float PRECISION = 0.001f;
- private static final int GPS_MODE = 0;
+ private static final int GPS_MODE = 0; // LOCATION_MODE_NO_CHANGE
private static final int DEFAULT_GPS_MODE =
PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF;
private static final String BATTERY_SAVER_CONSTANTS = "vibration_disabled=true,"
+ + "advertise_is_enabled=true,"
+ "animation_disabled=false,"
+ "soundtrigger_disabled=true,"
+ "firewall_disabled=false,"
@@ -56,7 +61,7 @@
+ "adjust_brightness_factor=0.7,"
+ "fullbackup_deferred=true,"
+ "keyvaluebackup_deferred=false,"
- + "gps_mode=0,"
+ + "gps_mode=0," // LOCATION_MODE_NO_CHANGE
+ "quick_doze_enabled=true";
private static final String BATTERY_SAVER_INCORRECT_CONSTANTS = "vi*,!=,,true";
@@ -97,6 +102,8 @@
mBatterySaverPolicy = new BatterySaverPolicyForTest(lock, getContext(),
new BatterySavingStats(lock, mMetricsLogger));
mBatterySaverPolicy.systemReady();
+
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
}
@SmallTest
@@ -148,12 +155,14 @@
@SmallTest
public void testGetBatterySaverPolicy_PolicyDataSaver_DefaultValueCorrect() {
mBatterySaverPolicy.updateConstantsLocked("", "");
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
final PowerSaveState batterySaverStateOn =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.DATA_SAVER, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.DATA_SAVER);
assertThat(batterySaverStateOn.batterySaverEnabled).isFalse();
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_OFF);
final PowerSaveState batterySaverStateOff = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.DATA_SAVER, BATTERY_SAVER_OFF);
+ ServiceType.DATA_SAVER);
assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
}
@@ -166,8 +175,9 @@
public void testGetBatterySaverPolicy_PolicyGps_DefaultValueCorrect() {
testServiceDefaultValue_On(ServiceType.GPS);
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
PowerSaveState stateOn =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, true);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS);
assertThat(stateOn.gpsMode).isEqualTo(DEFAULT_GPS_MODE);
}
@@ -180,47 +190,51 @@
public void testUpdateConstants_getCorrectData() {
mBatterySaverPolicy.updateConstantsLocked(BATTERY_SAVER_CONSTANTS, "");
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
+ verifyBatterySaverConstantsUpdated();
+ }
+
+ private void verifyBatterySaverConstantsUpdated() {
final PowerSaveState vibrationState =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.VIBRATION);
assertThat(vibrationState.batterySaverEnabled).isTrue();
final PowerSaveState animationState =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.ANIMATION);
assertThat(animationState.batterySaverEnabled).isFalse();
final PowerSaveState soundState =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SOUND);
assertThat(soundState.batterySaverEnabled).isTrue();
final PowerSaveState networkState = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.NETWORK_FIREWALL, BATTERY_SAVER_ON);
+ ServiceType.NETWORK_FIREWALL);
assertThat(networkState.batterySaverEnabled).isTrue();
final PowerSaveState screenState =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS,
- BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.SCREEN_BRIGHTNESS);
assertThat(screenState.batterySaverEnabled).isFalse();
assertThat(screenState.brightnessFactor).isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
final PowerSaveState fullBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.FULL_BACKUP, BATTERY_SAVER_ON);
+ ServiceType.FULL_BACKUP);
assertThat(fullBackupState.batterySaverEnabled).isTrue();
final PowerSaveState keyValueBackupState = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.KEYVALUE_BACKUP, BATTERY_SAVER_ON);
+ ServiceType.KEYVALUE_BACKUP);
assertThat(keyValueBackupState.batterySaverEnabled).isFalse();
final PowerSaveState dataSaverState = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.DATA_SAVER, BATTERY_SAVER_ON);
+ ServiceType.DATA_SAVER);
assertThat(dataSaverState.batterySaverEnabled).isTrue();
final PowerSaveState gpsState =
- mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.GPS);
assertThat(gpsState.batterySaverEnabled).isTrue();
assertThat(gpsState.gpsMode).isEqualTo(GPS_MODE);
final PowerSaveState quickDozeState = mBatterySaverPolicy.getBatterySaverPolicy(
- ServiceType.QUICK_DOZE, BATTERY_SAVER_ON);
+ ServiceType.QUICK_DOZE);
assertThat(quickDozeState.batterySaverEnabled).isTrue();
}
@@ -233,23 +247,27 @@
private void testServiceDefaultValue_On(@ServiceType int type) {
mBatterySaverPolicy.updateConstantsLocked("", "");
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
final PowerSaveState batterySaverStateOn =
- mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(type);
assertThat(batterySaverStateOn.batterySaverEnabled).isTrue();
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_OFF);
final PowerSaveState batterySaverStateOff =
- mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
+ mBatterySaverPolicy.getBatterySaverPolicy(type);
assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
}
private void testServiceDefaultValue_Off(@ServiceType int type) {
mBatterySaverPolicy.updateConstantsLocked("", "");
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
final PowerSaveState batterySaverStateOn =
- mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_ON);
+ mBatterySaverPolicy.getBatterySaverPolicy(type);
assertThat(batterySaverStateOn.batterySaverEnabled).isFalse();
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_OFF);
final PowerSaveState batterySaverStateOff =
- mBatterySaverPolicy.getBatterySaverPolicy(type, BATTERY_SAVER_OFF);
+ mBatterySaverPolicy.getBatterySaverPolicy(type);
assertThat(batterySaverStateOff.batterySaverEnabled).isFalse();
}
@@ -291,4 +309,26 @@
+ "/sys/devices/system/cpu/cpu5/cpufreq/scaling_max_freq=15}");
assertThat(mBatterySaverPolicy.getFileValues(false).toString()).isEqualTo("{}");
}
+
+ public void testSetPolicyLevel_Off() {
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_OFF);
+
+ // +1 to make sure the default value is off as well.
+ for (int i = 0; i < MAX_SERVICE_TYPE + 1; ++i) {
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(i).batterySaverEnabled).isFalse();
+ }
+ }
+
+ public void testSetPolicyLevel_Adaptive() {
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_ADAPTIVE);
+
+ mBatterySaverPolicy.setAdaptivePolicyLocked(BatterySaverPolicy.OFF_POLICY);
+ for (int i = 0; i < MAX_SERVICE_TYPE + 1; ++i) {
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(i).batterySaverEnabled).isFalse();
+ }
+
+ mBatterySaverPolicy.setAdaptivePolicyLocked(
+ Policy.fromSettings(BATTERY_SAVER_CONSTANTS, ""));
+ verifyBatterySaverConstantsUpdated();
+ }
}