diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index deed6c8c7f257ac83dbe377f5038d64453ce8b46..90cc1fbb1fba193c87a85482764b457a411134f0 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -965,14 +965,6 @@ <!-- Whether to show bottom sheets edge to edge --> <bool name="config_edgeToEdgeBottomSheetDialog">true</bool> - <!-- - Whether the scene container framework is enabled. - - The scene container framework is a newer (2023) way to organize the various "scenes" between the - bouncer, lockscreen, shade, and quick settings. - --> - <bool name="config_sceneContainerFrameworkEnabled">true</bool> - <!-- Time in milliseconds the user has to touch the side FPS sensor to successfully authenticate TODO(b/302332976) Get this value from the HAL if they can provide an API for it. diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt index 5ec51f4c3dade25d788120391991e370f6231775..15404238099d9b54ced63f3b72a3b5d1a6a12148 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt @@ -25,7 +25,9 @@ import com.android.server.notification.Flags.vibrateWhileUnlocked import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR import com.android.systemui.Flags.keyguardBottomAreaRefactor import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.flags.Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl +import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor @@ -36,20 +38,28 @@ import javax.inject.Inject class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, handler: Handler) : FlagDependenciesBase(featureFlags, handler) { override fun defineDependencies() { + // Internal notification backend dependencies + crossAppPoliteNotifications dependsOn politeNotifications + vibrateWhileUnlockedToken dependsOn politeNotifications + + // Internal notification frontend dependencies NotificationsLiveDataStoreRefactor.token dependsOn NotificationIconContainerRefactor.token FooterViewRefactor.token dependsOn NotificationIconContainerRefactor.token - val keyguardBottomAreaRefactor = FlagToken( - FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, keyguardBottomAreaRefactor()) + // Internal keyguard dependencies KeyguardShadeMigrationNssl.token dependsOn keyguardBottomAreaRefactor - val crossAppPoliteNotifToken = - FlagToken(FLAG_CROSS_APP_POLITE_NOTIFICATIONS, crossAppPoliteNotifications()) - val politeNotifToken = FlagToken(FLAG_POLITE_NOTIFICATIONS, politeNotifications()) - crossAppPoliteNotifToken dependsOn politeNotifToken - - val vibrateWhileUnlockedToken = - FlagToken(FLAG_VIBRATE_WHILE_UNLOCKED, vibrateWhileUnlocked()) - vibrateWhileUnlockedToken dependsOn politeNotifToken + // SceneContainer dependencies + SceneContainerFlag.getFlagDependencies().forEach { (alpha, beta) -> alpha dependsOn beta } + SceneContainerFlag.getMainStaticFlag() dependsOn MIGRATE_KEYGUARD_STATUS_BAR_VIEW } + + private inline val politeNotifications + get() = FlagToken(FLAG_POLITE_NOTIFICATIONS, politeNotifications()) + private inline val crossAppPoliteNotifications + get() = FlagToken(FLAG_CROSS_APP_POLITE_NOTIFICATIONS, crossAppPoliteNotifications()) + private inline val vibrateWhileUnlockedToken: FlagToken + get() = FlagToken(FLAG_VIBRATE_WHILE_UNLOCKED, vibrateWhileUnlocked()) + private inline val keyguardBottomAreaRefactor + get() = FlagToken(FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, keyguardBottomAreaRefactor()) } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt index 898298c58b32a0401189cdbd5b1f5a0b66b206f1..77279f225d8387aa77d3272c20e10bb68a5a689b 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaInSceneContainerFlag.kt @@ -17,6 +17,7 @@ package com.android.systemui.media.controls.util import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the media_in_scene_container flag state. */ @@ -25,6 +26,10 @@ object MediaInSceneContainerFlag { /** The aconfig flag name */ const val FLAG_NAME = Flags.FLAG_MEDIA_IN_SCENE_CONTAINER + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + /** Is the flag enabled? */ @JvmStatic inline val isEnabled diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt index 1156250666f338a8359aeb5777222ccbdd9490db..8c3e4a5d0be215d35af1b389822db2bae30798a9 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt @@ -14,30 +14,94 @@ * limitations under the License. */ +@file:Suppress("NOTHING_TO_INLINE") + package com.android.systemui.scene.shared.flag -import android.content.Context -import androidx.annotation.VisibleForTesting -import com.android.systemui.Flags as AConfigFlags +import com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.Flags.keyguardBottomAreaRefactor import com.android.systemui.Flags.sceneContainer import com.android.systemui.compose.ComposeFacade import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.flags.FeatureFlagsClassic -import com.android.systemui.flags.Flag -import com.android.systemui.flags.Flags -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.ResourceBooleanFlag -import com.android.systemui.flags.UnreleasedFlag +import com.android.systemui.flags.FlagToken +import com.android.systemui.flags.Flags.SCENE_CONTAINER_ENABLED +import com.android.systemui.flags.RefactorFlagUtils import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl import com.android.systemui.media.controls.util.MediaInSceneContainerFlag -import com.android.systemui.res.R import dagger.Module import dagger.Provides -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject + +/** Helper for reading or using the scene container flag state. */ +object SceneContainerFlag { + /** The flag description -- not an aconfig flag name */ + const val DESCRIPTION = "SceneContainerFlag" + + inline val isEnabled + get() = + SCENE_CONTAINER_ENABLED && // mainStaticFlag + sceneContainer() && // mainAconfigFlag + keyguardBottomAreaRefactor() && + KeyguardShadeMigrationNssl.isEnabled && + MediaInSceneContainerFlag.isEnabled && + ComposeFacade.isComposeAvailable() + + /** + * The main static flag, SCENE_CONTAINER_ENABLED. This is an explicit static flag check that + * helps with downstream optimizations (like unused code stripping) in builds where aconfig + * flags are still writable. Do not remove! + */ + inline fun getMainStaticFlag() = + FlagToken("Flags.SCENE_CONTAINER_ENABLED", SCENE_CONTAINER_ENABLED) + + /** The main aconfig flag. */ + inline fun getMainAconfigFlag() = FlagToken(FLAG_SCENE_CONTAINER, sceneContainer()) + + /** The set of secondary flags which must be enabled for scene container to work properly */ + inline fun getSecondaryFlags(): Sequence<FlagToken> = + sequenceOf( + FlagToken(FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, keyguardBottomAreaRefactor()), + KeyguardShadeMigrationNssl.token, + MediaInSceneContainerFlag.token, + ) + + /** The full set of requirements for SceneContainer */ + inline fun getAllRequirements(): Sequence<FlagToken> { + val composeRequirement = + FlagToken("ComposeFacade.isComposeAvailable()", ComposeFacade.isComposeAvailable()) + return sequenceOf(getMainStaticFlag(), getMainAconfigFlag()) + + getSecondaryFlags() + + composeRequirement + } + + /** Return all dependencies of this flag in pairs where [Pair.first] depends on [Pair.second] */ + inline fun getFlagDependencies(): Sequence<Pair<FlagToken, FlagToken>> { + val mainStaticFlag = getMainStaticFlag() + val mainAconfigFlag = getMainAconfigFlag() + return sequence { + // The static and aconfig flags should be equal; make them co-dependent + yield(mainAconfigFlag to mainStaticFlag) + yield(mainStaticFlag to mainAconfigFlag) + // all other flags depend on the static flag for brevity + } + getSecondaryFlags().map { mainStaticFlag to it } + } + + /** + * Called to ensure code is only run when the flag is enabled. This protects users from the + * unintended behaviors caused by accidentally running new logic, while also crashing on an eng + * build to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun isUnexpectedlyInLegacyMode() = + RefactorFlagUtils.isUnexpectedlyInLegacyMode(isEnabled, DESCRIPTION) + + /** + * Called to ensure code is only run when the flag is disabled. This will throw an exception if + * the flag is enabled to ensure that the refactor author catches issues in testing. + */ + @JvmStatic + inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, DESCRIPTION) +} /** * Defines interface for classes that can check whether the scene container framework feature is @@ -52,133 +116,25 @@ interface SceneContainerFlags { fun requirementDescription(): String } -class SceneContainerFlagsImpl -@AssistedInject -constructor( - @Application private val context: Context, - private val featureFlagsClassic: FeatureFlagsClassic, - @Assisted private val isComposeAvailable: Boolean, -) : SceneContainerFlags { - - companion object { - @VisibleForTesting - val classicFlagTokens: List<Flag<Boolean>> = - listOf( - Flags.MIGRATE_KEYGUARD_STATUS_BAR_VIEW, - ) - } - - /** The list of requirements, all must be met for the feature to be enabled. */ - private val requirements = - listOf( - AconfigFlagMustBeEnabled( - flagName = AConfigFlags.FLAG_SCENE_CONTAINER, - flagValue = sceneContainer(), - ), - AconfigFlagMustBeEnabled( - flagName = AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, - flagValue = keyguardBottomAreaRefactor(), - ), - AconfigFlagMustBeEnabled( - flagName = KeyguardShadeMigrationNssl.FLAG_NAME, - flagValue = KeyguardShadeMigrationNssl.isEnabled, - ), - AconfigFlagMustBeEnabled( - flagName = MediaInSceneContainerFlag.FLAG_NAME, - flagValue = MediaInSceneContainerFlag.isEnabled, - ), - ) + - classicFlagTokens.map { flagToken -> FlagMustBeEnabled(flagToken) } + - listOf( - ComposeMustBeAvailable(), - CompileTimeFlagMustBeEnabled(), - ResourceConfigMustBeEnabled() - ) +class SceneContainerFlagsImpl : SceneContainerFlags { override fun isEnabled(): Boolean { - // SCENE_CONTAINER_ENABLED is an explicit static flag check that helps with downstream - // optimizations, e.g., unused code stripping. Do not remove! - return Flags.SCENE_CONTAINER_ENABLED && requirements.all { it.isMet() } + return SceneContainerFlag.isEnabled } override fun requirementDescription(): String { return buildString { - requirements.forEach { requirement -> + SceneContainerFlag.getAllRequirements().forEach { requirement -> append('\n') - append(if (requirement.isMet()) " [MET]" else "[NOT MET]") + append(if (requirement.isEnabled) " [MET]" else "[NOT MET]") append(" ${requirement.name}") } } } - - private interface Requirement { - val name: String - - fun isMet(): Boolean - } - - private inner class ComposeMustBeAvailable : Requirement { - override val name = "Jetpack Compose must be available" - - override fun isMet(): Boolean { - return isComposeAvailable - } - } - - private inner class CompileTimeFlagMustBeEnabled : Requirement { - override val name = "Flags.SCENE_CONTAINER_ENABLED must be enabled in code" - - override fun isMet(): Boolean { - return Flags.SCENE_CONTAINER_ENABLED - } - } - - private inner class FlagMustBeEnabled<FlagType : Flag<*>>( - private val flag: FlagType, - ) : Requirement { - override val name = "Flag ${flag.name} must be enabled" - - override fun isMet(): Boolean { - return when (flag) { - is ResourceBooleanFlag -> featureFlagsClassic.isEnabled(flag) - is ReleasedFlag -> featureFlagsClassic.isEnabled(flag) - is UnreleasedFlag -> featureFlagsClassic.isEnabled(flag) - else -> error("Unsupported flag type ${flag.javaClass}") - } - } - } - - private inner class AconfigFlagMustBeEnabled( - flagName: String, - private val flagValue: Boolean, - ) : Requirement { - override val name: String = "Aconfig flag $flagName must be enabled" - - override fun isMet(): Boolean { - return flagValue - } - } - - private inner class ResourceConfigMustBeEnabled : Requirement { - override val name: String = "R.bool.config_sceneContainerFrameworkEnabled must be true" - - override fun isMet(): Boolean { - return context.resources.getBoolean(R.bool.config_sceneContainerFrameworkEnabled) - } - } - - @AssistedFactory - interface Factory { - fun create(isComposeAvailable: Boolean): SceneContainerFlagsImpl - } } @Module object SceneContainerFlagsModule { - @Provides - @SysUISingleton - fun impl(factory: SceneContainerFlagsImpl.Factory): SceneContainerFlags { - return factory.create(ComposeFacade.isComposeAvailable()) - } + @Provides @SysUISingleton fun impl(): SceneContainerFlags = SceneContainerFlagsImpl() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionRefactor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionRefactor.kt index 2624363c7decf0e285f8f622f60b36b8e431f821..db33f92c184893e490bd55c2bcda0d1ddd3f2236 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionRefactor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionRefactor.kt @@ -17,12 +17,17 @@ package com.android.systemui.statusbar.notification.interruption import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the visual interruptions refactor flag state. */ object VisualInterruptionRefactor { const val FLAG_NAME = Flags.FLAG_VISUAL_INTERRUPTIONS_REFACTOR + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + /** Whether the refactor is enabled */ @JvmStatic inline val isEnabled diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/AsyncHybridViewInflation.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/AsyncHybridViewInflation.kt index 24e7f05a9c1d3a5e0748b7f71b74a94b04c4e229..9556c2e3159cc124a3804932ca02d5404b7d45f6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/AsyncHybridViewInflation.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/shared/AsyncHybridViewInflation.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.row.shared import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the async hybrid view inflation flag state. */ @@ -24,6 +25,10 @@ import com.android.systemui.flags.RefactorFlagUtils object AsyncHybridViewInflation { const val FLAG_NAME = Flags.FLAG_NOTIFICATION_ASYNC_HYBRID_VIEW_INFLATION + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + /** Is async hybrid (single-line) view inflation enabled */ @JvmStatic inline val isEnabled diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/DisplaySwitchNotificationsHiderFlag.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/DisplaySwitchNotificationsHiderFlag.kt index 98c1734021091b5fb37c0e20483497a6b22a2694..3cd9a8f598a44ae6a776556b3a65bf9bbcce99ca 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/DisplaySwitchNotificationsHiderFlag.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/shared/DisplaySwitchNotificationsHiderFlag.kt @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.stack.shared import com.android.systemui.Flags +import com.android.systemui.flags.FlagToken import com.android.systemui.flags.RefactorFlagUtils /** Helper for reading or using the DisplaySwitchNotificationsHider flag state. */ @@ -24,6 +25,10 @@ import com.android.systemui.flags.RefactorFlagUtils object DisplaySwitchNotificationsHiderFlag { const val FLAG_NAME = Flags.FLAG_NOTIFICATIONS_HIDE_ON_DISPLAY_SWITCH + /** A token used for dependency declaration */ + val token: FlagToken + get() = FlagToken(FLAG_NAME, isEnabled) + /** Is the hiding enabled? */ @JvmStatic inline val isEnabled diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt index b90ccc0e3d7e0acfbf2fa4004be865d049f02d8c..994166172aff1d2911d9c792417dfe479179653e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 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. @@ -16,35 +16,23 @@ package com.android.systemui.scene.shared.flag -import android.platform.test.flag.junit.SetFlagsRule +import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest -import com.android.systemui.FakeFeatureFlagsImpl -import com.android.systemui.Flags as AconfigFlags import com.android.systemui.SysuiTestCase -import com.android.systemui.flags.FakeFeatureFlagsClassic +import com.android.systemui.compose.ComposeFacade import com.android.systemui.flags.Flags -import com.android.systemui.flags.ReleasedFlag -import com.android.systemui.flags.ResourceBooleanFlag -import com.android.systemui.flags.UnreleasedFlag +import com.android.systemui.flags.setFlagValue import com.android.systemui.keyguard.shared.KeyguardShadeMigrationNssl import com.android.systemui.media.controls.util.MediaInSceneContainerFlag -import com.android.systemui.res.R -import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth +import org.junit.Assume import org.junit.Before -import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import org.junit.runners.Parameterized @SmallTest -@RunWith(Parameterized::class) -internal class SceneContainerFlagsTest( - private val testCase: TestCase, -) : SysuiTestCase() { - - @Rule @JvmField val setFlagsRule: SetFlagsRule = SetFlagsRule() - - private lateinit var underTest: SceneContainerFlags +@RunWith(AndroidJUnit4::class) +internal class SceneContainerFlagsTest : SysuiTestCase() { @Before fun setUp() { @@ -52,83 +40,39 @@ internal class SceneContainerFlagsTest( // Flags.SCENE_CONTAINER_ENABLED is no longer needed. val field = Flags::class.java.getField("SCENE_CONTAINER_ENABLED") field.isAccessible = true - field.set(null, true) - - val featureFlags = - FakeFeatureFlagsClassic().apply { - SceneContainerFlagsImpl.classicFlagTokens.forEach { flagToken -> - when (flagToken) { - is ResourceBooleanFlag -> set(flagToken, testCase.areAllFlagsSet) - is ReleasedFlag -> set(flagToken, testCase.areAllFlagsSet) - is UnreleasedFlag -> set(flagToken, testCase.areAllFlagsSet) - else -> error("Unsupported flag type ${flagToken.javaClass}") - } - } - } - // TODO(b/306421592): get the aconfig FeatureFlags from the SetFlagsRule. - val aconfigFlags = FakeFeatureFlagsImpl() + field.set(null, true) // note: this does not work with multivalent tests + } + private fun setAconfigFlagsEnabled(enabled: Boolean) { listOf( - AconfigFlags.FLAG_SCENE_CONTAINER, - AconfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, + com.android.systemui.Flags.FLAG_SCENE_CONTAINER, + com.android.systemui.Flags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR, KeyguardShadeMigrationNssl.FLAG_NAME, MediaInSceneContainerFlag.FLAG_NAME, ) - .forEach { flagToken -> - setFlagsRule.enableFlags(flagToken) - aconfigFlags.setFlag(flagToken, testCase.areAllFlagsSet) - overrideResource( - R.bool.config_sceneContainerFrameworkEnabled, - testCase.isResourceConfigEnabled - ) - } - - underTest = - SceneContainerFlagsImpl( - context = context, - featureFlagsClassic = featureFlags, - isComposeAvailable = testCase.isComposeAvailable, - ) + .forEach { flagName -> mSetFlagsRule.setFlagValue(flagName, enabled) } } @Test - fun isEnabled() { - assertThat(underTest.isEnabled()).isEqualTo(testCase.expectedEnabled) + fun isNotEnabled_withoutAconfigFlags() { + setAconfigFlagsEnabled(false) + Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(false) + Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(false) } - internal data class TestCase( - val isComposeAvailable: Boolean, - val areAllFlagsSet: Boolean, - val isResourceConfigEnabled: Boolean, - val expectedEnabled: Boolean, - ) { - override fun toString(): String { - return "(compose=$isComposeAvailable + flags=$areAllFlagsSet) + XML" + - " config=$isResourceConfigEnabled -> expected=$expectedEnabled" - } + @Test + fun isEnabled_withAconfigFlags_withCompose() { + Assume.assumeTrue(ComposeFacade.isComposeAvailable()) + setAconfigFlagsEnabled(true) + Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(true) + Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(true) } - companion object { - @Parameterized.Parameters(name = "{0}") - @JvmStatic - fun testCases() = buildList { - repeat(8) { combination -> - val isComposeAvailable = combination and 0b100 != 0 - val areAllFlagsSet = combination and 0b010 != 0 - val isResourceConfigEnabled = combination and 0b001 != 0 - - val expectedEnabled = - isComposeAvailable && areAllFlagsSet && isResourceConfigEnabled - - add( - TestCase( - isComposeAvailable = isComposeAvailable, - areAllFlagsSet = areAllFlagsSet, - expectedEnabled = expectedEnabled, - isResourceConfigEnabled = isResourceConfigEnabled, - ) - ) - } - } + @Test + fun isNotEnabled_withAconfigFlags_withoutCompose() { + Assume.assumeFalse(ComposeFacade.isComposeAvailable()) + setAconfigFlagsEnabled(true) + Truth.assertThat(SceneContainerFlag.isEnabled).isEqualTo(false) + Truth.assertThat(SceneContainerFlagsImpl().isEnabled()).isEqualTo(false) } }