Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d9ded03 authored by Antony Sargent's avatar Antony Sargent
Browse files

Lock default display when it sleeps independent of global wakefulness

When dealing with multiple PowerGroups, we calculate the global
wakefulness as the highest of any individual group. In the case where
a non-default PowerGroup (e.g. for a VirtualDisplay) is awake and the
default PowerGroup transitions from awake to asleep, we need to let
the PhoneWindowManager know so it can tell Keyguard to lock the
default display.

Fixes: 208229988
Test: atest PowerManagerServiceTest
Change-Id: Ib0fc4fdc30ca6f111e3c9d428a45bab5d403ad15
parent 8089e6f2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -4524,6 +4524,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        mCameraGestureTriggered = false;
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness,
            @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness) {
        if (wakefulness != globalWakefulness
                && wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE
                && groupId == Display.DEFAULT_DISPLAY_GROUP
                && mKeyguardDelegate != null) {
            mKeyguardDelegate.doKeyguardTimeout(null);
        }
    }

    // Called on the PowerManager's Notifier thread.
    @Override
    public void startedWakingUp(@PowerManager.WakeReason int pmWakeReason) {
+14 −0
Original line number Diff line number Diff line
@@ -772,6 +772,20 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
     */
    public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason);

    /**
     * Called when a particular PowerGroup has changed wakefulness.
     *
     * @param groupId The id of the PowerGroup.
     * @param wakefulness One of PowerManagerInternal.WAKEFULNESS_* indicating the wake state for
     * the group
     * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the reason this
     * group is going to sleep.
     * @param globalWakefulness The global wakefulness, which may or may not match that of this
     * group. One of PowerManagerInternal.WAKEFULNESS_*
     */
    void onPowerGroupWakefulnessChanged(int groupId, int wakefulness,
            @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness);

    /**
     * Called when the display is about to turn on to show content.
     * When waking up, this method will be called once after the call to wakingUp().
+9 −0
Original line number Diff line number Diff line
@@ -552,6 +552,15 @@ public class Notifier {
        }
    }

    /**
     * Called when an individual PowerGroup changes wakefulness.
     */
    public void onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason,
            int globalWakefulness) {
        mHandler.post(() -> mPolicy.onPowerGroupWakefulnessChanged(groupId, groupWakefulness,
                changeReason, globalWakefulness));
    }

    /**
     * Called when there has been user activity.
     */
+2 −0
Original line number Diff line number Diff line
@@ -674,6 +674,8 @@ public final class PowerManagerService extends SystemService
            }
            mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS;
            updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details);
            mNotifier.onPowerGroupWakefulnessChanged(groupId, wakefulness, reason,
                    getGlobalWakefulnessLocked());
            updatePowerStateLocked();
        }
    }
+93 −0
Original line number Diff line number Diff line
@@ -1696,6 +1696,99 @@ public class PowerManagerServiceTest {
        assertThat(mService.getLocalServiceInstance().getLastWakeup()).isEqualTo(initialWakeData);
    }

    @Test
    public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventFires() {
        createService();
        startSystem();
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        forceSleep();
        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                WAKEFULNESS_ASLEEP);

        verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
                eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP));
    }

    @Test
    public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventFiresCorrectly() {
        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);

        createService();
        startSystem();

        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);

        mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                null, null);
        mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0,
                null, null);

        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                WAKEFULNESS_ASLEEP);
        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
                WAKEFULNESS_ASLEEP);

        verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(nonDefaultDisplayGroupId),
                eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE));
        verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
                eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP));
    }

    @Test
    public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly() {
        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);

        createService();
        startSystem();

        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId);

        final String pkg = mContextSpy.getOpPackageName();
        final Binder token = new Binder();
        final String tag =
                "testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly";
        mService.getBinderServiceInstance().acquireWakeLock(token,
                PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
                null /* workSource */, null /* historyTag */, nonDefaultDisplay, null);

        forceSleep();

        // The wakelock should have kept the second display awake, and we should notify that the
        // default display went to sleep.
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
        assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
                WAKEFULNESS_ASLEEP);
        assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo(
                WAKEFULNESS_AWAKE);
        verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP),
                eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE));
        verify(mNotifierMock, never()).onPowerGroupWakefulnessChanged(
                eq(nonDefaultDisplayGroupId), anyInt(), anyInt(), anyInt());
    }

    @Test
    public void testGetFullPowerSavePolicy_returnsStateMachineResult() {
        createService();
Loading