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
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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<DisplayManagerInternal.DisplayGroupListener> listener =
|
||||
new AtomicReference<>();
|
||||
doAnswer((Answer<Void>) 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();
|
||||
|
||||
Reference in New Issue
Block a user