summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Will Leshner <wleshner@google.com> 2022-10-20 14:18:57 -0700
committer Will Leshner <wleshner@google.com> 2022-11-17 15:08:04 -0800
commit6eb4c1a28c84750b9745503d4aa5c37814462192 (patch)
treedb04906ba5a3da1f78f155417535d3de492d454f
parentfb435f4376077013f555adff8117e90060e610de (diff)
Stop dreaming when undocking while showing low-light clock.
Bug: 254633538 Test: atest PowerManagerServiceTest Merged-In: I8a9999f9648b9591bf8672d138463d0d401fcf75 Change-Id: I5f06162868496e220201c2f3ee651cc07477ef78
-rw-r--r--core/java/android/service/dreams/DreamManagerInternal.java35
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java37
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java29
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java66
4 files changed, 153 insertions, 14 deletions
diff --git a/core/java/android/service/dreams/DreamManagerInternal.java b/core/java/android/service/dreams/DreamManagerInternal.java
index cd38e8a01d62..7c2f9520bb00 100644
--- a/core/java/android/service/dreams/DreamManagerInternal.java
+++ b/core/java/android/service/dreams/DreamManagerInternal.java
@@ -58,4 +58,39 @@ public abstract class DreamManagerInternal {
* @param isScreenOn True if the screen is currently on.
*/
public abstract boolean canStartDreaming(boolean isScreenOn);
+
+ /**
+ * Return whether dreams can continue when undocking by default. Even if the default is true,
+ * it can be overridden temporarily, in which case {@link DreamManagerStateListener} will be
+ * informed of any changes.
+ */
+ public abstract boolean keepDreamingWhenUndockedDefault();
+
+ /**
+ * Register a {@link DreamManagerStateListener}, which will be called when there are changes to
+ * dream state.
+ *
+ * @param listener The listener to register.
+ */
+ public abstract void registerDreamManagerStateListener(DreamManagerStateListener listener);
+
+ /**
+ * Unregister a {@link DreamManagerStateListener}, which will be called when there are changes
+ * to dream state.
+ *
+ * @param listener The listener to unregister.
+ */
+ public abstract void unregisterDreamManagerStateListener(DreamManagerStateListener listener);
+
+ /**
+ * Called when there are changes to dream state.
+ */
+ public interface DreamManagerStateListener {
+ /**
+ * Called when keep dreaming when undocked has changed.
+ *
+ * @param keepDreaming True if the current dream should continue when undocking.
+ */
+ void onKeepDreamingWhenUndockedChanged(boolean keepDreaming);
+ }
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 8f6df0f52527..3a49d8627c23 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -81,6 +81,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* Service api for managing dreams.
@@ -120,6 +121,10 @@ public final class DreamManagerService extends SystemService {
private final boolean mDreamsEnabledByDefaultConfig;
private final boolean mDreamsActivatedOnChargeByDefault;
private final boolean mDreamsActivatedOnDockByDefault;
+ private final boolean mKeepDreamingWhenUndockedDefault;
+
+ private final CopyOnWriteArrayList<DreamManagerInternal.DreamManagerStateListener>
+ mDreamManagerStateListeners = new CopyOnWriteArrayList<>();
@GuardedBy("mLock")
private DreamRecord mCurrentDream;
@@ -226,6 +231,8 @@ public final class DreamManagerService extends SystemService {
mDreamsActivatedOnDockByDefault = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_dreamsActivatedOnDockByDefault);
mSettingsObserver = new SettingsObserver(mHandler);
+ mKeepDreamingWhenUndockedDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_keepDreamingWhenUndocking);
}
@Override
@@ -300,6 +307,7 @@ public final class DreamManagerService extends SystemService {
pw.println("mIsDocked=" + mIsDocked);
pw.println("mIsCharging=" + mIsCharging);
pw.println("mWhenToDream=" + mWhenToDream);
+ pw.println("mKeepDreamingWhenUndockedDefault=" + mKeepDreamingWhenUndockedDefault);
pw.println("getDozeComponent()=" + getDozeComponent());
pw.println();
@@ -328,7 +336,16 @@ public final class DreamManagerService extends SystemService {
}
}
- /** Whether a real dream is occurring. */
+ private void reportKeepDreamingWhenUndockedChanged(boolean keepDreaming) {
+ mHandler.post(() -> {
+ for (DreamManagerInternal.DreamManagerStateListener listener
+ : mDreamManagerStateListeners) {
+ listener.onKeepDreamingWhenUndockedChanged(keepDreaming);
+ }
+ });
+ }
+
+ /** Whether a real dream is occurring. */
private boolean isDreamingInternal() {
synchronized (mLock) {
return mCurrentDream != null && !mCurrentDream.isPreview
@@ -571,6 +588,8 @@ public final class DreamManagerService extends SystemService {
}
mSystemDreamComponent = componentName;
+ reportKeepDreamingWhenUndockedChanged(
+ mKeepDreamingWhenUndockedDefault && mSystemDreamComponent == null);
// Switch dream if currently dreaming and not dozing.
if (isDreamingInternal() && !isDozingInternal()) {
@@ -1012,6 +1031,22 @@ public final class DreamManagerService extends SystemService {
public void requestDream() {
requestDreamInternal();
}
+
+ @Override
+ public boolean keepDreamingWhenUndockedDefault() {
+ // This value does not change, so a lock should not be needed.
+ return mKeepDreamingWhenUndockedDefault;
+ }
+
+ @Override
+ public void registerDreamManagerStateListener(DreamManagerStateListener listener) {
+ mDreamManagerStateListeners.add(listener);
+ }
+
+ @Override
+ public void unregisterDreamManagerStateListener(DreamManagerStateListener listener) {
+ mDreamManagerStateListeners.remove(listener);
+ }
}
private static final class DreamRecord {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 377a651eb031..ab90ef929d28 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -468,9 +468,6 @@ public final class PowerManagerService extends SystemService
// True if the device should wake up when plugged or unplugged.
private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
- // True if the device should keep dreaming when undocked.
- private boolean mKeepDreamingWhenUndockingConfig;
-
// True if the device should wake up when plugged or unplugged in theater mode.
private boolean mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig;
@@ -677,6 +674,19 @@ public final class PowerManagerService extends SystemService
// but the DreamService has not yet been told to start (it's an async process).
private boolean mDozeStartInProgress;
+ // Whether to keep dreaming when the device is undocked.
+ private boolean mKeepDreamingWhenUndocked;
+
+ private final class DreamManagerStateListener implements
+ DreamManagerInternal.DreamManagerStateListener {
+ @Override
+ public void onKeepDreamingWhenUndockedChanged(boolean keepDreaming) {
+ synchronized (mLock) {
+ mKeepDreamingWhenUndocked = keepDreaming;
+ }
+ }
+ }
+
private final class PowerGroupWakefulnessChangeListener implements
PowerGroup.PowerGroupListener {
@GuardedBy("mLock")
@@ -1265,6 +1275,12 @@ public final class PowerManagerService extends SystemService
new DisplayGroupPowerChangeListener();
mDisplayManagerInternal.registerDisplayGroupListener(displayGroupPowerChangeListener);
+ // These DreamManager methods do not acquire locks, so they should be safe to call.
+ mKeepDreamingWhenUndocked = mDreamManager.keepDreamingWhenUndockedDefault();
+ if (mKeepDreamingWhenUndocked) {
+ mDreamManager.registerDreamManagerStateListener(new DreamManagerStateListener());
+ }
+
mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
mInjector.createSuspendBlocker(
this, "PowerManagerService.WirelessChargerDetector"),
@@ -1382,8 +1398,6 @@ public final class PowerManagerService extends SystemService
com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
com.android.internal.R.bool.config_unplugTurnsOnScreen);
- mKeepDreamingWhenUndockingConfig = resources.getBoolean(
- com.android.internal.R.bool.config_keepDreamingWhenUndocking);
mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig = resources.getBoolean(
com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug);
mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
@@ -2508,7 +2522,7 @@ public final class PowerManagerService extends SystemService
}
// Don't wake when undocking while dreaming if configured not to.
- if (mKeepDreamingWhenUndockingConfig
+ if (mKeepDreamingWhenUndocked
&& getGlobalWakefulnessLocked() == WAKEFULNESS_DREAMING
&& wasPowered && !mIsPowered
&& oldPlugType == BatteryManager.BATTERY_PLUGGED_DOCK) {
@@ -4457,8 +4471,7 @@ public final class PowerManagerService extends SystemService
+ mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
pw.println(" mTheaterModeEnabled="
+ mTheaterModeEnabled);
- pw.println(" mKeepDreamingWhenUndockingConfig="
- + mKeepDreamingWhenUndockingConfig);
+ pw.println(" mKeepDreamingWhenUndocked=" + mKeepDreamingWhenUndocked);
pw.println(" mSuspendWhenScreenOffDueToProximityConfig="
+ mSuspendWhenScreenOffDueToProximityConfig);
pw.println(" mDreamsSupportedConfig=" + mDreamsSupportedConfig);
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 f5ed41a7fa8b..32772a41f71b 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -619,17 +619,42 @@ public class PowerManagerServiceTest {
}
/**
- * Tests that dreaming continues when undocking and configured to do so.
+ * Tests that dreaming stops when undocking and not configured to keep dreaming.
*/
@Test
- public void testWakefulnessDream_shouldKeepDreamingWhenUndocked() {
+ public void testWakefulnessDream_shouldStopDreamingWhenUndocked_whenNotConfigured() {
+ // Make sure "unplug turns on screen" is configured to true.
+ when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen))
+ .thenReturn(true);
+ when(mDreamManagerInternalMock.keepDreamingWhenUndockedDefault()).thenReturn(false);
+
createService();
startSystem();
- when(mResourcesSpy.getBoolean(
- com.android.internal.R.bool.config_keepDreamingWhenUndocking))
+ when(mBatteryManagerInternalMock.getPlugType())
+ .thenReturn(BatteryManager.BATTERY_PLUGGED_DOCK);
+ setPluggedIn(true);
+
+ forceAwake(); // Needs to be awake first before it can dream.
+ forceDream();
+ when(mBatteryManagerInternalMock.getPlugType()).thenReturn(0);
+ setPluggedIn(false);
+
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ }
+
+ /**
+ * Tests that dreaming continues when undocking and configured to do so.
+ */
+ @Test
+ public void testWakefulnessDream_shouldKeepDreamingWhenUndocked_whenConfigured() {
+ // Make sure "unplug turns on screen" is configured to true.
+ when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen))
.thenReturn(true);
- mService.readConfigurationLocked();
+ when(mDreamManagerInternalMock.keepDreamingWhenUndockedDefault()).thenReturn(true);
+
+ createService();
+ startSystem();
when(mBatteryManagerInternalMock.getPlugType())
.thenReturn(BatteryManager.BATTERY_PLUGGED_DOCK);
@@ -643,6 +668,37 @@ public class PowerManagerServiceTest {
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
}
+ /**
+ * Tests that dreaming stops when undocking while showing a dream that prevents it.
+ */
+ @Test
+ public void testWakefulnessDream_shouldStopDreamingWhenUndocked_whenDreamPrevents() {
+ // Make sure "unplug turns on screen" is configured to true.
+ when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen))
+ .thenReturn(true);
+ when(mDreamManagerInternalMock.keepDreamingWhenUndockedDefault()).thenReturn(true);
+
+ createService();
+ startSystem();
+
+ ArgumentCaptor<DreamManagerInternal.DreamManagerStateListener> dreamManagerStateListener =
+ ArgumentCaptor.forClass(DreamManagerInternal.DreamManagerStateListener.class);
+ verify(mDreamManagerInternalMock).registerDreamManagerStateListener(
+ dreamManagerStateListener.capture());
+
+ when(mBatteryManagerInternalMock.getPlugType())
+ .thenReturn(BatteryManager.BATTERY_PLUGGED_DOCK);
+ setPluggedIn(true);
+
+ forceAwake(); // Needs to be awake first before it can dream.
+ forceDream();
+ dreamManagerStateListener.getValue().onKeepDreamingWhenUndockedChanged(false);
+ when(mBatteryManagerInternalMock.getPlugType()).thenReturn(0);
+ setPluggedIn(false);
+
+ assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
+ }
+
@Test
public void testWakefulnessDoze_goToSleep() {
createService();