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

Commit 1e25b062 authored by Nick Chameyev's avatar Nick Chameyev Committed by Android (Google) Code Review
Browse files

Merge "Force SHOW_WALLPAPER flag when display switching" into main

parents 3e4d4369 2ab78863
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import androidx.test.filters.SmallTest
import com.android.internal.policy.IKeyguardService.SCREEN_TURNING_ON_REASON_UNKNOWN
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.shade.display.PendingDisplayChangeController
import com.android.systemui.unfold.FoldAodAnimationController
import com.android.systemui.unfold.FullscreenLightRevealAnimation
import com.android.systemui.unfold.SysUIUnfoldComponent
@@ -57,6 +58,8 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
    private lateinit var fullscreenLightRevealAnimation: FullscreenLightRevealAnimation
    @Mock
    private lateinit var fullScreenLightRevealAnimations: Set<FullscreenLightRevealAnimation>
    @Mock
    private lateinit var pendingDisplayChangeController: PendingDisplayChangeController
    @Captor
    private lateinit var readyCaptor: ArgumentCaptor<Runnable>

@@ -78,7 +81,8 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {

        screenOnCoordinator = ScreenOnCoordinator(
            Optional.of(unfoldComponent),
            testHandler
            testHandler,
            pendingDisplayChangeController,
        )
    }

@@ -128,7 +132,8 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
        // Recreate with empty unfoldComponent
        screenOnCoordinator = ScreenOnCoordinator(
            Optional.empty(),
            testHandler
            testHandler,
            pendingDisplayChangeController,
        )
        screenOnCoordinator.onScreenTurningOn(reason = SCREEN_TURNING_ON_REASON_UNKNOWN, runnable)
        waitHandlerIdle()
@@ -142,7 +147,8 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
        // Recreate with empty unfoldComponent
        screenOnCoordinator = ScreenOnCoordinator(
                Optional.empty(),
                testHandler
                testHandler,
                pendingDisplayChangeController,
        )
        screenOnCoordinator.onScreenTurningOn(reason = SCREEN_TURNING_ON_REASON_UNKNOWN, runnable)

@@ -156,7 +162,8 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
        // Recreate with empty unfoldComponent
        screenOnCoordinator = ScreenOnCoordinator(
                Optional.empty(),
                testHandler
                testHandler,
                pendingDisplayChangeController,
        )
        screenOnCoordinator.onScreenTurningOn(reason = SCREEN_TURNING_ON_REASON_UNKNOWN, runnable)
        // No need to wait for the handler to be idle, as it shouldn't be used
+26 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.shade;

