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

Commit f4d19d20 authored by Darrell Shi's avatar Darrell Shi
Browse files

Prioritize checks in canDreamLocked when device is kept awake

Previously, the canDreamLocked function would immediately return true if
the device was kept awake, bypassing other crucial checks like whether
the device is powered. This could lead to unintended behaviors, such as
starting a dream even when the device was not powered but the proximity
sensor returned a positive value.

This change modifies canDreamLocked to ensure that all relevant
condition checks are evaluated *before* allowing a dream to start.

Test: atest PowerManagerServiceTest
Test: manually tested dream starting while powered and not powered
Bug: 404968947
Flag: EXEMPT bugfix
Change-Id: I5c3f529db95e9a2f006e600ddea24f20a182a3fc
parent e835c3b4
Loading
Loading
Loading
Loading
+28 −14
Original line number Diff line number Diff line
@@ -3536,6 +3536,7 @@ public final class PowerManagerService extends SystemService
     */
    private void handleSandman(int groupId) { // runs on handler thread
        // Handle preconditions.
        final boolean canDream;
        final boolean startDreaming;
        final int wakefulness;
        synchronized (mLock) {
@@ -3546,8 +3547,9 @@ public final class PowerManagerService extends SystemService
            }
            final PowerGroup powerGroup = mPowerGroups.get(groupId);
            wakefulness = powerGroup.getWakefulnessLocked();
            canDream = canDreamLocked(powerGroup);
            if (powerGroup.isSandmanSummonedLocked() && powerGroup.isReadyLocked()) {
                startDreaming = canDreamLocked(powerGroup) || canDozeLocked(powerGroup);
                startDreaming = canDream || canDozeLocked(powerGroup);
                powerGroup.setSandmanSummonedLocked(/* isSandmanSummoned= */ false);
            } else {
                startDreaming = false;
@@ -3603,7 +3605,7 @@ public final class PowerManagerService extends SystemService
            // Determine whether the dream should continue.
            long now = mClock.uptimeMillis();
            if (wakefulness == WAKEFULNESS_DREAMING) {
                if (isDreaming && canDreamLocked(powerGroup)) {
                if (isDreaming && canDream) {
                    if (mDreamsBatteryLevelDrainCutoffConfig >= 0
                            && mDreamsBatteryLevelDrain > mDreamsBatteryLevelDrainCutoffConfig
                            && !isBeingKeptAwakeLocked(powerGroup)) {
@@ -3668,7 +3670,6 @@ public final class PowerManagerService extends SystemService
        }
    }


    /**
     * Returns true if the {@code groupId} is allowed to dream in its current state.
     */
@@ -3687,21 +3688,34 @@ public final class PowerManagerService extends SystemService
                | USER_ACTIVITY_SCREEN_DIM | USER_ACTIVITY_SCREEN_DREAM)) == 0) {
            return false;
        }
        if (!isBeingKeptAwakeLocked(powerGroup)) {

        if (!mIsPowered && !mDreamsEnabledOnBatteryConfig) {
            if (DEBUG) {
                Slog.d(TAG, "Cannot dream because device is not powered");
            }
            return false;
        }

        if (!mIsPowered
                && mDreamsBatteryLevelMinimumWhenNotPoweredConfig >= 0
                && mBatteryLevel < mDreamsBatteryLevelMinimumWhenNotPoweredConfig) {
            if (DEBUG) {
                Slog.d(TAG, "Cannot dream because device battery level is lower than required");
            }
            return false;
        }

        if (isBeingKeptAwakeLocked(powerGroup)) {
            if (DEBUG) {
                Slog.d(TAG, "Dream allowed because power group is being kept awake");
            }
            return true;
        }

        return !mIsPowered
                || mDreamsBatteryLevelMinimumWhenPoweredConfig < 0
                || mBatteryLevel >= mDreamsBatteryLevelMinimumWhenPoweredConfig;
    }
        return true;
    }

    /**
     * Returns true if the device is allowed to doze in its current state.
+31 −0
Original line number Diff line number Diff line
@@ -1329,6 +1329,36 @@ public class PowerManagerServiceTest {
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
    }

    @Test
    public void testDreamPreventedWhenNotPowered_proximityPositive_afterTimeout_staysAwake() {
        AtomicReference<DisplayManagerInternal.DisplayPowerCallbacks> callback =
                new AtomicReference<>();
        doAnswer((Answer<Void>) invocation -> {
            callback.set(invocation.getArgument(0));
            return null;
        }).when(mDisplayManagerInternalMock).initPowerManagement(any(), any(), any());
        when(mBatteryManagerInternalMock.isPowered(anyInt())).thenReturn(false);
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_ACTIVATE_ON_SLEEP, 1);
        Settings.Secure.putInt(mContextSpy.getContentResolver(),
                Settings.Secure.SCREENSAVER_RESTRICT_TO_WIRELESS_CHARGING, 1);

        doAnswer(inv -> {
            when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
            return null;
        }).when(mDreamManagerInternalMock).startDream(anyBoolean(), anyString());

        setMinimumScreenOffTimeoutConfig(5);
        createService();
        startSystem();
        callback.get().onProximityPositive();

        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);

        advanceTime(15000);
        assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
    }

    @EnableFlags(android.companion.virtualdevice.flags.Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER)
    @SuppressWarnings("GuardedBy")
    @Test
@@ -1693,6 +1723,7 @@ public class PowerManagerServiceTest {
        setAttentiveTimeout(100);
        createService();
        startSystem();
        setPluggedIn(true);
        advanceTime(50);
        verify(mInattentiveSleepWarningControllerMock, atLeastOnce()).show();
        when(mInattentiveSleepWarningControllerMock.isShown()).thenReturn(true);