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

Commit c0ddfda6 authored by Lucas Silva's avatar Lucas Silva Committed by Android (Google) Code Review
Browse files

Merge "Revert "Refine hub power button behavior"" into main

parents 1caf584c 06467edc
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -21,18 +21,23 @@ import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.backgroundScope
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.scene.shared.model.SceneDataSource
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.flowOf
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.argumentCaptor
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify

@SmallTest
@RunWith(AndroidJUnit4::class)
@@ -44,8 +49,10 @@ class CommunalSceneRepositoryImplTest : SysuiTestCase() {
    private val Kosmos.underTest by
        Kosmos.Fixture {
            CommunalSceneRepositoryImpl(
                applicationScope = applicationCoroutineScope,
                backgroundScope = backgroundScope,
                sceneDataSource = delegator,
                delegator = delegator,
            )
        }

@@ -83,4 +90,18 @@ class CommunalSceneRepositoryImplTest : SysuiTestCase() {
            assertThat(transitionState)
                .isEqualTo(ObservableTransitionState.Idle(CommunalScenes.Default))
        }

    @Test
    fun showHubFromPowerButton() =
        kosmos.runTest {
            fakeKeyguardRepository.setKeyguardShowing(false)

            underTest.showHubFromPowerButton()

            argumentCaptor<SceneDataSource>().apply {
                verify(delegator).setDelegate(capture())

                assertThat(firstValue.currentScene.value).isEqualTo(CommunalScenes.Communal)
            }
        }
}
+2 −11
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.Flags.FLAG_COMMUNAL_RESPONSIVE_GRID
import com.android.systemui.Flags.FLAG_COMMUNAL_WIDGET_RESIZING
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.Flags.glanceableHubV2
import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.broadcastDispatcher
import com.android.systemui.communal.data.model.CommunalSmartspaceTimer
@@ -91,7 +90,6 @@ import platform.test.runner.parameterized.Parameters

@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
@EnableFlags(FLAG_COMMUNAL_HUB)
class CommunalInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {
    private val mainUser =
        UserInfo(/* id= */ 0, /* name= */ "primary user", /* flags= */ UserInfo.FLAG_MAIN)
@@ -112,9 +110,7 @@ class CommunalInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {
        kosmos.fakeUserRepository.setUserInfos(listOf(mainUser, secondaryUser))

        kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true)
        if (glanceableHubV2()) {
            kosmos.setCommunalV2ConfigEnabled(true)
        }
        mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB)
    }

    @Test
@@ -124,9 +120,7 @@ class CommunalInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {
            assertThat(underTest.isCommunalEnabled.value).isTrue()
        }

    /** Test not applicable when [FLAG_GLANCEABLE_HUB_V2] enabled */
    @Test
    @DisableFlags(FLAG_GLANCEABLE_HUB_V2)
    fun isCommunalAvailable_whenKeyguardShowing_true() =
        kosmos.runTest {
            communalSettingsInteractor.setSuppressionReasons(emptyList())
@@ -1218,10 +1212,7 @@ class CommunalInteractorTest(flags: FlagsParameterization) : SysuiTestCase() {
        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf(
                FLAG_COMMUNAL_RESPONSIVE_GRID,
                FLAG_GLANCEABLE_HUB_V2,
            )
            return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_RESPONSIVE_GRID)
        }

        private val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
+9 −25
Original line number Diff line number Diff line
@@ -18,18 +18,15 @@ package com.android.systemui.communal.widgets

import android.appwidget.AppWidgetProviderInfo
import android.content.pm.UserInfo
import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_COMMUNAL_HUB
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.fakeCommunalWidgetRepository
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.communal.domain.interactor.communalSettingsInteractor
import com.android.systemui.communal.domain.interactor.setCommunalEnabled
import com.android.systemui.communal.domain.interactor.setCommunalV2ConfigEnabled
import com.android.systemui.communal.shared.model.FakeGlanceableHubMultiUserHelper
import com.android.systemui.communal.shared.model.fakeGlanceableHubMultiUserHelper
import com.android.systemui.coroutines.collectLastValue
@@ -57,13 +54,10 @@ import org.mockito.Mockito.never
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters

@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
@EnableFlags(FLAG_COMMUNAL_HUB)
class CommunalAppWidgetHostStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
@RunWith(AndroidJUnit4::class)
class CommunalAppWidgetHostStartableTest : SysuiTestCase() {
    private val kosmos = testKosmos()

    @Mock private lateinit var appWidgetHost: CommunalAppWidgetHost
@@ -77,27 +71,12 @@ class CommunalAppWidgetHostStartableTest(flags: FlagsParameterization) : SysuiTe
    private lateinit var communalInteractorSpy: CommunalInteractor
    private lateinit var underTest: CommunalAppWidgetHostStartable

    init {
        mSetFlagsRule.setFlagsParameterization(flags)
    }