import static android.service.dreams.Flags.FLAG_DREAMS_V2;
import static com.android.window.flags.Flags.FLAG_ENSURE_WALLPAPER_DRAWN_ON_DISPLAY_SWITCH;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
@@ -274,6 +275,31 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
    }

    @EnableFlags(FLAG_ENSURE_WALLPAPER_DRAWN_ON_DISPLAY_SWITCH)
    @Test
    public void attach_pendingDisplayChange_wallpaperVisible() {
        mNotificationShadeWindowController.attach();
        clearInvocations(mWindowManager);

        mNotificationShadeWindowController.setPendingDisplayChange(true);

        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isTrue();
    }

    @EnableFlags(FLAG_ENSURE_WALLPAPER_DRAWN_ON_DISPLAY_SWITCH)
    @Test
    public void attach_pendingDisplayChangeFinished_wallpaperNotVisible() {
        mNotificationShadeWindowController.attach();
        mNotificationShadeWindowController.setPendingDisplayChange(true);
        clearInvocations(mWindowManager);

        mNotificationShadeWindowController.setPendingDisplayChange(false);

        verify(mWindowManager).updateViewLayout(any(), mLayoutParameters.capture());
        assertThat((mLayoutParameters.getValue().flags & FLAG_SHOW_WALLPAPER) != 0).isFalse();
    }

    @Test
    public void setBouncerShowing_isFocusable_whenNeedsInput() {
        mNotificationShadeWindowController.setKeyguardNeedsInput(true);
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.shade.display

import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.policy.IKeyguardService.SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH
import com.android.internal.policy.IKeyguardService.SCREEN_TURNING_ON_REASON_UNKNOWN
import com.android.systemui.SysuiTestCase
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.verifyCurrent
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.ScreenPowerState
import com.android.systemui.statusbar.notificationShadeWindowController
import com.android.systemui.testKosmos
import kotlinx.coroutines.test.advanceTimeBy
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.inOrder
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoInteractions
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableFlags(com.android.window.flags.Flags.FLAG_ENSURE_WALLPAPER_DRAWN_ON_DISPLAY_SWITCH)
class PendingDisplayChangeControllerTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val powerRepository = kosmos.fakePowerRepository

    private lateinit var underTest: PendingDisplayChangeController

    @Test
    fun onScreenTurningOnWithDisplaySwitching_notifiesShadeWindowController() =
        kosmos.runTest {
            createAndStartController()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH, mock<Runnable>())

            verifyCurrent(notificationShadeWindowController).setPendingDisplayChange(true)
        }

    @Test
    fun onScreenTurningOnWithDisplaySwitching_notifiesScreenTurningOnComplete() =
        kosmos.runTest {
            createAndStartController()
            val onScreenTurningOnComplete = mock<Runnable>()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH, onScreenTurningOnComplete)

            verifyCurrent(onScreenTurningOnComplete).run()
        }

    @Test
    fun onScreenTurningWithoutDisplaySwitching_notifiesScreenTurningOnComplete() =
        kosmos.runTest {
            createAndStartController()
            val onScreenTurningOnComplete = mock<Runnable>()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_UNKNOWN, onScreenTurningOnComplete)

            verifyCurrent(onScreenTurningOnComplete).run()
        }

    @Test
    fun onScreenTurningWithoutDisplaySwitching_doesNotSetPendingScreenState() =
        kosmos.runTest {
            createAndStartController()
            val onScreenTurningOnComplete = mock<Runnable>()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_UNKNOWN, onScreenTurningOnComplete)

            runCurrent()

            verify(notificationShadeWindowController, never()).setPendingDisplayChange(anyBoolean())
        }

    @Test
    fun onScreenTurningOnWithDisplaySwitching_screenTurnedOn_resetsPendingDisplayChange() =
        kosmos.runTest {
            createAndStartController()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH, mock<Runnable>())
            runCurrent()
            clearInvocations(notificationShadeWindowController)

            powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)

            verifyCurrent(notificationShadeWindowController).setPendingDisplayChange(false)
        }

    @Test
    fun onScreenTurningOnWithDisplaySwitching_screenTurningOnTimeout_resetsPendingDisplayChange() =
        kosmos.runTest {
            createAndStartController()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH, mock<Runnable>())
            runCurrent()
            clearInvocations(notificationShadeWindowController)

            testScope.advanceTimeBy(15.seconds)

            verify(notificationShadeWindowController).setPendingDisplayChange(false)
        }

    @Test
    fun onScreenTurningOnWithDisplaySwitching_beforeTurningOnTimeout_noPendingDisplayChange() =
        kosmos.runTest {
            createAndStartController()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH, mock<Runnable>())
            runCurrent()
            clearInvocations(notificationShadeWindowController)

            testScope.advanceTimeBy(100.milliseconds)

            verifyNoInteractions(notificationShadeWindowController)
        }

    @Test
    fun onScreenTurningOnWithDisplaySwitching_previousOneIsStillInProgress_processesBoth() =
        kosmos.runTest {
            createAndStartController()
            val onScreenTurningOnComplete1 = mock<Runnable>()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH,
                onScreenTurningOnComplete1)
            runCurrent()

            val onScreenTurningOnComplete2 = mock<Runnable>()
            underTest.onScreenTurningOn(SCREEN_TURNING_ON_REASON_DISPLAY_SWITCH,
                onScreenTurningOnComplete2)
            runCurrent()

            powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)

            verifyCurrent(onScreenTurningOnComplete1).run()
            verifyCurrent(onScreenTurningOnComplete2).run()

            inOrder(notificationShadeWindowController) {
                verify(notificationShadeWindowController).setPendingDisplayChange(true)
                verify(notificationShadeWindowController).setPendingDisplayChange(false)
                verify(notificationShadeWindowController).setPendingDisplayChange(true)
                verify(notificationShadeWindowController).setPendingDisplayChange(false)
            }
        }

    private fun Kosmos.createAndStartController() {
        underTest = PendingDisplayChangeController(
            testScope.backgroundScope,
            testScope.backgroundScope,
            { notificationShadeWindowController },
            powerInteractor
        ).also { it.start() }
        runCurrent()
    }
}
 No newline at end of file
