Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b981a2d authored by Chaohui Wang's avatar Chaohui Wang
Browse files

New SettingsSecureBoolean and flow

To easily collect the Setting.Secure changes.

Also refactor SettingsGlobalBoolean.

Bug: 308903704
Test: unit tests
Change-Id: Id85ffe9d8e4ea3d9daf1e04143d4a3069a0e95e5
parent 7ac65614
Loading
Loading
Loading
Loading
+11 −13
Original line number Diff line number Diff line
@@ -14,12 +14,11 @@
 * limitations under the License.
 */

package com.android.settingslib.spaprivileged.settingsprovider
package com.android.settingslib.spaprivileged.database

import android.content.Context
import android.database.ContentObserver
import android.os.Handler
import android.provider.Settings
import android.net.Uri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
@@ -27,20 +26,19 @@ import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.flowOn

internal fun <T> Context.settingsGlobalFlow(
    name: String,
    sendInitialValue: Boolean = true,
    value: () -> T,
): Flow<T> = callbackFlow {
    val contentObserver = object : ContentObserver(Handler.getMain()) {
/** Content change flow for the given [uri]. */
internal fun Context.contentChangeFlow(
    uri: Uri,
    sendInitial: Boolean = true,
): Flow<Unit> = callbackFlow {
    val contentObserver = object : ContentObserver(null) {
        override fun onChange(selfChange: Boolean) {
            trySend(value())
            trySend(Unit)
        }
    }
    val uri = Settings.Global.getUriFor(name)
    contentResolver.registerContentObserver(uri, false, contentObserver)
    if (sendInitialValue) {
        trySend(value())
    if (sendInitial) {
        trySend(Unit)
    }

    awaitClose { contentResolver.unregisterContentObserver(contentObserver) }
+3 −1
Original line number Diff line number Diff line
@@ -22,13 +22,15 @@ import android.provider.Settings
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map

fun Context.settingsGlobalBoolean(name: String, defaultValue: Boolean = false):
    ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)

fun Context.settingsGlobalBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
    val value by settingsGlobalBoolean(name, defaultValue)
    return settingsGlobalFlow(name) { value }
    return settingsGlobalChangeFlow(name).map { value }.distinctUntilChanged()
}

private class SettingsGlobalBooleanDelegate(
+3 −1
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package com.android.settingslib.spaprivileged.settingsprovider

import android.content.Context
import android.provider.Settings
import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlinx.coroutines.flow.Flow

fun Context.settingsGlobalChangeFlow(name: String, sendInitialValue: Boolean = true): Flow<Unit> =
    settingsGlobalFlow(name, sendInitialValue) { }
    contentChangeFlow(Settings.Global.getUriFor(name), sendInitialValue)
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.settingslib.spaprivileged.settingsprovider

import android.content.ContentResolver
import android.content.Context
import android.provider.Settings
import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map

fun Context.settingsSecureBoolean(name: String, defaultValue: Boolean = false):
    ReadWriteProperty<Any?, Boolean> = SettingsSecureBooleanDelegate(this, name, defaultValue)

fun Context.settingsSecureBooleanFlow(name: String, defaultValue: Boolean = false): Flow<Boolean> {
    val value by settingsSecureBoolean(name, defaultValue)
    return contentChangeFlow(Settings.Secure.getUriFor(name)).map { value }.distinctUntilChanged()
}

private class SettingsSecureBooleanDelegate(
    context: Context,
    private val name: String,
    private val defaultValue: Boolean = false,
) : ReadWriteProperty<Any?, Boolean> {

    private val contentResolver: ContentResolver = context.contentResolver

    override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean =
        Settings.Secure.getInt(contentResolver, name, if (defaultValue) 1 else 0) != 0

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
        Settings.Secure.putInt(contentResolver, name, if (value) 1 else 0)
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class SettingsGlobalBooleanRepositoryTest {
class SettingsGlobalBooleanTest {

    private val context: Context = ApplicationProvider.getApplicationContext()

Loading