summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java198
-rw-r--r--services/tests/servicestests/src/com/android/server/power/batterysaver/BatterySaverPolicyTest.java55
2 files changed, 200 insertions, 53 deletions
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 233417da3e00..059861b65e20 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverPolicy.java
@@ -16,8 +16,13 @@
package com.android.server.power.batterysaver;
import android.annotation.IntDef;
+import android.app.UiModeManager;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.BatterySaverPolicyConfig;
@@ -183,18 +188,15 @@ public class BatterySaverPolicy extends ContentObserver {
private String mEventLogKeys;
/**
- * Whether vibration should *really* be disabled -- i.e. {@link Policy#disableVibration}
- * is true *and* {@link #mAccessibilityEnabled} is false.
- */
- @GuardedBy("mLock")
- private boolean mDisableVibrationEffective;
-
- /**
* Whether accessibility is currently enabled or not.
*/
@GuardedBy("mLock")
private boolean mAccessibilityEnabled;
+ /** Whether the phone is projecting in car mode or not. */
+ @GuardedBy("mLock")
+ private boolean mCarModeEnabled;
+
/** The current default adaptive policy. */
@GuardedBy("mLock")
private Policy mDefaultAdaptivePolicy = DEFAULT_ADAPTIVE_POLICY;
@@ -207,6 +209,13 @@ public class BatterySaverPolicy extends ContentObserver {
@GuardedBy("mLock")
private Policy mFullPolicy = DEFAULT_FULL_POLICY;
+ /**
+ * The current effective policy. This is based on the current policy level's policy, with any
+ * required adjustments.
+ */
+ @GuardedBy("mLock")
+ private Policy mEffectivePolicy = OFF_POLICY;
+
@IntDef(prefix = {"POLICY_LEVEL_"}, value = {
POLICY_LEVEL_OFF,
POLICY_LEVEL_ADAPTIVE,
@@ -230,6 +239,20 @@ public class BatterySaverPolicy extends ContentObserver {
private final ContentResolver mContentResolver;
private final BatterySavingStats mBatterySavingStats;
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ switch (intent.getAction()) {
+ case UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED:
+ setCarModeEnabled(true);
+ break;
+ case UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED:
+ setCarModeEnabled(false);
+ break;
+ }
+ }
+ };
+
@GuardedBy("mLock")
private final List<BatterySaverPolicyListener> mListeners = new ArrayList<>();
@@ -263,16 +286,25 @@ public class BatterySaverPolicy extends ContentObserver {
final AccessibilityManager acm = mContext.getSystemService(AccessibilityManager.class);
- acm.addAccessibilityStateChangeListener((enabled) -> {
- synchronized (mLock) {
- mAccessibilityEnabled = enabled;
- }
- refreshSettings();
- });
- final boolean enabled = acm.isEnabled();
+ acm.addAccessibilityStateChangeListener((enabled) -> setAccessibilityEnabled(enabled));
+ final boolean accessibilityEnabled = acm.isEnabled();
synchronized (mLock) {
- mAccessibilityEnabled = enabled;
+ mAccessibilityEnabled = accessibilityEnabled;
}
+
+ final IntentFilter filter = new IntentFilter(
+ UiModeManager.ACTION_ENTER_CAR_MODE_PRIORITIZED);
+ filter.addAction(UiModeManager.ACTION_EXIT_CAR_MODE_PRIORITIZED);
+ // The ENTER/EXIT_CAR_MODE_PRIORITIZED intents are sent to UserHandle.ALL, so no need to
+ // register as all users here.
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ final boolean carModeEnabled =
+ mContext.getSystemService(UiModeManager.class).getCurrentModeType()
+ == Configuration.UI_MODE_TYPE_CAR;
+ synchronized (mLock) {
+ mCarModeEnabled = carModeEnabled;
+ }
+
onChange(true, null);
}
@@ -299,13 +331,34 @@ public class BatterySaverPolicy extends ContentObserver {
PowerManager.invalidatePowerSaveModeCaches();
}
+ /**
+ * Notifies listeners of a policy change on the handler thread only if the current policy level
+ * is not {@link POLICY_LEVEL_OFF}.
+ */
+ private void maybeNotifyListenersOfPolicyChange() {
+ final BatterySaverPolicyListener[] listeners;
+ synchronized (mLock) {
+ if (getPolicyLevelLocked() == POLICY_LEVEL_OFF) {
+ // Current policy is OFF, so there's no change to notify listeners of.
+ return;
+ }
+ // Don't call out to listeners with the lock held.
+ listeners = mListeners.toArray(new BatterySaverPolicyListener[mListeners.size()]);
+ }
+
+ mHandler.post(() -> {
+ for (BatterySaverPolicyListener listener : listeners) {
+ listener.onBatterySaverPolicyChanged(this);
+ }
+ });
+ }
+
@Override
public void onChange(boolean selfChange, Uri uri) {
refreshSettings();
}
private void refreshSettings() {
- final BatterySaverPolicyListener[] listeners;
synchronized (mLock) {
// Load the non-device-specific setting.
final String setting = getGlobalSetting(Settings.Global.BATTERY_SAVER_CONSTANTS);
@@ -334,16 +387,9 @@ public class BatterySaverPolicy extends ContentObserver {
// Nothing of note changed.
return;
}
-
- listeners = mListeners.toArray(new BatterySaverPolicyListener[0]);
}
- // Notify the listeners.
- mHandler.post(() -> {
- for (BatterySaverPolicyListener listener : listeners) {
- listener.onBatterySaverPolicyChanged(this);
- }
- });
+ maybeNotifyListenersOfPolicyChange();
}
@GuardedBy("mLock")
@@ -404,31 +450,63 @@ public class BatterySaverPolicy extends ContentObserver {
@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 Policy rawPolicy = getCurrentRawPolicyLocked();
+
+ final int locationMode;
+ if (mCarModeEnabled
+ && rawPolicy.locationMode != PowerManager.LOCATION_MODE_NO_CHANGE
+ && rawPolicy.locationMode != PowerManager.LOCATION_MODE_FOREGROUND_ONLY) {
+ // If car projection is enabled, ensure that navigation works.
+ locationMode = PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
+ } else {
+ locationMode = rawPolicy.locationMode;
+ }
+ mEffectivePolicy = new Policy(
+ rawPolicy.adjustBrightnessFactor,
+ rawPolicy.advertiseIsEnabled,
+ rawPolicy.deferFullBackup,
+ rawPolicy.deferKeyValueBackup,
+ rawPolicy.disableAnimation,
+ rawPolicy.disableAod,
+ rawPolicy.disableLaunchBoost,
+ rawPolicy.disableOptionalSensors,
+ rawPolicy.disableSoundTrigger,
+ // Don't disable vibration when accessibility is on.
+ rawPolicy.disableVibration && !mAccessibilityEnabled,
+ rawPolicy.enableAdjustBrightness,
+ rawPolicy.enableDataSaver,
+ rawPolicy.enableFirewall,
+ // Don't force night mode when car projection is enabled.
+ rawPolicy.enableNightMode && !mCarModeEnabled,
+ rawPolicy.enableQuickDoze,
+ rawPolicy.filesForInteractive,
+ rawPolicy.filesForNoninteractive,
+ rawPolicy.forceAllAppsStandby,
+ rawPolicy.forceBackgroundCheck,
+ locationMode
+ );
+
final StringBuilder sb = new StringBuilder();
- if (currPolicy.forceAllAppsStandby) sb.append("A");
- if (currPolicy.forceBackgroundCheck) sb.append("B");
+ if (mEffectivePolicy.forceAllAppsStandby) sb.append("A");
+ if (mEffectivePolicy.forceBackgroundCheck) sb.append("B");
- if (mDisableVibrationEffective) sb.append("v");
- 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 (mEffectivePolicy.disableVibration) sb.append("v");
+ if (mEffectivePolicy.disableAnimation) sb.append("a");
+ if (mEffectivePolicy.disableSoundTrigger) sb.append("s");
+ if (mEffectivePolicy.deferFullBackup) sb.append("F");
+ if (mEffectivePolicy.deferKeyValueBackup) sb.append("K");
+ if (mEffectivePolicy.enableFirewall) sb.append("f");
+ if (mEffectivePolicy.enableDataSaver) sb.append("d");
+ if (mEffectivePolicy.enableAdjustBrightness) sb.append("b");
- 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 (mEffectivePolicy.disableLaunchBoost) sb.append("l");
+ if (mEffectivePolicy.disableOptionalSensors) sb.append("S");
+ if (mEffectivePolicy.disableAod) sb.append("o");
+ if (mEffectivePolicy.enableQuickDoze) sb.append("q");
- sb.append(currPolicy.locationMode);
+ sb.append(mEffectivePolicy.locationMode);
mEventLogKeys = sb.toString();
}
@@ -857,7 +935,7 @@ public class BatterySaverPolicy extends ContentObserver {
return builder.setBatterySaverEnabled(currPolicy.disableSoundTrigger)
.build();
case ServiceType.VIBRATION:
- return builder.setBatterySaverEnabled(mDisableVibrationEffective)
+ return builder.setBatterySaverEnabled(currPolicy.disableVibration)
.build();
case ServiceType.FORCE_ALL_APPS_STANDBY:
return builder.setBatterySaverEnabled(currPolicy.forceAllAppsStandby)
@@ -933,6 +1011,10 @@ public class BatterySaverPolicy extends ContentObserver {
}
private Policy getCurrentPolicyLocked() {
+ return mEffectivePolicy;
+ }
+
+ private Policy getCurrentRawPolicyLocked() {
switch (getPolicyLevelLocked()) {
case POLICY_LEVEL_FULL:
return mFullPolicy;
@@ -994,11 +1076,13 @@ public class BatterySaverPolicy extends ContentObserver {
pw.println(" value: " + mAdaptiveDeviceSpecificSettings);
pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled);
+ pw.println(" mCarModeEnabled=" + mCarModeEnabled);
pw.println(" mPolicyLevel=" + getPolicyLevelLocked());
dumpPolicyLocked(pw, " ", "full", mFullPolicy);
dumpPolicyLocked(pw, " ", "default adaptive", mDefaultAdaptivePolicy);
dumpPolicyLocked(pw, " ", "current adaptive", mAdaptivePolicy);
+ dumpPolicyLocked(pw, " ", "effective", mEffectivePolicy);
}
}
@@ -1009,11 +1093,7 @@ public class BatterySaverPolicy extends ContentObserver {
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.println(" " + KEY_VIBRATION_DISABLED + "=" + p.disableVibration);
pw.print(indent);
pw.println(" " + KEY_ANIMATION_DISABLED + "=" + p.disableAnimation);
pw.print(indent);
@@ -1070,10 +1150,24 @@ public class BatterySaverPolicy extends ContentObserver {
}
@VisibleForTesting
- public void setAccessibilityEnabledForTest(boolean enabled) {
+ void setAccessibilityEnabled(boolean enabled) {
synchronized (mLock) {
- mAccessibilityEnabled = enabled;
- updatePolicyDependenciesLocked();
+ if (mAccessibilityEnabled != enabled) {
+ mAccessibilityEnabled = enabled;
+ updatePolicyDependenciesLocked();
+ maybeNotifyListenersOfPolicyChange();
+ }
+ }
+ }
+
+ @VisibleForTesting
+ void setCarModeEnabled(boolean enabled) {
+ synchronized (mLock) {
+ if (mCarModeEnabled != enabled) {
+ mCarModeEnabled = enabled;
+ updatePolicyDependenciesLocked();
+ maybeNotifyListenersOfPolicyChange();
+ }
}
}
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 30ab9cd2f875..dc30add1b383 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
@@ -117,7 +117,7 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
@SmallTest
public void testGetBatterySaverPolicy_PolicyVibration_WithAccessibilityEnabled() {
- mBatterySaverPolicy.setAccessibilityEnabledForTest(true);
+ mBatterySaverPolicy.setAccessibilityEnabled(true);
testServiceDefaultValue_Off(ServiceType.VIBRATION);
}
@@ -339,4 +339,57 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
Policy.fromSettings(BATTERY_SAVER_CONSTANTS, ""));
verifyBatterySaverConstantsUpdated();
}
+
+ public void testCarModeChanges_Full() {
+ mBatterySaverPolicy.updateConstantsLocked(
+ "gps_mode=" + PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF
+ + ",enable_night_mode=true", "");
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_FULL);
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isEqualTo(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
+ assertTrue(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+
+ mBatterySaverPolicy.setCarModeEnabled(true);
+
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isAnyOf(PowerManager.LOCATION_MODE_NO_CHANGE,
+ PowerManager.LOCATION_MODE_FOREGROUND_ONLY);
+ assertFalse(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+
+ mBatterySaverPolicy.setCarModeEnabled(false);
+
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isEqualTo(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
+ assertTrue(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+ }
+
+ public void testCarModeChanges_Adaptive() {
+ mBatterySaverPolicy.setAdaptivePolicyLocked(
+ Policy.fromSettings(
+ "gps_mode=" + PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF
+ + ",enable_night_mode=true", ""));
+ mBatterySaverPolicy.setPolicyLevel(POLICY_LEVEL_ADAPTIVE);
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isEqualTo(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
+ assertTrue(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+
+ mBatterySaverPolicy.setCarModeEnabled(true);
+
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isAnyOf(PowerManager.LOCATION_MODE_NO_CHANGE,
+ PowerManager.LOCATION_MODE_FOREGROUND_ONLY);
+ assertFalse(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+
+ mBatterySaverPolicy.setCarModeEnabled(false);
+
+ assertThat(mBatterySaverPolicy.getBatterySaverPolicy(ServiceType.LOCATION).locationMode)
+ .isEqualTo(PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF);
+ assertTrue(mBatterySaverPolicy.getBatterySaverPolicy(
+ ServiceType.NIGHT_MODE).batterySaverEnabled);
+ }
}