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

Commit 04b421bc authored by Kevin Chyn's avatar Kevin Chyn Committed by Android (Google) Code Review
Browse files

Merge "Ensure RDM dialog is shown after screen off/on" into main

parents 9dd1b5f0 f4bf234d
Loading
Loading
Loading
Loading
+47 −20
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.content.Context
import android.hardware.devicestate.DeviceStateManager
import android.hardware.devicestate.feature.flags.Flags
import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -28,8 +30,11 @@ import com.android.systemui.statusbar.phone.SystemUIDialog
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

/**
 * Provides a {@link com.android.systemui.statusbar.phone.SystemUIDialog} to be shown on the inner
@@ -46,6 +51,7 @@ internal constructor(
    private val rearDisplayStateInteractor: RearDisplayStateInteractor,
    private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory,
    @Application private val scope: CoroutineScope,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
) : CoreStartable, AutoCloseable {

    companion object {
@@ -53,6 +59,16 @@ internal constructor(
    }

    @VisibleForTesting var stateChangeListener: Job? = null
    private val keyguardVisible = MutableStateFlow(false)
    private val keyguardVisibleFlow = keyguardVisible.asStateFlow()

    @VisibleForTesting
    val keyguardCallback =
        object : KeyguardUpdateMonitorCallback() {
            override fun onKeyguardVisibilityChanged(visible: Boolean) {
                keyguardVisible.value = visible
            }
        }

    override fun close() {
        stateChangeListener?.cancel()
@@ -62,13 +78,23 @@ internal constructor(
        if (Flags.deviceStateRdmV2()) {
            var dialog: SystemUIDialog? = null

            keyguardUpdateMonitor.registerCallback(keyguardCallback)

            stateChangeListener =
                rearDisplayStateInteractor.state
                    .map {
                        when (it) {
                scope.launch {
                    combine(rearDisplayStateInteractor.state, keyguardVisibleFlow) {
                            rearDisplayState,
                            keyguardVisible ->
                            Pair(rearDisplayState, keyguardVisible)
                        }
                        .collectLatest { (rearDisplayState, keyguardVisible) ->
                            when (rearDisplayState) {
                                is RearDisplayStateInteractor.State.Enabled -> {
                                    if (!keyguardVisible) {
                                        val rearDisplayContext =
                                    context.createDisplayContext(it.innerDisplay)
                                            context.createDisplayContext(
                                                rearDisplayState.innerDisplay
                                            )
                                        val delegate =
                                            rearDisplayInnerDialogDelegateFactory.create(
                                                rearDisplayContext,
@@ -76,6 +102,7 @@ internal constructor(
                                            )
                                        dialog = delegate.createDialog().apply { show() }
                                    }
                                }

                                is RearDisplayStateInteractor.State.Disabled -> {
                                    dialog?.dismiss()
@@ -83,7 +110,7 @@ internal constructor(
                                }
                            }
                        }
                    .launchIn(scope)
                }
        }
    }
}
+23 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.Display
import androidx.test.filters.SmallTest
import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
import com.android.systemui.deviceStateManager
import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor
@@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import org.junit.Before
import org.junit.Test
import org.mockito.Mockito.times
import org.mockito.kotlin.any
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
@@ -59,6 +61,7 @@ class RearDisplayCoreStartableTest : SysuiTestCase() {
            fakeRearDisplayStateInteractor,
            kosmos.rearDisplayInnerDialogDelegateFactory,
            kosmos.testScope,
            kosmos.keyguardUpdateMonitor,
        )

    @Before
@@ -96,6 +99,26 @@ class RearDisplayCoreStartableTest : SysuiTestCase() {
            }
        }

    @Test
    @EnableFlags(FLAG_DEVICE_STATE_RDM_V2)
    fun testDialogResumesAfterKeyguardGone() =
        kosmos.runTest {
            impl.use {
                it.start()
                fakeRearDisplayStateInteractor.emitRearDisplay()

                verify(mockDialog).show()

                it.keyguardCallback.onKeyguardVisibilityChanged(true)
                // Do not need to check that the dialog is dismissed, since SystemUIDialog
                // implementation handles that. We just toggle keyguard here so that the flow
                // emits.

                it.keyguardCallback.onKeyguardVisibilityChanged(false)
                verify(mockDialog, times(2)).show()
            }
        }

    private class FakeRearDisplayStateInteractor(private val kosmos: Kosmos) :
        RearDisplayStateInteractor {
        private val stateFlow = MutableSharedFlow<RearDisplayStateInteractor.State>()