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

Commit 670ba514 authored by Jeff DeCew's avatar Jeff DeCew
Browse files

[flexiglass] Revamp SharedNotificationContainerViewModelTest

- Adds an extension function which allows parameterizing SceneContainerFlag
- Adds parameterization to SharedNotificationContainerViewModelTest
- Disables some tests under scene container where we have flagged off the code

Bug: 332750091
Test: atest SystemUITest
Test: atest SystemUiRoboTest
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint TEAMFOOD
Change-Id: Ief5202cf04d3b7692593f3e15d8893ea3dee2a18
parent c28bd6bb
Loading
Loading
Loading
Loading
+70 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.scene.shared.flag

import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_COMPOSE_LOCKSCREEN
import com.android.systemui.Flags.FLAG_EXAMPLE_FLAG
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.andSceneContainer
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
internal class SceneContainerFlagParameterizationTest : SysuiTestCase() {

    @Test
    fun emptyAndSceneContainer() {
        val result = FlagsParameterization.allCombinationsOf().andSceneContainer()
        Truth.assertThat(result).hasSize(2)
        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
    }

    @Test
    fun oneUnrelatedAndSceneContainer() {
        val unrelatedFlag = FLAG_EXAMPLE_FLAG
        val result = FlagsParameterization.allCombinationsOf(unrelatedFlag).andSceneContainer()
        Truth.assertThat(result).hasSize(4)
        Truth.assertThat(result[0].mOverrides[unrelatedFlag]).isFalse()
        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
        Truth.assertThat(result[1].mOverrides[unrelatedFlag]).isFalse()
        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
        Truth.assertThat(result[2].mOverrides[unrelatedFlag]).isTrue()
        Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
        Truth.assertThat(result[3].mOverrides[unrelatedFlag]).isTrue()
        Truth.assertThat(result[3].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
    }

    @Test
    fun oneDependencyAndSceneContainer() {
        val dependentFlag = FLAG_COMPOSE_LOCKSCREEN
        val result = FlagsParameterization.allCombinationsOf(dependentFlag).andSceneContainer()
        Truth.assertThat(result).hasSize(3)
        Truth.assertThat(result[0].mOverrides[dependentFlag]).isFalse()
        Truth.assertThat(result[0].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
        Truth.assertThat(result[1].mOverrides[dependentFlag]).isTrue()
        Truth.assertThat(result[1].mOverrides[FLAG_SCENE_CONTAINER]).isFalse()
        Truth.assertThat(result[2].mOverrides[dependentFlag]).isTrue()
        Truth.assertThat(result[2].mOverrides[FLAG_SCENE_CONTAINER]).isTrue()
    }
}
+62 −18
Original line number Original line Diff line number Diff line
@@ -20,9 +20,11 @@
package com.android.systemui.statusbar.notification.stack.ui.viewmodel
package com.android.systemui.statusbar.notification.stack.ui.viewmodel


import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.DisableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX
import com.android.systemui.Flags.FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX
import com.android.systemui.Flags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.NotificationContainerBounds
import com.android.systemui.common.shared.model.NotificationContainerBounds
@@ -31,6 +33,7 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.coroutines.collectValues
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.Flags
import com.android.systemui.flags.andSceneContainer
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -64,10 +67,30 @@ import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith
import org.mockito.Mockito.mock
import org.mockito.Mockito.mock
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters


@SmallTest
@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWith(ParameterizedAndroidJunit4::class)
class SharedNotificationContainerViewModelTest : SysuiTestCase() {
// SharedNotificationContainerViewModel is only bound when FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT is on
@EnableFlags(FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
class SharedNotificationContainerViewModelTest(flags: FlagsParameterization?) : SysuiTestCase() {

    companion object {
        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf(
                    FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX,
                )
                .andSceneContainer()
        }
    }

    init {
        mSetFlagsRule.setFlagsParameterization(flags!!)
    }

    val aodBurnInViewModel = mock(AodBurnInViewModel::class.java)
    val aodBurnInViewModel = mock(AodBurnInViewModel::class.java)
    lateinit var movementFlow: MutableStateFlow<BurnInModel>
    lateinit var movementFlow: MutableStateFlow<BurnInModel>


@@ -84,14 +107,22 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
    }
    }


    val testScope = kosmos.testScope
    val testScope = kosmos.testScope
    val configurationRepository = kosmos.fakeConfigurationRepository
    val configurationRepository
    val keyguardRepository = kosmos.fakeKeyguardRepository
        get() = kosmos.fakeConfigurationRepository
    val keyguardInteractor = kosmos.keyguardInteractor
    val keyguardRepository
    val keyguardRootViewModel = kosmos.keyguardRootViewModel
        get() = kosmos.fakeKeyguardRepository
    val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
    val keyguardInteractor
    val shadeRepository = kosmos.shadeRepository
        get() = kosmos.keyguardInteractor
    val sharedNotificationContainerInteractor = kosmos.sharedNotificationContainerInteractor
    val keyguardRootViewModel
    val largeScreenHeaderHelper = kosmos.mockLargeScreenHeaderHelper
        get() = kosmos.keyguardRootViewModel
    val keyguardTransitionRepository
        get() = kosmos.fakeKeyguardTransitionRepository
    val shadeRepository
        get() = kosmos.shadeRepository
    val sharedNotificationContainerInteractor
        get() = kosmos.sharedNotificationContainerInteractor
    val largeScreenHeaderHelper
        get() = kosmos.mockLargeScreenHeaderHelper


    lateinit var underTest: SharedNotificationContainerViewModel
    lateinit var underTest: SharedNotificationContainerViewModel


@@ -130,9 +161,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
    fun validatePaddingTopInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
    fun validatePaddingTopInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
            overrideResource(R.bool.config_use_split_notification_shade, true)
            overrideResource(R.bool.config_use_split_notification_shade, true)
            overrideResource(R.bool.config_use_large_screen_shade_header, true)
            overrideResource(R.bool.config_use_large_screen_shade_header, true)
@@ -148,9 +179,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
    fun validatePaddingTopInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
    fun validatePaddingTopInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight()).thenReturn(5)
            overrideResource(R.bool.config_use_split_notification_shade, true)
            overrideResource(R.bool.config_use_split_notification_shade, true)
            overrideResource(R.bool.config_use_large_screen_shade_header, true)
            overrideResource(R.bool.config_use_large_screen_shade_header, true)
@@ -243,9 +274,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    @DisableFlags(FLAG_SCENE_CONTAINER)
    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
    fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() =
    fun validateMarginTopWithLargeScreenHeader_refactorFlagOn_usesHelper() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            val headerResourceHeight = 50
            val headerResourceHeight = 50
            val headerHelperHeight = 100
            val headerHelperHeight = 100
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
@@ -263,9 +294,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {


    @Test
    @Test
    @EnableSceneContainer
    @EnableSceneContainer
    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
    fun validateMarginTopWithLargeScreenHeader_sceneContainerFlagOn_stillZero() =
    fun validateMarginTopWithLargeScreenHeader_sceneContainerFlagOn_stillZero() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            val headerResourceHeight = 50
            val headerResourceHeight = 50
            val headerHelperHeight = 100
            val headerHelperHeight = 100
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
            whenever(largeScreenHeaderHelper.getLargeScreenHeaderHeight())
@@ -503,6 +534,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun boundsOnLockscreenNotInSplitShade() =
    fun boundsOnLockscreenNotInSplitShade() =
        testScope.runTest {
        testScope.runTest {
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)
@@ -523,9 +555,9 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX, FLAG_SCENE_CONTAINER)
    fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
    fun boundsOnLockscreenInSplitShade_refactorFlagOff_usesLargeHeaderResource() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.disableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)


