diff options
| author | 2024-05-03 14:41:51 +0000 | |
|---|---|---|
| committer | 2024-05-06 16:58:15 +0000 | |
| commit | 6bcca2e18adc1a54b32d9a56345b46d5a5a254a7 (patch) | |
| tree | 33456b84a9b00cc3ef9d52ffe3d5868bf23a51e2 | |
| parent | e2d3dbdbeb9e0a1e5e612d3a6d9b7338ef9aba6c (diff) | |
[bc25] Create the `QuickSettingsShade` scene.
The scope of the CL includes the following:
* New scene key for the Quick Settings Shade scene.
* New module for the Quick Settings Shade scene.
* Conditional references to the new scene key wherever appropriate.
* Define the scene navigational mapping.
* Create the new scene composable, reusing OverlayShade.
* Create the scene view model with basic destination scenes mapping.
* New unit tests for the QuickSettingsShadeSceneViewModel.
Test: Manually verified by swiping down and swiping up on both the
lockscreen and gone scenes, with the feature flag both enabled and
disabled.
Test: Added unit tests.
Fix: 338009249.
Flag: ACONFIG com.android.systemui.dual_shade DEVELOPMENT
Change-Id: I001e14383e45b6a0f7ecb5d7cf1d3968cb87f99a
16 files changed, 380 insertions, 10 deletions
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt new file mode 100644 index 000000000000..3d7401d8f263 --- /dev/null +++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/scene/QuickSettingsShadeSceneModule.kt @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.scene + +import com.android.systemui.qs.ui.composable.QuickSettingsShadeScene +import com.android.systemui.scene.shared.model.Scene +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoSet + +@Module +interface QuickSettingsShadeSceneModule { + + @Binds @IntoSet fun quickSettingsShade(scene: QuickSettingsShadeScene): Scene +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt new file mode 100644 index 000000000000..636c6c3b7d14 --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt @@ -0,0 +1,71 @@ +/* + * 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.qs.ui.composable + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.android.compose.animation.scene.SceneScope +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneViewModel +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.scene.ui.composable.ComposableScene +import com.android.systemui.shade.ui.composable.OverlayShade +import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel +import javax.inject.Inject +import kotlinx.coroutines.flow.StateFlow + +@SysUISingleton +class QuickSettingsShadeScene +@Inject +constructor( + viewModel: QuickSettingsShadeSceneViewModel, + private val overlayShadeViewModel: OverlayShadeViewModel, +) : ComposableScene { + + override val key = Scenes.QuickSettingsShade + + override val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = + viewModel.destinationScenes + + @Composable + override fun SceneScope.Content( + modifier: Modifier, + ) { + OverlayShade( + viewModel = overlayShadeViewModel, + modifier = modifier, + horizontalArrangement = Arrangement.End, + ) { + Text( + text = "Quick settings grid", + modifier = Modifier.padding(QuickSettingsShade.Dimensions.Padding) + ) + } + } +} + +object QuickSettingsShade { + object Dimensions { + val Padding = 16.dp + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt new file mode 100644 index 000000000000..034c2e9b6789 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt @@ -0,0 +1,124 @@ +/* + * 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.qs.ui.viewmodel + +import android.testing.TestableLooper +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.compose.animation.scene.Swipe +import com.android.systemui.SysuiTestCase +import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository +import com.android.systemui.authentication.shared.model.AuthenticationMethodModel +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository +import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor +import com.android.systemui.flags.EnableSceneContainer +import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository +import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus +import com.android.systemui.kosmos.testScope +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.model.Scenes +import com.android.systemui.shade.ui.viewmodel.quickSettingsShadeSceneViewModel +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +@RunWith(AndroidJUnit4::class) +@TestableLooper.RunWithLooper +@EnableSceneContainer +class QuickSettingsShadeSceneViewModelTest : SysuiTestCase() { + + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val sceneInteractor = kosmos.sceneInteractor + private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor + + private val underTest = kosmos.quickSettingsShadeSceneViewModel + + @Test + fun upTransitionSceneKey_deviceLocked_lockscreen() = + testScope.runTest { + val destinationScenes by collectLastValue(underTest.destinationScenes) + lockDevice() + + assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen) + } + + @Test + fun upTransitionSceneKey_deviceUnlocked_gone() = + testScope.runTest { + val destinationScenes by collectLastValue(underTest.destinationScenes) + lockDevice() + unlockDevice() + + assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone) + } + + @Test + fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() = + testScope.runTest { + val destinationScenes by collectLastValue(underTest.destinationScenes) + kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.None + ) + sceneInteractor.changeScene(Scenes.Lockscreen, "reason") + + assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen) + } + + @Test + fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() = + testScope.runTest { + val destinationScenes by collectLastValue(underTest.destinationScenes) + kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true) + kosmos.fakeAuthenticationRepository.setAuthenticationMethod( + AuthenticationMethodModel.None + ) + runCurrent() + sceneInteractor.changeScene(Scenes.Gone, "reason") + + assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone) + } + + private fun TestScope.lockDevice() { + val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus) + + kosmos.fakeAuthenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin) + assertThat(deviceUnlockStatus?.isUnlocked).isFalse() + sceneInteractor.changeScene(Scenes.Lockscreen, "reason") + runCurrent() + } + + private fun TestScope.unlockDevice() { + val deviceUnlockStatus by collectLastValue(deviceUnlockedInteractor.deviceUnlockStatus) + + kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus( + SuccessFingerprintAuthenticationStatus(0, true) + ) + assertThat(deviceUnlockStatus?.isUnlocked).isTrue() + sceneInteractor.changeScene(Scenes.Gone, "reason") + runCurrent() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt index 2c1e75e2263b..d8b50133949d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt @@ -100,7 +100,13 @@ constructor( // Swiping down from the top edge goes to QS (or shade if in split shade mode). swipeDownFromTop(pointerCount = 1) to quickSettingsIfSingleShade, - swipeDownFromTop(pointerCount = 2) to quickSettingsIfSingleShade, + swipeDownFromTop(pointerCount = 2) to + // TODO(b/338577208): Remove 'Dual' once we add Dual Shade invocation zones. + if (shadeMode is ShadeMode.Dual) { + Scenes.QuickSettingsShade + } else { + quickSettingsIfSingleShade + }, // Swiping down, not from the edge, always navigates to the shade scene. swipeDown(pointerCount = 1) to shadeSceneKey, diff --git a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt index 0c07c0543246..89e4760615f0 100644 --- a/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt +++ b/packages/SystemUI/src/com/android/systemui/model/SceneContainerPlugin.kt @@ -85,7 +85,10 @@ constructor( { it.scene == Scenes.NotificationsShade || it.scene == Scenes.Shade }, - SYSUI_STATE_QUICK_SETTINGS_EXPANDED to { it.scene == Scenes.QuickSettings }, + SYSUI_STATE_QUICK_SETTINGS_EXPANDED to + { + it.scene == Scenes.QuickSettingsShade || it.scene == Scenes.QuickSettings + }, SYSUI_STATE_BOUNCER_SHOWING to { it.scene == Scenes.Bouncer }, SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING to { diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt new file mode 100644 index 000000000000..d48d55dd9918 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt @@ -0,0 +1,57 @@ +/* + * 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.qs.ui.viewmodel + +import com.android.compose.animation.scene.Back +import com.android.compose.animation.scene.SceneKey +import com.android.compose.animation.scene.Swipe +import com.android.compose.animation.scene.UserAction +import com.android.compose.animation.scene.UserActionResult +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn + +/** Models UI state and handles user input for the Quick Settings Shade scene. */ +@SysUISingleton +class QuickSettingsShadeSceneViewModel +@Inject +constructor( + @Application private val applicationScope: CoroutineScope, + overlayShadeViewModel: OverlayShadeViewModel, +) { + val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> = + overlayShadeViewModel.backgroundScene + .map(::destinationScenes) + .stateIn( + scope = applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = destinationScenes(overlayShadeViewModel.backgroundScene.value), + ) + + private fun destinationScenes(backgroundScene: SceneKey): Map<UserAction, UserActionResult> { + return mapOf( + Swipe.Up to backgroundScene, + Back to backgroundScene, + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt index aa8ecfc41fc1..28569d817279 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt @@ -63,7 +63,8 @@ interface KeyguardlessSceneContainerFrameworkModule { sceneKeys = listOfNotNull( Scenes.Gone, - Scenes.QuickSettings, + Scenes.QuickSettings.takeUnless { DualShade.isEnabled }, + Scenes.QuickSettingsShade.takeIf { DualShade.isEnabled }, Scenes.NotificationsShade.takeIf { DualShade.isEnabled }, Scenes.Shade.takeUnless { DualShade.isEnabled }, ), @@ -73,7 +74,8 @@ interface KeyguardlessSceneContainerFrameworkModule { Scenes.Gone to 0, Scenes.NotificationsShade to 1.takeIf { DualShade.isEnabled }, Scenes.Shade to 1.takeUnless { DualShade.isEnabled }, - Scenes.QuickSettings to 2, + Scenes.QuickSettingsShade to 2.takeIf { DualShade.isEnabled }, + Scenes.QuickSettings to 2.takeUnless { DualShade.isEnabled }, ) .filterValues { it != null } .mapValues { checkNotNull(it.value) } diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt index 551aa124727d..dbe0342a5319 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt @@ -41,6 +41,7 @@ import dagger.multibindings.IntoMap LockscreenSceneModule::class, QuickSettingsSceneModule::class, ShadeSceneModule::class, + QuickSettingsShadeSceneModule::class, NotificationsShadeSceneModule::class, ], ) @@ -71,7 +72,8 @@ interface SceneContainerFrameworkModule { Scenes.Communal, Scenes.Lockscreen, Scenes.Bouncer, - Scenes.QuickSettings, + Scenes.QuickSettings.takeUnless { DualShade.isEnabled }, + Scenes.QuickSettingsShade.takeIf { DualShade.isEnabled }, Scenes.NotificationsShade.takeIf { DualShade.isEnabled }, Scenes.Shade.takeUnless { DualShade.isEnabled }, ), @@ -83,7 +85,8 @@ interface SceneContainerFrameworkModule { Scenes.Communal to 1, Scenes.NotificationsShade to 2.takeIf { DualShade.isEnabled }, Scenes.Shade to 2.takeUnless { DualShade.isEnabled }, - Scenes.QuickSettings to 3, + Scenes.QuickSettingsShade to 3.takeIf { DualShade.isEnabled }, + Scenes.QuickSettings to 3.takeUnless { DualShade.isEnabled }, Scenes.Bouncer to 4, ) .filterValues { it != null } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt index ace449136fad..6bcd92316106 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneContainerOcclusionInteractor.kt @@ -127,6 +127,7 @@ constructor( Scenes.Lockscreen -> true Scenes.NotificationsShade -> false Scenes.QuickSettings -> false + Scenes.QuickSettingsShade -> false Scenes.Shade -> false else -> error("SceneKey \"$this\" doesn't have a mapping for canBeOccluded!") } diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt index de3b87aebcd3..9c2b992c0de6 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/WindowRootViewVisibilityInteractor.kt @@ -78,13 +78,16 @@ constructor( is ObservableTransitionState.Idle -> state.currentScene == Scenes.Shade || state.currentScene == Scenes.NotificationsShade || + state.currentScene == Scenes.QuickSettingsShade || state.currentScene == Scenes.Lockscreen is ObservableTransitionState.Transition -> state.toScene == Scenes.Shade || state.toScene == Scenes.NotificationsShade || + state.toScene == Scenes.QuickSettingsShade || state.toScene == Scenes.Lockscreen || state.fromScene == Scenes.Shade || state.fromScene == Scenes.NotificationsShade || + state.fromScene == Scenes.QuickSettingsShade || state.fromScene == Scenes.Lockscreen } } diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt index 08f1be908afd..6d139da99345 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt @@ -47,19 +47,45 @@ object Scenes { * overlay UI. * * It's used only in the dual shade configuration, where there are two separate shades: one for - * notifications (this scene) and another for quick settings (where a separate scene is used). + * notifications (this scene) and another for [QuickSettingsShade]. * * It's not used in the single/accordion configuration (swipe down once to reveal the shade, - * swipe down again the to expand quick settings) and for the "split" shade configuration (on + * swipe down again the to expand quick settings) or in the "split" shade configuration (on * large screens or unfolded foldables, where notifications and quick settings are shown * side-by-side in their own columns). */ @JvmField val NotificationsShade = SceneKey("notifications_shade") - /** The quick settings scene shows the quick setting tiles. */ + /** + * The quick settings scene shows the quick setting tiles. + * + * This scene is used for single/accordion configuration (swipe down once to reveal the shade, + * swipe down again the to expand quick settings). + * + * For the "split" shade configuration (on large screens or unfolded foldables, where + * notifications and quick settings are shown side-by-side in their own columns), the [Shade] + * scene is used]. + * + * For the dual shade configuration, where there are two separate shades: one for notifications + * and one for quick settings, [NotificationsShade] and [QuickSettingsShade] scenes are used + * respectively. + */ @JvmField val QuickSettings = SceneKey("quick_settings") /** + * The quick settings shade scene shows the quick setting tiles as an overlay UI. + * + * It's used only in the dual shade configuration, where there are two separate shades: one for + * quick settings (this scene) and another for [NotificationsShade]. + * + * It's not used in the single/accordion configuration (swipe down once to reveal the shade, + * swipe down again the to expand quick settings) or in the "split" shade configuration (on + * large screens or unfolded foldables, where notifications and quick settings are shown + * side-by-side in their own columns). + */ + @JvmField val QuickSettingsShade = SceneKey("quick_settings_shade") + + /** * The shade is the scene that shows a scrollable list of notifications and the minimized * version of quick settings (AKA "quick quick settings" or "QQS"). * diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt index e4435ccd205c..b0af7f9ce072 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt @@ -60,6 +60,16 @@ constructor( )] = UserActionResult(Scenes.QuickSettings) } + // TODO(b/338577208): Remove this once we add Dual Shade invocation zones. + if (shadeMode is ShadeMode.Dual) { + this[ + Swipe( + pointerCount = 2, + fromSource = Edge.Top, + direction = SwipeDirection.Down, + )] = UserActionResult(Scenes.QuickSettingsShade) + } + this[Swipe(direction = SwipeDirection.Down)] = UserActionResult( if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt index 7fbede475e69..09c80b09a388 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt @@ -127,6 +127,7 @@ constructor( Scenes.NotificationsShade -> Classifier.NOTIFICATION_DRAG_DOWN Scenes.Shade -> Classifier.NOTIFICATION_DRAG_DOWN Scenes.QuickSettings -> Classifier.QUICK_SETTINGS + Scenes.QuickSettingsShade -> Classifier.QUICK_SETTINGS else -> null } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt index 5cc30bd8c27f..43e782c44206 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt @@ -203,7 +203,11 @@ constructor( } override fun expandToQs() { - sceneInteractor.changeScene(Scenes.QuickSettings, "ShadeController.animateExpandQs") + val shadeMode = shadeInteractor.shadeMode.value + sceneInteractor.changeScene( + if (shadeMode is ShadeMode.Dual) Scenes.QuickSettingsShade else Scenes.QuickSettings, + "ShadeController.animateExpandQs" + ) } override fun setVisibilityListener(listener: ShadeVisibilityListener) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index 96a50f7686b9..70632d5aa27a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -679,6 +679,7 @@ public class StatusBarStateControllerImpl implements Scenes.Shade, StatusBarState.SHADE_LOCKED, Scenes.NotificationsShade, StatusBarState.SHADE_LOCKED, Scenes.QuickSettings, StatusBarState.SHADE_LOCKED, + Scenes.QuickSettingsShade, StatusBarState.SHADE_LOCKED, Scenes.Gone, StatusBarState.SHADE ); diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt new file mode 100644 index 000000000000..8c5ff1d5d216 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt @@ -0,0 +1,29 @@ +/* + * 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.shade.ui.viewmodel + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneViewModel + +val Kosmos.quickSettingsShadeSceneViewModel: QuickSettingsShadeSceneViewModel by + Kosmos.Fixture { + QuickSettingsShadeSceneViewModel( + applicationScope = applicationCoroutineScope, + overlayShadeViewModel = overlayShadeViewModel, + ) + } |