diff options
| author | 2024-06-19 06:27:47 +0000 | |
|---|---|---|
| committer | 2024-06-19 06:27:47 +0000 | |
| commit | b11c760c278874b808e41045acd62d22a8336a45 (patch) | |
| tree | 61d9f6b29b79febed901133e5f89213deebeffe2 | |
| parent | ae444b4894a9d9c87750fc332340058d2f0fab94 (diff) | |
| parent | 2c555e9b2446aaf05ba74933a0ae0c61db9a40cc (diff) | |
Merge "Create settingsSecureStringFlow" into main
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" + } +} |