1 /*
2  * 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 package com.android.systemui.accessibility.data.repository
18 
19 import android.provider.Settings
20 import com.android.systemui.dagger.qualifiers.Application
21 import com.android.systemui.dagger.qualifiers.Background
22 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository
23 import com.android.systemui.util.settings.SecureSettings
24 import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
25 import dagger.assisted.Assisted
26 import dagger.assisted.AssistedFactory
27 import dagger.assisted.AssistedInject
28 import kotlinx.coroutines.CoroutineDispatcher
29 import kotlinx.coroutines.CoroutineScope
30 import kotlinx.coroutines.flow.SharingStarted
31 import kotlinx.coroutines.flow.flowOn
32 import kotlinx.coroutines.flow.map
33 import kotlinx.coroutines.flow.onStart
34 import kotlinx.coroutines.flow.shareIn
35 
36 /**
37  * Single user version of [AccessibilityQsShortcutsRepository]. It provides a similar interface as
38  * [TileSpecRepository], but focusing solely on the user it was created for. It observes the changes
39  * on the [Settings.Secure.ACCESSIBILITY_QS_TARGETS] for a given user
40  */
41 class UserA11yQsShortcutsRepository
42 @AssistedInject
43 constructor(
44     @Assisted private val userId: Int,
45     private val secureSettings: SecureSettings,
46     @Application private val applicationScope: CoroutineScope,
47     @Background private val backgroundDispatcher: CoroutineDispatcher,
48 ) {
49     val targets =
50         secureSettings
51             .observerFlow(userId, SETTING_NAME)
52             // Force an update
<lambda>null53             .onStart { emit(Unit) }
<lambda>null54             .map { getA11yQsShortcutTargets(userId) }
55             .flowOn(backgroundDispatcher)
56             .shareIn(
57                 scope = applicationScope,
58                 started = SharingStarted.WhileSubscribed(),
59                 replay = 1
60             )
61 
getA11yQsShortcutTargetsnull62     private fun getA11yQsShortcutTargets(userId: Int): Set<String> {
63         val settingValue = secureSettings.getStringForUser(SETTING_NAME, userId) ?: ""
64         return settingValue.split(SETTING_SEPARATOR).filterNot { it.isEmpty() }.toSet()
65     }
66 
67     companion object {
68         const val SETTING_NAME = Settings.Secure.ACCESSIBILITY_QS_TARGETS
69         const val SETTING_SEPARATOR = ":"
70     }
71 
72     @AssistedFactory
73     interface Factory {
createnull74         fun create(
75             userId: Int,
76         ): UserA11yQsShortcutsRepository
77     }
78 }
79