+8 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.os.Trace
import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.shade.display.EnsureWallpaperDrawnOnDisplaySwitch
import com.android.systemui.shade.display.PendingDisplayChangeController
import com.android.systemui.unfold.SysUIUnfoldComponent
import com.android.systemui.util.concurrency.PendingTasksContainer
import com.android.systemui.util.kotlin.getOrNull
@@ -40,6 +42,7 @@ class ScreenOnCoordinator
constructor(
    unfoldComponent: Optional<SysUIUnfoldComponent>,
    @Main private val mainHandler: Handler,
    private val pendingDisplayChangeController: PendingDisplayChangeController
) {

    private val foldAodAnimationController =
@@ -63,6 +66,11 @@ constructor(
            it.onScreenTurningOn(pendingTasks.registerTask(it::class.java.simpleName))
        }

        if (EnsureWallpaperDrawnOnDisplaySwitch.isEnabled) {
            pendingDisplayChangeController.onScreenTurningOn(reason,
                pendingTasks.registerTask("pending-display-change-controller"));
        }

        pendingTasks.onTasksComplete {
            if (Flags.enableBackgroundKeyguardOndrawnCallback()) {
                // called by whatever thread completes the last task registered.
+15 −1
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.scene.ui.view.WindowRootViewComponent;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shade.display.EnsureWallpaperDrawnOnDisplaySwitch;
import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel;
import com.android.systemui.statusbar.NotificationShadeWindowController;
@@ -402,7 +403,9 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
        final boolean keyguardOrAod = state.keyguardShowing
                || (state.dozing && mDozeParameters.getAlwaysOn());
        if ((keyguardOrAod && !state.mediaBackdropShowing && !state.lightRevealScrimOpaque)
                || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()) {
                || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind()
                || (EnsureWallpaperDrawnOnDisplaySwitch.isEnabled() && state.pendingDisplayChange)
        ) {
            // Show the wallpaper if we're on keyguard/AOD and the wallpaper is not occluded by a
            // solid backdrop. Also, show it if we are currently animating between the
            // keyguard and the surface behind the keyguard - we want to use the wallpaper as a
@@ -655,6 +658,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
                state.qsExpanded,
                state.headsUpNotificationShowing,
                state.lightRevealScrimOpaque,
                state.pendingDisplayChange,
                state.isSwitchingUsers,
                state.forceWindowCollapsed,
                state.forceDozeBrightness,
@@ -896,6 +900,16 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
        apply(mCurrentState);
    }

    @Override
    public void setPendingDisplayChange(boolean pendingDisplayChange) {
        if (EnsureWallpaperDrawnOnDisplaySwitch.isUnexpectedlyInLegacyMode()
                || mCurrentState.pendingDisplayChange == pendingDisplayChange) {
            return;
        }
        mCurrentState.pendingDisplayChange = pendingDisplayChange;
        apply(mCurrentState);
    }

    /**
     * @param state The {@link StatusBarStateController} of the status bar.
     */
Loading