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

Commit 31833c21 authored by Liana Kazanova (xWF)'s avatar Liana Kazanova (xWF) Committed by Android (Google) Code Review
Browse files

Merge "Revert "[Dual Shade] Fix blur and depth effects in scene container."" into main

parents 3da6b8d1 aabdc462
Loading
Loading
Loading
Loading
+189 −2
Original line number Diff line number Diff line
@@ -19,17 +19,24 @@ package com.android.systemui.shade.domain.interactor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.ObservableTransitionState.Transition.ShowOrHideOverlay
import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
import com.android.systemui.deviceentry.shared.model.DeviceUnlockStatus
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
@@ -39,13 +46,13 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class PanelExpansionInteractorImplTest : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
    private val sceneInteractor by lazy { kosmos.sceneInteractor }
    private val shadeAnimationInteractor by lazy { kosmos.shadeAnimationInteractor }
    private val transitionState =
@@ -61,6 +68,118 @@ class PanelExpansionInteractorImplTest : SysuiTestCase() {
        sceneInteractor.setTransitionState(transitionState)
    }

    @Test
    @EnableSceneContainer
    fun legacyPanelExpansion_whenIdle_whenLocked() =
        testScope.runTest {
            underTest = kosmos.panelExpansionInteractorImpl
            val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)

            changeScene(Scenes.Lockscreen) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            showOverlay(Overlays.Bouncer) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.Shade) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.QuickSettings) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.Communal) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)
        }

    @Test
    @EnableSceneContainer
    fun legacyPanelExpansion_whenIdle_whenUnlocked() =
        testScope.runTest {
            underTest = kosmos.panelExpansionInteractorImpl
            val unlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            runCurrent()

            assertThat(unlockStatus)
                .isEqualTo(DeviceUnlockStatus(true, DeviceUnlockSource.Fingerprint))

            val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)

            changeScene(Scenes.Gone) { assertThat(panelExpansion).isEqualTo(0f) }
            assertThat(panelExpansion).isEqualTo(0f)

            changeScene(Scenes.Shade) { progress -> assertThat(panelExpansion).isEqualTo(progress) }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.QuickSettings) {
                // Shade's already expanded, so moving to QS should also be 1f.
                assertThat(panelExpansion).isEqualTo(1f)
            }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.Communal) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)
        }

    @Test
    @EnableSceneContainer
    fun legacyPanelExpansion_dualShade_whenIdle_whenLocked() =
        testScope.runTest {
            underTest = kosmos.panelExpansionInteractorImpl
            val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)

            changeScene(Scenes.Lockscreen) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            showOverlay(Overlays.Bouncer) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            showOverlay(Overlays.NotificationsShade) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            showOverlay(Overlays.QuickSettingsShade) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.Communal) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)
        }

    @Test
    @EnableSceneContainer
    fun legacyPanelExpansion_dualShade_whenIdle_whenUnlocked() =
        testScope.runTest {
            underTest = kosmos.panelExpansionInteractorImpl
            val unlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus)
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            runCurrent()

            assertThat(unlockStatus)
                .isEqualTo(DeviceUnlockStatus(true, DeviceUnlockSource.Fingerprint))

            val panelExpansion by collectLastValue(underTest.legacyPanelExpansion)

            changeScene(Scenes.Gone) { assertThat(panelExpansion).isEqualTo(0f) }
            assertThat(panelExpansion).isEqualTo(0f)

            showOverlay(Overlays.NotificationsShade) { progress ->
                assertThat(panelExpansion).isEqualTo(progress)
            }
            assertThat(panelExpansion).isEqualTo(1f)

            showOverlay(Overlays.QuickSettingsShade) {
                // Notification shade is already expanded, so moving to QS shade should also be 1f.
                assertThat(panelExpansion).isEqualTo(1f)
            }
            assertThat(panelExpansion).isEqualTo(1f)

            changeScene(Scenes.Communal) { assertThat(panelExpansion).isEqualTo(1f) }
            assertThat(panelExpansion).isEqualTo(1f)
        }

    @Test
    @EnableSceneContainer
    fun shouldHideStatusBarIconsWhenExpanded_goneScene() =
