[Catalyst] Update RemoveAnimationsPreference

Bug: 373451690
Flag: com.android.settings.flags.catalyst_accessibility_color_and_motion
Test: atest & devtool
Change-Id: Id648febf32bebb391f1277e28f58ddb0d5130d59
This commit is contained in:
Jacky Wang
2024-11-23 06:24:13 +08:00
parent 851bf18783
commit 8e73d0f51e
4 changed files with 61 additions and 49 deletions

View File

@@ -62,7 +62,6 @@
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:icon="@drawable/ic_accessibility_animation" android:icon="@drawable/ic_accessibility_animation"
android:key="animator_duration_scale" android:key="animator_duration_scale"
android:persistent="false"
android:summary="@string/accessibility_disable_animations_summary" android:summary="@string/accessibility_disable_animations_summary"
android:title="@string/accessibility_disable_animations" android:title="@string/accessibility_disable_animations"
settings:controller="com.android.settings.accessibility.DisableAnimationsPreferenceController"/> settings:controller="com.android.settings.accessibility.DisableAnimationsPreferenceController"/>

View File

@@ -50,7 +50,6 @@ public class ColorAndMotionFragment extends DashboardFragment {
// Preferences // Preferences
private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN = "daltonizer_preference"; private static final String DISPLAY_DALTONIZER_PREFERENCE_SCREEN = "daltonizer_preference";
private static final String TOGGLE_DISABLE_ANIMATIONS = "toggle_disable_animations";
private static final String TOGGLE_LARGE_POINTER_ICON = "toggle_large_pointer_icon"; private static final String TOGGLE_LARGE_POINTER_ICON = "toggle_large_pointer_icon";
@VisibleForTesting @VisibleForTesting
static final String TOGGLE_FORCE_INVERT = "toggle_force_invert"; static final String TOGGLE_FORCE_INVERT = "toggle_force_invert";
@@ -125,7 +124,7 @@ public class ColorAndMotionFragment extends DashboardFragment {
mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN); mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN);
// Disable animation. // Disable animation.
mToggleDisableAnimationsPreference = findPreference(TOGGLE_DISABLE_ANIMATIONS); mToggleDisableAnimationsPreference = findPreference(RemoveAnimationsPreference.KEY);
// Large pointer icon. // Large pointer icon.
mToggleLargePointerIconPreference = findPreference(TOGGLE_LARGE_POINTER_ICON); mToggleLargePointerIconPreference = findPreference(TOGGLE_LARGE_POINTER_ICON);

View File

