diff options
30 files changed, 446 insertions, 165 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index d90785dd266d..4d906c474970 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -83,6 +83,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.shared.system.SysUiStatsLog; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; @@ -123,6 +124,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard private final UserSwitcherController mUserSwitcherController; private final GlobalSettings mGlobalSettings; private final FeatureFlags mFeatureFlags; + private final SceneContainerFlags mSceneContainerFlags; private final SessionTracker mSessionTracker; private final Optional<SideFpsController> mSideFpsController; private final FalsingA11yDelegate mFalsingA11yDelegate; @@ -433,6 +435,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard FalsingManager falsingManager, UserSwitcherController userSwitcherController, FeatureFlags featureFlags, + SceneContainerFlags sceneContainerFlags, GlobalSettings globalSettings, SessionTracker sessionTracker, Optional<SideFpsController> sideFpsController, @@ -466,6 +469,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard mFalsingManager = falsingManager; mUserSwitcherController = userSwitcherController; mFeatureFlags = featureFlags; + mSceneContainerFlags = sceneContainerFlags; mGlobalSettings = globalSettings; mSessionTracker = sessionTracker; mSideFpsController = sideFpsController; @@ -503,7 +507,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard showPrimarySecurityScreen(false); - if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (mSceneContainerFlags.isEnabled()) { // When the scene framework says that the lockscreen has been dismissed, dismiss the // keyguard here, revealing the underlying app or launcher: mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow( diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt index fc32f4c138d7..9527f327a837 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt @@ -26,9 +26,8 @@ import com.android.systemui.classifier.FalsingClassifier import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.flags.Flags import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel import com.android.systemui.util.kotlin.pairwise @@ -51,7 +50,7 @@ constructor( private val repository: BouncerRepository, private val authenticationInteractor: AuthenticationInteractor, private val sceneInteractor: SceneInteractor, - featureFlags: FeatureFlags, + flags: SceneContainerFlags, private val falsingInteractor: FalsingInteractor, ) { @@ -94,7 +93,7 @@ constructor( val isPatternVisible: StateFlow<Boolean> = authenticationInteractor.isPatternVisible init { - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (flags.isEnabled()) { // Clear the message if moved from throttling to no-longer throttling. applicationScope.launch { isThrottled.pairwise().collect { (wasThrottled, currentlyThrottled) -> diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt index 5b1998d1e5f6..f6794d4f40b3 100644 --- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt @@ -23,8 +23,7 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode import com.android.systemui.bouncer.domain.interactor.BouncerInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.flags.Flags +import com.android.systemui.scene.shared.flag.SceneContainerFlags import javax.inject.Inject import kotlin.math.ceil import kotlinx.coroutines.CoroutineScope @@ -47,7 +46,7 @@ constructor( @Application private val applicationScope: CoroutineScope, private val bouncerInteractor: BouncerInteractor, private val authenticationInteractor: AuthenticationInteractor, - featureFlags: FeatureFlags, + flags: SceneContainerFlags, ) { private val isInputEnabled: StateFlow<Boolean> = bouncerInteractor.isThrottled @@ -102,7 +101,7 @@ constructor( ) init { - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (flags.isEnabled()) { applicationScope.launch { bouncerInteractor.isThrottled .map { isThrottled -> diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java index 3195d093a711..0a1aed65c205 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingModule.java @@ -22,8 +22,7 @@ import android.view.ViewConfiguration; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.flags.FeatureFlagsClassic; -import com.android.systemui.flags.Flags; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.statusbar.phone.NotificationTapHelper; import dagger.Binds; @@ -53,8 +52,8 @@ public interface FalsingModule { static FalsingCollector providesFalsingCollectorLegacy( FalsingCollectorImpl impl, FalsingCollectorNoOp noOp, - FeatureFlagsClassic featureFlags) { - return featureFlags.isEnabled(Flags.SCENE_CONTAINER) ? noOp : impl; + SceneContainerFlags flags) { + return flags.isEnabled() ? noOp : impl; } /** Provides the actual {@link FalsingCollector}. */ diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index ea2568ddba8d..0d375b45ef2f 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -643,6 +643,18 @@ object Flags { */ // TODO(b/283300105): Tracking Bug @JvmField val SCENE_CONTAINER_ENABLED = false + @Deprecated( + message = """ + Do not use this flag directly. Please use + [com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled]. + + (Not really deprecated but using this as a simple way to bring attention to the above). + """, + replaceWith = ReplaceWith( + "com.android.systemui.scene.shared.flag.SceneContainerFlags#isEnabled", + ), + level = DeprecationLevel.WARNING, + ) @JvmField val SCENE_CONTAINER = unreleasedFlag("scene_container") // 1900 diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index e374549b9101..572785721b4f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -45,6 +45,7 @@ import com.android.systemui.keyguard.shared.model.ScreenModel import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.statusbar.CommandQueue @@ -77,6 +78,7 @@ constructor( private val repository: KeyguardRepository, private val commandQueue: CommandQueue, featureFlags: FeatureFlags, + sceneContainerFlags: SceneContainerFlags, bouncerRepository: KeyguardBouncerRepository, configurationRepository: ConfigurationRepository, shadeRepository: ShadeRepository, @@ -249,7 +251,7 @@ constructor( /** Whether to animate the next doze mode transition. */ val animateDozingTransitions: Flow<Boolean> by lazy { - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (sceneContainerFlags.isEnabled()) { sceneInteractorProvider .get() .transitioningTo diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 3a64a6a989f2..d23bedace06f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -85,7 +85,6 @@ import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.model.SysUiState; @@ -96,6 +95,7 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.navigationbar.buttons.KeyButtonView; import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.settings.DisplayTracker; import com.android.systemui.settings.UserTracker; import com.android.systemui.shade.ShadeViewController; @@ -143,6 +143,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis private final Context mContext; private final FeatureFlags mFeatureFlags; + private final SceneContainerFlags mSceneContainerFlags; private final Executor mMainExecutor; private final ShellInterface mShellInterface; private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; @@ -218,7 +219,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis // If scene framework is enabled, set the scene container window to // visible and let the touch "slip" into that window. - if (mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (mSceneContainerFlags.isEnabled()) { mSceneInteractor.get().setVisible(true, "swipe down on launcher"); } else { centralSurfaces.onInputFocusTransfer( @@ -229,7 +230,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis if (action == ACTION_UP || action == ACTION_CANCEL) { mInputFocusTransferStarted = false; - if (!mFeatureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (!mSceneContainerFlags.isEnabled()) { float velocity = (event.getY() - mInputFocusTransferStartY) / (event.getEventTime() - mInputFocusTransferStartMillis); centralSurfaces.onInputFocusTransfer(mInputFocusTransferStarted, @@ -582,6 +583,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis KeyguardUnlockAnimationController sysuiUnlockAnimationController, AssistUtils assistUtils, FeatureFlags featureFlags, + SceneContainerFlags sceneContainerFlags, DumpManager dumpManager, Optional<UnfoldTransitionProgressForwarder> unfoldTransitionProgressForwarder ) { @@ -592,6 +594,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis mContext = context; mFeatureFlags = featureFlags; + mSceneContainerFlags = sceneContainerFlags; mMainExecutor = mainExecutor; mShellInterface = shellInterface; mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy; diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt index c5fbf7b96fff..fcbe9a6675ab 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt @@ -16,6 +16,7 @@ package com.android.systemui.scene +import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneKey import dagger.Module @@ -28,6 +29,7 @@ import dagger.Provides EmptySceneModule::class, GoneSceneModule::class, QuickSettingsSceneModule::class, + SceneContainerFlagsModule::class, ShadeSceneModule::class, ], ) diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt index 85ef21aa9542..b36ec3274083 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt @@ -19,6 +19,7 @@ package com.android.systemui.scene import com.android.systemui.CoreStartable import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor import com.android.systemui.scene.domain.startable.SceneContainerStartable +import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneKey import dagger.Binds @@ -36,6 +37,7 @@ import dagger.multibindings.IntoMap GoneSceneModule::class, LockscreenSceneModule::class, QuickSettingsSceneModule::class, + SceneContainerFlagsModule::class, ShadeSceneModule::class, ], ) diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt index 5fda9b1a323b..c10e51b68ba2 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt @@ -16,6 +16,7 @@ package com.android.systemui.scene +import com.android.systemui.scene.shared.flag.SceneContainerFlagsModule import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneKey import dagger.Module @@ -29,6 +30,7 @@ import dagger.Provides EmptySceneModule::class, GoneSceneModule::class, LockscreenSceneModule::class, + SceneContainerFlagsModule::class, ], ) object ShadelessSceneContainerFrameworkModule { diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt index 7f77acc1789a..722d3661d0ae 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt @@ -26,13 +26,12 @@ import com.android.systemui.classifier.FalsingCollectorActual import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.DisplayId -import com.android.systemui.flags.FeatureFlags -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.model.SysUiState import com.android.systemui.model.updateFlags import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.logger.SceneLogger import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey @@ -66,7 +65,7 @@ constructor( private val sceneInteractor: SceneInteractor, private val authenticationInteractor: AuthenticationInteractor, private val keyguardInteractor: KeyguardInteractor, - private val featureFlags: FeatureFlags, + private val flags: SceneContainerFlags, private val sysUiState: SysUiState, @DisplayId private val displayId: Int, private val sceneLogger: SceneLogger, @@ -74,14 +73,17 @@ constructor( ) : CoreStartable { override fun start() { - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (flags.isEnabled()) { sceneLogger.logFrameworkEnabled(isEnabled = true) hydrateVisibility() automaticallySwitchScenes() hydrateSystemUiState() collectFalsingSignals() } else { - sceneLogger.logFrameworkEnabled(isEnabled = false) + sceneLogger.logFrameworkEnabled( + isEnabled = false, + reason = flags.requirementDescription(), + ) } } 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 new file mode 100644 index 000000000000..83fb723eda82 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/flag/SceneContainerFlags.kt @@ -0,0 +1,136 @@ +/* + * Copyright 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. + * 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 androidx.annotation.VisibleForTesting +import com.android.systemui.compose.ComposeFacade +import com.android.systemui.dagger.SysUISingleton +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 dagger.Module +import dagger.Provides +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject + +/** + * Defines interface for classes that can check whether the scene container framework feature is + * enabled. + */ +interface SceneContainerFlags { + + /** Returns `true` if the Scene Container Framework is enabled; `false` otherwise. */ + fun isEnabled(): Boolean + + /** Returns a developer-readable string that describes the current requirement list. */ + fun requirementDescription(): String +} + +class SceneContainerFlagsImpl +@AssistedInject +constructor( + private val featureFlags: FeatureFlagsClassic, + @Assisted private val isComposeAvailable: Boolean, +) : SceneContainerFlags { + + companion object { + @VisibleForTesting + val flags: List<Flag<Boolean>> = + listOf( + Flags.SCENE_CONTAINER, + Flags.MIGRATE_SPLIT_KEYGUARD_BOTTOM_AREA, + Flags.MIGRATE_LOCK_ICON, + Flags.MIGRATE_NSSL, + Flags.MIGRATE_KEYGUARD_STATUS_VIEW, + ) + } + + /** The list of requirements, all must be met for the feature to be enabled. */ + private val requirements = + flags.map { FlagMustBeEnabled(it) } + + listOf(ComposeMustBeAvailable(), CompileTimeFlagMustBeEnabled()) + + override fun isEnabled(): Boolean { + return requirements.all { it.isMet() } + } + + override fun requirementDescription(): String { + return buildString { + requirements.forEach { requirement -> + append('\n') + append(if (requirement.isMet()) " [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 -> featureFlags.isEnabled(flag) + is ReleasedFlag -> featureFlags.isEnabled(flag) + is UnreleasedFlag -> featureFlags.isEnabled(flag) + else -> error("Unsupported flag type ${flag.javaClass}") + } + } + } + + @AssistedFactory + interface Factory { + fun create(isComposeAvailable: Boolean): SceneContainerFlagsImpl + } +} + +@Module +object SceneContainerFlagsModule { + + @Provides + @SysUISingleton + fun impl(factory: SceneContainerFlagsImpl.Factory): SceneContainerFlags { + return factory.create(ComposeFacade.isComposeAvailable()) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt index 62136dcd8e1d..c2c2e04990c2 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/logger/SceneLogger.kt @@ -24,16 +24,21 @@ import javax.inject.Inject class SceneLogger @Inject constructor(@SceneFrameworkLog private val logBuffer: LogBuffer) { - fun logFrameworkEnabled(isEnabled: Boolean) { + fun logFrameworkEnabled(isEnabled: Boolean, reason: String? = null) { fun asWord(isEnabled: Boolean): String { return if (isEnabled) "enabled" else "disabled" } logBuffer.log( tag = TAG, - level = LogLevel.INFO, - messageInitializer = { bool1 = isEnabled }, - messagePrinter = { "Scene framework is ${asWord(bool1)}" } + level = if (isEnabled) LogLevel.INFO else LogLevel.WARNING, + messageInitializer = { + bool1 = isEnabled + str1 = reason + }, + messagePrinter = { + "Scene framework is ${asWord(bool1)}${if (str1 != null) " $str1" else ""}" + } ) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt index ed719a651978..3f7512a25732 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt @@ -26,13 +26,13 @@ import com.android.systemui.R import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController import com.android.systemui.biometrics.AuthRippleView -import com.android.systemui.compose.ComposeFacade import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.ui.view.KeyguardRootView import com.android.systemui.privacy.OngoingPrivacyChip +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.shared.model.Scene import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.ui.view.SceneWindowRootView @@ -70,17 +70,13 @@ abstract class ShadeViewProviderModule { @SysUISingleton fun providesWindowRootView( layoutInflater: LayoutInflater, - featureFlags: FeatureFlags, + sceneContainerFlags: SceneContainerFlags, viewModelProvider: Provider<SceneContainerViewModel>, containerConfigProvider: Provider<SceneContainerConfig>, scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>, layoutInsetController: NotificationInsetsController, ): WindowRootView { - return if ( - Flags.SCENE_CONTAINER_ENABLED && - featureFlags.isEnabled(Flags.SCENE_CONTAINER) && - ComposeFacade.isComposeAvailable() - ) { + return if (sceneContainerFlags.isEnabled()) { val sceneWindowRootView = layoutInflater.inflate(R.layout.scene_window_root, null) as SceneWindowRootView sceneWindowRootView.init( @@ -104,9 +100,9 @@ abstract class ShadeViewProviderModule { @SysUISingleton fun providesNotificationShadeWindowView( root: WindowRootView, - featureFlags: FeatureFlags, + sceneContainerFlags: SceneContainerFlags, ): NotificationShadeWindowView { - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (sceneContainerFlags.isEnabled()) { return root.requireViewById(R.id.legacy_window_root) } return root as NotificationShadeWindowView? diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt index cc41bf843565..23b0ee0ec9bc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt @@ -27,6 +27,7 @@ import com.android.systemui.Gefingerpoken import com.android.systemui.R import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.ShadeController import com.android.systemui.shade.ShadeLogger @@ -48,8 +49,9 @@ import javax.inject.Provider private const val TAG = "PhoneStatusBarViewController" -/** Controller for [PhoneStatusBarView]. */ -class PhoneStatusBarViewController private constructor( +/** Controller for [PhoneStatusBarView]. */ +class PhoneStatusBarViewController +private constructor( view: PhoneStatusBarView, @Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?, private val centralSurfaces: CentralSurfaces, @@ -61,42 +63,42 @@ class PhoneStatusBarViewController private constructor( private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?, private val userChipViewModel: StatusBarUserChipViewModel, private val viewUtil: ViewUtil, - private val featureFlags: FeatureFlags, + private val sceneContainerFlags: SceneContainerFlags, private val configurationController: ConfigurationController, private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory, ) : ViewController<PhoneStatusBarView>(view) { private lateinit var statusContainer: View - private val configurationListener = object : ConfigurationController.ConfigurationListener { - override fun onConfigChanged(newConfig: Configuration?) { - mView.updateResources() + private val configurationListener = + object : ConfigurationController.ConfigurationListener { + override fun onConfigChanged(newConfig: Configuration?) { + mView.updateResources() + } } - } override fun onViewAttached() { statusContainer = mView.requireViewById(R.id.system_icons) statusContainer.setOnHoverListener( - statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer)) + statusOverlayHoverListenerFactory.createDarkAwareListener(statusContainer) + ) if (moveFromCenterAnimationController == null) return val statusBarLeftSide: View = - mView.requireViewById(R.id.status_bar_start_side_except_heads_up) + mView.requireViewById(R.id.status_bar_start_side_except_heads_up) val systemIconArea: ViewGroup = mView.requireViewById(R.id.status_bar_end_side_content) - val viewsToAnimate = arrayOf( - statusBarLeftSide, - systemIconArea - ) + val viewsToAnimate = arrayOf(statusBarLeftSide, systemIconArea) - mView.viewTreeObserver.addOnPreDrawListener(object : - ViewTreeObserver.OnPreDrawListener { - override fun onPreDraw(): Boolean { - moveFromCenterAnimationController.onViewsReady(viewsToAnimate) - mView.viewTreeObserver.removeOnPreDrawListener(this) - return true + mView.viewTreeObserver.addOnPreDrawListener( + object : ViewTreeObserver.OnPreDrawListener { + override fun onPreDraw(): Boolean { + moveFromCenterAnimationController.onViewsReady(viewsToAnimate) + mView.viewTreeObserver.removeOnPreDrawListener(this) + return true + } } - }) + ) mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ -> val widthChanged = right - left != oldRight - oldLeft @@ -121,8 +123,7 @@ class PhoneStatusBarViewController private constructor( mView.init(userChipViewModel) } - override fun onInit() { - } + override fun onInit() {} fun setImportantForAccessibility(mode: Int) { mView.importantForAccessibility = mode @@ -151,10 +152,11 @@ class PhoneStatusBarViewController private constructor( fun onTouch(event: MotionEvent) { if (statusBarWindowStateController.windowIsShowing()) { val upOrCancel = - event.action == MotionEvent.ACTION_UP || - event.action == MotionEvent.ACTION_CANCEL - centralSurfaces.setInteracting(WINDOW_STATUS_BAR, - !upOrCancel || shadeController.isExpandedVisible) + event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL + centralSurfaces.setInteracting( + WINDOW_STATUS_BAR, + !upOrCancel || shadeController.isExpandedVisible + ) } } @@ -171,15 +173,20 @@ class PhoneStatusBarViewController private constructor( // panel view. if (!centralSurfaces.commandQueuePanelsEnabled) { if (event.action == MotionEvent.ACTION_DOWN) { - Log.v(TAG, String.format("onTouchForwardedFromStatusBar: panel disabled, " + - "ignoring touch at (${event.x.toInt()},${event.y.toInt()})")) + Log.v( + TAG, + String.format( + "onTouchForwardedFromStatusBar: panel disabled, " + + "ignoring touch at (${event.x.toInt()},${event.y.toInt()})" + ) + ) } return false } // If scene framework is enabled, route the touch to it and // ignore the rest of the gesture. - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (sceneContainerFlags.isEnabled()) { windowRootView.get().dispatchTouchEvent(event) return true } @@ -188,12 +195,13 @@ class PhoneStatusBarViewController private constructor( // If the view that would receive the touch is disabled, just have status // bar eat the gesture. if (!shadeViewController.isViewEnabled) { - shadeLogger.logMotionEvent(event, - "onTouchForwardedFromStatusBar: panel view disabled") + shadeLogger.logMotionEvent( + event, + "onTouchForwardedFromStatusBar: panel view disabled" + ) return true } - if (shadeViewController.isFullyCollapsed && - event.y < 1f) { + if (shadeViewController.isFullyCollapsed && event.y < 1f) { // b/235889526 Eat events on the top edge of the phone when collapsed shadeLogger.logMotionEvent(event, "top edge touch ignored") return true @@ -218,9 +226,7 @@ class PhoneStatusBarViewController private constructor( else -> super.getViewCenter(view, outPoint) } - /** - * Returns start or end (based on [isStart]) center point of the view - */ + /** Returns start or end (based on [isStart]) center point of the view */ private fun getViewEdgeCenter(view: View, outPoint: Point, isStart: Boolean) { val isRtl = view.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL val isLeftEdge = isRtl xor isStart @@ -236,11 +242,14 @@ class PhoneStatusBarViewController private constructor( } } - class Factory @Inject constructor( + class Factory + @Inject + constructor( private val unfoldComponent: Optional<SysUIUnfoldComponent>, @Named(UNFOLD_STATUS_BAR) private val progressProvider: Optional<ScopedUnfoldTransitionProgressProvider>, private val featureFlags: FeatureFlags, + private val sceneContainerFlags: SceneContainerFlags, private val userChipViewModel: StatusBarUserChipViewModel, private val centralSurfaces: CentralSurfaces, private val statusBarWindowStateController: StatusBarWindowStateController, @@ -252,9 +261,7 @@ class PhoneStatusBarViewController private constructor( private val configurationController: ConfigurationController, private val statusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory, ) { - fun create( - view: PhoneStatusBarView - ): PhoneStatusBarViewController { + fun create(view: PhoneStatusBarView): PhoneStatusBarViewController { val statusBarMoveFromCenterAnimationController = if (featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) { unfoldComponent.getOrNull()?.getStatusBarMoveFromCenterAnimationController() @@ -274,10 +281,10 @@ class PhoneStatusBarViewController private constructor( statusBarMoveFromCenterAnimationController, userChipViewModel, viewUtil, - featureFlags, + sceneContainerFlags, configurationController, statusOverlayHoverListenerFactory, ) } } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index fa9b9d2c571a..5773612d55c7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -34,9 +34,8 @@ import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.ScreenDecorations; import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.scene.domain.interactor.SceneInteractor; +import com.android.systemui.scene.shared.flag.SceneContainerFlags; import com.android.systemui.shade.ShadeExpansionStateManager; import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.policy.ConfigurationController; @@ -85,7 +84,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { ShadeExpansionStateManager shadeExpansionStateManager, Provider<SceneInteractor> sceneInteractor, Provider<JavaAdapter> javaAdapter, - FeatureFlags featureFlags, + SceneContainerFlags sceneContainerFlags, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController ) { mContext = context; @@ -123,7 +122,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; shadeExpansionStateManager.addFullExpansionListener(this::onShadeExpansionFullyChanged); - if (featureFlags.isEnabled(Flags.SCENE_CONTAINER)) { + if (sceneContainerFlags.isEnabled()) { javaAdapter.get().alwaysCollectFlow( sceneInteractor.get().isVisible(), this::onShadeExpansionFullyChanged); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt index 6bff4ce4aad9..02b9bf06fc2a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt @@ -191,7 +191,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { featureFlags = FakeFeatureFlags() featureFlags.set(Flags.REVAMPED_BOUNCER_MESSAGES, true) - featureFlags.set(Flags.SCENE_CONTAINER, false) featureFlags.set(Flags.BOUNCER_USER_SWITCHER, false) featureFlags.set(Flags.KEYGUARD_WM_STATE_REFACTOR, false) @@ -244,6 +243,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { falsingManager, userSwitcherController, featureFlags, + sceneTestUtils.sceneContainerFlags, globalSettings, sessionTracker, Optional.of(sideFpsController), @@ -802,8 +802,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() { @Test fun dismissesKeyguard_whenSceneChangesToGone() = sceneTestUtils.testScope.runTest { - featureFlags.set(Flags.SCENE_CONTAINER, true) - // Upon init, we have never dismisses the keyguard. underTest.onInit() runCurrent() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt index e2362f64b885..f62137c62c65 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/CustomizationProviderTest.kt @@ -175,7 +175,6 @@ class CustomizationProviderTest : SysuiTestCase() { set(Flags.REVAMPED_WALLPAPER_UI, true) set(Flags.WALLPAPER_FULLSCREEN_PREVIEW, true) set(Flags.FACE_AUTH_REFACTOR, true) - set(Flags.SCENE_CONTAINER, false) } underTest.interactor = KeyguardQuickAffordanceInteractor( diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index ce280d7b221b..14cdf2f58a7d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -29,7 +29,6 @@ import com.android.systemui.common.ui.data.repository.FakeConfigurationRepositor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.FakeFeatureFlags import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR -import com.android.systemui.flags.Flags.SCENE_CONTAINER import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel @@ -70,11 +69,7 @@ class KeyguardInteractorTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - featureFlags = - FakeFeatureFlags().apply { - set(FACE_AUTH_REFACTOR, true) - set(SCENE_CONTAINER, true) - } + featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) } commandQueue = FakeCommandQueue() val sceneTestUtils = SceneTestUtils(this) testScope = sceneTestUtils.testScope @@ -90,6 +85,7 @@ class KeyguardInteractorTest : SysuiTestCase() { repository = repository, commandQueue = commandQueue, featureFlags = featureFlags, + sceneContainerFlags = sceneTestUtils.sceneContainerFlags, bouncerRepository = bouncerRepository, configurationRepository = configurationRepository, shadeRepository = shadeRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt index 499a6362ce05..bdcb9abba745 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/OccludingAppDeviceEntryInteractorTest.kt @@ -104,7 +104,6 @@ class OccludingAppDeviceEntryInteractorTest : SysuiTestCase() { FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, false) set(Flags.DELAY_BOUNCER, false) - set(Flags.SCENE_CONTAINER, false) } trustRepository = FakeTrustRepository() powerRepository = FakePowerRepository() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt index 7fecfc234392..b935e1d3c65a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardQuickAffordancesCombinedViewModelTest.kt @@ -129,7 +129,6 @@ class KeyguardQuickAffordancesCombinedViewModelTest : SysuiTestCase() { set(Flags.FACE_AUTH_REFACTOR, true) set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, false) set(Flags.LOCK_SCREEN_LONG_PRESS_DIRECT_TO_WPP, false) - set(Flags.SCENE_CONTAINER, false) } val withDeps = KeyguardInteractorFactory.create(featureFlags = featureFlags) diff --git a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt index ef07fab70bb0..e353a53af752 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt @@ -36,6 +36,7 @@ import com.android.systemui.model.SysUiState import com.android.systemui.navigationbar.NavigationBarController import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP +import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.settings.FakeDisplayTracker import com.android.systemui.settings.UserTracker import com.android.systemui.shade.ShadeViewController @@ -146,6 +147,7 @@ class OverviewProxyServiceTest : SysuiTestCase() { sysuiUnlockAnimationController, assistUtils, featureFlags, + FakeSceneContainerFlags(), dumpManager, unfoldTransitionProgressForwarder ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 6006cd42424a..2f26a53afe7c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -25,8 +25,6 @@ import com.android.systemui.authentication.domain.model.AuthenticationMethodMode import com.android.systemui.authentication.domain.model.AuthenticationMethodModel import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel import com.android.systemui.coroutines.collectLastValue -import com.android.systemui.flags.FakeFeatureFlags -import com.android.systemui.flags.Flags import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel @@ -140,8 +138,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { @Before fun setUp() { - val featureFlags = FakeFeatureFlags().apply { set(Flags.SCENE_CONTAINER, true) } - authenticationRepository.setUnlocked(false) val displayTracker = FakeDisplayTracker(context) @@ -152,7 +148,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { sceneInteractor = sceneInteractor, authenticationInteractor = authenticationInteractor, keyguardInteractor = keyguardInteractor, - featureFlags = featureFlags, + flags = utils.sceneContainerFlags, sysUiState = sysUiState, displayId = displayTracker.defaultDisplayId, sceneLogger = mock(), diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt index 771c3e330e8a..145629a65f68 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt @@ -42,6 +42,7 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest +import org.junit.Assume.assumeTrue import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 @@ -57,7 +58,7 @@ class SceneContainerStartableTest : SysuiTestCase() { private val utils = SceneTestUtils(this) private val testScope = utils.testScope private val sceneInteractor = utils.sceneInteractor() - private val featureFlags = utils.featureFlags + private val sceneContainerFlags = utils.sceneContainerFlags private val authenticationRepository = utils.authenticationRepository() private val authenticationInteractor = utils.authenticationInteractor( @@ -78,7 +79,7 @@ class SceneContainerStartableTest : SysuiTestCase() { sceneInteractor = sceneInteractor, authenticationInteractor = authenticationInteractor, keyguardInteractor = keyguardInteractor, - featureFlags = featureFlags, + flags = sceneContainerFlags, sysUiState = sysUiState, displayId = Display.DEFAULT_DISPLAY, sceneLogger = mock(), @@ -516,7 +517,8 @@ class SceneContainerStartableTest : SysuiTestCase() { initialSceneKey: SceneKey? = null, authenticationMethod: AuthenticationMethodModel? = null, ): MutableStateFlow<ObservableTransitionState> { - featureFlags.set(Flags.SCENE_CONTAINER, true) + assumeTrue(Flags.SCENE_CONTAINER_ENABLED) + sceneContainerFlags.enabled = true authenticationRepository.setUnlocked(isDeviceUnlocked) keyguardRepository.setBypassEnabled(isBypassEnabled) val transitionStateFlow = 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 new file mode 100644 index 000000000000..17ee3a1cc906 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/shared/flag/SceneContainerFlagsTest.kt @@ -0,0 +1,96 @@ +/* + * Copyright 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. + * 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 androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.FakeFeatureFlagsClassic +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.google.common.truth.Truth.assertThat +import org.junit.Assume.assumeTrue +import org.junit.Before +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() { + + private lateinit var underTest: SceneContainerFlags + + @Before + fun setUp() { + val featureFlags = + FakeFeatureFlagsClassic().apply { + SceneContainerFlagsImpl.flags.forEach { flag -> + when (flag) { + is ResourceBooleanFlag -> set(flag, testCase.areAllFlagsSet) + is ReleasedFlag -> set(flag, testCase.areAllFlagsSet) + is UnreleasedFlag -> set(flag, testCase.areAllFlagsSet) + else -> error("Unsupported flag type ${flag.javaClass}") + } + } + } + underTest = SceneContainerFlagsImpl(featureFlags, testCase.isComposeAvailable) + } + + @Test + fun isEnabled() { + assumeTrue(Flags.SCENE_CONTAINER_ENABLED) + assertThat(underTest.isEnabled()).isEqualTo(testCase.expectedEnabled) + } + + internal data class TestCase( + val isComposeAvailable: Boolean, + val areAllFlagsSet: Boolean, + val expectedEnabled: Boolean, + ) { + override fun toString(): String { + return """ + (compose=$isComposeAvailable + flags=$areAllFlagsSet) -> expected=$expectedEnabled + """ + .trimIndent() + } + } + + companion object { + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun testCases() = buildList { + repeat(4) { combination -> + val isComposeAvailable = combination and 0b100 != 0 + val areAllFlagsSet = combination and 0b001 != 0 + + val expectedEnabled = isComposeAvailable && areAllFlagsSet + + add( + TestCase( + isComposeAvailable = isComposeAvailable, + areAllFlagsSet = areAllFlagsSet, + expectedEnabled = expectedEnabled, + ) + ) + } + } + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt index 4c3c3f9d8da5..4349d738b0f3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt @@ -31,6 +31,7 @@ import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags +import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.ui.view.WindowRootView import com.android.systemui.shade.ShadeControllerImpl import com.android.systemui.shade.ShadeLogger @@ -47,6 +48,8 @@ import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.whenever import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat +import java.util.Optional +import javax.inject.Provider import org.junit.Before import org.junit.Test import org.mockito.ArgumentCaptor @@ -57,40 +60,24 @@ import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import org.mockito.MockitoAnnotations -import java.util.Optional -import javax.inject.Provider @SmallTest class PhoneStatusBarViewControllerTest : SysuiTestCase() { - @Mock - private lateinit var shadeViewController: ShadeViewController - @Mock - private lateinit var featureFlags: FeatureFlags - @Mock - private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController - @Mock - private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent - @Mock - private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider - @Mock - private lateinit var configurationController: ConfigurationController - @Mock - private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory - @Mock - private lateinit var userChipViewModel: StatusBarUserChipViewModel - @Mock - private lateinit var centralSurfacesImpl: CentralSurfacesImpl - @Mock - private lateinit var commandQueue: CommandQueue - @Mock - private lateinit var shadeControllerImpl: ShadeControllerImpl - @Mock - private lateinit var windowRootView: Provider<WindowRootView> - @Mock - private lateinit var shadeLogger: ShadeLogger - @Mock - private lateinit var viewUtil: ViewUtil + @Mock private lateinit var shadeViewController: ShadeViewController + @Mock private lateinit var featureFlags: FeatureFlags + @Mock private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController + @Mock private lateinit var sysuiUnfoldComponent: SysUIUnfoldComponent + @Mock private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider + @Mock private lateinit var configurationController: ConfigurationController + @Mock private lateinit var mStatusOverlayHoverListenerFactory: StatusOverlayHoverListenerFactory + @Mock private lateinit var userChipViewModel: StatusBarUserChipViewModel + @Mock private lateinit var centralSurfacesImpl: CentralSurfacesImpl + @Mock private lateinit var commandQueue: CommandQueue + @Mock private lateinit var shadeControllerImpl: ShadeControllerImpl + @Mock private lateinit var windowRootView: Provider<WindowRootView> + @Mock private lateinit var shadeLogger: ShadeLogger + @Mock private lateinit var viewUtil: ViewUtil private lateinit var statusBarWindowStateController: StatusBarWindowStateController private lateinit var view: PhoneStatusBarView @@ -109,16 +96,16 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { // create the view and controller on main thread as it requires main looper InstrumentationRegistry.getInstrumentation().runOnMainSync { val parent = FrameLayout(mContext) // add parent to keep layout params - view = LayoutInflater.from(mContext) - .inflate(R.layout.status_bar, parent, false) as PhoneStatusBarView + view = + LayoutInflater.from(mContext).inflate(R.layout.status_bar, parent, false) + as PhoneStatusBarView controller = createAndInitController(view) } } @Test fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() { - whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) - .thenReturn(true) + whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)).thenReturn(true) val view = createViewMock() val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java) unfoldConfig.isEnabled = true @@ -136,7 +123,7 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test fun onViewAttachedAndDrawn_statusBarAnimationDisabled_animationNotInitialized() { whenever(featureFlags.isEnabled(Flags.ENABLE_UNFOLD_STATUS_BAR_ANIMATIONS)) - .thenReturn(false) + .thenReturn(false) val view = createViewMock() unfoldConfig.isEnabled = true // create the controller on main thread as it requires main looper @@ -150,8 +137,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { @Test fun handleTouchEventFromStatusBar_panelsNotEnabled_returnsFalseAndNoViewEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(false) - val returnVal = view.onTouchEvent( - MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) + val returnVal = + view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) assertThat(returnVal).isFalse() verify(shadeViewController, never()).handleExternalTouch(any()) } @@ -160,8 +147,8 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { fun handleTouchEventFromStatusBar_viewNotEnabled_returnsTrueAndNoViewEvent() { `when`(centralSurfacesImpl.commandQueuePanelsEnabled).thenReturn(true) `when`(shadeViewController.isViewEnabled).thenReturn(false) - val returnVal = view.onTouchEvent( - MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) + val returnVal = + view.onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0)) assertThat(returnVal).isTrue() verify(shadeViewController, never()).handleExternalTouch(any()) } @@ -245,22 +232,23 @@ class PhoneStatusBarViewControllerTest : SysuiTestCase() { private fun createAndInitController(view: PhoneStatusBarView): PhoneStatusBarViewController { return PhoneStatusBarViewController.Factory( - Optional.of(sysuiUnfoldComponent), - Optional.of(progressProvider), - featureFlags, - userChipViewModel, - centralSurfacesImpl, - statusBarWindowStateController, - shadeControllerImpl, - shadeViewController, - windowRootView, - shadeLogger, - viewUtil, - configurationController, - mStatusOverlayHoverListenerFactory - ).create(view).also { - it.init() - } + Optional.of(sysuiUnfoldComponent), + Optional.of(progressProvider), + featureFlags, + FakeSceneContainerFlags(), + userChipViewModel, + centralSurfacesImpl, + statusBarWindowStateController, + shadeControllerImpl, + shadeViewController, + windowRootView, + shadeLogger, + viewUtil, + configurationController, + mStatusOverlayHoverListenerFactory + ) + .create(view) + .also { it.init() } } private class UnfoldConfig : UnfoldTransitionConfig { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java index 28b7d4171df1..aa88a46d670c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java @@ -166,7 +166,9 @@ public abstract class SysuiTestCase { } disallowTestableLooperAsMainThread(); mContext.cleanUpReceivers(this.getClass().getSimpleName()); - mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName()); + if (mFakeBroadcastDispatcher != null) { + mFakeBroadcastDispatcher.cleanUpReceivers(this.getClass().getSimpleName()); + } } @AfterClass diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt index 11ea513c53e7..2e3bb2b545d8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt @@ -24,6 +24,8 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags +import com.android.systemui.scene.shared.flag.SceneContainerFlags import com.android.systemui.shade.data.repository.FakeShadeRepository import com.android.systemui.util.mockito.mock @@ -37,6 +39,7 @@ object KeyguardInteractorFactory { @JvmStatic fun create( featureFlags: FakeFeatureFlags = createFakeFeatureFlags(), + sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(), repository: FakeKeyguardRepository = FakeKeyguardRepository(), commandQueue: FakeCommandQueue = FakeCommandQueue(), bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(), @@ -48,6 +51,7 @@ object KeyguardInteractorFactory { repository = repository, commandQueue = commandQueue, featureFlags = featureFlags, + sceneContainerFlags = sceneContainerFlags, bouncerRepository = bouncerRepository, configurationRepository = configurationRepository, shadeRepository = shadeRepository, @@ -55,6 +59,7 @@ object KeyguardInteractorFactory { repository = repository, commandQueue = commandQueue, featureFlags = featureFlags, + sceneContainerFlags = sceneContainerFlags, bouncerRepository = bouncerRepository, configurationRepository = configurationRepository, shadeRepository = shadeRepository, @@ -72,6 +77,7 @@ object KeyguardInteractorFactory { val repository: FakeKeyguardRepository, val commandQueue: FakeCommandQueue, val featureFlags: FakeFeatureFlags, + val sceneContainerFlags: SceneContainerFlags, val bouncerRepository: FakeKeyguardBouncerRepository, val configurationRepository: FakeConfigurationRepository, val shadeRepository: FakeShadeRepository, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt index 282d79833baa..9dea0a0c26d5 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt @@ -31,7 +31,7 @@ import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.classifier.domain.interactor.FalsingInteractor import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.flags.FakeFeatureFlags +import com.android.systemui.flags.FakeFeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.keyguard.data.repository.FakeCommandQueue import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository @@ -43,6 +43,7 @@ import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.power.data.repository.FakePowerRepository import com.android.systemui.scene.data.repository.SceneContainerRepository import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.FakeSceneContainerFlags import com.android.systemui.scene.shared.model.SceneContainerConfig import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.shade.data.repository.FakeShadeRepository @@ -67,11 +68,8 @@ class SceneTestUtils( ) { val testDispatcher = StandardTestDispatcher() val testScope = TestScope(testDispatcher) - val featureFlags = - FakeFeatureFlags().apply { - set(Flags.SCENE_CONTAINER, true) - set(Flags.FACE_AUTH_REFACTOR, false) - } + val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) } + val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true } private val userRepository: UserRepository by lazy { FakeUserRepository().apply { val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0)) @@ -164,6 +162,7 @@ class SceneTestUtils( repository = repository, commandQueue = FakeCommandQueue(), featureFlags = featureFlags, + sceneContainerFlags = sceneContainerFlags, bouncerRepository = FakeKeyguardBouncerRepository(), configurationRepository = FakeConfigurationRepository(), shadeRepository = FakeShadeRepository(), @@ -181,7 +180,7 @@ class SceneTestUtils( repository = BouncerRepository(), authenticationInteractor = authenticationInteractor, sceneInteractor = sceneInteractor, - featureFlags = featureFlags, + flags = sceneContainerFlags, falsingInteractor = falsingInteractor(), ) } @@ -195,7 +194,7 @@ class SceneTestUtils( applicationScope = applicationScope(), bouncerInteractor = bouncerInteractor, authenticationInteractor = authenticationInteractor, - featureFlags = featureFlags, + flags = sceneContainerFlags, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt new file mode 100644 index 000000000000..01a1ecea9997 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/shared/flag/FakeSceneContainerFlags.kt @@ -0,0 +1,30 @@ +/* + * Copyright 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. + * 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 + +class FakeSceneContainerFlags( + var enabled: Boolean = false, +) : SceneContainerFlags { + + override fun isEnabled(): Boolean { + return enabled + } + + override fun requirementDescription(): String { + return "" + } +} |