@@ -131,4 +250,72 @@ class PanelExpansionInteractorImplTest : SysuiTestCase() {

        assertThat(currentScene).isEqualTo(toScene)
    }

    private fun TestScope.showOverlay(
        toOverlay: OverlayKey,
        assertDuringProgress: ((progress: Float) -> Unit) = {},
    ) {
        val currentScene by collectLastValue(sceneInteractor.currentScene)
        val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)
        val progressFlow = MutableStateFlow(0f)
        transitionState.value =
            if (checkNotNull(currentOverlays).isEmpty()) {
                ShowOrHideOverlay(
                    overlay = toOverlay,
                    fromContent = checkNotNull(currentScene),
                    toContent = toOverlay,
                    currentScene = checkNotNull(currentScene),
                    currentOverlays = flowOf(emptySet()),
                    progress = progressFlow,
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(true),
                    previewProgress = flowOf(0f),
                    isInPreviewStage = flowOf(false),
                )
            } else {
                ObservableTransitionState.Transition.ReplaceOverlay(
                    fromOverlay = checkNotNull(currentOverlays).first(),
                    toOverlay = toOverlay,
                    currentScene = checkNotNull(currentScene),
                    currentOverlays = flowOf(emptySet()),
                    progress = progressFlow,
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(true),
                    previewProgress = flowOf(0f),
                    isInPreviewStage = flowOf(false),
                )
            }
        runCurrent()
        assertDuringProgress(progressFlow.value)

        progressFlow.value = 0.2f
        runCurrent()
        assertDuringProgress(progressFlow.value)

        progressFlow.value = 0.6f
        runCurrent()
        assertDuringProgress(progressFlow.value)

        progressFlow.value = 1f
        runCurrent()
        assertDuringProgress(progressFlow.value)

        transitionState.value =
            ObservableTransitionState.Idle(
                currentScene = checkNotNull(currentScene),
                currentOverlays = setOf(toOverlay),
            )
        if (checkNotNull(currentOverlays).isEmpty()) {
            fakeSceneDataSource.showOverlay(toOverlay)
        } else {
            fakeSceneDataSource.replaceOverlay(
                from = checkNotNull(currentOverlays).first(),
                to = toOverlay,
            )
        }
        runCurrent()
        assertDuringProgress(progressFlow.value)

        assertThat(currentOverlays).containsExactly(toOverlay)
    }
}
+20 −62
Original line number Diff line number Diff line
@@ -17,13 +17,13 @@
package com.android.systemui.shade.domain.startable

import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper.RunWithLooper
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.flags.EnableSceneContainer
@@ -31,33 +31,29 @@ import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeMode
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.notificationStackScrollLayoutController
import com.android.systemui.statusbar.notificationShadeDepthController
import com.android.systemui.statusbar.phone.scrimController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlin.math.max
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.verify
@@ -66,20 +62,16 @@ import platform.test.runner.parameterized.Parameters

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWithLooper(setAsMainLooper = true)
@RunWith(ParameterizedAndroidJunit4::class)
class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val sceneInteractor by lazy { kosmos.sceneInteractor }
    private val shadeExpansionStateManager by lazy { kosmos.shadeExpansionStateManager }
    private val fakeConfigurationRepository by lazy { kosmos.fakeConfigurationRepository }
    private val fakeSceneDataSource by lazy { kosmos.fakeSceneDataSource }
    private val shadeDepthController by lazy { kosmos.notificationShadeDepthController }
    private val shadeExpansionStateManager by lazy {
        kosmos.shadeExpansionStateManager.also { it.addExpansionListener(shadeDepthController) }
    }

    private lateinit var underTest: ShadeStartable
    private val underTest: ShadeStartable = kosmos.shadeStartable

    companion object {
        @JvmStatic
@@ -93,50 +85,43 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    @Before
    fun setUp() {
        underTest = kosmos.shadeStartable
    }

    @Test
    fun hydrateShadeMode_dualShadeDisabled() =
        testScope.runTest {
            overrideResource(R.bool.config_use_split_notification_shade, false)
            kosmos.disableDualShade()
            val shadeMode by collectLastValue(kosmos.shadeMode)
            val isShadeLayoutWide by collectLastValue(kosmos.shadeModeInteractor.isShadeLayoutWide)
            underTest.start()

            kosmos.enableSingleShade()
            underTest.start()
            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
            assertThat(isShadeLayoutWide).isFalse()

            kosmos.enableSplitShade()
            overrideResource(R.bool.config_use_split_notification_shade, true)
            fakeConfigurationRepository.onAnyConfigurationChange()
            assertThat(shadeMode).isEqualTo(ShadeMode.Split)
            assertThat(isShadeLayoutWide).isTrue()

            kosmos.enableSingleShade()
            overrideResource(R.bool.config_use_split_notification_shade, false)
            fakeConfigurationRepository.onAnyConfigurationChange()
            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
            assertThat(isShadeLayoutWide).isFalse()
        }

    @Test
    @EnableSceneContainer
    fun hydrateShadeMode_dualShadeEnabled() =
        testScope.runTest {
            overrideResource(R.bool.config_use_split_notification_shade, false)
            kosmos.enableDualShade()
            val shadeMode by collectLastValue(kosmos.shadeMode)
            val isShadeLayoutWide by collectLastValue(kosmos.shadeModeInteractor.isShadeLayoutWide)
            underTest.start()

            kosmos.enableDualShade(wideLayout = false)
            underTest.start()
            assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
            assertThat(isShadeLayoutWide).isFalse()

            kosmos.enableDualShade(wideLayout = true)
            overrideResource(R.bool.config_use_split_notification_shade, true)
            fakeConfigurationRepository.onAnyConfigurationChange()
            assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
            assertThat(isShadeLayoutWide).isTrue()

            kosmos.enableDualShade(wideLayout = false)
            overrideResource(R.bool.config_use_split_notification_shade, false)
            fakeConfigurationRepository.onAnyConfigurationChange()
            assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
            assertThat(isShadeLayoutWide).isFalse()
        }

    @Test
@@ -178,34 +163,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {

            changeScene(Scenes.Shade, transitionState) { progress ->
                assertThat(latestChangeEvent?.fraction).isEqualTo(progress)
                assertThat(shadeDepthController.qsPanelExpansion).isZero()
                assertThat(shadeDepthController.shadeExpansion).isEqualTo(progress)
                assertThat(shadeDepthController.transitionToFullShadeProgress).isEqualTo(progress)
            }
            assertThat(currentScene).isEqualTo(Scenes.Shade)

            changeScene(Scenes.QuickSettings, transitionState) { progress ->
                assertThat(latestChangeEvent?.fraction).isEqualTo(1 - progress)
                assertThat(shadeDepthController.qsPanelExpansion).isEqualTo(progress)
                assertThat(shadeDepthController.shadeExpansion).isEqualTo(1 - progress)
                assertThat(shadeDepthController.transitionToFullShadeProgress)
                    .isEqualTo(
                        max(
                            shadeDepthController.qsPanelExpansion,
                            shadeDepthController.shadeExpansion,
                        )
                    )
            }
            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)

            changeScene(Scenes.Lockscreen, transitionState) { progress ->
                assertThat(latestChangeEvent?.fraction).isZero()
                assertThat(shadeDepthController.qsPanelExpansion).isEqualTo(1 - progress)
                assertThat(shadeDepthController.shadeExpansion).isZero()
                assertThat(shadeDepthController.transitionToFullShadeProgress)
                    .isEqualTo(1 - progress)
            }
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
        }

    @Test
