Loading src/com/android/settings/notification/SoundScreen.kt +1 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ open class SoundScreen : PreferenceScreenMixin, PreferenceIconProvider { +ScreenLockSoundPreference() order -45 +ChargingSoundPreference() order -40 +DockingSoundPreference() order -35 +TouchSoundPreference() order -30 +TouchSoundPreference(context) order -30 } } } Loading src/com/android/settings/notification/TouchSoundPreference.kt +22 −12 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.app.settings.SettingsEnums.ACTION_TOUCH_SOUND import android.content.Context import android.media.AudioManager import android.provider.Settings.System.SOUND_EFFECTS_ENABLED import androidx.annotation.VisibleForTesting import com.android.settings.R import com.android.settings.contract.KEY_TOUCH_SOUNDS import com.android.settings.metrics.PreferenceActionMetricsProvider Loading @@ -32,14 +33,18 @@ import com.android.settingslib.metadata.SwitchPreference import com.android.settingslib.preference.SwitchPreferenceBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch // LINT.IfChange class TouchSoundPreference : class TouchSoundPreference(context: Context) : SwitchPreference(KEY, R.string.touch_sounds_title), PreferenceActionMetricsProvider, SwitchPreferenceBinding, PreferenceActionMetricsProvider, PreferenceAvailabilityProvider { private val storage = TouchSoundStorage(context) override val preferenceActionMetrics: Int get() = ACTION_TOUCH_SOUND Loading @@ -48,7 +53,7 @@ class TouchSoundPreference : override fun isAvailable(context: Context) = context.resources.getBoolean(R.bool.config_show_touch_sounds) override fun storage(context: Context): KeyValueStore = TouchSoundStorage(context) override fun storage(context: Context): KeyValueStore = storage override fun getReadPermissions(context: Context) = SettingsSystemStore.getReadPermissions() Loading @@ -68,16 +73,21 @@ class TouchSoundPreference : } } private class TouchSoundStorage(private val context: Context) : KeyValueStoreDelegate { internal class TouchSoundStorage(private val context: Context) : KeyValueStoreDelegate { // use limitedParallelism to prevent race condition and achieve sequential semantic private val coroutineScope = CoroutineScope(Dispatchers.IO.limitedParallelism(1)) @VisibleForTesting internal var job: Job? = null override val keyValueStoreDelegate: KeyValueStore = SettingsSystemStore.get(context).apply { setDefaultValue(TouchSoundPreference.KEY, true) } override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { super.setValue(key, valueType, value) val isChecked = getBoolean(key) val coroutineScope = CoroutineScope(Dispatchers.Default.limitedParallelism(1)) job?.cancel() job = coroutineScope.launch { val audioManager = context.getSystemService(AudioManager::class.java) val audioManager = context.getSystemService(AudioManager::class.java)!! if (isChecked == true) { audioManager.loadSoundEffects() } else { Loading tests/robotests/src/com/android/settings/notification/TouchSoundPreferenceTest.kt +9 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.preference.createAndBindWidget import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt Loading @@ -51,7 +52,7 @@ class TouchSoundPreferenceTest { override fun getResources(): Resources = mockResources } private val touchSoundPreference = TouchSoundPreference() private val touchSoundPreference = TouchSoundPreference(context) @Test fun isAvailable_configTrue_shouldReturnTrue() { Loading Loading @@ -107,23 +108,28 @@ class TouchSoundPreferenceTest { } @Test fun toggleOff_shouldUnloadSoundEffects() { fun toggleOff_shouldUnloadSoundEffects() = runTest { enableTouchSound(true) getSwitchPreference().performClick() waitForJob() verify(audioManager).unloadSoundEffects() } @Test fun toggleOn_shouldLoadSoundEffects() { fun toggleOn_shouldLoadSoundEffects() = runTest { enableTouchSound(false) getSwitchPreference().performClick() waitForJob() verify(audioManager).loadSoundEffects() } private suspend fun waitForJob() = (touchSoundPreference.storage(context) as TouchSoundStorage).job?.join() private fun getSwitchPreference(): SwitchPreferenceCompat = touchSoundPreference.createAndBindWidget(context) Loading Loading
src/com/android/settings/notification/SoundScreen.kt +1 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,7 @@ open class SoundScreen : PreferenceScreenMixin, PreferenceIconProvider { +ScreenLockSoundPreference() order -45 +ChargingSoundPreference() order -40 +DockingSoundPreference() order -35 +TouchSoundPreference() order -30 +TouchSoundPreference(context) order -30 } } } Loading
src/com/android/settings/notification/TouchSoundPreference.kt +22 −12 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.app.settings.SettingsEnums.ACTION_TOUCH_SOUND import android.content.Context import android.media.AudioManager import android.provider.Settings.System.SOUND_EFFECTS_ENABLED import androidx.annotation.VisibleForTesting import com.android.settings.R import com.android.settings.contract.KEY_TOUCH_SOUNDS import com.android.settings.metrics.PreferenceActionMetricsProvider Loading @@ -32,14 +33,18 @@ import com.android.settingslib.metadata.SwitchPreference import com.android.settingslib.preference.SwitchPreferenceBinding import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.launch // LINT.IfChange class TouchSoundPreference : class TouchSoundPreference(context: Context) : SwitchPreference(KEY, R.string.touch_sounds_title), PreferenceActionMetricsProvider, SwitchPreferenceBinding, PreferenceActionMetricsProvider, PreferenceAvailabilityProvider { private val storage = TouchSoundStorage(context) override val preferenceActionMetrics: Int get() = ACTION_TOUCH_SOUND Loading @@ -48,7 +53,7 @@ class TouchSoundPreference : override fun isAvailable(context: Context) = context.resources.getBoolean(R.bool.config_show_touch_sounds) override fun storage(context: Context): KeyValueStore = TouchSoundStorage(context) override fun storage(context: Context): KeyValueStore = storage override fun getReadPermissions(context: Context) = SettingsSystemStore.getReadPermissions() Loading @@ -68,16 +73,21 @@ class TouchSoundPreference : } } private class TouchSoundStorage(private val context: Context) : KeyValueStoreDelegate { internal class TouchSoundStorage(private val context: Context) : KeyValueStoreDelegate { // use limitedParallelism to prevent race condition and achieve sequential semantic private val coroutineScope = CoroutineScope(Dispatchers.IO.limitedParallelism(1)) @VisibleForTesting internal var job: Job? = null override val keyValueStoreDelegate: KeyValueStore = SettingsSystemStore.get(context).apply { setDefaultValue(TouchSoundPreference.KEY, true) } override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) { super.setValue(key, valueType, value) val isChecked = getBoolean(key) val coroutineScope = CoroutineScope(Dispatchers.Default.limitedParallelism(1)) job?.cancel() job = coroutineScope.launch { val audioManager = context.getSystemService(AudioManager::class.java) val audioManager = context.getSystemService(AudioManager::class.java)!! if (isChecked == true) { audioManager.loadSoundEffects() } else { Loading
tests/robotests/src/com/android/settings/notification/TouchSoundPreferenceTest.kt +9 −3 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.preference.createAndBindWidget import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyInt Loading @@ -51,7 +52,7 @@ class TouchSoundPreferenceTest { override fun getResources(): Resources = mockResources } private val touchSoundPreference = TouchSoundPreference() private val touchSoundPreference = TouchSoundPreference(context) @Test fun isAvailable_configTrue_shouldReturnTrue() { Loading Loading @@ -107,23 +108,28 @@ class TouchSoundPreferenceTest { } @Test fun toggleOff_shouldUnloadSoundEffects() { fun toggleOff_shouldUnloadSoundEffects() = runTest { enableTouchSound(true) getSwitchPreference().performClick() waitForJob() verify(audioManager).unloadSoundEffects() } @Test fun toggleOn_shouldLoadSoundEffects() { fun toggleOn_shouldLoadSoundEffects() = runTest { enableTouchSound(false) getSwitchPreference().performClick() waitForJob() verify(audioManager).loadSoundEffects() } private suspend fun waitForJob() = (touchSoundPreference.storage(context) as TouchSoundStorage).job?.join() private fun getSwitchPreference(): SwitchPreferenceCompat = touchSoundPreference.createAndBindWidget(context) Loading