From 50db665776572c6839437dc2376b823c2ff37005 Mon Sep 17 00:00:00 2001 From: Michal Brzezinski Date: Wed, 26 Apr 2023 12:06:48 +0100 Subject: [PATCH] Adding newlyConnectedKeyboard flow to KeyboardRepository newlyConnectedKeyboard emits new physical Keyboards that are connected to the device. Other changes: 1. Because keyboardConnected starts to be confusing now, I renamed it to isAnyKeyboardConnected. 2. Extracting inputDeviceListener flow to separate shared flow so that both newlyConnectedKeyboard and isAnyKeyboardConnected can use it without each registering their own listener. 3. Commenting KeyboardRepository flows 4. Adding tests for newlyConnectedKeyboard Flag: KEYBOARD_EDUCATION Bug: 277192620 Test: KeyboardRepositoryTest Change-Id: I61044362a4e924d80546ae92300844280174db00 --- .../interactor/KeyboardBacklightInteractor.kt | 4 +- .../systemui/keyboard/data/model/Keyboard.kt | 20 ++++ .../data/repository/KeyboardRepository.kt | 76 ++++++++++-- .../KeyboardBacklightInteractorTest.kt | 8 +- .../viewmodel/BacklightDialogViewModelTest.kt | 4 +- .../data/repository/KeyboardRepositoryTest.kt | 112 ++++++++++++++++-- .../data/repository/FakeKeyboardRepository.kt | 16 ++- 7 files changed, 204 insertions(+), 36 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/keyboard/data/model/Keyboard.kt diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt index 65e70b319923c..df2a33f95872d 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractor.kt @@ -21,6 +21,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyboard.data.repository.KeyboardRepository import com.android.systemui.keyboard.shared.model.BacklightModel import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf @@ -34,8 +35,9 @@ constructor( ) { /** Emits current backlight level as [BacklightModel] or null if keyboard is not connected */ + @ExperimentalCoroutinesApi val backlight: Flow = - keyboardRepository.keyboardConnected.flatMapLatest { connected -> + keyboardRepository.isAnyKeyboardConnected.flatMapLatest { connected -> if (connected) keyboardRepository.backlight else flowOf(null) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/model/Keyboard.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/Keyboard.kt new file mode 100644 index 0000000000000..ee6dd0de96a24 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/Keyboard.kt @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.keyboard.data.model + +data class Keyboard(val vendorId: Int, val productId: Int) diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt index 1f1329111ce7e..2fac40a48d3dd 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt @@ -25,22 +25,41 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background +import com.android.systemui.keyboard.data.model.Keyboard import com.android.systemui.keyboard.shared.model.BacklightModel import java.util.concurrent.Executor import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.channels.SendChannel import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow +import kotlinx.coroutines.flow.flatMapConcat +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.mapNotNull import kotlinx.coroutines.flow.shareIn interface KeyboardRepository { - val keyboardConnected: Flow + /** Emits true if any physical keyboard is connected to the device, false otherwise. */ + val isAnyKeyboardConnected: Flow + + /** + * Emits [Keyboard] object whenever new physical keyboard connects. When SysUI (re)starts it + * emits all currently connected keyboards + */ + val newlyConnectedKeyboard: Flow + + /** + * Emits [BacklightModel] whenever user changes backlight level from keyboard press. Can only + * happen when physical keyboard is connected + */ val backlight: Flow } @@ -53,33 +72,65 @@ constructor( private val inputManager: InputManager, ) : KeyboardRepository { - private val connectedDeviceIds: Flow> = + private sealed interface DeviceChange + private data class DeviceAdded(val deviceId: Int) : DeviceChange + private object DeviceRemoved : DeviceChange + private object FreshStart : DeviceChange + + /** + * Emits collection of all currently connected keyboards and what was the last [DeviceChange]. + * It emits collection so that every new subscriber to this SharedFlow can get latest state of + * all keyboards. Otherwise we might get into situation where subscriber timing on + * initialization matter and later subscriber will only get latest device and will miss all + * previous devices. + */ + private val keyboardsChange: Flow, DeviceChange>> = conflatedCallbackFlow { - var connectedKeyboards = inputManager.inputDeviceIds.toSet() + var connectedDevices = inputManager.inputDeviceIds.toSet() val listener = object : InputManager.InputDeviceListener { override fun onInputDeviceAdded(deviceId: Int) { - connectedKeyboards = connectedKeyboards + deviceId - sendWithLogging(connectedKeyboards) + connectedDevices = connectedDevices + deviceId + sendWithLogging(connectedDevices to DeviceAdded(deviceId)) } override fun onInputDeviceChanged(deviceId: Int) = Unit override fun onInputDeviceRemoved(deviceId: Int) { - connectedKeyboards = connectedKeyboards - deviceId - sendWithLogging(connectedKeyboards) + connectedDevices = connectedDevices - deviceId + sendWithLogging(connectedDevices to DeviceRemoved) } } - sendWithLogging(connectedKeyboards) + sendWithLogging(connectedDevices to FreshStart) inputManager.registerInputDeviceListener(listener, /* handler= */ null) awaitClose { inputManager.unregisterInputDeviceListener(listener) } } + .map { (ids, change) -> ids.filter { id -> isPhysicalFullKeyboard(id) } to change } .shareIn( scope = applicationScope, started = SharingStarted.Lazily, replay = 1, ) + @FlowPreview + override val newlyConnectedKeyboard: Flow = + keyboardsChange + .flatMapConcat { (devices, operation) -> + when (operation) { + FreshStart -> devices.asFlow() + is DeviceAdded -> flowOf(operation.deviceId) + is DeviceRemoved -> emptyFlow() + } + } + .mapNotNull { deviceIdToKeyboard(it) } + .flowOn(backgroundDispatcher) + + override val isAnyKeyboardConnected: Flow = + keyboardsChange + .map { (devices, _) -> devices.isNotEmpty() } + .distinctUntilChanged() + .flowOn(backgroundDispatcher) + private val backlightStateListener: Flow = conflatedCallbackFlow { val listener = KeyboardBacklightListener { _, state, isTriggeredByKeyPress -> if (isTriggeredByKeyPress) { @@ -90,11 +141,10 @@ constructor( awaitClose { inputManager.unregisterKeyboardBacklightListener(listener) } } - override val keyboardConnected: Flow = - connectedDeviceIds - .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } } - .distinctUntilChanged() - .flowOn(backgroundDispatcher) + private fun deviceIdToKeyboard(deviceId: Int): Keyboard? { + val device = inputManager.getInputDevice(deviceId) ?: return null + return Keyboard(device.vendorId, device.productId) + } override val backlight: Flow = backlightStateListener diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt index ec94cdec78f0c..d7a0d5b5e062e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/domain/interactor/KeyboardBacklightInteractorTest.kt @@ -47,14 +47,14 @@ class KeyboardBacklightInteractorTest : SysuiTestCase() { @Test fun emitsNull_whenKeyboardJustConnected() = runTest { val latest by collectLastValue(underTest.backlight) - keyboardRepository.setKeyboardConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) assertThat(latest).isNull() } @Test fun emitsBacklight_whenKeyboardConnectedAndBacklightChanged() = runTest { - keyboardRepository.setKeyboardConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) keyboardRepository.setBacklight(BacklightModel(1, 5)) assertThat(underTest.backlight.first()).isEqualTo(BacklightModel(1, 5)) @@ -63,10 +63,10 @@ class KeyboardBacklightInteractorTest : SysuiTestCase() { @Test fun emitsNull_afterKeyboardDisconnecting() = runTest { val latest by collectLastValue(underTest.backlight) - keyboardRepository.setKeyboardConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) keyboardRepository.setBacklight(BacklightModel(1, 5)) - keyboardRepository.setKeyboardConnected(false) + keyboardRepository.setIsAnyKeyboardConnected(false) assertThat(latest).isNull() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt index ec05d10b793cc..1fec5a4d0f370 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/backlight/ui/viewmodel/BacklightDialogViewModelTest.kt @@ -58,7 +58,7 @@ class BacklightDialogViewModelTest : SysuiTestCase() { KeyboardBacklightInteractor(keyboardRepository), accessibilityManagerWrapper ) - keyboardRepository.setKeyboardConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) } @Test @@ -81,7 +81,7 @@ class BacklightDialogViewModelTest : SysuiTestCase() { @Test fun emitsNull_after5secDelay_fromLastBacklightChange() = runTest { val latest by collectLastValue(underTest.dialogContent) - keyboardRepository.setKeyboardConnected(true) + keyboardRepository.setIsAnyKeyboardConnected(true) keyboardRepository.setBacklight(BacklightModel(1, 5)) assertThat(latest).isEqualTo(BacklightDialogContentViewModel(1, 5)) diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt index fae637541028a..4410e68e64aa9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt @@ -25,6 +25,8 @@ import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.FlowValue import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.coroutines.collectValues +import com.android.systemui.keyboard.data.model.Keyboard import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable @@ -36,6 +38,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.first import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -78,7 +81,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { @Test fun emitsDisconnected_ifNothingIsConnected() = testScope.runTest { - val initialState = underTest.keyboardConnected.first() + val initialState = underTest.isAnyKeyboardConnected.first() assertThat(initialState).isFalse() } @@ -86,7 +89,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsConnected_ifKeyboardAlreadyConnectedAtTheStart() = testScope.runTest { whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID)) - val initialValue = underTest.keyboardConnected.first() + val initialValue = underTest.isAnyKeyboardConnected.first() assertThat(initialValue).isTrue() } @@ -94,7 +97,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsConnected_whenNewPhysicalKeyboardConnects() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) @@ -105,7 +108,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsDisconnected_whenDeviceWithIdDoesNotExist() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(NULL_DEVICE_ID) assertThat(isKeyboardConnected).isFalse() @@ -115,7 +118,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsDisconnected_whenKeyboardDisconnects() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) assertThat(isKeyboardConnected).isTrue() @@ -125,7 +128,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { } private suspend fun captureDeviceListener(): InputManager.InputDeviceListener { - underTest.keyboardConnected.first() + underTest.isAnyKeyboardConnected.first() verify(inputManager).registerInputDeviceListener(deviceListenerCaptor.capture(), nullable()) return deviceListenerCaptor.value } @@ -134,7 +137,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsDisconnected_whenVirtualOrNotFullKeyboardConnects() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(PHYSICAL_NOT_FULL_KEYBOARD_ID) assertThat(isKeyboardConnected).isFalse() @@ -147,7 +150,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsDisconnected_whenKeyboardDisconnectsAndWasAlreadyConnectedAtTheStart() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID) assertThat(isKeyboardConnected).isFalse() @@ -157,7 +160,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsConnected_whenAnotherDeviceDisconnects() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) deviceListener.onInputDeviceRemoved(VIRTUAL_FULL_KEYBOARD_ID) @@ -169,7 +172,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { fun emitsConnected_whenOnePhysicalKeyboardDisconnectsButAnotherRemainsConnected() = testScope.runTest { val deviceListener = captureDeviceListener() - val isKeyboardConnected by collectLastValue(underTest.keyboardConnected) + val isKeyboardConnected by collectLastValue(underTest.isAnyKeyboardConnected) deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID) @@ -205,7 +208,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { @Test fun keyboardBacklightValuesNotPassed_fromBacklightListener_whenNotTriggeredByKeyPress() { - testScope.runTest() { + testScope.runTest { val backlight by collectLastValueImmediately(underTest.backlight) verify(inputManager) .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture()) @@ -221,7 +224,7 @@ class KeyboardRepositoryTest : SysuiTestCase() { @Test fun passesKeyboardBacklightValues_fromBacklightListener_whenTriggeredByKeyPress() { - testScope.runTest() { + testScope.runTest { val backlight by collectLastValueImmediately(underTest.backlight) verify(inputManager) .registerKeyboardBacklightListener(any(), backlightListenerCaptor.capture()) @@ -235,6 +238,86 @@ class KeyboardRepositoryTest : SysuiTestCase() { } } + @Test + fun passessAllKeyboards_thatWereAlreadyConnectedOnInitialization() { + testScope.runTest { + whenever(inputManager.inputDeviceIds) + .thenReturn( + intArrayOf( + PHYSICAL_FULL_KEYBOARD_ID, + ANOTHER_PHYSICAL_FULL_KEYBOARD_ID, + VIRTUAL_FULL_KEYBOARD_ID // not a physical keyboard - that's why result is 2 + ) + ) + val keyboards by collectValues(underTest.newlyConnectedKeyboard) + + assertThat(keyboards).hasSize(2) + } + } + + @Test + fun passesNewlyConnectedKeyboard() { + testScope.runTest { + val deviceListener = captureDeviceListener() + + deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) + + assertThat(underTest.newlyConnectedKeyboard.first()) + .isEqualTo(Keyboard(VENDOR_ID, PRODUCT_ID)) + } + } + + @Test + fun emitsOnlyNewlyConnectedKeyboards() { + testScope.runTest { + whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID)) + underTest.newlyConnectedKeyboard.first() + verify(inputManager) + .registerInputDeviceListener(deviceListenerCaptor.capture(), nullable()) + val deviceListener = deviceListenerCaptor.value + + deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID) + val keyboards by collectValues(underTest.newlyConnectedKeyboard) + + assertThat(keyboards).hasSize(1) + } + } + + @Test + fun stillEmitsNewKeyboardEvenIfFlowWasSubscribedAfterOtherFlows() { + testScope.runTest { + whenever(inputManager.inputDeviceIds) + .thenReturn( + intArrayOf( + PHYSICAL_FULL_KEYBOARD_ID, + ANOTHER_PHYSICAL_FULL_KEYBOARD_ID, + VIRTUAL_FULL_KEYBOARD_ID // not a physical keyboard - that's why result is 2 + ) + ) + collectLastValueImmediately(underTest.isAnyKeyboardConnected) + + // let's pretend second flow is subscribed after some delay + advanceTimeBy(1000) + val keyboards by collectValues(underTest.newlyConnectedKeyboard) + + assertThat(keyboards).hasSize(2) + } + } + + @Test + fun emitsKeyboardWhenItWasReconnected() { + testScope.runTest { + val deviceListener = captureDeviceListener() + val keyboards by collectValues(underTest.newlyConnectedKeyboard) + + deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) + deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID) + deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID) + + assertThat(keyboards).hasSize(2) + } + } + private fun KeyboardBacklightListener.onBacklightChanged( current: Int, max: Int, @@ -254,6 +337,9 @@ class KeyboardRepositoryTest : SysuiTestCase() { private const val ANOTHER_PHYSICAL_FULL_KEYBOARD_ID = 4 private const val NULL_DEVICE_ID = 5 + private const val VENDOR_ID = 99 + private const val PRODUCT_ID = 101 + private val INPUT_DEVICES_MAP: Map = mapOf( PHYSICAL_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = true), @@ -267,6 +353,8 @@ class KeyboardRepositoryTest : SysuiTestCase() { mock().also { whenever(it.isVirtual).thenReturn(virtual) whenever(it.isFullKeyboard).thenReturn(fullKeyboard) + whenever(it.vendorId).thenReturn(VENDOR_ID) + whenever(it.productId).thenReturn(PRODUCT_ID) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt index 4e435462be508..b37cac1d36fdc 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyboard/data/repository/FakeKeyboardRepository.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyboard.data.repository +import com.android.systemui.keyboard.data.model.Keyboard import com.android.systemui.keyboard.shared.model.BacklightModel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -24,18 +25,25 @@ import kotlinx.coroutines.flow.filterNotNull class FakeKeyboardRepository : KeyboardRepository { - private val _keyboardConnected = MutableStateFlow(false) - override val keyboardConnected: Flow = _keyboardConnected + private val _isAnyKeyboardConnected = MutableStateFlow(false) + override val isAnyKeyboardConnected: Flow = _isAnyKeyboardConnected private val _backlightState: MutableStateFlow = MutableStateFlow(null) // filtering to make sure backlight doesn't have default initial value override val backlight: Flow = _backlightState.filterNotNull() + private val _newlyConnectedKeyboard: MutableStateFlow = MutableStateFlow(null) + override val newlyConnectedKeyboard: Flow = _newlyConnectedKeyboard.filterNotNull() + fun setBacklight(state: BacklightModel) { _backlightState.value = state } - fun setKeyboardConnected(connected: Boolean) { - _keyboardConnected.value = connected + fun setIsAnyKeyboardConnected(connected: Boolean) { + _isAnyKeyboardConnected.value = connected + } + + fun setNewlyConnectedKeyboard(keyboard: Keyboard) { + _newlyConnectedKeyboard.value = keyboard } }