+6 −0
Original line number Diff line number Diff line
@@ -210,6 +210,7 @@ import dagger.Lazy;
import kotlin.Unit;

import kotlinx.coroutines.CoroutineDispatcher;
import kotlinx.coroutines.flow.Flow;
import kotlinx.coroutines.flow.MutableStateFlow;
import kotlinx.coroutines.flow.StateFlow;

@@ -3122,6 +3123,11 @@ public final class NotificationPanelViewController implements
        return mShadeRepository.getUdfpsTransitionToFullShadeProgress();
    }

    @Override
    public Flow<Float> getLegacyPanelExpansion() {
        return  mShadeRepository.getLegacyShadeExpansion();
    }

    @Override
    public boolean isFullyExpanded() {
        return mExpandedHeight >= getMaxPanelTransitionDistance();
+5 −1
Original line number Diff line number Diff line
@@ -29,7 +29,11 @@ import com.android.systemui.util.Compile
import java.util.concurrent.CopyOnWriteArrayList
import javax.inject.Inject

/** A class responsible for managing the notification panel's current state. */
/**
 * A class responsible for managing the notification panel's current state.
 *
 * TODO(b/200063118): Make this class the one source of truth for the state of panel expansion.
 */
@SysUISingleton
@Deprecated("Use ShadeInteractor instead")
class ShadeExpansionStateManager @Inject constructor() {
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.systemui.statusbar.phone.HeadsUpAppearanceController
import java.util.function.Consumer
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf

/** Empty implementation of ShadeViewController for variants with no shade. */
open class ShadeViewControllerEmptyImpl @Inject constructor() :
@@ -110,6 +111,8 @@ open class ShadeViewControllerEmptyImpl @Inject constructor() :

    override val shadeHeadsUpTracker = ShadeHeadsUpTrackerEmptyImpl()
    override val shadeFoldAnimator = ShadeFoldAnimatorEmptyImpl()
    @Deprecated("Use SceneInteractor.currentScene instead.")
    override val legacyPanelExpansion = flowOf(0f)
    override val udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
}

Loading