1 /*
<lambda>null2  * Copyright (C) 2024 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 package com.android.systemui.keyboard.stickykeys.data.repository
18 
19 import android.hardware.input.InputManager
20 import android.hardware.input.InputManager.StickyModifierStateListener
21 import android.hardware.input.StickyModifierState
22 import android.provider.Settings
23 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
24 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
25 import com.android.systemui.dagger.SysUISingleton
26 import com.android.systemui.dagger.qualifiers.Background
27 import com.android.systemui.keyboard.stickykeys.StickyKeysLogger
28 import com.android.systemui.keyboard.stickykeys.shared.model.Locked
29 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey
30 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.ALT
31 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.ALT_GR
32 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.CTRL
33 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.META
34 import com.android.systemui.keyboard.stickykeys.shared.model.ModifierKey.SHIFT
35 import com.android.systemui.util.settings.repository.UserAwareSecureSettingsRepository
36 import kotlinx.coroutines.CoroutineDispatcher
37 import kotlinx.coroutines.channels.awaitClose
38 import kotlinx.coroutines.flow.Flow
39 import kotlinx.coroutines.flow.flowOn
40 import kotlinx.coroutines.flow.map
41 import kotlinx.coroutines.flow.onEach
42 import javax.inject.Inject
43 
44 interface StickyKeysRepository {
45     val stickyKeys: Flow<LinkedHashMap<ModifierKey, Locked>>
46     val settingEnabled: Flow<Boolean>
47 }
48 
49 @SysUISingleton
50 class StickyKeysRepositoryImpl
51 @Inject
52 constructor(
53     private val inputManager: InputManager,
54     @Background private val backgroundDispatcher: CoroutineDispatcher,
55     secureSettingsRepository: UserAwareSecureSettingsRepository,
56     private val stickyKeysLogger: StickyKeysLogger,
57 ) : StickyKeysRepository {
58 
59     override val stickyKeys: Flow<LinkedHashMap<ModifierKey, Locked>> =
<lambda>null60         conflatedCallbackFlow {
61                 val listener = StickyModifierStateListener { stickyModifierState ->
62                     trySendWithFailureLogging(stickyModifierState, TAG)
63                 }
64                 // after registering, InputManager calls listener with the current value
65                 inputManager.registerStickyModifierStateListener(Runnable::run, listener)
66                 awaitClose { inputManager.unregisterStickyModifierStateListener(listener) }
67             }
<lambda>null68             .map { toStickyKeysMap(it) }
<lambda>null69             .onEach { stickyKeysLogger.logNewStickyKeysReceived(it) }
70             .flowOn(backgroundDispatcher)
71 
72     override val settingEnabled: Flow<Boolean> =
73         secureSettingsRepository
74             .boolSettingForActiveUser(SETTING_KEY, defaultValue = false)
<lambda>null75             .onEach { stickyKeysLogger.logNewSettingValue(it) }
76             .flowOn(backgroundDispatcher)
77 
toStickyKeysMapnull78     private fun toStickyKeysMap(state: StickyModifierState): LinkedHashMap<ModifierKey, Locked> {
79         val keys = linkedMapOf<ModifierKey, Locked>()
80         state.apply {
81             if (isAltGrModifierOn) keys[ALT_GR] = Locked(false)
82             if (isAltGrModifierLocked) keys[ALT_GR] = Locked(true)
83             if (isAltModifierOn) keys[ALT] = Locked(false)
84             if (isAltModifierLocked) keys[ALT] = Locked(true)
85             if (isCtrlModifierOn) keys[CTRL] = Locked(false)
86             if (isCtrlModifierLocked) keys[CTRL] = Locked(true)
87             if (isMetaModifierOn) keys[META] = Locked(false)
88             if (isMetaModifierLocked) keys[META] = Locked(true)
89             if (isShiftModifierOn) keys[SHIFT] = Locked(false)
90             if (isShiftModifierLocked) keys[SHIFT] = Locked(true)
91         }
92         return keys
93     }
94 
95     companion object {
96         const val TAG = "StickyKeysRepositoryImpl"
97         const val SETTING_KEY = Settings.Secure.ACCESSIBILITY_STICKY_KEYS
98     }
99 }
100