• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17 
18 package com.android.systemui.keyboard.data.repository
19 
20 import android.hardware.input.InputManager
21 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
22 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
23 import com.android.systemui.dagger.SysUISingleton
24 import com.android.systemui.dagger.qualifiers.Application
25 import com.android.systemui.dagger.qualifiers.Background
26 import com.android.systemui.keyboard.shared.model.BacklightModel
27 import javax.inject.Inject
28 import kotlinx.coroutines.CoroutineDispatcher
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.channels.awaitClose
31 import kotlinx.coroutines.flow.Flow
32 import kotlinx.coroutines.flow.SharingStarted
33 import kotlinx.coroutines.flow.distinctUntilChanged
34 import kotlinx.coroutines.flow.flowOn
35 import kotlinx.coroutines.flow.map
36 import kotlinx.coroutines.flow.shareIn
37 
38 interface KeyboardRepository {
39     val keyboardConnected: Flow<Boolean>
40     val backlight: Flow<BacklightModel>
41 }
42 
43 @SysUISingleton
44 class KeyboardRepositoryImpl
45 @Inject
46 constructor(
47     @Application private val applicationScope: CoroutineScope,
48     @Background private val backgroundDispatcher: CoroutineDispatcher,
49     private val inputManager: InputManager,
50 ) : KeyboardRepository {
51 
52     private val connectedDeviceIds: Flow<Set<Int>> =
<lambda>null53         conflatedCallbackFlow {
54                 fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
55 
56                 var connectedKeyboards = inputManager.inputDeviceIds.toSet()
57                 val listener =
58                     object : InputManager.InputDeviceListener {
59                         override fun onInputDeviceAdded(deviceId: Int) {
60                             connectedKeyboards = connectedKeyboards + deviceId
61                             send(connectedKeyboards)
62                         }
63 
64                         override fun onInputDeviceChanged(deviceId: Int) = Unit
65 
66                         override fun onInputDeviceRemoved(deviceId: Int) {
67                             connectedKeyboards = connectedKeyboards - deviceId
68                             send(connectedKeyboards)
69                         }
70                     }
71                 send(connectedKeyboards)
72                 inputManager.registerInputDeviceListener(listener, /* handler= */ null)
73                 awaitClose { inputManager.unregisterInputDeviceListener(listener) }
74             }
75             .shareIn(
76                 scope = applicationScope,
77                 started = SharingStarted.Lazily,
78                 replay = 1,
79             )
80 
81     override val keyboardConnected: Flow<Boolean> =
82         connectedDeviceIds
<lambda>null83             .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
84             .distinctUntilChanged()
85             .flowOn(backgroundDispatcher)
86 
87     override val backlight: Flow<BacklightModel> =
<lambda>null88         conflatedCallbackFlow {
89             // TODO(b/268645734) register BacklightListener
90         }
91 
isPhysicalFullKeyboardnull92     private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
93         val device = inputManager.getInputDevice(deviceId)
94         return !device.isVirtual && device.isFullKeyboard
95     }
96 
97     companion object {
98         const val TAG = "KeyboardRepositoryImpl"
99     }
100 }
101