Loading packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt +14 −0 Original line number Diff line number Diff line Loading @@ -18,9 +18,11 @@ package com.android.systemui.shared.notifications.data.repository import android.provider.Settings import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn Loading @@ -33,6 +35,7 @@ class NotificationSettingsRepository( private val scope: CoroutineScope, private val backgroundDispatcher: CoroutineDispatcher, private val secureSettingsRepository: SecureSettingsRepository, private val systemSettingsRepository: SystemSettingsRepository, ) { val isNotificationHistoryEnabled: Flow<Boolean> = secureSettingsRepository Loading Loading @@ -60,4 +63,15 @@ class NotificationSettingsRepository( ) } } val isCooldownEnabled: StateFlow<Boolean> = systemSettingsRepository .intSetting(name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED) .map { it == 1 } .flowOn(backgroundDispatcher) .stateIn( scope = scope, started = SharingStarted.Eagerly, initialValue = false, ) } packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt +2 −1 Original line number Diff line number Diff line Loading @@ -38,4 +38,5 @@ class NotificationSettingsInteractor( val current = repository.isShowNotificationsOnLockScreenEnabled().value repository.setShowNotificationsOnLockscreenEnabled(!current) } } val isCooldownEnabled = repository.isCooldownEnabled} packages/SystemUI/customization/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepository.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shared.settings.data.repository import android.content.ContentResolver import android.database.ContentObserver import android.provider.Settings import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext /** * Defines interface for classes that can provide access to data from [Settings.System]. This * repository doesn't guarantee to provide value across different users. For that see: * [UserAwareSecureSettingsRepository] which does that for secure settings. */ interface SystemSettingsRepository { /** Returns a [Flow] tracking the value of a setting as an [Int]. */ fun intSetting( name: String, defaultValue: Int = 0, ): Flow<Int> /** Updates the value of the setting with the given name. */ suspend fun setInt( name: String, value: Int, ) suspend fun getInt( name: String, defaultValue: Int = 0, ): Int suspend fun getString(name: String): String? } class SystemSettingsRepositoryImpl( private val contentResolver: ContentResolver, private val backgroundDispatcher: CoroutineDispatcher, ) : SystemSettingsRepository { override fun intSetting( name: String, defaultValue: Int, ): Flow<Int> { return callbackFlow { val observer = object : ContentObserver(null) { override fun onChange(selfChange: Boolean) { trySend(Unit) } } contentResolver.registerContentObserver( Settings.System.getUriFor(name), /* notifyForDescendants= */ false, observer, ) send(Unit) awaitClose { contentResolver.unregisterContentObserver(observer) } } .map { Settings.System.getInt(contentResolver, name, defaultValue) } // The above work is done on the background thread (which is important for accessing // settings through the content resolver). .flowOn(backgroundDispatcher) } override suspend fun setInt(name: String, value: Int) { withContext(backgroundDispatcher) { Settings.System.putInt( contentResolver, name, value, ) } } override suspend fun getInt(name: String, defaultValue: Int): Int { return withContext(backgroundDispatcher) { Settings.System.getInt( contentResolver, name, defaultValue, ) } } override suspend fun getString(name: String): String? { return withContext(backgroundDispatcher) { Settings.System.getString( contentResolver, name, ) } } } packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSystemSettingsRepository.kt 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shared.settings.data.repository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map class FakeSystemSettingsRepository : SystemSettingsRepository { private val settings = MutableStateFlow<Map<String, String>>(mutableMapOf()) override fun intSetting(name: String, defaultValue: Int): Flow<Int> { return settings.map { it.getOrDefault(name, defaultValue.toString()) }.map { it.toInt() } } override suspend fun setInt(name: String, value: Int) { settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() } } override suspend fun getInt(name: String, defaultValue: Int): Int { return settings.value[name]?.toInt() ?: defaultValue } override suspend fun getString(name: String): String? { return settings.value[name] } } packages/SystemUI/src/com/android/systemui/settings/SystemSettingsRepositoryModule.kt 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.settings import android.content.ContentResolver import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import com.android.systemui.shared.settings.data.repository.SystemSettingsRepositoryImpl import dagger.Module import dagger.Provides import kotlinx.coroutines.CoroutineDispatcher @Module object SystemSettingsRepositoryModule { @JvmStatic @Provides @SysUISingleton fun provideSystemSettingsRepository( contentResolver: ContentResolver, @Background backgroundDispatcher: CoroutineDispatcher, ): SystemSettingsRepository = SystemSettingsRepositoryImpl(contentResolver, backgroundDispatcher) } Loading
packages/SystemUI/customization/src/com/android/systemui/shared/notifications/data/repository/NotificationSettingsRepository.kt +14 −0 Original line number Diff line number Diff line Loading @@ -18,9 +18,11 @@ package com.android.systemui.shared.notifications.data.repository import android.provider.Settings import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn Loading @@ -33,6 +35,7 @@ class NotificationSettingsRepository( private val scope: CoroutineScope, private val backgroundDispatcher: CoroutineDispatcher, private val secureSettingsRepository: SecureSettingsRepository, private val systemSettingsRepository: SystemSettingsRepository, ) { val isNotificationHistoryEnabled: Flow<Boolean> = secureSettingsRepository Loading Loading @@ -60,4 +63,15 @@ class NotificationSettingsRepository( ) } } val isCooldownEnabled: StateFlow<Boolean> = systemSettingsRepository .intSetting(name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED) .map { it == 1 } .flowOn(backgroundDispatcher) .stateIn( scope = scope, started = SharingStarted.Eagerly, initialValue = false, ) }
packages/SystemUI/customization/src/com/android/systemui/shared/notifications/domain/interactor/NotificationSettingsInteractor.kt +2 −1 Original line number Diff line number Diff line Loading @@ -38,4 +38,5 @@ class NotificationSettingsInteractor( val current = repository.isShowNotificationsOnLockScreenEnabled().value repository.setShowNotificationsOnLockscreenEnabled(!current) } } val isCooldownEnabled = repository.isCooldownEnabled}
packages/SystemUI/customization/src/com/android/systemui/shared/settings/data/repository/SystemSettingsRepository.kt 0 → 100644 +117 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shared.settings.data.repository import android.content.ContentResolver import android.database.ContentObserver import android.provider.Settings import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.withContext /** * Defines interface for classes that can provide access to data from [Settings.System]. This * repository doesn't guarantee to provide value across different users. For that see: * [UserAwareSecureSettingsRepository] which does that for secure settings. */ interface SystemSettingsRepository { /** Returns a [Flow] tracking the value of a setting as an [Int]. */ fun intSetting( name: String, defaultValue: Int = 0, ): Flow<Int> /** Updates the value of the setting with the given name. */ suspend fun setInt( name: String, value: Int, ) suspend fun getInt( name: String, defaultValue: Int = 0, ): Int suspend fun getString(name: String): String? } class SystemSettingsRepositoryImpl( private val contentResolver: ContentResolver, private val backgroundDispatcher: CoroutineDispatcher, ) : SystemSettingsRepository { override fun intSetting( name: String, defaultValue: Int, ): Flow<Int> { return callbackFlow { val observer = object : ContentObserver(null) { override fun onChange(selfChange: Boolean) { trySend(Unit) } } contentResolver.registerContentObserver( Settings.System.getUriFor(name), /* notifyForDescendants= */ false, observer, ) send(Unit) awaitClose { contentResolver.unregisterContentObserver(observer) } } .map { Settings.System.getInt(contentResolver, name, defaultValue) } // The above work is done on the background thread (which is important for accessing // settings through the content resolver). .flowOn(backgroundDispatcher) } override suspend fun setInt(name: String, value: Int) { withContext(backgroundDispatcher) { Settings.System.putInt( contentResolver, name, value, ) } } override suspend fun getInt(name: String, defaultValue: Int): Int { return withContext(backgroundDispatcher) { Settings.System.getInt( contentResolver, name, defaultValue, ) } } override suspend fun getString(name: String): String? { return withContext(backgroundDispatcher) { Settings.System.getString( contentResolver, name, ) } } }
packages/SystemUI/customization/tests/utils/src/com/android/systemui/shared/settings/data/repository/FakeSystemSettingsRepository.kt 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.shared.settings.data.repository import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map class FakeSystemSettingsRepository : SystemSettingsRepository { private val settings = MutableStateFlow<Map<String, String>>(mutableMapOf()) override fun intSetting(name: String, defaultValue: Int): Flow<Int> { return settings.map { it.getOrDefault(name, defaultValue.toString()) }.map { it.toInt() } } override suspend fun setInt(name: String, value: Int) { settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() } } override suspend fun getInt(name: String, defaultValue: Int): Int { return settings.value[name]?.toInt() ?: defaultValue } override suspend fun getString(name: String): String? { return settings.value[name] } }
packages/SystemUI/src/com/android/systemui/settings/SystemSettingsRepositoryModule.kt 0 → 100644 +38 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.settings import android.content.ContentResolver import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository import com.android.systemui.shared.settings.data.repository.SystemSettingsRepositoryImpl import dagger.Module import dagger.Provides import kotlinx.coroutines.CoroutineDispatcher @Module object SystemSettingsRepositoryModule { @JvmStatic @Provides @SysUISingleton fun provideSystemSettingsRepository( contentResolver: ContentResolver, @Background backgroundDispatcher: CoroutineDispatcher, ): SystemSettingsRepository = SystemSettingsRepositoryImpl(contentResolver, backgroundDispatcher) }