@@ -27,45 +27,50 @@ import com.android.settingslib.datastore.NoOpKeyedObservable
import com.android.settingslib.datastore.SettingsGlobalStore import com.android.settingslib.datastore.SettingsGlobalStore
import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleContext
import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceLifecycleProvider
import com.android.settingslib.metadata.ReadWritePermit
import com.android.settingslib.metadata.SwitchPreference import com.android.settingslib.metadata.SwitchPreference
import com.android.settingslib.preference.SwitchPreferenceBinding
class RemoveAnimationsPreference : class RemoveAnimationsPreference :
SwitchPreference( SwitchPreference(
KEY, KEY,
R.string.accessibility_disable_animations, R.string.accessibility_disable_animations,
R.string.accessibility_disable_animations_summary R.string.accessibility_disable_animations_summary,
), ),
SwitchPreferenceBinding,
PreferenceLifecycleProvider { PreferenceLifecycleProvider {
private var mSettingsKeyedObserver: KeyedObserver<String?>? = null private var mSettingsKeyedObserver: KeyedObserver<String>? = null
override val icon: Int override val icon: Int
@DrawableRes get() = R.drawable.ic_accessibility_animation @DrawableRes get() = R.drawable.ic_accessibility_animation
override fun onStart(context: PreferenceLifecycleContext) { override fun onStart(context: PreferenceLifecycleContext) {
mSettingsKeyedObserver = object : KeyedObserver<String?> { val observer = KeyedObserver<String> { _, _ -> context.notifyPreferenceChange(KEY) }
override fun onKeyChanged(key: String?, reason: Int) { mSettingsKeyedObserver = observer
context.notifyPreferenceChange(KEY) val storage = SettingsGlobalStore.get(context)
} for (key in getAnimationKeys()) {
} storage.addObserver(key, observer, HandlerExecutor.main)
mSettingsKeyedObserver?.let {
for (key in TOGGLE_ANIMATION_KEYS) {
SettingsGlobalStore.get(context).addObserver(key, it, HandlerExecutor.main)
}
} }
} }
override fun onStop(context: PreferenceLifecycleContext) { override fun onStop(context: PreferenceLifecycleContext) {
mSettingsKeyedObserver?.let { mSettingsKeyedObserver?.let {
SettingsGlobalStore.get(context).removeObserver(it) val storage = SettingsGlobalStore.get(context)
for (key in getAnimationKeys()) {
storage.removeObserver(key, it)
}
mSettingsKeyedObserver = null mSettingsKeyedObserver = null
} }
} }
override fun storage(context: Context): KeyValueStore = RemoveAnimationsStorage(context) override fun storage(context: Context): KeyValueStore = RemoveAnimationsStorage(context)
override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
ReadWritePermit.ALLOW
@Suppress("UNCHECKED_CAST")
private class RemoveAnimationsStorage(private val context: Context) : private class RemoveAnimationsStorage(private val context: Context) :
NoOpKeyedObservable<String>(), KeyValueStore { NoOpKeyedObservable<String>(), KeyValueStore {
override fun contains(key: String) = key == KEY override fun contains(key: String) = key == KEY
@@ -74,7 +79,6 @@ class RemoveAnimationsPreference :
when { when {
key == KEY && valueType == Boolean::class.javaObjectType -> key == KEY && valueType == Boolean::class.javaObjectType ->
!isAnimationEnabled(context) as T !isAnimationEnabled(context) as T
else -> null else -> null
} }
@@ -94,16 +98,11 @@ class RemoveAnimationsPreference :
const val ANIMATION_ON_VALUE: Float = 1.0f const val ANIMATION_ON_VALUE: Float = 1.0f
const val ANIMATION_OFF_VALUE: Float = 0.0f const val ANIMATION_OFF_VALUE: Float = 0.0f
val TOGGLE_ANIMATION_KEYS: List<String> = listOf(
Settings.Global.WINDOW_ANIMATION_SCALE, Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.ANIMATOR_DURATION_SCALE
)
fun isAnimationEnabled(context: Context): Boolean { fun isAnimationEnabled(context: Context): Boolean {
val storage = SettingsGlobalStore.get(context)
// This pref treats animation as enabled if *any* of the animation types are enabled. // This pref treats animation as enabled if *any* of the animation types are enabled.
for (animationSetting in TOGGLE_ANIMATION_KEYS) { for (animationSetting in getAnimationKeys()) {
val animationValue: Float? = val animationValue: Float? = storage.getFloat(animationSetting)
SettingsGlobalStore.get(context).getFloat(animationSetting)
// Animation is enabled by default, so treat null as enabled. // Animation is enabled by default, so treat null as enabled.
if (animationValue == null || animationValue > ANIMATION_OFF_VALUE) { if (animationValue == null || animationValue > ANIMATION_OFF_VALUE) {
return true return true
@@ -113,10 +112,18 @@ class RemoveAnimationsPreference :
} }
fun setAnimationEnabled(context: Context, enabled: Boolean) { fun setAnimationEnabled(context: Context, enabled: Boolean) {
val value = if (enabled) ANIMATION_ON_VALUE else ANIMATION_OFF_VALUE; val storage = SettingsGlobalStore.get(context)
for (animationSetting in TOGGLE_ANIMATION_KEYS) { val value = if (enabled) ANIMATION_ON_VALUE else ANIMATION_OFF_VALUE
SettingsGlobalStore.get(context).setFloat(animationSetting, value) for (animationSetting in getAnimationKeys()) {
storage.setFloat(animationSetting, value)
} }
} }
fun getAnimationKeys() =
listOf(
Settings.Global.WINDOW_ANIMATION_SCALE,
Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.Global.ANIMATOR_DURATION_SCALE,
)
} }
} }

View File

@@ -20,10 +20,11 @@ import android.content.Context
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import androidx.test.core.app.ApplicationProvider import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.accessibility.RemoveAnimationsPreference.Companion.ANIMATION_ON_VALUE import com.android.settings.accessibility.RemoveAnimationsPreference.Companion.ANIMATION_ON_VALUE
import com.android.settings.accessibility.RemoveAnimationsPreference.Companion.TOGGLE_ANIMATION_KEYS
import com.android.settingslib.datastore.SettingsGlobalStore import com.android.settingslib.datastore.SettingsGlobalStore
import com.android.settingslib.preference.createAndBindWidget import com.android.settingslib.preference.PreferenceScreenBindingHelper
import com.android.settingslib.preference.PreferenceScreenFactory
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
@@ -33,53 +34,59 @@ class RemoveAnimationsPreferenceTest {
private val appContext: Context = ApplicationProvider.getApplicationContext() private val appContext: Context = ApplicationProvider.getApplicationContext()
private val removeAnimationsPreference = private fun getRemoveAnimationsSwitchPreference(): SwitchPreferenceCompat =
RemoveAnimationsPreference() PreferenceScreenFactory(appContext).let {
val preferenceScreen = it.inflate(R.xml.accessibility_color_and_motion)!!
private fun getSwitchPreferenceCompat(): SwitchPreferenceCompat = it.preferenceManager.setPreferences(preferenceScreen)
removeAnimationsPreference.createAndBindWidget(appContext) PreferenceScreenBindingHelper.bind(preferenceScreen)
preferenceScreen.findPreference(RemoveAnimationsPreference.KEY)!!
}
@Test @Test
fun animationOff_switchPreferenceIsChecked() { fun animationOff_switchPreferenceIsChecked() {
RemoveAnimationsPreference.setAnimationEnabled(appContext, false) RemoveAnimationsPreference.setAnimationEnabled(appContext, false)
assertThat(getSwitchPreferenceCompat().isChecked).isTrue() assertThat(getRemoveAnimationsSwitchPreference().isChecked).isTrue()
} }
@Test @Test
fun animationOn_switchPreferenceIsNotChecked() { fun animationOn_switchPreferenceIsNotChecked() {
RemoveAnimationsPreference.setAnimationEnabled(appContext, true) RemoveAnimationsPreference.setAnimationEnabled(appContext, true)
assertThat(getSwitchPreferenceCompat().isChecked).isFalse() assertThat(getRemoveAnimationsSwitchPreference().isChecked).isFalse()
} }
@Test @Test
fun oneAnimationValueOn_switchPreferenceIsNotChecked() { fun oneAnimationValueOn_switchPreferenceIsNotChecked() {
// Animation is disabled, except for one value. // Animation is disabled, except for one value.
RemoveAnimationsPreference.setAnimationEnabled(appContext, false) RemoveAnimationsPreference.setAnimationEnabled(appContext, false)
SettingsGlobalStore.get(appContext).setFloat(TOGGLE_ANIMATION_KEYS[0], ANIMATION_ON_VALUE) SettingsGlobalStore.get(appContext)
.setFloat(RemoveAnimationsPreference.getAnimationKeys()[0], ANIMATION_ON_VALUE)
assertThat(getSwitchPreferenceCompat().isChecked).isFalse() assertThat(getRemoveAnimationsSwitchPreference().isChecked).isFalse()
} }
@Test @Test
fun storageSetTrue_turnsOffAnimation() { fun toggleOnSwitch_turnsOffAnimation() {
RemoveAnimationsPreference.setAnimationEnabled(appContext, true) RemoveAnimationsPreference.setAnimationEnabled(appContext, true)
storageSetValue(true) val switchPreference = getRemoveAnimationsSwitchPreference()
assertThat(switchPreference.isChecked).isFalse()
switchPreference.performClick()
assertThat(switchPreference.isChecked).isTrue()
assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isFalse() assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isFalse()
} }
@Test @Test
fun storageSetFalse_turnsOnAnimation() { fun toggleOffSwitch_turnsOnAnimation() {
RemoveAnimationsPreference.setAnimationEnabled(appContext, false) RemoveAnimationsPreference.setAnimationEnabled(appContext, false)
storageSetValue(false) val switchPreference = getRemoveAnimationsSwitchPreference()
assertThat(switchPreference.isChecked).isTrue()
switchPreference.performClick()
assertThat(switchPreference.isChecked).isFalse()
assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isTrue() assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isTrue()
} }
private fun storageSetValue(enabled: Boolean) = removeAnimationsPreference.storage(appContext)
.setValue(RemoveAnimationsPreference.KEY, Boolean::class.javaObjectType, enabled)
} }