diff options
12 files changed, 149 insertions, 20 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 1e5ebd0c2acd..e207ff278a42 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -52,6 +52,7 @@ import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.pipeline.MediaDataManager import com.android.systemui.model.SysUiState +import com.android.systemui.model.sceneContainerPlugin import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.powerInteractor @@ -244,7 +245,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { kosmos.fakeDeviceEntryRepository.setUnlocked(false) val displayTracker = FakeDisplayTracker(context) - val sysUiState = SysUiState(displayTracker) + val sysUiState = SysUiState(displayTracker, kosmos.sceneContainerPlugin) val startable = SceneContainerStartable( applicationScope = testScope.backgroundScope, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java index 92300efdc930..c1870c0de6e9 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java @@ -66,6 +66,7 @@ import com.android.systemui.log.dagger.MonitorLog; import com.android.systemui.log.table.TableLogBuffer; import com.android.systemui.mediaprojection.appselector.MediaProjectionModule; import com.android.systemui.mediaprojection.taskswitcher.MediaProjectionTaskSwitcherModule; +import com.android.systemui.model.SceneContainerPlugin; import com.android.systemui.model.SysUiState; import com.android.systemui.motiontool.MotionToolModule; import com.android.systemui.navigationbar.NavigationBarComponent; @@ -268,8 +269,11 @@ public abstract class SystemUIModule { @SysUISingleton @Provides - static SysUiState provideSysUiState(DisplayTracker displayTracker, DumpManager dumpManager) { - final SysUiState state = new SysUiState(displayTracker); + static SysUiState provideSysUiState( + DisplayTracker displayTracker, + DumpManager dumpManager, + SceneContainerPlugin sceneContainerPlugin) { + final SysUiState state = new SysUiState(displayTracker, sceneContainerPlugin); dumpManager.registerDumpable(state); return state; } diff --git a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt new file mode 100644 index 000000000000..6eb62263eb9a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt @@ -0,0 +1,77 @@ +/* + * 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.model + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.scene.domain.interactor.SceneInteractor +import com.android.systemui.scene.shared.flag.SceneContainerFlag +import com.android.systemui.scene.shared.model.ObservableTransitionState +import com.android.systemui.scene.shared.model.SceneKey +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED +import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING +import dagger.Lazy +import javax.inject.Inject + +/** + * A plugin for [SysUiState] that provides overrides for certain state flags that must be pulled + * from the scene framework when that framework is enabled. + */ +@SysUISingleton +class SceneContainerPlugin +@Inject +constructor( + private val interactor: Lazy<SceneInteractor>, +) { + /** + * Returns an override value for the given [flag] or `null` if the scene framework isn't enabled + * or if the flag value doesn't need to be overridden. + */ + fun flagValueOverride(flag: Int): Boolean? { + if (!SceneContainerFlag.isEnabled) { + return null + } + + val transitionState = interactor.get().transitionState.value + val idleTransitionStateOrNull = transitionState as? ObservableTransitionState.Idle + val currentSceneOrNull = idleTransitionStateOrNull?.scene + return currentSceneOrNull?.let { sceneKey -> EvaluatorByFlag[flag]?.invoke(sceneKey) } + } + + companion object { + + /** + * Value evaluator function by state flag ID. + * + * The value evaluator function can be invoked, passing in the current [SceneKey] to know + * the override value of the flag ID. + * + * If the map doesn't contain an entry for a certain flag ID, it means that it doesn't need + * to be overridden by the scene framework. + */ + val EvaluatorByFlag = + mapOf<Int, (SceneKey) -> Boolean>( + SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE to { it != SceneKey.Gone }, + SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to { it == SceneKey.Shade }, + SYSUI_STATE_QUICK_SETTINGS_EXPANDED to { it == SceneKey.QuickSettings }, + SYSUI_STATE_BOUNCER_SHOWING to { it == SceneKey.Bouncer }, + SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to { it == SceneKey.Lockscreen }, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java index 3cdcb2c4f550..2dd2327e5387 100644 --- a/packages/SystemUI/src/com/android/systemui/model/SysUiState.java +++ b/packages/SystemUI/src/com/android/systemui/model/SysUiState.java @@ -41,13 +41,15 @@ public class SysUiState implements Dumpable { public static final boolean DEBUG = false; private final DisplayTracker mDisplayTracker; + private final SceneContainerPlugin mSceneContainerPlugin; private @QuickStepContract.SystemUiStateFlags int mFlags; private final List<SysUiStateCallback> mCallbacks = new ArrayList<>(); private int mFlagsToSet = 0; private int mFlagsToClear = 0; - public SysUiState(DisplayTracker displayTracker) { + public SysUiState(DisplayTracker displayTracker, SceneContainerPlugin sceneContainerPlugin) { mDisplayTracker = displayTracker; + mSceneContainerPlugin = sceneContainerPlugin; } /** @@ -71,6 +73,16 @@ public class SysUiState implements Dumpable { /** Methods to this call can be chained together before calling {@link #commitUpdate(int)}. */ public SysUiState setFlag(int flag, boolean enabled) { + final Boolean overrideOrNull = mSceneContainerPlugin.flagValueOverride(flag); + if (overrideOrNull != null && enabled != overrideOrNull) { + if (DEBUG) { + Log.d(TAG, "setFlag for flag " + flag + " and value " + enabled + " overridden to " + + overrideOrNull + " by scene container plugin"); + } + + enabled = overrideOrNull; + } + if (enabled) { mFlagsToSet |= flag; } else { 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 c96651c1057e..23688e1214ae 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 @@ -30,6 +30,7 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.DisplayId import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.model.SceneContainerPlugin import com.android.systemui.model.SysUiState import com.android.systemui.model.updateFlags import com.android.systemui.power.domain.interactor.PowerInteractor @@ -39,11 +40,6 @@ import com.android.systemui.scene.shared.logger.SceneLogger import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey import com.android.systemui.scene.shared.model.SceneModel -import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING -import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED -import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE -import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED -import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.notification.stack.shared.flexiNotifsEnabled import com.android.systemui.util.asIndenting @@ -291,12 +287,10 @@ constructor( .collect { sceneKey -> sysUiState.updateFlags( displayId, - SYSUI_STATE_NOTIFICATION_PANEL_VISIBLE to (sceneKey != SceneKey.Gone), - SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED to (sceneKey == SceneKey.Shade), - SYSUI_STATE_QUICK_SETTINGS_EXPANDED to (sceneKey == SceneKey.QuickSettings), - SYSUI_STATE_BOUNCER_SHOWING to (sceneKey == SceneKey.Bouncer), - SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to - (sceneKey == SceneKey.Lockscreen), + *SceneContainerPlugin.EvaluatorByFlag.map { (flag, evaluator) -> + flag to evaluator.invoke(sceneKey) + } + .toTypedArray(), ) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java index 044881e57897..04aef82cef43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java @@ -92,6 +92,7 @@ import androidx.test.filters.LargeTest; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.AnimatorTestRule; +import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.model.SysUiState; import com.android.systemui.res.R; import com.android.systemui.settings.FakeDisplayTracker; @@ -159,6 +160,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { private View mSpyView; private View.OnTouchListener mTouchListener; private MotionEventHelper mMotionEventHelper = new MotionEventHelper(); + private KosmosJavaAdapter mKosmos; /** * return whether window magnification is supported for current test context. @@ -170,6 +172,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); + mKosmos = new KosmosJavaAdapter(this); mContext = Mockito.spy(getContext()); mHandler = new FakeHandler(TestableLooper.get(this).getLooper()); mInstrumentation = InstrumentationRegistry.getInstrumentation(); @@ -185,7 +188,7 @@ public class WindowMagnificationControllerTest extends SysuiTestCase { return null; }).when(mSfVsyncFrameProvider).postFrameCallback( any(FrameCallback.class)); - mSysUiState = new SysUiState(mDisplayTracker); + mSysUiState = new SysUiState(mDisplayTracker, mKosmos.getSceneContainerPlugin()); mSysUiState.addCallback(Mockito.mock(SysUiState.SysUiStateCallback.class)); when(mSecureSettings.getIntForUser(anyString(), anyInt(), anyInt())).then( returnsSecondArg()); diff --git a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt index f5a70f07c968..8e0541008f59 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateExtTest.kt @@ -20,6 +20,7 @@ import android.view.Display import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.settings.FakeDisplayTracker +import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import org.junit.Test import org.junit.runner.RunWith @@ -29,7 +30,13 @@ import org.junit.runners.JUnit4 @RunWith(JUnit4::class) class SysUiStateExtTest : SysuiTestCase() { - private val underTest = SysUiState(FakeDisplayTracker(context)) + private val kosmos = testKosmos() + + private val underTest = + SysUiState( + FakeDisplayTracker(context), + kosmos.sceneContainerPlugin, + ) @Test fun updateFlags() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java index 1a93adc7a631..f03f4f7375f5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/model/SysUiStateTest.java @@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; +import com.android.systemui.kosmos.KosmosJavaAdapter; import com.android.systemui.settings.FakeDisplayTracker; import org.junit.Before; @@ -42,13 +43,15 @@ public class SysUiStateTest extends SysuiTestCase { private static final int FLAG_4 = 1 << 3; private static final int DISPLAY_ID = DEFAULT_DISPLAY; + private KosmosJavaAdapter mKosmos; private SysUiState.SysUiStateCallback mCallback; private SysUiState mFlagsContainer; @Before public void setup() { FakeDisplayTracker displayTracker = new FakeDisplayTracker(mContext); - mFlagsContainer = new SysUiState(displayTracker); + mKosmos = new KosmosJavaAdapter(this); + mFlagsContainer = new SysUiState(displayTracker, mKosmos.getSceneContainerPlugin()); mCallback = mock(SysUiState.SysUiStateCallback.class); mFlagsContainer.addCallback(mCallback); } 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 70a48f574949..f390e12045af 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/recents/OverviewProxyServiceTest.kt @@ -35,6 +35,7 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager import com.android.systemui.model.SysUiState +import com.android.systemui.model.sceneContainerPlugin import com.android.systemui.navigationbar.NavigationBarController import com.android.systemui.navigationbar.NavigationModeController import com.android.systemui.recents.OverviewProxyService.ACTION_QUICKSTEP @@ -50,6 +51,7 @@ import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_GOING_TO import com.android.systemui.shared.system.QuickStepContract.WAKEFULNESS_WAKING import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.NotificationShadeWindowController +import com.android.systemui.testKosmos import com.android.systemui.unfold.progress.UnfoldTransitionProgressForwarder import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever @@ -79,11 +81,12 @@ class OverviewProxyServiceTest : SysuiTestCase() { @Main private val executor: Executor = MoreExecutors.directExecutor() + private val kosmos = testKosmos() private lateinit var subject: OverviewProxyService private val dumpManager = DumpManager() private val displayTracker = FakeDisplayTracker(mContext) private val fakeSystemClock = FakeSystemClock() - private val sysUiState = SysUiState(displayTracker) + private val sysUiState = SysUiState(displayTracker, kosmos.sceneContainerPlugin) private val featureFlags = FakeFeatureFlags() private val wakefulnessLifecycle = WakefulnessLifecycle(mContext, null, fakeSystemClock, dumpManager) diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index 98f3ede850f4..7eba3f0602d5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -548,7 +548,7 @@ public class BubblesTest extends SysuiTestCase { mZenModeConfig.suppressedVisualEffects = 0; when(mZenModeController.getConfig()).thenReturn(mZenModeConfig); - mSysUiState = new SysUiState(mDisplayTracker); + mSysUiState = new SysUiState(mDisplayTracker, mKosmos.getSceneContainerPlugin()); mSysUiState.addCallback(sysUiFlags -> { mSysUiStateBubblesManageMenuExpanded = (sysUiFlags diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt index 321f94468a2e..11f2938141b4 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt @@ -32,6 +32,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteract import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.jank.interactionJankMonitor import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository +import com.android.systemui.model.sceneContainerPlugin import com.android.systemui.plugins.statusbar.statusBarStateController import com.android.systemui.power.data.repository.fakePowerRepository import com.android.systemui.power.domain.interactor.powerInteractor @@ -74,6 +75,7 @@ class KosmosJavaAdapter( val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor } val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor } val communalInteractor by lazy { kosmos.communalInteractor } + val sceneContainerPlugin by lazy { kosmos.sceneContainerPlugin } init { kosmos.applicationContext = testCase.context diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/model/SceneContainerPluginKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SceneContainerPluginKosmos.kt new file mode 100644 index 000000000000..b1027b923a26 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/model/SceneContainerPluginKosmos.kt @@ -0,0 +1,23 @@ +/* + * 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.model + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.scene.domain.interactor.sceneInteractor + +val Kosmos.sceneContainerPlugin by Fixture { SceneContainerPlugin { sceneInteractor } } |