summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chaohui Wang <chaohuiw@google.com> 2024-06-19 06:27:47 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-06-19 06:27:47 +0000
commitb11c760c278874b808e41045acd62d22a8336a45 (patch)
tree61d9f6b29b79febed901133e5f89213deebeffe2
parentae444b4894a9d9c87750fc332340058d2f0fab94 (diff)
parent2c555e9b2446aaf05ba74933a0ae0c61db9a40cc (diff)
Merge "Create settingsSecureStringFlow" into main
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt15
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt15
-rw-r--r--packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt60
-rw-r--r--packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt92
4 files changed, 176 insertions, 6 deletions
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
index 5d67f57136e3..425286953759 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsGlobalBoolean.kt
@@ -21,16 +21,25 @@ import android.content.Context
import android.provider.Settings
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-fun Context.settingsGlobalBoolean(name: String, defaultValue: Boolean = false):
- ReadWriteProperty<Any?, Boolean> = SettingsGlobalBooleanDelegate(this, name, defaultValue)
+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 settingsGlobalChangeFlow(name).map { value }.distinctUntilChanged()
+ return settingsGlobalChangeFlow(name)
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
}
private class SettingsGlobalBooleanDelegate(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
index 25090a4140a4..d5f4ec264e43 100644
--- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureBoolean.kt
@@ -22,16 +22,25 @@ import android.provider.Settings
import com.android.settingslib.spaprivileged.database.contentChangeFlow
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
+import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
-fun Context.settingsSecureBoolean(name: String, defaultValue: Boolean = false):
- ReadWriteProperty<Any?, Boolean> = SettingsSecureBooleanDelegate(this, name, defaultValue)
+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()
+ return contentChangeFlow(Settings.Secure.getUriFor(name))
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
}
private class SettingsSecureBooleanDelegate(
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt
new file mode 100644
index 000000000000..a70630819c0d
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureString.kt
@@ -0,0 +1,60 @@
+/*
+ * 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.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.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+
+fun Context.settingsSecureString(
+ name: String,
+ defaultValue: String = ""
+): ReadWriteProperty<Any?, String> = SettingsSecureStringDelegate(this, name, defaultValue)
+
+fun Context.settingsSecureStringFlow(name: String, defaultValue: String = ""): Flow<String> {
+ val value by settingsSecureString(name, defaultValue)
+ return contentChangeFlow(Settings.Secure.getUriFor(name))
+ .map { value }
+ .distinctUntilChanged()
+ .conflate()
+ .flowOn(Dispatchers.Default)
+}
+
+private class SettingsSecureStringDelegate(
+ context: Context,
+ private val name: String,
+ private val defaultValue: String = "",
+) : ReadWriteProperty<Any?, String> {
+
+ private val contentResolver: ContentResolver = context.contentResolver
+
+ override fun getValue(thisRef: Any?, property: KProperty<*>): String =
+ Settings.Secure.getString(contentResolver, name) ?: defaultValue
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
+ Settings.Secure.putString(contentResolver, name, value)
+ }
+}
diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt
new file mode 100644
index 000000000000..e3d182bb5ace
--- /dev/null
+++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/settingsprovider/SettingsSecureStringTest.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.settingslib.spaprivileged.settingsprovider
+
+import android.content.Context
+import android.provider.Settings
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class SettingsSecureStringTest {
+
+ private val context: Context = ApplicationProvider.getApplicationContext()
+
+ @Test
+ fun getValue_returnCorrectValue() {
+ Settings.Secure.putString(context.contentResolver, TEST_NAME, VALUE)
+
+ val value by context.settingsSecureString(TEST_NAME)
+
+ assertThat(value).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun setValue_correctValueSet() {
+ var value by context.settingsSecureString(TEST_NAME)
+
+ value = VALUE
+
+ assertThat(Settings.Secure.getString(context.contentResolver, TEST_NAME)).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_valueNotChanged() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = VALUE
+
+ val flow = context.settingsSecureStringFlow(TEST_NAME)
+
+ assertThat(flow.firstWithTimeoutOrNull()).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_collectAfterValueChanged_onlyKeepLatest() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = ""
+
+ val flow = context.settingsSecureStringFlow(TEST_NAME)
+ value = VALUE
+
+ assertThat(flow.firstWithTimeoutOrNull()).isEqualTo(VALUE)
+ }
+
+ @Test
+ fun settingsSecureStringFlow_collectBeforeValueChanged_getBoth() = runBlocking {
+ var value by context.settingsSecureString(TEST_NAME)
+ value = ""
+
+ val listDeferred = async { context.settingsSecureStringFlow(TEST_NAME).toListWithTimeout() }
+ delay(100)
+ value = VALUE
+
+ assertThat(listDeferred.await()).containsAtLeast("", VALUE).inOrder()
+ }
+
+ private companion object {
+ const val TEST_NAME = "test_string_delegate"
+ const val VALUE = "value"
+ }
+}