diff options
author | 2025-03-10 20:43:54 +0000 | |
---|---|---|
committer | 2025-03-10 22:30:53 +0000 | |
commit | f4bf234df1dae61861799561a00ffac1d223de0c (patch) | |
tree | 19c9e0d122b0affaae2cd562073bf527e74d395d | |
parent | fedfa7913018180ad37f22ebbc7ffe773331ecdb (diff) |
Ensure RDM dialog is shown after screen off/on
Turning off the display dismisses the RDM dialog. However, when the
device turns on again, the device is still in the RDM state. In this
case, we should re-show the RDM dialog once Keyguard is dismissed.
Fixes: 394228925
Flag: EXEMPT bugfix
Test: manual
Test: atest RearDisplayCoreStartableTest
Change-Id: Id9c80a870ed27099f2ce809c4b7ce452f108bfa7
-rw-r--r-- | packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt | 67 | ||||
-rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt | 23 |
2 files changed, 70 insertions, 20 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt index bc15bbb5e57d..263ef09ea767 100644 --- a/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt @@ -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,28 +78,39 @@ internal constructor( if (Flags.deviceStateRdmV2()) { var dialog: SystemUIDialog? = null + keyguardUpdateMonitor.registerCallback(keyguardCallback) + stateChangeListener = - rearDisplayStateInteractor.state - .map { - when (it) { - is RearDisplayStateInteractor.State.Enabled -> { - val rearDisplayContext = - context.createDisplayContext(it.innerDisplay) - val delegate = - rearDisplayInnerDialogDelegateFactory.create( - rearDisplayContext, - deviceStateManager::cancelStateRequest, - ) - dialog = delegate.createDialog().apply { show() } - } + 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( + rearDisplayState.innerDisplay + ) + val delegate = + rearDisplayInnerDialogDelegateFactory.create( + rearDisplayContext, + deviceStateManager::cancelStateRequest, + ) + dialog = delegate.createDialog().apply { show() } + } + } - is RearDisplayStateInteractor.State.Disabled -> { - dialog?.dismiss() - dialog = null + is RearDisplayStateInteractor.State.Disabled -> { + dialog?.dismiss() + dialog = null + } } } - } - .launchIn(scope) + } } } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt index cf54df8565d3..997cf417fe10 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt @@ -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>() |