From f5358585a26b2089875282f7ef9cf2d22e2ae59f Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Tue, 20 Sep 2022 23:29:16 -0700 Subject: [PATCH] Workaround for doze/AOD problem with global wakefulness When the global wakefulness is dozing and a non-default group VirtualDisplay wakes up, the global wakefulness becomes awake and the default display's individual wakefulness remains dozing. But some of our code in Notifier and PhoneWindowManager that listen to the global wakefulness kick off a chain of events that results in KeyguardViewMediator thinking dozing has stopped, and the display gets stuck in what feels like a sort of half on / half off state where it shows keyguard at the low brightness and refresh rate we're supposed to use for AOD, but it isn't responsive to touch inputs. The workaround in this CL is to restart dreaming in this case to get the AOD unstuck. Bug: 187231320 Test: atest PowerManagerServiceTest Change-Id: I8e348ffe52c7f2d5cbdd11b058254cb087b1021d --- .../server/power/PowerManagerService.java | 9 ++++ .../server/power/PowerManagerServiceTest.java | 44 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 725fb3fec6163..fa11aa7fe3c09 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -2185,6 +2185,15 @@ public final class PowerManagerService extends SystemService if (sQuiescent) { mDirty |= DIRTY_QUIESCENT; } + PowerGroup defaultGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP); + if (defaultGroup.getWakefulnessLocked() == WAKEFULNESS_DOZING) { + // Workaround for b/187231320 where the AOD can get stuck in a "half on / + // half off" state when a non-default-group VirtualDisplay causes the global + // wakefulness to change to awake, even though the default display is + // dozing. We set sandman summoned to restart dreaming to get it unstuck. + // TODO(b/255688811) - fix this so that AOD never gets interrupted at all. + defaultGroup.setSandmanSummonedLocked(true); + } break; case WAKEFULNESS_ASLEEP: 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 f5ed41a7fa8b5..3d8edf3b553ed 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -1819,6 +1819,50 @@ public class PowerManagerServiceTest { verify(mDreamManagerInternalMock).startDream(eq(true), anyString()); } + @Test + public void testMultiDisplay_defaultDozing_addNewDisplayDefaultGoesBackToDoze() { + final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; + final AtomicReference listener = + new AtomicReference<>(); + doAnswer((Answer) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + final DisplayInfo info = new DisplayInfo(); + info.displayGroupId = nonDefaultDisplayGroupId; + when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); + + doAnswer(inv -> { + when(mDreamManagerInternalMock.isDreaming()).thenReturn(true); + return null; + }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString()); + + createService(); + startSystem(); + + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_AWAKE); + + forceDozing(); + advanceTime(500); + + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_DOZING); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + verify(mDreamManagerInternalMock).startDream(eq(true), anyString()); + + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + advanceTime(500); + + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_DOZING); + verify(mDreamManagerInternalMock, times(2)).startDream(eq(true), anyString()); + } + @Test public void testLastSleepTime_notUpdatedWhenDreaming() { createService();