Loading packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt +4 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.stateIn Loading @@ -48,7 +49,7 @@ interface DisplayRepository { * * When `null`, it means there is no pending display waiting to be enabled. */ val pendingDisplay: Flow<Int?> val pendingDisplayId: Flow<Int?> } @SysUISingleton Loading Loading @@ -98,7 +99,7 @@ constructor( displayManager.displays?.toSet() ?: emptySet() } override val pendingDisplay: Flow<Int?> = override val pendingDisplayId: Flow<Int?> = conflatedCallbackFlow { val callback = object : DisplayConnectionListener { Loading Loading @@ -128,6 +129,7 @@ constructor( ) awaitClose { displayManager.unregisterDisplayListener(callback) } } .distinctUntilChanged() .flowOn(backgroundCoroutineDispatcher) .stateIn( applicationScope, Loading packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt +13 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.util.traceSection import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading Loading @@ -65,6 +67,7 @@ class ConnectedDisplayInteractorImpl @Inject constructor( private val displayManager: DisplayManager, keyguardRepository: KeyguardRepository, displayRepository: DisplayRepository, ) : ConnectedDisplayInteractor { Loading @@ -87,8 +90,17 @@ constructor( } .distinctUntilChanged() // Provides the pending display only if the lockscreen is unlocked override val pendingDisplay: Flow<PendingDisplay?> = displayRepository.pendingDisplay.distinctUntilChanged().map { it?.toPendingDisplay() } displayRepository.pendingDisplayId.combine(keyguardRepository.isKeyguardUnlocked) { pendingDisplayId, keyguardUnlocked -> if (pendingDisplayId != null && keyguardUnlocked) { pendingDisplayId.toPendingDisplay() } else { null } } private fun Int.toPendingDisplay() = object : PendingDisplay { Loading packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ class DisplayRepositoryTest : SysuiTestCase() { } private fun TestScope.latestPendingDisplayFlowValue(): FlowValue<Int?> { val flowValue = collectLastValue(displayRepository.pendingDisplay) val flowValue = collectLastValue(displayRepository.pendingDisplayId) verify(displayManager) .registerDisplayListener( displayListener.capture(), Loading packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt +41 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.display.data.repository.FakeDisplayRepository import com.android.systemui.display.data.repository.display import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito Loading @@ -49,10 +51,20 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { private val displayManager = mock<DisplayManager>() private val fakeDisplayRepository = FakeDisplayRepository() private val fakeKeyguardRepository = FakeKeyguardRepository() private val connectedDisplayStateProvider: ConnectedDisplayInteractor = ConnectedDisplayInteractorImpl(displayManager, fakeDisplayRepository) ConnectedDisplayInteractorImpl( displayManager, fakeKeyguardRepository, fakeDisplayRepository ) private val testScope = TestScope(UnconfinedTestDispatcher()) @Before fun setup() { fakeKeyguardRepository.setKeyguardUnlocked(true) } @Test fun displayState_nullDisplays_disconnected() = testScope.runTest { Loading Loading @@ -165,6 +177,34 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { Mockito.verify(displayManager).disableConnectedDisplay(eq(1)) } @Test fun onPendingDisplay_keyguardUnlocked_returnsPendingDisplay() = testScope.runTest { fakeKeyguardRepository.setKeyguardUnlocked(false) val pendingDisplay by lastPendingDisplay() fakeDisplayRepository.emit(1) assertThat(pendingDisplay).isNull() fakeKeyguardRepository.setKeyguardUnlocked(true) assertThat(pendingDisplay).isNotNull() } @Test fun onPendingDisplay_keyguardLocked_returnsNull() = testScope.runTest { fakeKeyguardRepository.setKeyguardUnlocked(true) val pendingDisplay by lastPendingDisplay() fakeDisplayRepository.emit(1) assertThat(pendingDisplay).isNotNull() fakeKeyguardRepository.setKeyguardUnlocked(false) assertThat(pendingDisplay).isNull() } private fun TestScope.lastValue(): FlowValue<State?> = collectLastValue(connectedDisplayStateProvider.connectedDisplayState) Loading packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +2 −2 Original line number Diff line number Diff line Loading @@ -38,12 +38,12 @@ class FakeDisplayRepository : DisplayRepository { /** Emits [value] as [displays] flow value. */ suspend fun emit(value: Set<Display>) = flow.emit(value) /** Emits [value] as [pendingDisplay] flow value. */ /** Emits [value] as [pendingDisplayId] flow value. */ suspend fun emit(value: Int?) = pendingDisplayFlow.emit(value) override val displays: Flow<Set<Display>> get() = flow override val pendingDisplay: Flow<Int?> override val pendingDisplayId: Flow<Int?> get() = pendingDisplayFlow } Loading
packages/SystemUI/src/com/android/systemui/display/data/repository/DisplayRepository.kt +4 −2 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.stateIn Loading @@ -48,7 +49,7 @@ interface DisplayRepository { * * When `null`, it means there is no pending display waiting to be enabled. */ val pendingDisplay: Flow<Int?> val pendingDisplayId: Flow<Int?> } @SysUISingleton Loading Loading @@ -98,7 +99,7 @@ constructor( displayManager.displays?.toSet() ?: emptySet() } override val pendingDisplay: Flow<Int?> = override val pendingDisplayId: Flow<Int?> = conflatedCallbackFlow { val callback = object : DisplayConnectionListener { Loading Loading @@ -128,6 +129,7 @@ constructor( ) awaitClose { displayManager.unregisterDisplayListener(callback) } } .distinctUntilChanged() .flowOn(backgroundCoroutineDispatcher) .stateIn( applicationScope, Loading
packages/SystemUI/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractor.kt +13 −1 Original line number Diff line number Diff line Loading @@ -22,9 +22,11 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DisplayRepository import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.util.traceSection import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading Loading @@ -65,6 +67,7 @@ class ConnectedDisplayInteractorImpl @Inject constructor( private val displayManager: DisplayManager, keyguardRepository: KeyguardRepository, displayRepository: DisplayRepository, ) : ConnectedDisplayInteractor { Loading @@ -87,8 +90,17 @@ constructor( } .distinctUntilChanged() // Provides the pending display only if the lockscreen is unlocked override val pendingDisplay: Flow<PendingDisplay?> = displayRepository.pendingDisplay.distinctUntilChanged().map { it?.toPendingDisplay() } displayRepository.pendingDisplayId.combine(keyguardRepository.isKeyguardUnlocked) { pendingDisplayId, keyguardUnlocked -> if (pendingDisplayId != null && keyguardUnlocked) { pendingDisplayId.toPendingDisplay() } else { null } } private fun Int.toPendingDisplay() = object : PendingDisplay { Loading
packages/SystemUI/tests/src/com/android/systemui/display/data/repository/DisplayRepositoryTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -230,7 +230,7 @@ class DisplayRepositoryTest : SysuiTestCase() { } private fun TestScope.latestPendingDisplayFlowValue(): FlowValue<Int?> { val flowValue = collectLastValue(displayRepository.pendingDisplay) val flowValue = collectLastValue(displayRepository.pendingDisplayId) verify(displayManager) .registerDisplayListener( displayListener.capture(), Loading
packages/SystemUI/tests/src/com/android/systemui/display/domain/interactor/ConnectedDisplayInteractorTest.kt +41 −1 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import com.android.systemui.display.data.repository.FakeDisplayRepository import com.android.systemui.display.data.repository.display import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.PendingDisplay import com.android.systemui.display.domain.interactor.ConnectedDisplayInteractor.State import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading @@ -37,6 +38,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito Loading @@ -49,10 +51,20 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { private val displayManager = mock<DisplayManager>() private val fakeDisplayRepository = FakeDisplayRepository() private val fakeKeyguardRepository = FakeKeyguardRepository() private val connectedDisplayStateProvider: ConnectedDisplayInteractor = ConnectedDisplayInteractorImpl(displayManager, fakeDisplayRepository) ConnectedDisplayInteractorImpl( displayManager, fakeKeyguardRepository, fakeDisplayRepository ) private val testScope = TestScope(UnconfinedTestDispatcher()) @Before fun setup() { fakeKeyguardRepository.setKeyguardUnlocked(true) } @Test fun displayState_nullDisplays_disconnected() = testScope.runTest { Loading Loading @@ -165,6 +177,34 @@ class ConnectedDisplayInteractorTest : SysuiTestCase() { Mockito.verify(displayManager).disableConnectedDisplay(eq(1)) } @Test fun onPendingDisplay_keyguardUnlocked_returnsPendingDisplay() = testScope.runTest { fakeKeyguardRepository.setKeyguardUnlocked(false) val pendingDisplay by lastPendingDisplay() fakeDisplayRepository.emit(1) assertThat(pendingDisplay).isNull() fakeKeyguardRepository.setKeyguardUnlocked(true) assertThat(pendingDisplay).isNotNull() } @Test fun onPendingDisplay_keyguardLocked_returnsNull() = testScope.runTest { fakeKeyguardRepository.setKeyguardUnlocked(true) val pendingDisplay by lastPendingDisplay() fakeDisplayRepository.emit(1) assertThat(pendingDisplay).isNotNull() fakeKeyguardRepository.setKeyguardUnlocked(false) assertThat(pendingDisplay).isNull() } private fun TestScope.lastValue(): FlowValue<State?> = collectLastValue(connectedDisplayStateProvider.connectedDisplayState) Loading
packages/SystemUI/tests/utils/src/com/android/systemui/display/data/repository/FakeDisplayRepository.kt +2 −2 Original line number Diff line number Diff line Loading @@ -38,12 +38,12 @@ class FakeDisplayRepository : DisplayRepository { /** Emits [value] as [displays] flow value. */ suspend fun emit(value: Set<Display>) = flow.emit(value) /** Emits [value] as [pendingDisplay] flow value. */ /** Emits [value] as [pendingDisplayId] flow value. */ suspend fun emit(value: Int?) = pendingDisplayFlow.emit(value) override val displays: Flow<Set<Display>> get() = flow override val pendingDisplay: Flow<Int?> override val pendingDisplayId: Flow<Int?> get() = pendingDisplayFlow }