diff options
19 files changed, 165 insertions, 64 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt index 0ab09595d6b0..e61b2d0f2e74 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt @@ -21,6 +21,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue @@ -35,6 +36,8 @@ import com.android.systemui.kosmos.applicationCoroutineScope import com.android.systemui.kosmos.testDispatcher import com.android.systemui.kosmos.testScope import com.android.systemui.statusbar.notificationShadeWindowController +import com.android.systemui.statusbar.phone.centralSurfaces +import com.android.systemui.statusbar.phone.centralSurfacesOptional import com.android.systemui.testKosmos import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat @@ -49,6 +52,7 @@ import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith +import org.mockito.kotlin.whenever @OptIn(ExperimentalCoroutinesApi::class) @SmallTest @@ -67,6 +71,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { CommunalSceneStartable( dockManager = dockManager, communalInteractor = communalInteractor, + communalSceneInteractor = communalSceneInteractor, keyguardTransitionInteractor = keyguardTransitionInteractor, keyguardInteractor = keyguardInteractor, systemSettings = fakeSettings, @@ -74,6 +79,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { applicationScope = applicationCoroutineScope, bgScope = applicationCoroutineScope, mainDispatcher = testDispatcher, + centralSurfacesOpt = centralSurfacesOptional, ) .apply { start() } @@ -90,9 +96,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun keyguardGoesAway_forceBlankScene() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) assertThat(scene).isEqualTo(CommunalScenes.Communal) fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -110,7 +116,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun deviceDocked_forceCommunalScene() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Blank) updateDocked(true) @@ -127,8 +133,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun occluded_forceBlankScene() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) - communalInteractor.changeScene(CommunalScenes.Communal) + whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(false) + val scene by collectLastValue(communalSceneInteractor.currentScene) + communalSceneInteractor.changeScene(CommunalScenes.Communal) assertThat(scene).isEqualTo(CommunalScenes.Communal) updateDocked(true) @@ -142,10 +149,29 @@ class CommunalSceneStartableTest : SysuiTestCase() { } @Test + fun occluded_doesNotForceBlankSceneIfLaunchingActivityOverLockscreen() = + with(kosmos) { + testScope.runTest { + whenever(centralSurfaces.isLaunchingActivityOverLockscreen).thenReturn(true) + val scene by collectLastValue(communalSceneInteractor.currentScene) + communalSceneInteractor.changeScene(CommunalScenes.Communal) + assertThat(scene).isEqualTo(CommunalScenes.Communal) + + updateDocked(true) + fakeKeyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.GLANCEABLE_HUB, + to = KeyguardState.OCCLUDED, + testScope = this + ) + assertThat(scene).isEqualTo(CommunalScenes.Communal) + } + } + + @Test fun deviceDocked_doesNotForceCommunalIfTransitioningFromCommunal() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Blank) updateDocked(true) @@ -162,8 +188,8 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun deviceAsleep_forceBlankSceneAfterTimeout() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) - communalInteractor.changeScene(CommunalScenes.Communal) + val scene by collectLastValue(communalSceneInteractor.currentScene) + communalSceneInteractor.changeScene(CommunalScenes.Communal) assertThat(scene).isEqualTo(CommunalScenes.Communal) fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -183,8 +209,8 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun deviceAsleep_wakesUpBeforeTimeout_noChangeInScene() = with(kosmos) { testScope.runTest { - val scene by collectLastValue(communalInteractor.desiredScene) - communalInteractor.changeScene(CommunalScenes.Communal) + val scene by collectLastValue(communalSceneInteractor.currentScene) + communalSceneInteractor.changeScene(CommunalScenes.Communal) assertThat(scene).isEqualTo(CommunalScenes.Communal) fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -212,8 +238,8 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun dockingOnLockscreen_forcesCommunal() = with(kosmos) { testScope.runTest { - communalInteractor.changeScene(CommunalScenes.Blank) - val scene by collectLastValue(communalInteractor.desiredScene) + communalSceneInteractor.changeScene(CommunalScenes.Blank) + val scene by collectLastValue(communalSceneInteractor.currentScene) // device is docked while on the lockscreen fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -234,8 +260,8 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun dockingOnLockscreen_doesNotForceCommunalIfDreamStarts() = with(kosmos) { testScope.runTest { - communalInteractor.changeScene(CommunalScenes.Blank) - val scene by collectLastValue(communalInteractor.desiredScene) + communalSceneInteractor.changeScene(CommunalScenes.Blank) + val scene by collectLastValue(communalSceneInteractor.currentScene) // device is docked while on the lockscreen fakeKeyguardTransitionRepository.sendTransitionSteps( @@ -266,9 +292,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Scene times out back to blank after the screen timeout. @@ -283,11 +309,11 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is not dreaming and on communal. updateDreaming(false) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) // Scene stays as Communal advanceTimeBy(SCREEN_TIMEOUT.milliseconds) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) } } @@ -298,9 +324,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Wait a bit, but not long enough to timeout. @@ -321,9 +347,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is on communal, but not dreaming. updateDreaming(false) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Wait a bit, but not long enough to timeout, then start dreaming. @@ -342,11 +368,11 @@ class CommunalSceneStartableTest : SysuiTestCase() { with(kosmos) { testScope.runTest { // Device is on communal. - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) // Device stays on the hub after the timeout since we're not dreaming. advanceTimeBy(SCREEN_TIMEOUT.milliseconds * 2) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Start dreaming. @@ -363,9 +389,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { testScope.runTest { // Device is dreaming and on communal. updateDreaming(true) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Wait a bit, but not long enough to timeout. @@ -392,9 +418,9 @@ class CommunalSceneStartableTest : SysuiTestCase() { // Device is dreaming and on communal. updateDreaming(true) - communalInteractor.changeScene(CommunalScenes.Communal) + communalSceneInteractor.changeScene(CommunalScenes.Communal) - val scene by collectLastValue(communalInteractor.desiredScene) + val scene by collectLastValue(communalSceneInteractor.currentScene) assertThat(scene).isEqualTo(CommunalScenes.Communal) // Scene times out back to blank after the screen timeout. @@ -421,12 +447,6 @@ class CommunalSceneStartableTest : SysuiTestCase() { runCurrent() } - private suspend fun TestScope.enableCommunal() = - with(kosmos) { - setCommunalAvailable(true) - runCurrent() - } - companion object { private const val SCREEN_TIMEOUT = 1000 } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt index 6ca04dfca6a4..84dbfd488fe7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt @@ -39,6 +39,7 @@ import com.android.systemui.communal.data.repository.fakeCommunalMediaRepository import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.log.CommunalUiEvent @@ -106,6 +107,7 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { underTest = CommunalEditModeViewModel( + kosmos.communalSceneInteractor, kosmos.communalInteractor, kosmos.communalSettingsInteractor, mediaHost, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt index 6b807754dead..351c5ae18064 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt @@ -36,6 +36,7 @@ import com.android.systemui.communal.data.repository.fakeCommunalRepository import com.android.systemui.communal.data.repository.fakeCommunalTutorialRepository import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository import com.android.systemui.communal.domain.interactor.communalInteractor +import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalTutorialInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalScenes @@ -143,6 +144,7 @@ class CommunalViewModelTest(flags: FlagsParameterization) : SysuiTestCase() { context.resources, kosmos.keyguardTransitionInteractor, kosmos.keyguardInteractor, + kosmos.communalSceneInteractor, kosmos.communalInteractor, kosmos.communalTutorialInteractor, kosmos.shadeInteractor, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt index b4f87c47a0b0..420b11c4bde3 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/widgets/WidgetInteractionHandlerTest.kt @@ -72,6 +72,7 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard( eq(testIntent), + eq(false), isNull(), notNull(), refEq(fillInIntent), @@ -91,6 +92,7 @@ class WidgetInteractionHandlerTest : SysuiTestCase() { verify(activityStarter) .startPendingIntentMaybeDismissingKeyguard( eq(testIntent), + eq(false), isNull(), isNull(), refEq(fillInIntent), diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt index 0ca620751ddf..57d325129fa2 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImplTest.kt @@ -33,6 +33,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.LaunchableView import com.android.systemui.assist.AssistManager +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.keyguard.KeyguardViewMediator import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.ActivityStarter.OnDismissAction @@ -94,6 +95,7 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { @Mock private lateinit var deviceProvisionedController: DeviceProvisionedController @Mock private lateinit var userTracker: UserTracker @Mock private lateinit var activityIntentHelper: ActivityIntentHelper + @Mock private lateinit var communalSceneInteractor: CommunalSceneInteractor private lateinit var underTest: LegacyActivityStarterInternalImpl private val mainExecutor = FakeExecutor(FakeSystemClock()) private val shadeAnimationInteractor = @@ -127,6 +129,7 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { userTracker = userTracker, activityIntentHelper = activityIntentHelper, mainExecutor = mainExecutor, + communalSceneInteractor = communalSceneInteractor, ) whenever(userTracker.userHandle).thenReturn(UserHandle.OWNER) } @@ -138,7 +141,7 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { whenever(keyguardStateController.isShowing).thenReturn(true) whenever(deviceProvisionedController.isDeviceProvisioned).thenReturn(true) - underTest.startPendingIntentDismissingKeyguard(pendingIntent) + underTest.startPendingIntentDismissingKeyguard(intent = pendingIntent, dismissShade = true) mainExecutor.runAllReady() verify(statusBarKeyguardViewManager) @@ -232,6 +235,7 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { underTest.startPendingIntentDismissingKeyguard( intent = pendingIntent, + dismissShade = true, intentSentUiThreadCallback = null, associatedView = associatedView, ) @@ -344,6 +348,7 @@ class LegacyActivityStarterInternalImplTest : SysuiTestCase() { ) { underTest.startPendingIntentDismissingKeyguard( intent = intent, + dismissShade = true, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java index 072ec9986c61..de659315e176 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ActivityStarter.java @@ -70,9 +70,11 @@ public interface ActivityStarter { /** * Similar to {@link #startPendingIntentMaybeDismissingKeyguard(PendingIntent, Runnable, * ActivityTransitionAnimator.Controller)}, but also specifies a fill-in intent and extra - * options that could be used to populate the pending intent and launch the activity. + * option that could be used to populate the pending intent and launch the activity. This also + * allows the caller to avoid dismissing the shade. */ void startPendingIntentMaybeDismissingKeyguard(PendingIntent intent, + boolean dismissShade, @Nullable Runnable intentSentUiThreadCallback, @Nullable ActivityTransitionAnimator.Controller animationController, @Nullable Intent fillInIntent, diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt index 6f20a8daf00a..d522c7e16603 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt @@ -20,6 +20,7 @@ import android.provider.Settings import com.android.compose.animation.scene.SceneKey import com.android.systemui.CoreStartable import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.communal.shared.model.CommunalTransitionKeys import com.android.systemui.dagger.SysUISingleton @@ -32,10 +33,13 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.statusbar.NotificationShadeWindowController +import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.util.kotlin.emitOnStart +import com.android.systemui.util.kotlin.getValue import com.android.systemui.util.kotlin.sample import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import com.android.systemui.util.settings.SystemSettings +import java.util.Optional import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.seconds @@ -64,9 +68,11 @@ class CommunalSceneStartable constructor( private val dockManager: DockManager, private val communalInteractor: CommunalInteractor, + private val communalSceneInteractor: CommunalSceneInteractor, private val keyguardTransitionInteractor: KeyguardTransitionInteractor, private val keyguardInteractor: KeyguardInteractor, private val systemSettings: SystemSettings, + centralSurfacesOpt: Optional<CentralSurfaces>, private val notificationShadeWindowController: NotificationShadeWindowController, @Application private val applicationScope: CoroutineScope, @Background private val bgScope: CoroutineScope, @@ -78,13 +84,15 @@ constructor( private var isDreaming: Boolean = false + private val centralSurfaces: CentralSurfaces? by centralSurfacesOpt + override fun start() { // Handle automatically switching based on keyguard state. keyguardTransitionInteractor.startedKeyguardTransitionStep .mapLatest(::determineSceneAfterTransition) .filterNotNull() .onEach { nextScene -> - communalInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade) + communalSceneInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade) } .launchIn(applicationScope) @@ -124,7 +132,7 @@ constructor( // app is updated by the Play store, a new timeout should be started. bgScope.launch { combine( - communalInteractor.desiredScene, + communalSceneInteractor.currentScene, // Emit a value on start so the combine starts. communalInteractor.userActivity.emitOnStart() ) { scene, _ -> @@ -140,19 +148,19 @@ constructor( } bgScope.launch { keyguardInteractor.isDreaming - .sample(communalInteractor.desiredScene, ::Pair) + .sample(communalSceneInteractor.currentScene, ::Pair) .collectLatest { (isDreaming, scene) -> this@CommunalSceneStartable.isDreaming = isDreaming if (scene == CommunalScenes.Communal && isDreaming && timeoutJob == null) { // If dreaming starts after timeout has expired, ex. if dream restarts under // the hub, just close the hub immediately. - communalInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene(CommunalScenes.Blank) } } } bgScope.launch { - communalInteractor.isIdleOnCommunal.collectLatest { + communalSceneInteractor.isIdleOnCommunal.collectLatest { withContext(mainDispatcher) { notificationShadeWindowController.setGlanceableHubShowing(it) } @@ -171,7 +179,7 @@ constructor( bgScope.launch { delay(screenTimeout.milliseconds) if (isDreaming) { - communalInteractor.changeScene(CommunalScenes.Blank) + communalSceneInteractor.changeScene(CommunalScenes.Blank) } timeoutJob = null } @@ -184,11 +192,15 @@ constructor( val to = lastStartedTransition.to val from = lastStartedTransition.from val docked = dockManager.isDocked + val launchingActivityOverLockscreen = + centralSurfaces?.isLaunchingActivityOverLockscreen ?: false return when { - to == KeyguardState.OCCLUDED -> { + to == KeyguardState.OCCLUDED && !launchingActivityOverLockscreen -> { // Hide communal when an activity is started on keyguard, to ensure the activity - // underneath the hub is shown. + // underneath the hub is shown. When launching activities over lockscreen, we only + // change scenes once the activity launch animation is finished, so avoid + // changing the scene here. CommunalScenes.Blank } to == KeyguardState.GLANCEABLE_HUB && from == KeyguardState.OCCLUDED -> { diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt index db251fde187d..3d9e8615fb18 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt @@ -23,6 +23,7 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.widgets.WidgetConfigurator import com.android.systemui.media.controls.ui.view.MediaHost @@ -33,10 +34,11 @@ import kotlinx.coroutines.flow.flowOf /** The base view model for the communal hub. */ abstract class BaseCommunalViewModel( + private val communalSceneInteractor: CommunalSceneInteractor, private val communalInteractor: CommunalInteractor, val mediaHost: MediaHost, ) { - val currentScene: Flow<SceneKey> = communalInteractor.desiredScene + val currentScene: Flow<SceneKey> = communalSceneInteractor.currentScene /** Whether communal hub should be focused by accessibility tools. */ open val isFocusable: Flow<Boolean> = MutableStateFlow(false) @@ -58,7 +60,7 @@ abstract class BaseCommunalViewModel( } fun changeScene(scene: SceneKey, transitionKey: TransitionKey? = null) { - communalInteractor.changeScene(scene, transitionKey) + communalSceneInteractor.changeScene(scene, transitionKey) } /** @@ -67,7 +69,7 @@ abstract class BaseCommunalViewModel( * Note that you must call is with `null` when the UI is done or risk a memory leak. */ fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) { - communalInteractor.setTransitionState(transitionState) + communalSceneInteractor.setTransitionState(transitionState) } /** diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt index 650852ce5876..bc65ccb9ed5a 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt @@ -25,6 +25,7 @@ import android.util.Log import androidx.activity.result.ActivityResultLauncher import com.android.internal.logging.UiEventLogger import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.log.CommunalUiEvent @@ -50,13 +51,14 @@ import kotlinx.coroutines.withContext class CommunalEditModeViewModel @Inject constructor( + communalSceneInteractor: CommunalSceneInteractor, private val communalInteractor: CommunalInteractor, private val communalSettingsInteractor: CommunalSettingsInteractor, @Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost, private val uiEventLogger: UiEventLogger, @CommunalLog logBuffer: LogBuffer, @Background private val backgroundDispatcher: CoroutineDispatcher, -) : BaseCommunalViewModel(communalInteractor, mediaHost) { +) : BaseCommunalViewModel(communalSceneInteractor, communalInteractor, mediaHost) { private val logger = Logger(logBuffer, "CommunalEditModeViewModel") diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt index 97db43bdf0f8..7f3a2dcb23dc 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalViewModel.kt @@ -20,6 +20,7 @@ import android.content.res.Resources import android.view.View import android.view.accessibility.AccessibilityNodeInfo import com.android.systemui.communal.domain.interactor.CommunalInteractor +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalTutorialInteractor import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.dagger.SysUISingleton @@ -65,12 +66,13 @@ constructor( @Main private val resources: Resources, keyguardTransitionInteractor: KeyguardTransitionInteractor, keyguardInteractor: KeyguardInteractor, + communalSceneInteractor: CommunalSceneInteractor, private val communalInteractor: CommunalInteractor, tutorialInteractor: CommunalTutorialInteractor, private val shadeInteractor: ShadeInteractor, @Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost, @CommunalLog logBuffer: LogBuffer, -) : BaseCommunalViewModel(communalInteractor, mediaHost) { +) : BaseCommunalViewModel(communalSceneInteractor, communalInteractor, mediaHost) { private val logger = Logger(logBuffer, "CommunalViewModel") diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt index 778d8cf56648..51a3a6d827dd 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetInteractionHandler.kt @@ -61,6 +61,7 @@ constructor( activityStarter.startPendingIntentMaybeDismissingKeyguard( pendingIntent, + /* dismissShade = */ false, /* intentSentUiThreadCallback = */ null, animationController, fillInIntent, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt index 6546db9a2868..2ab7aa95ff56 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterImpl.kt @@ -42,7 +42,10 @@ constructor( private val activityStarterInternal: ActivityStarterInternal = legacyActivityStarter.get() override fun startPendingIntentDismissingKeyguard(intent: PendingIntent) { - activityStarterInternal.startPendingIntentDismissingKeyguard(intent = intent) + activityStarterInternal.startPendingIntentDismissingKeyguard( + intent = intent, + dismissShade = true + ) } override fun startPendingIntentDismissingKeyguard( @@ -52,6 +55,7 @@ constructor( activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, + dismissShade = true, ) } @@ -64,6 +68,7 @@ constructor( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, associatedView = associatedView, + dismissShade = true, ) } @@ -76,6 +81,7 @@ constructor( intent = intent, intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, + dismissShade = true, ) } @@ -89,11 +95,13 @@ constructor( intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, + dismissShade = true, ) } override fun startPendingIntentMaybeDismissingKeyguard( intent: PendingIntent, + dismissShade: Boolean, intentSentUiThreadCallback: Runnable?, animationController: ActivityTransitionAnimator.Controller?, fillInIntent: Intent?, @@ -104,6 +112,7 @@ constructor( intentSentUiThreadCallback = intentSentUiThreadCallback, animationController = animationController, showOverLockscreen = true, + dismissShade = dismissShade, fillInIntent = fillInIntent, extraOptions = extraOptions, ) @@ -179,6 +188,7 @@ constructor( showOverLockscreenWhenLocked = showOverLockscreenWhenLocked, ) } + override fun startActivity( intent: Intent, dismissShade: Boolean, @@ -199,6 +209,7 @@ constructor( postOnUiThread { activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, + dismissShade = true, ) } } @@ -211,6 +222,7 @@ constructor( activityStarterInternal.startPendingIntentDismissingKeyguard( intent = intent, animationController = animationController, + dismissShade = true, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt index e8443982d560..c9becb4289b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternal.kt @@ -34,6 +34,7 @@ interface ActivityStarterInternal { */ fun startPendingIntentDismissingKeyguard( intent: PendingIntent, + dismissShade: Boolean, intentSentUiThreadCallback: Runnable? = null, associatedView: View? = null, animationController: ActivityTransitionAnimator.Controller? = null, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt index c101755bcf38..e580f6458be8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ActivityStarterInternalImpl.kt @@ -35,6 +35,7 @@ import javax.inject.Inject class ActivityStarterInternalImpl @Inject constructor() : ActivityStarterInternal { override fun startPendingIntentDismissingKeyguard( intent: PendingIntent, + dismissShade: Boolean, intentSentUiThreadCallback: Runnable?, associatedView: View?, animationController: ActivityTransitionAnimator.Controller?, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 8fb552f167bc..7b7a35b4928f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -199,6 +199,11 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable boolean isLaunchingActivityOverLockscreen(); + /** + * Whether an activity launch over lockscreen is causing the shade to be dismissed. + */ + boolean isDismissingShadeForActivityLaunch(); + void onKeyguardViewManagerStatesUpdated(); /** */ @@ -333,7 +338,8 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner, CoreStartable /** * Sets launching activity over LS state in central surfaces. */ - void setIsLaunchingActivityOverLockscreen(boolean isLaunchingActivityOverLockscreen); + void setIsLaunchingActivityOverLockscreen( + boolean isLaunchingActivityOverLockscreen, boolean dismissShade); /** * Gets an animation controller from a notification row. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt index 8af7ee8389e5..5ab56ae4be4d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesEmptyImpl.kt @@ -39,6 +39,7 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces { override fun updateIsKeyguard(forceStateChange: Boolean) = false override fun getKeyguardMessageArea(): AuthKeyguardMessageArea? = null override fun isLaunchingActivityOverLockscreen() = false + override fun isDismissingShadeForActivityLaunch() = false override fun onKeyguardViewManagerStatesUpdated() {} override fun getCommandQueuePanelsEnabled() = false override fun showWirelessChargingAnimation(batteryLevel: Int) {} @@ -96,7 +97,10 @@ abstract class CentralSurfacesEmptyImpl : CentralSurfaces { override fun setLaunchEmergencyActionOnFinishedWaking(launch: Boolean) {} override fun getQSPanelController(): QSPanelController? = null override fun getDisplayDensity() = 0f - override fun setIsLaunchingActivityOverLockscreen(isLaunchingActivityOverLockscreen: Boolean) {} + override fun setIsLaunchingActivityOverLockscreen( + isLaunchingActivityOverLockscreen: Boolean, + dismissShade: Boolean, + ) {} override fun getAnimatorControllerFromNotification( associatedView: ExpandableNotificationRow?, ): ActivityTransitionAnimator.Controller? = null diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index d3d2b1ebcb88..e0da2fe584b6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -544,6 +544,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { // Fingerprint (as computed by getLoggingFingerprint() of the last logged state. private int mLastLoggedStateFingerprint; private boolean mIsLaunchingActivityOverLockscreen; + private boolean mDismissingShadeForActivityLaunch; private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this); protected final BatteryController mBatteryController; @@ -1575,6 +1576,11 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { return mIsLaunchingActivityOverLockscreen; } + @Override + public boolean isDismissingShadeForActivityLaunch() { + return mDismissingShadeForActivityLaunch; + } + /** * To be called when there's a state change in StatusBarKeyguardViewManager. */ @@ -3306,8 +3312,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { } @Override - public void setIsLaunchingActivityOverLockscreen(boolean isLaunchingActivityOverLockscreen) { + public void setIsLaunchingActivityOverLockscreen( + boolean isLaunchingActivityOverLockscreen, boolean dismissShade) { mIsLaunchingActivityOverLockscreen = isLaunchingActivityOverLockscreen; + mDismissingShadeForActivityLaunch = dismissShade; mKeyguardViewMediator.launchingActivityOverLockscreen(mIsLaunchingActivityOverLockscreen); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt index bcc7db162ddd..b448d85bfd49 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyActivityStarterInternalImpl.kt @@ -33,10 +33,13 @@ import android.view.View import android.view.WindowManager import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.ActivityIntentHelper +import com.android.systemui.Flags.communalHub import com.android.systemui.animation.ActivityTransitionAnimator import com.android.systemui.animation.DelegateTransitionAnimatorController import com.android.systemui.assist.AssistManager import com.android.systemui.camera.CameraIntents +import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor +import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.DisplayId import com.android.systemui.dagger.qualifiers.Main @@ -89,6 +92,7 @@ constructor( private val userTracker: UserTracker, private val activityIntentHelper: ActivityIntentHelper, @Main private val mainExecutor: DelayableExecutor, + private val communalSceneInteractor: CommunalSceneInteractor, ) : ActivityStarterInternal { private val centralSurfaces: CentralSurfaces? get() = centralSurfacesOptLazy.get().getOrNull() @@ -219,6 +223,7 @@ constructor( override fun startPendingIntentDismissingKeyguard( intent: PendingIntent, + dismissShade: Boolean, intentSentUiThreadCallback: Runnable?, associatedView: View?, animationController: ActivityTransitionAnimator.Controller?, @@ -257,12 +262,12 @@ constructor( val statusBarController = wrapAnimationControllerForShadeOrStatusBar( animationController = animationController, - dismissShade = true, + dismissShade = dismissShade, isLaunchForActivity = intent.isActivity, ) val controller = if (actuallyShowOverLockscreen) { - wrapAnimationControllerForLockscreen(statusBarController) + wrapAnimationControllerForLockscreen(dismissShade, statusBarController) } else { statusBarController } @@ -270,7 +275,7 @@ constructor( // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we // run the animation on the keyguard). The animation will take care of (instantly) // collapsing the shade and hiding the keyguard once it is done. - val collapse = !animate + val collapse = dismissShade && !animate val runnable = Runnable { try { activityTransitionAnimator.startPendingIntentWithAnimation( @@ -377,7 +382,7 @@ constructor( dismissShade = dismissShade, isLaunchForActivity = true, ) - controller = wrapAnimationControllerForLockscreen(delegate) + controller = wrapAnimationControllerForLockscreen(dismissShade, delegate) } else if (dismissShade) { // The animation will take care of dismissing the shade at the end of the animation. // If we don't animate, collapse it directly. @@ -462,6 +467,9 @@ constructor( if (dismissShade) { shadeControllerLazy.get().collapseShadeForActivityStart() } + if (communalHub()) { + communalSceneInteractor.snapToScene(CommunalScenes.Blank) + } return deferred } @@ -532,6 +540,7 @@ constructor( * lockscreen, the correct flags are set for it to be occluded. */ private fun wrapAnimationControllerForLockscreen( + dismissShade: Boolean, animationController: ActivityTransitionAnimator.Controller? ): ActivityTransitionAnimator.Controller? { return animationController?.let { @@ -539,7 +548,7 @@ constructor( override fun onIntentStarted(willAnimate: Boolean) { delegate.onIntentStarted(willAnimate) if (willAnimate) { - centralSurfaces?.setIsLaunchingActivityOverLockscreen(true) + centralSurfaces?.setIsLaunchingActivityOverLockscreen(true, dismissShade) } } @@ -570,7 +579,10 @@ constructor( // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the post collapse runnables) // later on. - centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) + centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) + if (communalHub()) { + communalSceneInteractor.snapToScene(CommunalScenes.Blank) + } delegate.onTransitionAnimationEnd(isExpandingFullyAbove) } @@ -586,7 +598,7 @@ constructor( // mIsLaunchingActivityOverLockscreen being true means that we will // collapse the shade (or at least run the // post collapse // runnables) later on. - centralSurfaces?.setIsLaunchingActivityOverLockscreen(false) + centralSurfaces?.setIsLaunchingActivityOverLockscreen(false, false) delegate.onTransitionAnimationCancelled(newKeyguardOccludedState) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index 5bbc3bd92543..ebb62ec7bcac 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -1071,12 +1071,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__OCCLUDED); if (mCentralSurfaces.isLaunchingActivityOverLockscreen()) { - // When isLaunchingActivityOverLockscreen() is true, we know for sure that the post - // collapse runnables will be run. - mShadeController.get().addPostCollapseAction(() -> { + final Runnable postCollapseAction = () -> { mNotificationShadeWindowController.setKeyguardOccluded(isOccluded); reset(true /* hideBouncerWhenShowing */); - }); + }; + if (mCentralSurfaces.isDismissingShadeForActivityLaunch()) { + // When isDismissingShadeForActivityLaunch() is true, we know for sure that the + // post collapse runnables will be run. + mShadeController.get().addPostCollapseAction(postCollapseAction); + } else { + postCollapseAction.run(); + } return; } } else if (isShowing && isUnOccluding) { |