Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f2e79ad authored by Lucas Silva's avatar Lucas Silva
Browse files

Fix hub<->occluded transition when undocked

Currently, if the hub is occluded while undocked, when the occluding
activity is finished, the user will land back on the lockscreen instead
of the hub if the device is undocked.

This is due to the fact that we tie whether or not to show the hub to
the dock signal. Instead, this change updates the logic to always go
back to the hub from the occluded state if we entered the occluded state
from the hub.

Fixes: 338203881
Test: atest CommunalInteractorTest
Test: atest WmShellTest
Test: atest KeyguardTransitionScenariosTest
Flag: ACONFIG com.android.systemui.communal_hub TEAMFOOD
Change-Id: Ic9adf4dba601d4c416e7e18711c7c371117cbb2e
parent 0499cf71
Loading
Loading
Loading
Loading
+74 −0
Original line number Original line Diff line number Diff line
@@ -57,6 +57,8 @@ import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.activityStarter
import com.android.systemui.plugins.activityStarter
@@ -1085,6 +1087,78 @@ class CommunalInteractorTest : SysuiTestCase() {
                .isEqualTo(USER_INFO_WORK.id)
                .isEqualTo(USER_INFO_WORK.id)
        }
        }


    @Test
    fun showCommunalFromOccluded_enteredOccludedFromHub() =
        testScope.runTest {
            kosmos.setCommunalAvailable(true)
            val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
            assertThat(showCommunalFromOccluded).isFalse()

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.OCCLUDED,
                testScope
            )

            assertThat(showCommunalFromOccluded).isTrue()
        }

    @Test
    fun showCommunalFromOccluded_enteredOccludedFromLockscreen() =
        testScope.runTest {
            kosmos.setCommunalAvailable(true)
            val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
            assertThat(showCommunalFromOccluded).isFalse()

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.OCCLUDED,
                testScope
            )

            assertThat(showCommunalFromOccluded).isFalse()
        }

    @Test
    fun showCommunalFromOccluded_communalBecomesUnavailableWhileOccluded() =
        testScope.runTest {
            kosmos.setCommunalAvailable(true)
            val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
            assertThat(showCommunalFromOccluded).isFalse()

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.OCCLUDED,
                testScope
            )
            runCurrent()
            kosmos.setCommunalAvailable(false)

            assertThat(showCommunalFromOccluded).isFalse()
        }

    @Test
    fun showCommunalFromOccluded_showBouncerWhileOccluded() =
        testScope.runTest {
            kosmos.setCommunalAvailable(true)
            val showCommunalFromOccluded by collectLastValue(underTest.showCommunalFromOccluded)
            assertThat(showCommunalFromOccluded).isFalse()

            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.OCCLUDED,
                testScope
            )
            runCurrent()
            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.OCCLUDED,
                to = KeyguardState.PRIMARY_BOUNCER,
                testScope
            )

            assertThat(showCommunalFromOccluded).isTrue()
        }

    private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget {
    private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget {
        val timer = mock(SmartspaceTarget::class.java)
        val timer = mock(SmartspaceTarget::class.java)
        whenever(timer.smartspaceTargetId).thenReturn(id)
        whenever(timer.smartspaceTargetId).thenReturn(id)
+10 −21
Original line number Original line Diff line number Diff line
@@ -24,16 +24,17 @@ import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.keyguardUpdateMonitor
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.domain.interactor.setCommunalAvailable
import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
import com.android.systemui.communal.ui.viewmodel.communalTransitionViewModel
import com.android.systemui.communal.util.fakeCommunalColors
import com.android.systemui.communal.util.fakeCommunalColors
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.concurrency.fakeExecutor
import com.android.systemui.dock.DockManager
import com.android.systemui.dock.fakeDockManager
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.keyguard.ScreenLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.wakefulnessLifecycle
import com.android.systemui.keyguard.wakefulnessLifecycle
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.SysUiState
import com.android.systemui.model.SysUiState
@@ -63,7 +64,6 @@ import com.android.wm.shell.sysui.ShellInterface
import java.util.Optional
import java.util.Optional
import java.util.concurrent.Executor
import java.util.concurrent.Executor
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
@@ -186,29 +186,18 @@ class WMShellTest : SysuiTestCase() {
            verify(mRecentTasks).setTransitionBackgroundColor(null)
            verify(mRecentTasks).setTransitionBackgroundColor(null)
            verify(mRecentTasks, never()).setTransitionBackgroundColor(black)
            verify(mRecentTasks, never()).setTransitionBackgroundColor(black)


            setDocked(true)
            // Transition to occluded from the glanceable hub.
            // Make communal available
            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
            kosmos.fakeKeyguardRepository.setIsEncryptedOrLockdown(false)
                from = KeyguardState.GLANCEABLE_HUB,
            kosmos.fakeUserRepository.setSelectedUserInfo(MAIN_USER_INFO)
                to = KeyguardState.OCCLUDED,
            kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
                testScope

            )
            kosmos.setCommunalAvailable(true)
            runCurrent()
            runCurrent()


            verify(mRecentTasks).setTransitionBackgroundColor(black)
            verify(mRecentTasks).setTransitionBackgroundColor(black)
        }
        }


    private fun TestScope.setDocked(docked: Boolean) {
        kosmos.fakeDockManager.setIsDocked(docked)
        val event =
            if (docked) {
                DockManager.STATE_DOCKED
            } else {
                DockManager.STATE_NONE
            }
        kosmos.fakeDockManager.setDockEvent(event)
        runCurrent()
    }

    private companion object {
    private companion object {
        val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
        val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
    }
    }
