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.util.settings.repository 18 19 import com.android.systemui.dagger.qualifiers.Background 20 import com.android.systemui.user.data.repository.UserRepository 21 import com.android.systemui.util.settings.SettingsProxyExt.observerFlow 22 import com.android.systemui.util.settings.UserSettingsProxy 23 import kotlin.coroutines.CoroutineContext 24 import kotlinx.coroutines.CoroutineDispatcher 25 import kotlinx.coroutines.flow.Flow 26 import kotlinx.coroutines.flow.distinctUntilChanged 27 import kotlinx.coroutines.flow.flatMapLatest 28 import kotlinx.coroutines.flow.flowOn 29 import kotlinx.coroutines.flow.map 30 import kotlinx.coroutines.flow.onStart 31 import kotlinx.coroutines.withContext 32 33 /** 34 * Repository for observing values of a [UserSettingsProxy], for the currently active user. That 35 * means that when the user is switched and the new user has a different value, the flow will emit 36 * the new value. For any system that tracks the desired user internally (e.g. the Quick Settings 37 * tiles system), use a [SettingsForUserRepository] instead. 38 */ 39 // TODO: b/377244768 - Make internal when UserAwareSecureSettingsRepository can be made internal. 40 abstract class UserAwareSettingsRepository( 41 private val userSettings: UserSettingsProxy, 42 private val userRepository: UserRepository, 43 @Background private val backgroundDispatcher: CoroutineDispatcher, 44 @Background private val bgContext: CoroutineContext, 45 ) { 46 47 fun boolSetting(name: String, defaultValue: Boolean): Flow<Boolean> = 48 userRepository.selectedUserInfo 49 .flatMapLatest { userInfo -> 50 settingObserver(name, userInfo.id) { 51 userSettings.getBoolForUser(name, defaultValue, userInfo.id) 52 } 53 } 54 .distinctUntilChanged() 55 .flowOn(backgroundDispatcher) 56 57 fun intSetting(name: String, defaultValue: Int): Flow<Int> { 58 return userRepository.selectedUserInfo 59 .flatMapLatest { userInfo -> 60 settingObserver(name, userInfo.id) { 61 userSettings.getIntForUser(name, defaultValue, userInfo.id) 62 } 63 } 64 .distinctUntilChanged() 65 .flowOn(backgroundDispatcher) 66 } 67 68 private fun <T> settingObserver(name: String, userId: Int, settingsReader: () -> T): Flow<T> { 69 return userSettings 70 .observerFlow(userId, name) 71 .onStart { emit(Unit) } 72 .map { settingsReader.invoke() } 73 } 74 75 suspend fun setInt(name: String, value: Int) { 76 withContext(bgContext) { 77 userSettings.putIntForUser(name, value, userRepository.getSelectedUserInfo().id) 78 } 79 } 80 81 suspend fun getInt(name: String, defaultValue: Int): Int { 82 return withContext(bgContext) { 83 userSettings.getIntForUser(name, defaultValue, userRepository.getSelectedUserInfo().id) 84 } 85 } 86 87 suspend fun setBoolean(name: String, value: Boolean) { 88 withContext(bgContext) { 89 userSettings.putBoolForUser(name, value, userRepository.getSelectedUserInfo().id) 90 } 91 } 92 93 suspend fun getString(name: String): String? { 94 return withContext(bgContext) { 95 userSettings.getStringForUser(name, userRepository.getSelectedUserInfo().id) 96 } 97 } 98 } 99