Loading core/res/res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2479,6 +2479,8 @@ <integer name="config_attentionMaximumExtension">900000</integer> <!-- 15 minutes. --> <!-- Is the system user the only user allowed to dream. --> <bool name="config_dreamsOnlyEnabledForSystemUser">false</bool> <!-- Whether dreams are disabled when ambient mode is suppressed. --> <bool name="config_dreamsDisabledByAmbientModeSuppressionConfig">false</bool> <!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to assistant activities (ACTIVITY_TYPE_ASSISTANT) --> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2235,6 +2235,7 @@ <java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" /> <java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" /> <java-symbol type="string" name="config_dreamsDefaultComponent" /> <java-symbol type="bool" name="config_dreamsDisabledByAmbientModeSuppressionConfig" /> <java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" /> <java-symbol type="array" name="config_supportedDreamComplications" /> <java-symbol type="array" name="config_disabledDreamComponents" /> Loading services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java +21 −4 Original line number Diff line number Diff line Loading @@ -40,13 +40,24 @@ import java.util.Set; public class AmbientDisplaySuppressionController { private static final String TAG = "AmbientDisplaySuppressionController"; private final Context mContext; private final Set<Pair<String, Integer>> mSuppressionTokens; private final AmbientDisplaySuppressionChangedCallback mCallback; private IStatusBarService mStatusBarService; AmbientDisplaySuppressionController(Context context) { mContext = requireNonNull(context); /** Interface to get a list of available logical devices. */ interface AmbientDisplaySuppressionChangedCallback { /** * Called when the suppression state changes. * * @param isSuppressed Whether ambient is suppressed. */ void onSuppressionChanged(boolean isSuppressed); } AmbientDisplaySuppressionController( @NonNull AmbientDisplaySuppressionChangedCallback callback) { mSuppressionTokens = Collections.synchronizedSet(new ArraySet<>()); mCallback = requireNonNull(callback); } /** Loading @@ -58,6 +69,7 @@ public class AmbientDisplaySuppressionController { */ public void suppress(@NonNull String token, int callingUid, boolean suppress) { Pair<String, Integer> suppressionToken = Pair.create(requireNonNull(token), callingUid); final boolean wasSuppressed = isSuppressed(); if (suppress) { mSuppressionTokens.add(suppressionToken); Loading @@ -65,9 +77,14 @@ public class AmbientDisplaySuppressionController { mSuppressionTokens.remove(suppressionToken); } final boolean isSuppressed = isSuppressed(); if (isSuppressed != wasSuppressed) { mCallback.onSuppressionChanged(isSuppressed); } try { synchronized (mSuppressionTokens) { getStatusBar().suppressAmbientDisplay(isSuppressed()); getStatusBar().suppressAmbientDisplay(isSuppressed); } } catch (RemoteException e) { Slog.e(TAG, "Failed to suppress ambient display", e); Loading services/core/java/com/android/server/power/PowerManagerService.java +41 −4 Original line number Diff line number Diff line Loading @@ -127,6 +127,7 @@ import com.android.server.am.BatteryStatsService; import com.android.server.lights.LightsManager; import com.android.server.lights.LogicalLight; import com.android.server.policy.WindowManagerPolicy; import com.android.server.power.AmbientDisplaySuppressionController.AmbientDisplaySuppressionChangedCallback; import com.android.server.power.batterysaver.BatterySaverController; import com.android.server.power.batterysaver.BatterySaverPolicy; import com.android.server.power.batterysaver.BatterySaverStateMachine; Loading Loading @@ -507,6 +508,9 @@ public final class PowerManagerService extends SystemService // effectively and terminate the dream. Use -1 to disable this safety feature. private int mDreamsBatteryLevelDrainCutoffConfig; // Whether dreams should be disabled when ambient mode is suppressed. private boolean mDreamsDisabledByAmbientModeSuppressionConfig; // True if dreams are enabled by the user. private boolean mDreamsEnabledSetting; Loading Loading @@ -964,8 +968,8 @@ public final class PowerManagerService extends SystemService } AmbientDisplaySuppressionController createAmbientDisplaySuppressionController( Context context) { return new AmbientDisplaySuppressionController(context); @NonNull AmbientDisplaySuppressionChangedCallback callback) { return new AmbientDisplaySuppressionController(callback); } InattentiveSleepWarningController createInattentiveSleepWarningController() { Loading Loading @@ -1044,7 +1048,8 @@ public final class PowerManagerService extends SystemService mConstants = new Constants(mHandler); mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context); mAmbientDisplaySuppressionController = mInjector.createAmbientDisplaySuppressionController(context); mInjector.createAmbientDisplaySuppressionController( mAmbientSuppressionChangedCallback); mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock); mFaceDownDetector = new FaceDownDetector(this::onFlip); mScreenUndimDetector = new ScreenUndimDetector(); Loading Loading @@ -1403,6 +1408,8 @@ public final class PowerManagerService extends SystemService com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered); mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger( com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff); mDreamsDisabledByAmbientModeSuppressionConfig = resources.getBoolean( com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig); mDozeAfterScreenOff = resources.getBoolean( com.android.internal.R.bool.config_dozeAfterScreenOffByDefault); mMinimumScreenOffTimeoutConfig = resources.getInteger( Loading Loading @@ -3340,12 +3347,32 @@ public final class PowerManagerService extends SystemService } } @GuardedBy("mLock") private void onDreamSuppressionChangedLocked(final boolean isSuppressed) { if (!mDreamsDisabledByAmbientModeSuppressionConfig) { return; } if (!isSuppressed && mIsPowered && mDreamsSupportedConfig && mDreamsEnabledSetting && shouldNapAtBedTimeLocked() && isItBedTimeYetLocked( mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP))) { napInternal(SystemClock.uptimeMillis(), Process.SYSTEM_UID, /* allowWake= */ true); } else if (isSuppressed) { mDirty |= DIRTY_SETTINGS; updatePowerStateLocked(); } } /** * Returns true if the {@code groupId} is allowed to dream in its current state. */ @GuardedBy("mLock") private boolean canDreamLocked(final PowerGroup powerGroup) { final boolean dreamsSuppressed = mDreamsDisabledByAmbientModeSuppressionConfig && mAmbientDisplaySuppressionController.isSuppressed(); if (!mBootCompleted || dreamsSuppressed || getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING || !mDreamsSupportedConfig || !mDreamsEnabledSetting Loading Loading @@ -5037,6 +5064,16 @@ public final class PowerManagerService extends SystemService } }; private final AmbientDisplaySuppressionChangedCallback mAmbientSuppressionChangedCallback = new AmbientDisplaySuppressionChangedCallback() { @Override public void onSuppressionChanged(boolean isSuppressed) { synchronized (mLock) { onDreamSuppressionChangedLocked(isSuppressed); } } }; /** * Callback for asynchronous operations performed by the power manager. */ Loading services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +91 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,12 @@ public class PowerManagerServiceTest { .thenReturn(minimumScreenOffTimeoutConfigMillis); } private void setDreamsDisabledByAmbientModeSuppressionConfig(boolean disable) { when(mResourcesSpy.getBoolean( com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig)) .thenReturn(disable); } private void advanceTime(long timeMs) { mClock.fastForward(timeMs); mTestLooper.dispatchAll(); Loading Loading @@ -790,6 +796,91 @@ public class PowerManagerServiceTest { assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @SuppressWarnings("GuardedBy") @Test public void testAmbientSuppression_disablesDreamingAndWakesDevice() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(true); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); advanceTime(50); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @SuppressWarnings("GuardedBy") @Test public void testAmbientSuppressionDisabled_shouldNotWakeDevice() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(false); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); advanceTime(50); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @Test public void testAmbientSuppression_doesNotAffectDreamForcing() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(true); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); // Verify that forcing dream still works even though ambient display is suppressed forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @Test public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() { final String suspendBlockerName = "PowerManagerService.Display"; Loading Loading
core/res/res/values/config.xml +2 −0 Original line number Diff line number Diff line Loading @@ -2479,6 +2479,8 @@ <integer name="config_attentionMaximumExtension">900000</integer> <!-- 15 minutes. --> <!-- Is the system user the only user allowed to dream. --> <bool name="config_dreamsOnlyEnabledForSystemUser">false</bool> <!-- Whether dreams are disabled when ambient mode is suppressed. --> <bool name="config_dreamsDisabledByAmbientModeSuppressionConfig">false</bool> <!-- Whether to dismiss the active dream when an activity is started. Doesn't apply to assistant activities (ACTIVITY_TYPE_ASSISTANT) --> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -2235,6 +2235,7 @@ <java-symbol type="integer" name="config_dreamsBatteryLevelMinimumWhenNotPowered" /> <java-symbol type="integer" name="config_dreamsBatteryLevelDrainCutoff" /> <java-symbol type="string" name="config_dreamsDefaultComponent" /> <java-symbol type="bool" name="config_dreamsDisabledByAmbientModeSuppressionConfig" /> <java-symbol type="bool" name="config_dreamsOnlyEnabledForSystemUser" /> <java-symbol type="array" name="config_supportedDreamComplications" /> <java-symbol type="array" name="config_disabledDreamComponents" /> Loading
services/core/java/com/android/server/power/AmbientDisplaySuppressionController.java +21 −4 Original line number Diff line number Diff line Loading @@ -40,13 +40,24 @@ import java.util.Set; public class AmbientDisplaySuppressionController { private static final String TAG = "AmbientDisplaySuppressionController"; private final Context mContext; private final Set<Pair<String, Integer>> mSuppressionTokens; private final AmbientDisplaySuppressionChangedCallback mCallback; private IStatusBarService mStatusBarService; AmbientDisplaySuppressionController(Context context) { mContext = requireNonNull(context); /** Interface to get a list of available logical devices. */ interface AmbientDisplaySuppressionChangedCallback { /** * Called when the suppression state changes. * * @param isSuppressed Whether ambient is suppressed. */ void onSuppressionChanged(boolean isSuppressed); } AmbientDisplaySuppressionController( @NonNull AmbientDisplaySuppressionChangedCallback callback) { mSuppressionTokens = Collections.synchronizedSet(new ArraySet<>()); mCallback = requireNonNull(callback); } /** Loading @@ -58,6 +69,7 @@ public class AmbientDisplaySuppressionController { */ public void suppress(@NonNull String token, int callingUid, boolean suppress) { Pair<String, Integer> suppressionToken = Pair.create(requireNonNull(token), callingUid); final boolean wasSuppressed = isSuppressed(); if (suppress) { mSuppressionTokens.add(suppressionToken); Loading @@ -65,9 +77,14 @@ public class AmbientDisplaySuppressionController { mSuppressionTokens.remove(suppressionToken); } final boolean isSuppressed = isSuppressed(); if (isSuppressed != wasSuppressed) { mCallback.onSuppressionChanged(isSuppressed); } try { synchronized (mSuppressionTokens) { getStatusBar().suppressAmbientDisplay(isSuppressed()); getStatusBar().suppressAmbientDisplay(isSuppressed); } } catch (RemoteException e) { Slog.e(TAG, "Failed to suppress ambient display", e); Loading
services/core/java/com/android/server/power/PowerManagerService.java +41 −4 Original line number Diff line number Diff line Loading @@ -127,6 +127,7 @@ import com.android.server.am.BatteryStatsService; import com.android.server.lights.LightsManager; import com.android.server.lights.LogicalLight; import com.android.server.policy.WindowManagerPolicy; import com.android.server.power.AmbientDisplaySuppressionController.AmbientDisplaySuppressionChangedCallback; import com.android.server.power.batterysaver.BatterySaverController; import com.android.server.power.batterysaver.BatterySaverPolicy; import com.android.server.power.batterysaver.BatterySaverStateMachine; Loading Loading @@ -507,6 +508,9 @@ public final class PowerManagerService extends SystemService // effectively and terminate the dream. Use -1 to disable this safety feature. private int mDreamsBatteryLevelDrainCutoffConfig; // Whether dreams should be disabled when ambient mode is suppressed. private boolean mDreamsDisabledByAmbientModeSuppressionConfig; // True if dreams are enabled by the user. private boolean mDreamsEnabledSetting; Loading Loading @@ -964,8 +968,8 @@ public final class PowerManagerService extends SystemService } AmbientDisplaySuppressionController createAmbientDisplaySuppressionController( Context context) { return new AmbientDisplaySuppressionController(context); @NonNull AmbientDisplaySuppressionChangedCallback callback) { return new AmbientDisplaySuppressionController(callback); } InattentiveSleepWarningController createInattentiveSleepWarningController() { Loading Loading @@ -1044,7 +1048,8 @@ public final class PowerManagerService extends SystemService mConstants = new Constants(mHandler); mAmbientDisplayConfiguration = mInjector.createAmbientDisplayConfiguration(context); mAmbientDisplaySuppressionController = mInjector.createAmbientDisplaySuppressionController(context); mInjector.createAmbientDisplaySuppressionController( mAmbientSuppressionChangedCallback); mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock); mFaceDownDetector = new FaceDownDetector(this::onFlip); mScreenUndimDetector = new ScreenUndimDetector(); Loading Loading @@ -1403,6 +1408,8 @@ public final class PowerManagerService extends SystemService com.android.internal.R.integer.config_dreamsBatteryLevelMinimumWhenNotPowered); mDreamsBatteryLevelDrainCutoffConfig = resources.getInteger( com.android.internal.R.integer.config_dreamsBatteryLevelDrainCutoff); mDreamsDisabledByAmbientModeSuppressionConfig = resources.getBoolean( com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig); mDozeAfterScreenOff = resources.getBoolean( com.android.internal.R.bool.config_dozeAfterScreenOffByDefault); mMinimumScreenOffTimeoutConfig = resources.getInteger( Loading Loading @@ -3340,12 +3347,32 @@ public final class PowerManagerService extends SystemService } } @GuardedBy("mLock") private void onDreamSuppressionChangedLocked(final boolean isSuppressed) { if (!mDreamsDisabledByAmbientModeSuppressionConfig) { return; } if (!isSuppressed && mIsPowered && mDreamsSupportedConfig && mDreamsEnabledSetting && shouldNapAtBedTimeLocked() && isItBedTimeYetLocked( mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP))) { napInternal(SystemClock.uptimeMillis(), Process.SYSTEM_UID, /* allowWake= */ true); } else if (isSuppressed) { mDirty |= DIRTY_SETTINGS; updatePowerStateLocked(); } } /** * Returns true if the {@code groupId} is allowed to dream in its current state. */ @GuardedBy("mLock") private boolean canDreamLocked(final PowerGroup powerGroup) { final boolean dreamsSuppressed = mDreamsDisabledByAmbientModeSuppressionConfig && mAmbientDisplaySuppressionController.isSuppressed(); if (!mBootCompleted || dreamsSuppressed || getGlobalWakefulnessLocked() != WAKEFULNESS_DREAMING || !mDreamsSupportedConfig || !mDreamsEnabledSetting Loading Loading @@ -5037,6 +5064,16 @@ public final class PowerManagerService extends SystemService } }; private final AmbientDisplaySuppressionChangedCallback mAmbientSuppressionChangedCallback = new AmbientDisplaySuppressionChangedCallback() { @Override public void onSuppressionChanged(boolean isSuppressed) { synchronized (mLock) { onDreamSuppressionChangedLocked(isSuppressed); } } }; /** * Callback for asynchronous operations performed by the power manager. */ Loading
services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +91 −0 Original line number Diff line number Diff line Loading @@ -393,6 +393,12 @@ public class PowerManagerServiceTest { .thenReturn(minimumScreenOffTimeoutConfigMillis); } private void setDreamsDisabledByAmbientModeSuppressionConfig(boolean disable) { when(mResourcesSpy.getBoolean( com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig)) .thenReturn(disable); } private void advanceTime(long timeMs) { mClock.fastForward(timeMs); mTestLooper.dispatchAll(); Loading Loading @@ -790,6 +796,91 @@ public class PowerManagerServiceTest { assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @SuppressWarnings("GuardedBy") @Test public void testAmbientSuppression_disablesDreamingAndWakesDevice() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(true); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); advanceTime(50); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); } @SuppressWarnings("GuardedBy") @Test public void testAmbientSuppressionDisabled_shouldNotWakeDevice() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(false); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); advanceTime(50); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @Test public void testAmbientSuppression_doesNotAffectDreamForcing() { Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1); Settings.Secure.putInt(mContextSpy.getContentResolver(), Settings.Secure.SCREENSAVER_ENABLED, 1); setDreamsDisabledByAmbientModeSuppressionConfig(true); setMinimumScreenOffTimeoutConfig(10000); createService(); startSystem(); doAnswer(inv -> { when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); return null; }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); mService.getBinderServiceInstance().suppressAmbientDisplay("test", true); setPluggedIn(true); // Allow asynchronous sandman calls to execute. advanceTime(10000); // Verify that forcing dream still works even though ambient display is suppressed forceDream(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING); } @Test public void testSetDozeOverrideFromDreamManager_triggersSuspendBlocker() { final String suspendBlockerName = "PowerManagerService.Display"; Loading