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

Commit 24afd430 authored by Kenneth Ford's avatar Kenneth Ford
Browse files

Checks if there is a device state override active

to determine if the device should be put to sleep or not

This allows the device to stay awake regardless of the state
it is transitioning to, provided it is an overridden state.
An override request is triggered by user action or a cts test,
so it provides a better user experience to stay awake during
this transition.

Bug: 216580217
Test: Manual & LogicalDisplayMapperTest
Merged-In: I36959310d8e6c9b5e4e1e4093d17cad7d4f6238e
Change-Id: I36959310d8e6c9b5e4e1e4093d17cad7d4f6238e
(cherry picked from commit 7709d355)
parent cc946d4e
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -3952,11 +3952,21 @@ public final class DisplayManagerService extends SystemService {
     * Listens to changes in device state and reports the state to LogicalDisplayMapper.
     */
    class DeviceStateListener implements DeviceStateManager.DeviceStateCallback {
        // Base state corresponds to the physical state of the device
        private int mBaseState = DeviceStateManager.INVALID_DEVICE_STATE;

        @Override
        public void onStateChanged(int deviceState) {
            boolean isDeviceStateOverrideActive = deviceState != mBaseState;
            synchronized (mSyncRoot) {
                mLogicalDisplayMapper.setDeviceStateLocked(deviceState);
                mLogicalDisplayMapper
                        .setDeviceStateLocked(deviceState, isDeviceStateOverrideActive);
            }
        }

        @Override
        public void onBaseStateChanged(int state) {
            mBaseState = state;
        }
    };

+52 −7
Original line number Diff line number Diff line
@@ -359,7 +359,7 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
        mDeviceStateToLayoutMap.dumpLocked(ipw);
    }

    void setDeviceStateLocked(int state) {
    void setDeviceStateLocked(int state, boolean isOverrideActive) {
        Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
                + ", interactive=" + mInteractive);
        // As part of a state transition, we may need to turn off some displays temporarily so that
@@ -370,12 +370,10 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
            resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
        }
        mPendingDeviceState = state;
        final boolean wakeDevice = mDeviceStatesOnWhichToWakeUp.get(mPendingDeviceState)
                && !mDeviceStatesOnWhichToWakeUp.get(mDeviceState)
                && !mInteractive && mBootCompleted;
        final boolean sleepDevice = mDeviceStatesOnWhichToSleep.get(mPendingDeviceState)
                && !mDeviceStatesOnWhichToSleep.get(mDeviceState)
                && mInteractive && mBootCompleted;
        final boolean wakeDevice = shouldDeviceBeWoken(mPendingDeviceState, mDeviceState,
                mInteractive, mBootCompleted);
        final boolean sleepDevice = shouldDeviceBePutToSleep(mPendingDeviceState, mDeviceState,
                isOverrideActive, mInteractive, mBootCompleted);

        // If all displays are off already, we can just transition here, unless we are trying to
        // wake or sleep the device as part of this transition. In that case defer the final
