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

Commit 956f4084 authored by Antony Sargent's avatar Antony Sargent
Browse files

Fix problem with AOD when secondary power groups are awake

Bug: 279845136
Test: atest UnlockedScreenOffAnimationControllerTest PowerManagerServiceTest
Change-Id: I129ef065f57c494333cbf8b82d3355344fdc8be1
parent abbe7c56
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ interface IPowerManager
    float getBrightnessConstraint(int constraint);
    @UnsupportedAppUsage
    boolean isInteractive();
    boolean isDisplayInteractive(int displayId);
    boolean areAutoPowerSaveModesEnabled();
    boolean isPowerSaveMode();
    PowerSaveState getPowerSaveState(int serviceType);
+20 −4
Original line number Diff line number Diff line
@@ -1150,13 +1150,17 @@ public final class PowerManager {
                }
            };

    private final PropertyInvalidatedCache<Void, Boolean> mInteractiveCache =
            new PropertyInvalidatedCache<Void, Boolean>(MAX_CACHE_ENTRIES,
    private final PropertyInvalidatedCache<Integer, Boolean> mInteractiveCache =
            new PropertyInvalidatedCache<Integer, Boolean>(MAX_CACHE_ENTRIES,
                CACHE_KEY_IS_INTERACTIVE_PROPERTY) {
                @Override
                public Boolean recompute(Void query) {
                public Boolean recompute(Integer displayId) {
                    try {
                        if (displayId == null) {
                            return mService.isInteractive();
                        } else {
                            return mService.isDisplayInteractive(displayId);
                        }
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
@@ -1802,6 +1806,18 @@ public final class PowerManager {
        return mInteractiveCache.query(null);
    }

    /**
     * Returns the interactive state for a specific display, which may not be the same as the
     * global wakefulness (which is true when any display is awake).
     *
     * @param displayId
     * @return whether the given display is present and interactive, or false
     *
     * @hide
     */
    public boolean isInteractive(int displayId) {
        return mInteractiveCache.query(displayId);
    }

    /**
     * Returns {@code true} if this device supports rebooting userspace.
+2 −1
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ import android.database.ContentObserver
import android.os.Handler
import android.os.PowerManager
import android.provider.Settings
import android.view.Display
import android.view.Surface
import android.view.View
import android.view.WindowManager.fixScale
@@ -272,7 +273,7 @@ class UnlockedScreenOffAnimationController @Inject constructor(
                // dispatched, a race condition could make it possible for this callback to be run
                // as the device is waking up. That results in the AOD UI being shown while we wake
                // up, with unpredictable consequences.
                if (!powerManager.isInteractive) {
                if (!powerManager.isInteractive(Display.DEFAULT_DISPLAY)) {
                    aodUiAnimationPlaying = true

                    // Show AOD. That'll cause the KeyguardVisibilityHelper to call
+18 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.os.Handler
import android.os.PowerManager
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
import android.view.Display
import androidx.test.filters.SmallTest
import com.android.internal.jank.InteractionJankMonitor
import com.android.systemui.SysuiTestCase
@@ -29,6 +30,7 @@ import com.android.systemui.shade.ShadeViewController
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.StatusBarStateControllerImpl
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.GlobalSettings
import junit.framework.Assert.assertFalse
import org.junit.After
@@ -141,7 +143,7 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
    @Test
    fun testAodUiNotShownIfInteractive() {
        `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true)
        `when`(powerManager.isInteractive).thenReturn(true)
        `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(true)

        val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java)
        controller.startAnimation()
@@ -152,6 +154,21 @@ class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
        verify(shadeViewController, never()).showAodUi()
    }

    @Test
    fun testAodUiShownIfGloballyInteractiveButDefaultDisplayNotInteractive() {
        `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(true)
        `when`(powerManager.isInteractive()).thenReturn(false)
        `when`(powerManager.isInteractive(eq(Display.DEFAULT_DISPLAY))).thenReturn(false)

        val callbackCaptor = ArgumentCaptor.forClass(Runnable::class.java)
        controller.startAnimation()

        verify(handler).postDelayed(callbackCaptor.capture(), anyLong())
        callbackCaptor.value.run()

        verify(shadeViewController).showAodUi()
    }

    @Test
    fun testNoAnimationPlaying_dozeParamsCanNotControlScreenOff() {
        `when`(dozeParameters.canControlUnlockedScreenOff()).thenReturn(false)
+34 −2
Original line number Diff line number Diff line
@@ -2079,6 +2079,7 @@ public final class PowerManagerService extends SystemService
            int opUid, String opPackageName, String details) {
        mPowerGroups.get(groupId).setWakefulnessLocked(wakefulness, eventTime, uid, reason, opUid,
                opPackageName, details);
        mInjector.invalidateIsInteractiveCaches();
    }

    @SuppressWarnings("deprecation")
@@ -3743,12 +3744,32 @@ public final class PowerManagerService extends SystemService
        }
    }

    private boolean isInteractiveInternal() {
    private boolean isGloballyInteractiveInternal() {
        synchronized (mLock) {
            return PowerManagerInternal.isInteractive(getGlobalWakefulnessLocked());
        }
    }

    private boolean isInteractiveInternal(int displayId, int uid) {
        synchronized (mLock) {
            DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(displayId);
            if (displayInfo == null) {
                Slog.w(TAG, "Did not find DisplayInfo for displayId " + displayId);
                return false;
            }
            if (!displayInfo.hasAccess(uid)) {
                throw new SecurityException(
                        "uid " + uid + " does not have access to display " + displayId);
            }
            PowerGroup powerGroup = mPowerGroups.get(displayInfo.displayGroupId);
            if (powerGroup == null) {
                Slog.w(TAG, "Did not find PowerGroup for displayId " + displayId);
                return false;
            }
            return PowerManagerInternal.isInteractive(powerGroup.getWakefulnessLocked());
        }
    }

    private boolean setLowPowerModeInternal(boolean enabled) {
        synchronized (mLock) {
            if (DEBUG) {
@@ -5805,7 +5826,18 @@ public final class PowerManagerService extends SystemService
        public boolean isInteractive() {
            final long ident = Binder.clearCallingIdentity();
            try {
                return isInteractiveInternal();
                return isGloballyInteractiveInternal();
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }

        @Override // Binder call
        public boolean isDisplayInteractive(int displayId) {
            int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
                return isInteractiveInternal(displayId, uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
Loading