            // When in split shade
            // When in split shade
@@ -547,13 +579,20 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
            runCurrent()
            runCurrent()


            // Top should be equal to bounds (1) - padding adjustment (10)
            // Top should be equal to bounds (1) - padding adjustment (10)
            assertThat(bounds).isEqualTo(NotificationContainerBounds(top = -9f, bottom = 2f))
            assertThat(bounds)
                .isEqualTo(
                    NotificationContainerBounds(
                        top = -9f,
                        bottom = 2f,
                    )
                )
        }
        }


    @Test
    @Test
    @EnableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
    fun boundsOnLockscreenInSplitShade_refactorFlagOn_usesLargeHeaderHelper() =
        testScope.runTest {
        testScope.runTest {
            mSetFlagsRule.enableFlags(FLAG_CENTRALIZED_STATUS_BAR_HEIGHT_FIX)
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)


            // When in split shade
            // When in split shade
@@ -579,6 +618,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun boundsOnShade() =
    fun boundsOnShade() =
        testScope.runTest {
        testScope.runTest {
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)
@@ -594,6 +634,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun boundsOnQS() =
    fun boundsOnQS() =
        testScope.runTest {
        testScope.runTest {
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)
@@ -693,6 +734,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun translationYUpdatesOnKeyguardForBurnIn() =
    fun translationYUpdatesOnKeyguardForBurnIn() =
        testScope.runTest {
        testScope.runTest {
            val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
            val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -726,6 +768,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun translationYDoesNotUpdateWhenShadeIsExpanded() =
    fun translationYDoesNotUpdateWhenShadeIsExpanded() =
        testScope.runTest {
        testScope.runTest {
            val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
            val translationY by collectLastValue(underTest.translationY(BurnInParameters()))
@@ -746,6 +789,7 @@ class SharedNotificationContainerViewModelTest : SysuiTestCase() {
        }
        }


    @Test
    @Test
    @DisableFlags(FLAG_SCENE_CONTAINER)
    fun updateBounds_fromKeyguardRoot() =
    fun updateBounds_fromKeyguardRoot() =
        testScope.runTest {
        testScope.runTest {
            val bounds by collectLastValue(underTest.bounds)
            val bounds by collectLastValue(underTest.bounds)
+3 −1
Original line number Original line Diff line number Diff line
@@ -350,7 +350,8 @@ constructor(
     *
     *
     * When the shade is expanding, the position is controlled by... the shade.
     * When the shade is expanding, the position is controlled by... the shade.
     */
     */
    val bounds: StateFlow<NotificationContainerBounds> =
    val bounds: StateFlow<NotificationContainerBounds> by lazy {
        SceneContainerFlag.assertInLegacyMode()
        combine(
        combine(
                isOnLockscreenWithoutShade,
                isOnLockscreenWithoutShade,
                keyguardInteractor.notificationContainerBounds,
                keyguardInteractor.notificationContainerBounds,
@@ -380,6 +381,7 @@ constructor(
                initialValue = NotificationContainerBounds(),
                initialValue = NotificationContainerBounds(),
            )
            )
            .dumpValue("bounds")
            .dumpValue("bounds")
    }


    /**
    /**
     * Ensure view is visible when the shade/qs are expanded. Also, as QS is expanding, fade out
     * Ensure view is visible when the shade/qs are expanded. Also, as QS is expanding, fade out
+60 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2024 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.flags

import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import com.android.systemui.Flags.FLAG_SCENE_CONTAINER

/** The name of the one flag to be disabled for OFF parameterization */
private const val flagNameToDisable = FLAG_SCENE_CONTAINER

/** Cache of the flags to be enabled for ON parameterization */
private val flagNamesToEnable =
    EnableSceneContainer::class.java.getAnnotation(EnableFlags::class.java)!!.value.toList()

/**
 * Provides one or two copies of this [FlagsParameterization]; one which disabled
 * [FLAG_SCENE_CONTAINER] and if none of the dependencies of it are disabled by this, a second copy
 * which enables [FLAG_SCENE_CONTAINER] and all the dependencies (just like [EnableSceneContainer]).
 */
fun FlagsParameterization.andSceneContainer(): Sequence<FlagsParameterization> = sequence {
    check(flagNameToDisable !in mOverrides) {
        "Can't add $flagNameToDisable to FlagsParameterization: $this"
    }
    yield(FlagsParameterization(mOverrides + mapOf(flagNameToDisable to false)))
    if (flagNamesToEnable.all { mOverrides[it] != false }) {
        // Can't add the parameterization of enabling SceneContainerFlag to a parameterization that
        // explicitly disables one of the prerequisite flags.
        yield(FlagsParameterization(mOverrides + flagNamesToEnable.associateWith { true }))
    }
}

/**
 * Doubles (roughly; see below) the given list of [FlagsParameterization] for enabling and disabling
 * SceneContainerFlag.
 *
 * The input parameterization may not define [FLAG_SCENE_CONTAINER].
 *
 * Any [FlagsParameterization] which disables any flag that is a dependency of
 * [FLAG_SCENE_CONTAINER], will not add a state for enabling, and the state will simply be converted
 * to one which disables. Just like [EnableSceneContainer], enabling will also enable all the other
 * dependencies. For any flag parameterization where a dependency is disabled, an "enabled"
 * parameterization is inconsistent, so it will not be added.
 */
fun List<FlagsParameterization>.andSceneContainer(): List<FlagsParameterization> =
    flatMap { it.andSceneContainer() }.toList()