Loading packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt +47 −20 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.feature.flags.Flags import android.hardware.devicestate.feature.flags.Flags import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.CoreStartable import com.android.systemui.CoreStartable 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 Loading @@ -28,8 +30,11 @@ import com.android.systemui.statusbar.phone.SystemUIDialog import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.Job import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map 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 * Provides a {@link com.android.systemui.statusbar.phone.SystemUIDialog} to be shown on the inner Loading @@ -46,6 +51,7 @@ internal constructor( private val rearDisplayStateInteractor: RearDisplayStateInteractor, private val rearDisplayStateInteractor: RearDisplayStateInteractor, private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory, private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory, @Application private val scope: CoroutineScope, @Application private val scope: CoroutineScope, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, ) : CoreStartable, AutoCloseable { ) : CoreStartable, AutoCloseable { companion object { companion object { Loading @@ -53,6 +59,16 @@ internal constructor( } } @VisibleForTesting var stateChangeListener: Job? = null @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() { override fun close() { stateChangeListener?.cancel() stateChangeListener?.cancel() Loading @@ -62,13 +78,23 @@ internal constructor( if (Flags.deviceStateRdmV2()) { if (Flags.deviceStateRdmV2()) { var dialog: SystemUIDialog? = null var dialog: SystemUIDialog? = null keyguardUpdateMonitor.registerCallback(keyguardCallback) stateChangeListener = stateChangeListener = rearDisplayStateInteractor.state scope.launch { .map { combine(rearDisplayStateInteractor.state, keyguardVisibleFlow) { when (it) { rearDisplayState, keyguardVisible -> Pair(rearDisplayState, keyguardVisible) } .collectLatest { (rearDisplayState, keyguardVisible) -> when (rearDisplayState) { is RearDisplayStateInteractor.State.Enabled -> { is RearDisplayStateInteractor.State.Enabled -> { if (!keyguardVisible) { val rearDisplayContext = val rearDisplayContext = context.createDisplayContext(it.innerDisplay) context.createDisplayContext( rearDisplayState.innerDisplay ) val delegate = val delegate = rearDisplayInnerDialogDelegateFactory.create( rearDisplayInnerDialogDelegateFactory.create( rearDisplayContext, rearDisplayContext, Loading @@ -76,6 +102,7 @@ internal constructor( ) ) dialog = delegate.createDialog().apply { show() } dialog = delegate.createDialog().apply { show() } } } } is RearDisplayStateInteractor.State.Disabled -> { is RearDisplayStateInteractor.State.Disabled -> { dialog?.dismiss() dialog?.dismiss() Loading @@ -83,7 +110,7 @@ internal constructor( } } } } } } .launchIn(scope) } } } } } } } packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt +23 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.EnableFlags import android.view.Display import android.view.Display import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.keyguard.keyguardUpdateMonitor import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.deviceStateManager import com.android.systemui.deviceStateManager import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow import org.junit.Before import org.junit.Before import org.junit.Test import org.junit.Test import org.mockito.Mockito.times import org.mockito.kotlin.any import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.never Loading @@ -59,6 +61,7 @@ class RearDisplayCoreStartableTest : SysuiTestCase() { fakeRearDisplayStateInteractor, fakeRearDisplayStateInteractor, kosmos.rearDisplayInnerDialogDelegateFactory, kosmos.rearDisplayInnerDialogDelegateFactory, kosmos.testScope, kosmos.testScope, kosmos.keyguardUpdateMonitor, ) ) @Before @Before Loading Loading @@ -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) : private class FakeRearDisplayStateInteractor(private val kosmos: Kosmos) : RearDisplayStateInteractor { RearDisplayStateInteractor { private val stateFlow = MutableSharedFlow<RearDisplayStateInteractor.State>() private val stateFlow = MutableSharedFlow<RearDisplayStateInteractor.State>() Loading Loading
packages/SystemUI/src/com/android/systemui/reardisplay/RearDisplayCoreStartable.kt +47 −20 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.feature.flags.Flags import android.hardware.devicestate.feature.flags.Flags import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.CoreStartable import com.android.systemui.CoreStartable 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 Loading @@ -28,8 +30,11 @@ import com.android.systemui.statusbar.phone.SystemUIDialog import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.Job import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map 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 * Provides a {@link com.android.systemui.statusbar.phone.SystemUIDialog} to be shown on the inner Loading @@ -46,6 +51,7 @@ internal constructor( private val rearDisplayStateInteractor: RearDisplayStateInteractor, private val rearDisplayStateInteractor: RearDisplayStateInteractor, private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory, private val rearDisplayInnerDialogDelegateFactory: RearDisplayInnerDialogDelegate.Factory, @Application private val scope: CoroutineScope, @Application private val scope: CoroutineScope, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, ) : CoreStartable, AutoCloseable { ) : CoreStartable, AutoCloseable { companion object { companion object { Loading @@ -53,6 +59,16 @@ internal constructor( } } @VisibleForTesting var stateChangeListener: Job? = null @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() { override fun close() { stateChangeListener?.cancel() stateChangeListener?.cancel() Loading @@ -62,13 +78,23 @@ internal constructor( if (Flags.deviceStateRdmV2()) { if (Flags.deviceStateRdmV2()) { var dialog: SystemUIDialog? = null var dialog: SystemUIDialog? = null keyguardUpdateMonitor.registerCallback(keyguardCallback) stateChangeListener = stateChangeListener = rearDisplayStateInteractor.state scope.launch { .map { combine(rearDisplayStateInteractor.state, keyguardVisibleFlow) { when (it) { rearDisplayState, keyguardVisible -> Pair(rearDisplayState, keyguardVisible) } .collectLatest { (rearDisplayState, keyguardVisible) -> when (rearDisplayState) { is RearDisplayStateInteractor.State.Enabled -> { is RearDisplayStateInteractor.State.Enabled -> { if (!keyguardVisible) { val rearDisplayContext = val rearDisplayContext = context.createDisplayContext(it.innerDisplay) context.createDisplayContext( rearDisplayState.innerDisplay ) val delegate = val delegate = rearDisplayInnerDialogDelegateFactory.create( rearDisplayInnerDialogDelegateFactory.create( rearDisplayContext, rearDisplayContext, Loading @@ -76,6 +102,7 @@ internal constructor( ) ) dialog = delegate.createDialog().apply { show() } dialog = delegate.createDialog().apply { show() } } } } is RearDisplayStateInteractor.State.Disabled -> { is RearDisplayStateInteractor.State.Disabled -> { dialog?.dismiss() dialog?.dismiss() Loading @@ -83,7 +110,7 @@ internal constructor( } } } } } } .launchIn(scope) } } } } } } }
packages/SystemUI/tests/src/com/android/systemui/reardisplay/RearDisplayCoreStartableTest.kt +23 −0 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.annotations.EnableFlags import android.view.Display import android.view.Display import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.keyguard.keyguardUpdateMonitor import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.deviceStateManager import com.android.systemui.deviceStateManager import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor import com.android.systemui.display.domain.interactor.RearDisplayStateInteractor Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow import org.junit.Before import org.junit.Before import org.junit.Test import org.junit.Test import org.mockito.Mockito.times import org.mockito.kotlin.any import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.never Loading @@ -59,6 +61,7 @@ class RearDisplayCoreStartableTest : SysuiTestCase() { fakeRearDisplayStateInteractor, fakeRearDisplayStateInteractor, kosmos.rearDisplayInnerDialogDelegateFactory, kosmos.rearDisplayInnerDialogDelegateFactory, kosmos.testScope, kosmos.testScope, kosmos.keyguardUpdateMonitor, ) ) @Before @Before Loading Loading @@ -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) : private class FakeRearDisplayStateInteractor(private val kosmos: Kosmos) : RearDisplayStateInteractor { RearDisplayStateInteractor { private val stateFlow = MutableSharedFlow<RearDisplayStateInteractor.State>() private val stateFlow = MutableSharedFlow<RearDisplayStateInteractor.State>() Loading