    companion object {
        private val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
        private val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE)

        @JvmStatic
        @Parameters(name = "{0}")
        fun getParams(): List<FlagsParameterization> {
            return FlagsParameterization.allCombinationsOf(FLAG_GLANCEABLE_HUB_V2)
        }
    }

    @Before
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        kosmos.fakeUserRepository.setUserInfos(listOf(MAIN_USER_INFO, USER_INFO_WORK))
        kosmos.fakeFeatureFlagsClassic.set(Flags.COMMUNAL_SERVICE_ENABLED, true)
        kosmos.setCommunalV2ConfigEnabled(true)
        mSetFlagsRule.enableFlags(FLAG_COMMUNAL_HUB)

        widgetManager = kosmos.mockGlanceableHubWidgetManager
        helper = kosmos.fakeGlanceableHubMultiUserHelper
@@ -348,4 +327,9 @@ class CommunalAppWidgetHostStartableTest(flags: FlagsParameterization) : SysuiTe
                fakeKeyguardRepository.setKeyguardShowing(true)
            }
        }

    private companion object {
        val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN)
        val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE)
    }
}
+26 −50
Original line number Diff line number Diff line
@@ -21,12 +21,8 @@ import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.communalSceneRepository
import com.android.systemui.communal.domain.interactor.setCommunalV2Enabled
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepositorySpy
@@ -36,12 +32,10 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.testKosmos
import com.google.common.truth.Truth
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
@@ -52,10 +46,12 @@ import org.mockito.Mockito.reset
@RunWith(AndroidJUnit4::class)
class FromGoneTransitionInteractorTest : SysuiTestCase() {
    private val kosmos =
        testKosmos().useUnconfinedTestDispatcher().apply {
        testKosmos().apply {
            this.keyguardTransitionRepository = fakeKeyguardTransitionRepositorySpy
        }
    private val testScope = kosmos.testScope
    private val underTest = kosmos.fromGoneTransitionInteractor
    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepositorySpy

    @Before
    fun setUp() {
@@ -65,8 +61,8 @@ class FromGoneTransitionInteractorTest : SysuiTestCase() {
    @Test
    @Ignore("Fails due to fix for b/324432820 - will re-enable once permanent fix is submitted.")
    fun testDoesNotTransitionToLockscreen_ifStartedButNotFinishedInGone() =
        kosmos.runTest {
            fakeKeyguardTransitionRepositorySpy.sendTransitionSteps(
        testScope.runTest {
            keyguardTransitionRepository.sendTransitionSteps(
                listOf(
                    TransitionStep(
                        from = KeyguardState.LOCKSCREEN,
@@ -81,74 +77,54 @@ class FromGoneTransitionInteractorTest : SysuiTestCase() {
                ),
                testScope,
            )
            reset(fakeKeyguardTransitionRepositorySpy)
            fakeKeyguardRepository.setKeyguardShowing(true)
            reset(keyguardTransitionRepository)
            kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
            runCurrent()

            // We're in the middle of a LOCKSCREEN -> GONE transition.
            assertThat(fakeKeyguardTransitionRepositorySpy).noTransitionsStarted()
            assertThat(keyguardTransitionRepository).noTransitionsStarted()
        }

    @Test
    @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
    @DisableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
    fun testTransitionsToLockscreen_ifFinishedInGone() =
        kosmos.runTest {
            fakeKeyguardTransitionRepositorySpy.sendTransitionSteps(
        testScope.runTest {
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GONE,
                testScope,
            )
            reset(fakeKeyguardTransitionRepositorySpy)
            fakeKeyguardRepository.setKeyguardShowing(true)
            reset(keyguardTransitionRepository)
            kosmos.fakeKeyguardRepository.setKeyguardShowing(true)
            runCurrent()

            // We're in the middle of a GONE -> LOCKSCREEN transition.
            assertThat(fakeKeyguardTransitionRepositorySpy)
            assertThat(keyguardTransitionRepository)
                .startedTransition(to = KeyguardState.LOCKSCREEN)
        }

    @Test
    @EnableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
    @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
    fun testTransitionsToLockscreen_ifFinishedInGone_wmRefactor() =
        kosmos.runTest {
            fakeKeyguardTransitionRepositorySpy.sendTransitionSteps(
        testScope.runTest {
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GONE,
                testScope,
            )
            reset(fakeKeyguardTransitionRepositorySpy)
            reset(keyguardTransitionRepository)

            // Trigger lockdown.
            fakeBiometricSettingsRepository.setAuthenticationFlags(
            kosmos.fakeBiometricSettingsRepository.setAuthenticationFlags(
                AuthenticationFlags(
                    0,
                    LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
                )
            )
            runCurrent()

            // We're in the middle of a GONE -> LOCKSCREEN transition.
            assertThat(fakeKeyguardTransitionRepositorySpy)
            assertThat(keyguardTransitionRepository)
                .startedTransition(to = KeyguardState.LOCKSCREEN)
        }

    @Test
    @EnableFlags(FLAG_GLANCEABLE_HUB_V2)
    @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
    fun testTransitionToGlanceableHub() =
        kosmos.runTest {
            val currentScene by collectLastValue(communalSceneRepository.currentScene)

            fakeKeyguardTransitionRepositorySpy.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GONE,
                testScope,
            )
            reset(fakeKeyguardTransitionRepositorySpy)
            // Communal is enabled
            setCommunalV2Enabled(true)
            Truth.assertThat(currentScene).isEqualTo(CommunalScenes.Blank)

            fakeKeyguardRepository.setKeyguardShowing(true)

            Truth.assertThat(currentScene).isEqualTo(CommunalScenes.Communal)
            assertThat(fakeKeyguardTransitionRepositorySpy).noTransitionsStarted()
        }
}
+59 −2
Original line number Diff line number Diff line
@@ -19,13 +19,16 @@ package com.android.systemui.communal.data.repository
import android.content.res.Configuration
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
import com.android.systemui.communal.dagger.Communal
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.scene.shared.model.SceneDataSource
import com.android.systemui.scene.shared.model.SceneDataSourceDelegator
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -56,6 +59,9 @@ interface CommunalSceneRepository {
    /** Immediately snaps to the desired scene. */
    fun snapToScene(toScene: SceneKey)

    /** Shows the hub from a power button press. */
    suspend fun showHubFromPowerButton()

    /**
     * Updates the transition state of the hub [SceneTransitionLayout].
     *
@@ -71,8 +77,10 @@ interface CommunalSceneRepository {
class CommunalSceneRepositoryImpl
@Inject
constructor(
    @Application private val applicationScope: CoroutineScope,
    @Background backgroundScope: CoroutineScope,
    @Communal private val sceneDataSource: SceneDataSource,
    @Communal private val delegator: SceneDataSourceDelegator,
) : CommunalSceneRepository {

    override val currentScene: StateFlow<SceneKey> = sceneDataSource.currentScene
@@ -94,17 +102,37 @@ constructor(
        _communalContainerOrientation.asStateFlow()

    override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) {
        applicationScope.launch {
            // SceneTransitionLayout state updates must be triggered on the thread the STL was
            // created on.
            sceneDataSource.changeScene(toScene, transitionKey)
        }
    }

    override fun snapToScene(toScene: SceneKey) {
        applicationScope.launch {
            // SceneTransitionLayout state updates must be triggered on the thread the STL was
            // created on.
            sceneDataSource.snapToScene(toScene)
        }
    }

    override fun setCommunalContainerOrientation(orientation: Int) {
        _communalContainerOrientation.value = orientation
    }

    override suspend fun showHubFromPowerButton() {
        // If keyguard is not showing yet, the hub view is not ready and the
        // [SceneDataSourceDelegator] will still be using the default [NoOpSceneDataSource]
        // and initial key, which is Blank. This means that when the hub container loads, it
        // will default to not showing the hub. Attempting to set the scene in this state
        // is simply ignored by the [NoOpSceneDataSource]. Instead, we temporarily override
        // it with a new one that defaults to Communal. This delegate will be overwritten
        // once the [CommunalContainer] loads.
        // TODO(b/392969914): show the hub first instead of forcing the scene.
        delegator.setDelegate(NoOpSceneDataSource(CommunalScenes.Communal))
    }

    /**
     * Updates the transition state of the hub [SceneTransitionLayout].
     *
@@ -113,4 +141,33 @@ constructor(
    override fun setTransitionState(transitionState: Flow<ObservableTransitionState>?) {
        _transitionState.value = transitionState
    }

    /** Noop implementation of a scene data source that always returns the initial [SceneKey]. */
    private class NoOpSceneDataSource(initialSceneKey: SceneKey) : SceneDataSource {
        override val currentScene: StateFlow<SceneKey> =
            MutableStateFlow(initialSceneKey).asStateFlow()

        override val currentOverlays: StateFlow<Set<OverlayKey>> =
            MutableStateFlow(emptySet<OverlayKey>()).asStateFlow()

        override fun changeScene(toScene: SceneKey, transitionKey: TransitionKey?) = Unit

        override fun snapToScene(toScene: SceneKey) = Unit

        override fun showOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) = Unit

        override fun hideOverlay(overlay: OverlayKey, transitionKey: TransitionKey?) = Unit

        override fun replaceOverlay(
            from: OverlayKey,
            to: OverlayKey,
            transitionKey: TransitionKey?,
        ) = Unit

        override fun instantlyShowOverlay(overlay: OverlayKey) = Unit

        override fun instantlyHideOverlay(overlay: OverlayKey) = Unit

        override fun freezeAndAnimateToCurrentState() = Unit
    }
}
Loading