+21 −6
Original line number Original line Diff line number Diff line
@@ -44,9 +44,10 @@ import com.android.systemui.communal.widgets.EditWidgetsActivityStarter
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dock.DockManager
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dock.retrieveIsDocked
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.Logger
import com.android.systemui.log.core.Logger
import com.android.systemui.log.dagger.CommunalLog
import com.android.systemui.log.dagger.CommunalLog
@@ -64,6 +65,7 @@ import com.android.systemui.util.kotlin.BooleanFlowOperators.not
import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.android.systemui.util.kotlin.BooleanFlowOperators.or
import com.android.systemui.util.kotlin.emitOnStart
import com.android.systemui.util.kotlin.emitOnStart
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.channels.BufferOverflow
@@ -77,9 +79,11 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.shareIn
@@ -92,6 +96,7 @@ class CommunalInteractor
@Inject
@Inject
constructor(
constructor(
    @Application val applicationScope: CoroutineScope,
    @Application val applicationScope: CoroutineScope,
    @Background val bgDispatcher: CoroutineDispatcher,
    broadcastDispatcher: BroadcastDispatcher,
    broadcastDispatcher: BroadcastDispatcher,
    private val communalRepository: CommunalRepository,
    private val communalRepository: CommunalRepository,
    private val widgetRepository: CommunalWidgetRepository,
    private val widgetRepository: CommunalWidgetRepository,
@@ -99,13 +104,13 @@ constructor(
    mediaRepository: CommunalMediaRepository,
    mediaRepository: CommunalMediaRepository,
    smartspaceRepository: SmartspaceRepository,
    smartspaceRepository: SmartspaceRepository,
    keyguardInteractor: KeyguardInteractor,
    keyguardInteractor: KeyguardInteractor,
    private val communalSettingsInteractor: CommunalSettingsInteractor,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    communalSettingsInteractor: CommunalSettingsInteractor,
    private val appWidgetHost: CommunalAppWidgetHost,
    private val appWidgetHost: CommunalAppWidgetHost,
    private val editWidgetsActivityStarter: EditWidgetsActivityStarter,
    private val editWidgetsActivityStarter: EditWidgetsActivityStarter,
    private val userTracker: UserTracker,
    private val userTracker: UserTracker,
    private val activityStarter: ActivityStarter,
    private val activityStarter: ActivityStarter,
    private val userManager: UserManager,
    private val userManager: UserManager,
    private val dockManager: DockManager,
    sceneInteractor: SceneInteractor,
    sceneInteractor: SceneInteractor,
    @CommunalLog logBuffer: LogBuffer,
    @CommunalLog logBuffer: LogBuffer,
    @CommunalTableLog tableLogBuffer: TableLogBuffer,
    @CommunalTableLog tableLogBuffer: TableLogBuffer,
@@ -145,8 +150,18 @@ constructor(
                replay = 1,
                replay = 1,
            )
            )


    /** Whether to show communal by default */
    /** Whether to show communal when exiting the occluded state. */
    val showByDefault: Flow<Boolean> = and(isCommunalAvailable, dockManager.retrieveIsDocked())
    val showCommunalFromOccluded: Flow<Boolean> =
        keyguardTransitionInteractor.startedKeyguardTransitionStep
            .filter { step -> step.to == KeyguardState.OCCLUDED }
            .combine(isCommunalAvailable, ::Pair)
            .map { (step, available) -> available && step.from == KeyguardState.GLANCEABLE_HUB }
            .flowOn(bgDispatcher)
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )


    /**
    /**
     * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
     * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
+7 −4
Original line number Original line Diff line number Diff line
@@ -63,8 +63,8 @@ constructor(
            )
            )
            .distinctUntilChanged()
            .distinctUntilChanged()


    /** Whether to show communal by default */
    /** Whether to show communal when exiting the occluded state. */
    val showByDefault: Flow<Boolean> = communalInteractor.showByDefault
    val showCommunalFromOccluded: Flow<Boolean> = communalInteractor.showCommunalFromOccluded


    val transitionFromOccludedEnded =
    val transitionFromOccludedEnded =
        keyguardTransitionInteractor.transitionStepsFromState(KeyguardState.OCCLUDED).filter { step
        keyguardTransitionInteractor.transitionStepsFromState(KeyguardState.OCCLUDED).filter { step
@@ -74,8 +74,11 @@ constructor(
        }
        }


    val recentsBackgroundColor: Flow<Color?> =
    val recentsBackgroundColor: Flow<Color?> =
        combine(showByDefault, communalColors.backgroundColor) { showByDefault, backgroundColor ->
        combine(showCommunalFromOccluded, communalColors.backgroundColor) {
            if (showByDefault) {
            showCommunalFromOccluded,
            backgroundColor,
            ->
            if (showCommunalFromOccluded) {
                backgroundColor
                backgroundColor
            } else {
            } else {
                null
                null
+9 −8
Original line number Original line Diff line number Diff line
@@ -177,10 +177,6 @@ import com.android.systemui.util.time.SystemClock;
import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
import com.android.systemui.wallpapers.data.repository.WallpaperRepository;
import com.android.wm.shell.keyguard.KeyguardTransitions;
import com.android.wm.shell.keyguard.KeyguardTransitions;


import dagger.Lazy;

import kotlinx.coroutines.CoroutineDispatcher;

import java.io.PrintWriter;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@@ -190,6 +186,9 @@ import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.function.Consumer;


import dagger.Lazy;
import kotlinx.coroutines.CoroutineDispatcher;

/**
/**
 * Mediates requests related to the keyguard.  This includes queries about the
 * Mediates requests related to the keyguard.  This includes queries about the
 * state of the keyguard, power management events that effect whether the keyguard
 * state of the keyguard, power management events that effect whether the keyguard
@@ -1234,7 +1233,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                            mUnoccludeAnimator.cancel();
                            mUnoccludeAnimator.cancel();
                        }
                        }


                        if (isDream || mShowCommunalByDefault) {
                        if (isDream || mShowCommunalWhenUnoccluding) {
                            initAlphaForAnimationTargets(wallpapers);
                            initAlphaForAnimationTargets(wallpapers);
                            if (isDream) {
                            if (isDream) {
                                mDreamViewModel.get().startTransitionFromDream();
                                mDreamViewModel.get().startTransitionFromDream();
@@ -1372,7 +1371,7 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
    private final Lazy<DreamViewModel> mDreamViewModel;
    private final Lazy<DreamViewModel> mDreamViewModel;
    private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel;
    private final Lazy<CommunalTransitionViewModel> mCommunalTransitionViewModel;
    private RemoteAnimationTarget mRemoteAnimationTarget;
    private RemoteAnimationTarget mRemoteAnimationTarget;
    private boolean mShowCommunalByDefault = false;
    private boolean mShowCommunalWhenUnoccluding = false;


    private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager;
    private final Lazy<WindowManagerLockscreenVisibilityManager> mWmLockscreenVisibilityManager;


@@ -1630,8 +1629,10 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
                    getRemoteSurfaceAlphaApplier());
                    getRemoteSurfaceAlphaApplier());
            mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(),
            mJavaAdapter.alwaysCollectFlow(dreamViewModel.getTransitionEnded(),
                    getFinishedCallbackConsumer());
                    getFinishedCallbackConsumer());
            mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowByDefault(),
            mJavaAdapter.alwaysCollectFlow(communalViewModel.getShowCommunalFromOccluded(),
                    (showByDefault) -> mShowCommunalByDefault = showByDefault);
                    (showCommunalFromOccluded) -> {
                        mShowCommunalWhenUnoccluding = showCommunalFromOccluded;
                    });
            mJavaAdapter.alwaysCollectFlow(communalViewModel.getTransitionFromOccludedEnded(),
            mJavaAdapter.alwaysCollectFlow(communalViewModel.getTransitionFromOccludedEnded(),
                    getFinishedCallbackConsumer());
                    getFinishedCallbackConsumer());
        }
        }
Loading