@@ -429,6 +427,53 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
        }
    }

    /**
     * Returns if the device should be woken up or not. Called to check if the device state we are
     * moving to is one that should awake the device, as well as if we are moving from a device
     * state that shouldn't have been already woken from.
     *
     * @param pendingState device state we are moving to
     * @param currentState device state we are currently in
     * @param isInteractive if the device is in an interactive state
     * @param isBootCompleted is the device fully booted
     *
     * @see #shouldDeviceBePutToSleep
     * @see #setDeviceStateLocked
     */
    @VisibleForTesting
    boolean shouldDeviceBeWoken(int pendingState, int currentState, boolean isInteractive,
            boolean isBootCompleted) {
        return mDeviceStatesOnWhichToWakeUp.get(pendingState)
                && !mDeviceStatesOnWhichToWakeUp.get(currentState)
                && !isInteractive && isBootCompleted;
    }

    /**
     * Returns if the device should be put to sleep or not.
     *
     * Includes a check to verify that the device state that we are moving to, {@code pendingState},
     * is the same as the physical state of the device, {@code baseState}. Different values for
     * these parameters indicate a device state override is active, and we shouldn't put the device
     * to sleep to provide a better user experience.
     *
     * @param pendingState device state we are moving to
     * @param currentState device state we are currently in
     * @param isOverrideActive if a device state override is currently active or not
     * @param isInteractive if the device is in an interactive state
     * @param isBootCompleted is the device fully booted
     *
     * @see #shouldDeviceBeWoken
     * @see #setDeviceStateLocked
     */
    @VisibleForTesting
    boolean shouldDeviceBePutToSleep(int pendingState, int currentState, boolean isOverrideActive,
            boolean isInteractive, boolean isBootCompleted) {
        return mDeviceStatesOnWhichToSleep.get(pendingState)
                && !mDeviceStatesOnWhichToSleep.get(currentState)
                && !isOverrideActive
                && isInteractive && isBootCompleted;
    }

    private boolean areAllTransitioningDisplaysOffLocked() {
        final int count = mLogicalDisplays.size();
        for (int i = 0; i < count; i++) {
+54 −0
Original line number Diff line number Diff line
@@ -28,7 +28,9 @@ import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EV
import static com.google.common.truth.Truth.assertThat;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.verify;
@@ -70,6 +72,8 @@ import java.util.Set;
@RunWith(AndroidJUnit4.class)
public class LogicalDisplayMapperTest {
    private static int sUniqueTestDisplayId = 0;
    private static final int DEVICE_STATE_CLOSED = 0;
    private static final int DEVICE_STATE_OPEN = 2;

    private DisplayDeviceRepository mDisplayDeviceRepo;
    private LogicalDisplayMapper mLogicalDisplayMapper;
@@ -113,6 +117,7 @@ public class LogicalDisplayMapperTest {

        mPowerManager = new PowerManager(mContextMock, mIPowerManagerMock, mIThermalServiceMock,
                null);

        when(mContextMock.getSystemServiceName(PowerManager.class))
                .thenReturn(Context.POWER_SERVICE);
        when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
@@ -120,6 +125,12 @@ public class LogicalDisplayMapperTest {
        when(mResourcesMock.getBoolean(
                com.android.internal.R.bool.config_supportsConcurrentInternalDisplays))
                .thenReturn(true);
        when(mResourcesMock.getIntArray(
                com.android.internal.R.array.config_deviceStatesOnWhichToWakeUp))
                .thenReturn(new int[]{1, 2});
        when(mResourcesMock.getIntArray(
                com.android.internal.R.array.config_deviceStatesOnWhichToSleep))
                .thenReturn(new int[]{0});

        mLooper = new TestLooper();
        mHandler = new Handler(mLooper.getLooper());
@@ -312,6 +323,49 @@ public class LogicalDisplayMapperTest {
                mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
    }

    @Test
    public void testDeviceShouldBeWoken() {
        assertTrue(mLogicalDisplayMapper.shouldDeviceBeWoken(DEVICE_STATE_OPEN,
                DEVICE_STATE_CLOSED,
                /* isInteractive= */false,
                /* isBootCompleted= */true));
    }

    @Test
    public void testDeviceShouldNotBeWoken() {
        assertFalse(mLogicalDisplayMapper.shouldDeviceBeWoken(DEVICE_STATE_CLOSED,
                DEVICE_STATE_OPEN,
                /* isInteractive= */false,
                /* isBootCompleted= */true));
    }

    @Test
    public void testDeviceShouldBePutToSleep() {
        assertTrue(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
                DEVICE_STATE_OPEN,
                /* isOverrideActive= */false,
                /* isInteractive= */true,
                /* isBootCompleted= */true));
    }

    @Test
    public void testDeviceShouldNotBePutToSleep() {
        assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_OPEN,
                DEVICE_STATE_CLOSED,
                /* isOverrideActive= */false,
                /* isInteractive= */true,
                /* isBootCompleted= */true));
    }

    @Test
    public void testDeviceShouldNotBePutToSleepDifferentBaseState() {
        assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
                DEVICE_STATE_OPEN,
                /* isOverrideActive= */true,
                /* isInteractive= */true,
                /* isBootCompleted= */true));
    }

    /////////////////
    // Helper Methods
    /////////////////