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

Commit f3c647e4 authored by Ale Nijamkin's avatar Ale Nijamkin
Browse files

[flexiglass] Fixes occlusion (once and for all!!1)

WindowManagerLockscreenVisibilityInteractor wasn't reporting lockscreen
visibility properly to its downstream consumers. It wasn't taking
overlays into account and was pretending like the keyguard should be
reported as false when transitioning away from non-keyguard scenes
(without taking into account what scene it was transitioning _to_).

This bug, combined with the fact that if the scene container becomes
invisible (like it does due to occlusion) when turning off the display
while on a "show over lockscreen" activity like that of the Calculator
app, but doesn't seem to finish the Gone -> Lockscreen transition,
caused the downstream system to fail to report to WM that the keyguard
has become visible which is causing the attached CTS tests to fail.

Bug: 416718983
Bug: 416718898
Test: manually verified that logcat shows that ATMS is being properly
told that the keyguard has become visible when turning off the display
from the power button while the Calculator app is in the foreground
Flag: com.android.systemui.scene_container

Change-Id: Iae22946d733e08905dbf3d65298d57a178727a47
parent 06bfedbf
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1104,7 +1104,7 @@ class WindowManagerLockscreenVisibilityInteractorTest : SysuiTestCase() {
            assertThat(lockscreenVisibility).isFalse()

            kosmos.setSceneTransition(Transition(from = Scenes.Gone, to = Scenes.Lockscreen))
            assertThat(lockscreenVisibility).isFalse()
            assertThat(lockscreenVisibility).isTrue()

            kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
            kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "")
+55 −33
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor

import com.android.compose.animation.scene.ObservableTransitionState.Idle
import com.android.compose.animation.scene.ObservableTransitionState.Transition
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
@@ -205,27 +206,62 @@ constructor(
                        sceneInteractor.get().transitionState.flatMapLatestConflated {
                            when (it) {
                                is Idle ->
                                    when (it.currentScene) {
                                        in keyguardContent -> flowOf(true)
                                        in nonKeyguardContent -> flowOf(false)
                                        in keyguardAgnosticContent -> isDeviceNotEnteredDirectly
                                        else ->
                                            throw IllegalStateException(
                                                "Unknown scene: ${it.currentScene}"
                                            )
                                    when {
                                        // If idle on one of the keyguard scenes, report that the
                                        // keyguard is visible.
                                        it.currentScene in keyguardScenes -> flowOf(true)
                                        // If showing the bouncer overlay, report that the keyguard
                                        // is visible.
                                        it.currentOverlays.contains(Overlays.Bouncer) ->
                                            flowOf(true)
                                        // If showing a shade scene, report that the keyguard is
                                        // visible if the device hasn't been entered yet.
                                        it.currentScene in shadeScenes -> isDeviceNotEnteredDirectly
                                        // If idle on any other scene, report that the keyguard is
                                        // not visible.
                                        else -> flowOf(false)
                                    }
                                is Transition ->

                                is Transition.ChangeScene ->
                                    when {
                                        it.isTransitioningSets(from = keyguardContent) ->
                                        // If transitioning between two scenes and any one of the
                                        // two scenes is one of the keyguard scenes, report that the
                                        // keyguard is visible.
                                        it.fromScene in keyguardScenes -> flowOf(true)
                                        it.toScene in keyguardScenes -> flowOf(true)
                                        // If transitioning between two non-keyguard scenes but the
                                        // bouncer overlay is showing, report that the keyguard is
                                        // visible.
                                        it.currentOverlays.contains(Overlays.Bouncer) ->
                                            flowOf(true)
                                        it.isTransitioningSets(from = nonKeyguardContent) ->
                                            flowOf(false)
                                        it.isTransitioningSets(from = keyguardAgnosticContent) ->
                                        // If transitioning between two shade scenes and the bouncer
                                        // overlay is not showing, report that the keyguard is
                                        // visible if the device hasn't yet been entered.
                                        it.fromScene in shadeScenes && it.toScene in shadeScenes ->
                                            isDeviceNotEnteredDirectly
                                        // In all other cases, report that the keyguard isn't
                                        // visible.
                                        else -> flowOf(false)
                                    }

                                is Transition.OverlayTransition ->
                                    when {
                                        // If showing, hiding, or replacing an overlay and the
                                        // current scene under those overlays is one of the keyguard
                                        // scenes, report that the keyguard is showing.
                                        it.currentScene in keyguardScenes -> flowOf(true)
                                        // While animating away the bouncer overlay, report that the
                                        // keyguard is still being shown.
                                        it.fromContent == Overlays.Bouncer -> flowOf(true)
                                        // While animating in the bouncer overlay, report that the
                                        // keyguard is still being shown.
                                        it.toContent == Overlays.Bouncer -> flowOf(true)
                                        // In all other cases, report that the keyguard is visible
                                        // while the bouncer overlay is visible.
                                        else ->
                                            throw IllegalStateException(
                                                "Unknown content: ${it.fromContent}"
                                            )
                                            it.currentOverlays.map { currentOverlays ->
                                                currentOverlays.contains(Overlays.Bouncer)
                                            }
                                    }
                            }
                        },
@@ -341,25 +377,11 @@ constructor(
         * Content that is part of the keyguard and are shown when the device is locked or when the
         * keyguard still needs to be dismissed.
         */
        val keyguardContent =
            setOf(Scenes.Lockscreen, Overlays.Bouncer, Scenes.Communal, Scenes.Dream)
        val keyguardScenes: Set<SceneKey> = setOf(Scenes.Lockscreen, Scenes.Communal, Scenes.Dream)

        /**
         * Content that doesn't belong in the keyguard family and cannot show when the device is
         * locked or when the keyguard still needs to be dismissed.
         * Scenes that show "shade" like content and can show whether the device is entered or not.
         */
        private val nonKeyguardContent = setOf(Scenes.Gone)

        /**
         * Content that can show regardless of device lock or keyguard dismissal states. Other
         * sources of state need to be consulted to know whether the device has been entered or not.
         */
        private val keyguardAgnosticContent =
            setOf(
                Scenes.Shade,
                Scenes.QuickSettings,
                Overlays.NotificationsShade,
                Overlays.QuickSettingsShade,
            )
        private val shadeScenes: Set<SceneKey> = setOf(Scenes.Shade, Scenes.QuickSettings)
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.TrustInteractor
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor.Companion.keyguardContent
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor.Companion.keyguardScenes
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.model.SceneContainerPlugin
import com.android.systemui.model.SceneContainerPluginImpl
@@ -442,7 +442,7 @@ constructor(
                    val isOnPrimaryBouncer = Overlays.Bouncer in renderedOverlays
                    if (!deviceUnlockStatus.isUnlocked) {
                        return@mapNotNull if (
                            renderedScenes.any { it in keyguardContent } ||
                            renderedScenes.any { it in keyguardScenes } ||
                                Overlays.Bouncer in renderedOverlays
                        ) {
                            // Already on a keyguard scene or bouncer, no need to change scenes.