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

Commit 082732ee authored by burakov's avatar burakov
Browse files

[bc25] Don't render lockscreen notifications on NotificationsShadeScene.

The notifications shade already renders its own notifications stack, so
we should avoid rendering lockscreen notifications in that scene.

This prevents unnecessarily rendering notifications twice, as well as
composing the same element key twice in the same scene.

In a future CL I'll make sure notifications shade renders its
notifications in the same position, making this imperceptible for the
user.

Flag: com.android.systemui.dual_shade
Flag: com.android.systemui.scene_container
Bug: 340553529
Test: Manually verified by opening and closing the notifications shade
on the lockscreen and observing that lockscreen notifications disappear.
Test: Added unit tests, and existing unit tests still pass.

Change-Id: Iba15e6c8bf71ef6d8f29b1b3d3e46b7512a6d6f2
parent e7ff88b1
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -90,10 +90,16 @@ constructor(
     */
    @Composable
    fun SceneScope.Notifications(burnInParams: BurnInParameters?, modifier: Modifier = Modifier) {
        val areNotificationsVisible by
            lockscreenContentViewModel
                .areNotificationsVisible(sceneKey)
                .collectAsStateWithLifecycle(initialValue = false)
        if (!areNotificationsVisible) {
            return
        }

        val isShadeLayoutWide by
            lockscreenContentViewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
        val areNotificationsVisible by
            lockscreenContentViewModel.areNotificationsVisible.collectAsStateWithLifecycle()
        val splitShadeTopMargin: Dp =
            if (Flags.centralizedStatusBarHeightFix()) {
                LargeScreenHeaderHelper.getLargeScreenHeaderHeight(LocalContext.current).dp
@@ -101,10 +107,6 @@ constructor(
                dimensionResource(id = R.dimen.large_screen_shade_header_height)
            }

        if (!areNotificationsVisible) {
            return
        }

        ConstrainedNotificationStack(
            stackScrollView = stackScrollView.get(),
            viewModel = viewModel,
+50 −3
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

package com.android.systemui.keyguard.ui.viewmodel

import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -37,6 +38,7 @@ 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.shade.data.repository.shadeRepository
import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.testKosmos
import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
import com.android.systemui.util.mockito.whenever
@@ -124,7 +126,50 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa
    fun areNotificationsVisible_splitShadeTrue_true() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
                shadeRepository.setShadeLayoutWide(true)
                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)

                assertThat(areNotificationsVisible).isTrue()
            }
        }

    @Test
    @EnableFlags(DualShade.FLAG_NAME)
    fun areNotificationsVisible_dualShadeWideOnLockscreen_true() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
                shadeRepository.setShadeLayoutWide(true)
                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)

                assertThat(areNotificationsVisible).isTrue()
            }
        }

    @Test
    @EnableFlags(DualShade.FLAG_NAME)
    fun areNotificationsVisible_dualShadeWideOnNotificationsShade_false() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.NotificationsShade))
                shadeRepository.setShadeLayoutWide(true)
                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)

                assertThat(areNotificationsVisible).isFalse()
            }
        }

    @Test
    @EnableFlags(DualShade.FLAG_NAME)
    fun areNotificationsVisible_dualShadeWideOnQuickSettingsShade_true() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.QuickSettingsShade))
                shadeRepository.setShadeLayoutWide(true)
                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)

@@ -137,7 +182,8 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa
    fun areNotificationsVisible_withSmallClock_true() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
                fakeKeyguardClockRepository.setClockSize(ClockSize.SMALL)
                assertThat(areNotificationsVisible).isTrue()
            }
@@ -148,7 +194,8 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa
    fun areNotificationsVisible_withLargeClock_false() =
        with(kosmos) {
            testScope.runTest {
                val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
                val areNotificationsVisible by
                    collectLastValue(underTest.areNotificationsVisible(Scenes.Lockscreen))
                fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
                assertThat(areNotificationsVisible).isFalse()
            }
+23 −13
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.ui.viewmodel

import android.content.res.Resources
import com.android.compose.animation.scene.SceneKey
import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.biometrics.AuthController
import com.android.systemui.dagger.SysUISingleton
@@ -26,14 +27,17 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn

@@ -57,19 +61,6 @@ constructor(

    val isShadeLayoutWide: StateFlow<Boolean> = shadeInteractor.isShadeLayoutWide

    val areNotificationsVisible: StateFlow<Boolean> =
        combine(
                clockSize,
                shadeInteractor.isShadeLayoutWide,
            ) { clockSize, isShadeLayoutWide ->
                clockSize == ClockSize.SMALL || isShadeLayoutWide
            }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )

    /** Amount of horizontal translation that should be applied to elements in the scene. */
    val unfoldTranslations: StateFlow<UnfoldTranslations> =
        combine(
@@ -97,6 +88,25 @@ constructor(
                initialValue = true,
            )

    /**
     * Returns a flow that indicates whether lockscreen notifications should be rendered in the
     * given [sceneKey].
     */
    fun areNotificationsVisible(sceneKey: SceneKey): Flow<Boolean> {
        // `Scenes.NotificationsShade` renders its own separate notifications stack, so when it's
        // open we avoid rendering the lockscreen notifications stack.
        if (sceneKey == Scenes.NotificationsShade) {
            return flowOf(false)
        }

        return combine(
            clockSize,
            shadeInteractor.isShadeLayoutWide,
        ) { clockSize, isShadeLayoutWide ->
            clockSize == ClockSize.SMALL || isShadeLayoutWide
        }
    }

    fun getSmartSpacePaddingTop(resources: Resources): Int {
        return if (clockSize.value == ClockSize.LARGE) {
            resources.getDimensionPixelSize(R.dimen.keyguard_smartspace_top_offset) +