diff options
10 files changed, 195 insertions, 19 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index c4d13ba6effa..a5879bfde187 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1237,6 +1237,13 @@ flag { } flag { + name: "glanceable_hub_back_action" + namespace: "systemui" + description: "Support back action from glanceable hub" + bug: "382771533" +} + +flag { name: "dream_overlay_updated_font" namespace: "systemui" description: "Flag to enable updated font settings for dream overlay" diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt index 41cc6ee182cf..271cd3a4f202 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/back/domain/interactor/BackActionInteractorTest.kt @@ -16,6 +16,7 @@ package com.android.systemui.back.domain.interactor +import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.RequiresFlagsDisabled import android.platform.test.annotations.RequiresFlagsEnabled import android.platform.test.flag.junit.DeviceFlagsValueProvider @@ -31,6 +32,7 @@ import androidx.test.filters.SmallTest import com.android.internal.statusbar.IStatusBarService import com.android.systemui.Flags import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.domain.interactor.CommunalBackActionInteractor import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.testScope @@ -93,6 +95,7 @@ class BackActionInteractorTest : SysuiTestCase() { @Mock private lateinit var onBackInvokedDispatcher: WindowOnBackInvokedDispatcher @Mock private lateinit var iStatusBarService: IStatusBarService @Mock private lateinit var headsUpManager: HeadsUpManager + @Mock private lateinit var communalBackActionInteractor: CommunalBackActionInteractor private val keyguardRepository = FakeKeyguardRepository() private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor by lazy { @@ -117,6 +120,7 @@ class BackActionInteractorTest : SysuiTestCase() { windowRootViewVisibilityInteractor, shadeBackActionInteractor, qsController, + communalBackActionInteractor, ) } @@ -306,6 +310,19 @@ class BackActionInteractorTest : SysuiTestCase() { verify(shadeBackActionInteractor).onBackProgressed(0.4f) } + @Test + @EnableFlags(Flags.FLAG_GLANCEABLE_HUB_BACK_ACTION) + fun onBackAction_communalCanBeDismissed_communalBackActionInteractorCalled() { + backActionInteractor.start() + windowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true) + powerInteractor.setAwakeForTest() + val callback = getBackInvokedCallback() + whenever(communalBackActionInteractor.canBeDismissed()).thenReturn(true) + callback.onBackInvoked() + + verify(communalBackActionInteractor).onBackPressed() + } + private fun getBackInvokedCallback(): OnBackInvokedCallback { testScope.runCurrent() val captor = argumentCaptor<OnBackInvokedCallback>() diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt new file mode 100644 index 000000000000..c365f1cb3872 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorTest.kt @@ -0,0 +1,63 @@ +/* + * 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.communal.domain.interactor + +import android.platform.test.annotations.EnableFlags +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.Flags.FLAG_COMMUNAL_HUB +import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.data.repository.communalSceneRepository +import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import com.android.systemui.kosmos.runCurrent +import com.android.systemui.kosmos.runTest +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@OptIn(ExperimentalCoroutinesApi::class) +@RunWith(AndroidJUnit4::class) +class CommunalBackActionInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos() + + private var Kosmos.underTest by Fixture { communalBackActionInteractor } + + @Test + @EnableFlags(FLAG_COMMUNAL_HUB) + fun communalShowing_canBeDismissed() = + kosmos.runTest { + setCommunalAvailable(true) + assertThat(underTest.canBeDismissed()).isEqualTo(false) + communalInteractor.changeScene(CommunalScenes.Communal, "test") + runCurrent() + assertThat(underTest.canBeDismissed()).isEqualTo(true) + } + + @Test + @EnableFlags(FLAG_COMMUNAL_HUB) + fun onBackPressed_invokesSceneChange() = + kosmos.runTest { + underTest.onBackPressed() + runCurrent() + assertThat(communalSceneRepository.currentScene.value).isEqualTo(CommunalScenes.Blank) + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt index 0bfcd242828d..8a9c42d9b64e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalTutorialInteractorTest.kt @@ -130,19 +130,6 @@ class CommunalTutorialInteractorTest : SysuiTestCase() { } @Test - fun tutorialState_startedAndCommunalSceneShowing_stateWillNotUpdate() = - testScope.runTest { - val tutorialSettingState by - collectLastValue(communalTutorialRepository.tutorialSettingState) - - communalTutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_STARTED) - - goToCommunal() - - assertThat(tutorialSettingState).isEqualTo(HUB_MODE_TUTORIAL_STARTED) - } - - @Test fun tutorialState_completedAndCommunalSceneShowing_stateWillNotUpdate() = testScope.runTest { val tutorialSettingState by diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java index fc536bdb126b..6f13d637d5c5 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java @@ -20,6 +20,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static com.android.systemui.Flags.glanceableHubBackAction; import static com.android.systemui.shared.Flags.shadeAllowBackGesture; import android.annotation.LongDef; @@ -352,6 +353,10 @@ public class QuickStepContract { } // Disable back gesture on the hub, but not when the shade is showing. if ((sysuiStateFlags & SYSUI_STATE_COMMUNAL_HUB_SHOWING) != 0) { + // Allow back gesture on Glanceable Hub with back action support. + if (glanceableHubBackAction()) { + return false; + } // Use QS expanded signal as the notification panel is always considered visible // expanded when on the lock screen and when opening hub over lock screen. This does // mean that back gesture is disabled when opening shade over hub while in portrait diff --git a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt index 232b62985ad0..47910f3d25bc 100644 --- a/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/back/domain/interactor/BackActionInteractor.kt @@ -21,8 +21,11 @@ import android.window.OnBackAnimationCallback import android.window.OnBackInvokedCallback import android.window.OnBackInvokedDispatcher import android.window.WindowOnBackInvokedDispatcher +import com.android.app.tracing.coroutines.launchTraced as launch import com.android.systemui.CoreStartable +import com.android.systemui.Flags.glanceableHubBackAction import com.android.systemui.Flags.predictiveBackAnimateShade +import com.android.systemui.communal.domain.interactor.CommunalBackActionInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.plugins.statusbar.StatusBarStateController @@ -35,7 +38,6 @@ import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import com.android.app.tracing.coroutines.launchTraced as launch /** Handles requests to go back either from a button or gesture. */ @SysUISingleton @@ -50,6 +52,7 @@ constructor( private val windowRootViewVisibilityInteractor: WindowRootViewVisibilityInteractor, private val shadeBackActionInteractor: ShadeBackActionInteractor, private val qsController: QuickSettingsController, + private val communalBackActionInteractor: CommunalBackActionInteractor, ) : CoreStartable { private var isCallbackRegistered = false @@ -114,6 +117,12 @@ constructor( if (shadeBackActionInteractor.closeUserSwitcherIfOpen()) { return true } + if (glanceableHubBackAction()) { + if (communalBackActionInteractor.canBeDismissed()) { + communalBackActionInteractor.onBackPressed() + return true + } + } if (shouldBackBeHandled()) { if (shadeBackActionInteractor.canBeCollapsed()) { // this is the Shade dismiss animation, so make sure QQS closes when it ends. diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt new file mode 100644 index 000000000000..2ccf96abff79 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractor.kt @@ -0,0 +1,56 @@ +/* + * 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.communal.domain.interactor + +import com.android.systemui.communal.shared.model.CommunalScenes +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.Scenes +import javax.inject.Inject + +/** + * {@link CommunalBackActionInteractor} is responsible for handling back gestures on the glanceable + * hub. When invoked SystemUI should navigate back to the lockscreen. + */ +@SysUISingleton +class CommunalBackActionInteractor +@Inject +constructor( + private val communalInteractor: CommunalInteractor, + private val communalSceneInteractor: CommunalSceneInteractor, + private val sceneInteractor: SceneInteractor, +) { + fun canBeDismissed(): Boolean { + return communalInteractor.isCommunalShowing.value + } + + fun onBackPressed() { + if (SceneContainerFlag.isEnabled) { + // TODO(b/384610333): Properly determine whether to go to dream or lockscreen on back. + sceneInteractor.changeScene( + toScene = Scenes.Lockscreen, + loggingReason = "CommunalBackActionInteractor", + ) + } else { + communalSceneInteractor.changeScene( + newScene = CommunalScenes.Blank, + loggingReason = "CommunalBackActionInteractor", + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index ea428698e476..947113da0e60 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -285,7 +285,7 @@ constructor( * use [isIdleOnCommunal]. */ // TODO(b/323215860): rename to something more appropriate after cleaning up usages - val isCommunalShowing: Flow<Boolean> = + val isCommunalShowing: StateFlow<Boolean> = flow { emit(SceneContainerFlag.isEnabled) } .flatMapLatest { sceneContainerEnabled -> if (sceneContainerEnabled) { @@ -304,10 +304,10 @@ constructor( columnName = "isCommunalShowing", initialValue = false, ) - .shareIn( + .stateIn( scope = applicationScope, - started = SharingStarted.WhileSubscribed(), - replay = 1, + started = SharingStarted.Eagerly, + initialValue = false, ) /** diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java index 571b37f43fd4..b272d65a8a11 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java @@ -54,6 +54,7 @@ import com.android.internal.logging.UiEventLogger; import com.android.internal.policy.PhoneWindow; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.systemui.Flags; import com.android.systemui.ambient.touch.TouchHandler; import com.android.systemui.ambient.touch.TouchMonitor; import com.android.systemui.ambient.touch.dagger.AmbientTouchComponent; @@ -210,6 +211,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ mCommunalVisible = communalVisible; updateLifecycleStateLocked(); + updateGestureBlockingLocked(); }); } }; @@ -585,7 +587,8 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ private void updateGestureBlockingLocked() { final boolean shouldBlock = mStarted && !mShadeExpanded && !mBouncerShowing - && !isDreamInPreviewMode(); + && !isDreamInPreviewMode() + && !(Flags.glanceableHubBackAction() && mCommunalVisible); if (shouldBlock) { mGestureInteractor.addGestureBlockedMatcher(DREAM_TYPE_MATCHER, diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.kt new file mode 100644 index 000000000000..57c8fd066ea8 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/communal/domain/interactor/CommunalBackActionInteractorKosmos.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.communal.domain.interactor + +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.scene.domain.interactor.sceneInteractor + +val Kosmos.communalBackActionInteractor by + Kosmos.Fixture { + CommunalBackActionInteractor( + communalInteractor = communalInteractor, + communalSceneInteractor = communalSceneInteractor, + sceneInteractor = sceneInteractor, + ) + } |