diff options
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); + } } |