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

Commit ada1af33 authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "New flow for Settings.Global" into main

parents c493ec35 089e677c
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -16,10 +16,16 @@

package com.android.settingslib.spa.framework.util

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch

/**
 * Returns a [Flow] whose values are a list which containing the results of applying the given
@@ -46,3 +52,19 @@ inline fun <T> Flow<List<T>>.filterItem(crossinline predicate: (T) -> Boolean):
 */
fun <T1, T2> Flow<T1>.waitFirst(otherFlow: Flow<T2>): Flow<T1> =
    combine(otherFlow.take(1)) { value, _ -> value }


/**
 * Collects the latest value of given flow with a provided action with [LifecycleOwner].
 */
fun <T> Flow<T>.collectLatestWithLifecycle(
    lifecycleOwner: LifecycleOwner,
    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
    action: suspend (value: T) -> Unit,
) {
    lifecycleOwner.lifecycleScope.launch {
        lifecycleOwner.repeatOnLifecycle(minActiveState) {
            collectLatest(action)
        }
    }
}
+14 −0
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.settingslib.spa.framework.util

import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.testutils.waitUntil
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.count
import kotlinx.coroutines.flow.emptyFlow
@@ -85,4 +87,16 @@ class FlowsTest {

        assertThat(outputFlow.toList()).containsExactly("A")
    }

    @Test
    fun collectLatestWithLifecycle() {
        val mainFlow = flowOf("A")
        var actual: String? = null

        mainFlow.collectLatestWithLifecycle(TestLifecycleOwner()) {
            actual = it
        }

        waitUntil { actual == "A" }
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -18,9 +18,17 @@ package com.android.settingslib.spa.testutils

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.withTimeoutOrNull

suspend fun <T> Flow<T>.firstWithTimeoutOrNull(timeMillis: Long = 500): T? =
    withTimeoutOrNull(timeMillis) {
        first()
    }

suspend fun <T> Flow<T>.toListWithTimeout(timeMillis: Long = 500): List<T> {
    val list = mutableListOf<T>()
    return withTimeoutOrNull(timeMillis) {
        toList(list)
    } ?: list
}
+1 −1
Original line number Diff line number Diff line
@@ -18,5 +18,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.android.settingslib.spaprivileged">
    <uses-permission android:name="android.permission.MANAGE_USERS" />
    <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
</manifest>
+45 −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 kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
import kotlinx.coroutines.flow.Flow

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

fun Context.settingsGlobalBooleanFlow(name: String): Flow<Boolean> {
    val value by settingsGlobalBoolean(name)
    return settingsGlobalFlow(name) { value }
}

private class SettingsGlobalBooleanDelegate(context: Context, private val name: String) :
    ReadWriteProperty<Any?, Boolean> {

    private val contentResolver: ContentResolver = context.contentResolver

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

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
        Settings.Global.putInt(contentResolver, name, if (value) 1 else 0)
    }
}
Loading