diff --git a/res/xml/accessibility_color_and_motion.xml b/res/xml/accessibility_color_and_motion.xml index 7d5ac4d7f9a..ffcdbddf7fe 100644 --- a/res/xml/accessibility_color_and_motion.xml +++ b/res/xml/accessibility_color_and_motion.xml @@ -62,7 +62,6 @@ diff --git a/src/com/android/settings/accessibility/ColorAndMotionFragment.java b/src/com/android/settings/accessibility/ColorAndMotionFragment.java index 7a7c21dd1af..7b2f04b9c21 100644 --- a/src/com/android/settings/accessibility/ColorAndMotionFragment.java +++ b/src/com/android/settings/accessibility/ColorAndMotionFragment.java @@ -50,7 +50,6 @@ public class ColorAndMotionFragment extends DashboardFragment { // Preferences 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"; @VisibleForTesting static final String TOGGLE_FORCE_INVERT = "toggle_force_invert"; @@ -125,7 +124,7 @@ public class ColorAndMotionFragment extends DashboardFragment { mDisplayDaltonizerPreferenceScreen = findPreference(DISPLAY_DALTONIZER_PREFERENCE_SCREEN); // Disable animation. - mToggleDisableAnimationsPreference = findPreference(TOGGLE_DISABLE_ANIMATIONS); + mToggleDisableAnimationsPreference = findPreference(RemoveAnimationsPreference.KEY); // Large pointer icon. mToggleLargePointerIconPreference = findPreference(TOGGLE_LARGE_POINTER_ICON); diff --git a/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt b/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt index 14e240f8a09..5b732bc32d1 100644 --- a/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt +++ b/src/com/android/settings/accessibility/RemoveAnimationsPreference.kt @@ -27,45 +27,50 @@ import com.android.settingslib.datastore.NoOpKeyedObservable import com.android.settingslib.datastore.SettingsGlobalStore import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider +import com.android.settingslib.metadata.ReadWritePermit import com.android.settingslib.metadata.SwitchPreference -import com.android.settingslib.preference.SwitchPreferenceBinding class RemoveAnimationsPreference : SwitchPreference( KEY, R.string.accessibility_disable_animations, - R.string.accessibility_disable_animations_summary + R.string.accessibility_disable_animations_summary, ), - SwitchPreferenceBinding, PreferenceLifecycleProvider { - private var mSettingsKeyedObserver: KeyedObserver? = null + private var mSettingsKeyedObserver: KeyedObserver? = null override val icon: Int @DrawableRes get() = R.drawable.ic_accessibility_animation override fun onStart(context: PreferenceLifecycleContext) { - mSettingsKeyedObserver = object : KeyedObserver { - override fun onKeyChanged(key: String?, reason: Int) { - context.notifyPreferenceChange(KEY) - } - } - mSettingsKeyedObserver?.let { - for (key in TOGGLE_ANIMATION_KEYS) { - SettingsGlobalStore.get(context).addObserver(key, it, HandlerExecutor.main) - } + val observer = KeyedObserver { _, _ -> context.notifyPreferenceChange(KEY) } + mSettingsKeyedObserver = observer + val storage = SettingsGlobalStore.get(context) + for (key in getAnimationKeys()) { + storage.addObserver(key, observer, HandlerExecutor.main) } } override fun onStop(context: PreferenceLifecycleContext) { mSettingsKeyedObserver?.let { - SettingsGlobalStore.get(context).removeObserver(it) + val storage = SettingsGlobalStore.get(context) + for (key in getAnimationKeys()) { + storage.removeObserver(key, it) + } mSettingsKeyedObserver = null } } 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) : NoOpKeyedObservable(), KeyValueStore { override fun contains(key: String) = key == KEY @@ -74,7 +79,6 @@ class RemoveAnimationsPreference : when { key == KEY && valueType == Boolean::class.javaObjectType -> !isAnimationEnabled(context) as T - else -> null } @@ -94,16 +98,11 @@ class RemoveAnimationsPreference : const val ANIMATION_ON_VALUE: Float = 1.0f const val ANIMATION_OFF_VALUE: Float = 0.0f - val TOGGLE_ANIMATION_KEYS: List = listOf( - Settings.Global.WINDOW_ANIMATION_SCALE, Settings.Global.TRANSITION_ANIMATION_SCALE, - Settings.Global.ANIMATOR_DURATION_SCALE - ) - fun isAnimationEnabled(context: Context): Boolean { + val storage = SettingsGlobalStore.get(context) // This pref treats animation as enabled if *any* of the animation types are enabled. - for (animationSetting in TOGGLE_ANIMATION_KEYS) { - val animationValue: Float? = - SettingsGlobalStore.get(context).getFloat(animationSetting) + for (animationSetting in getAnimationKeys()) { + val animationValue: Float? = storage.getFloat(animationSetting) // Animation is enabled by default, so treat null as enabled. if (animationValue == null || animationValue > ANIMATION_OFF_VALUE) { return true @@ -113,10 +112,18 @@ class RemoveAnimationsPreference : } fun setAnimationEnabled(context: Context, enabled: Boolean) { - val value = if (enabled) ANIMATION_ON_VALUE else ANIMATION_OFF_VALUE; - for (animationSetting in TOGGLE_ANIMATION_KEYS) { - SettingsGlobalStore.get(context).setFloat(animationSetting, value) + val storage = SettingsGlobalStore.get(context) + val value = if (enabled) ANIMATION_ON_VALUE else ANIMATION_OFF_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, + ) } -} \ No newline at end of file +} diff --git a/tests/robotests/src/com/android/settings/accessibility/RemoveAnimationsPreferenceTest.kt b/tests/robotests/src/com/android/settings/accessibility/RemoveAnimationsPreferenceTest.kt index dda6c68a0c5..294632ff482 100644 --- a/tests/robotests/src/com/android/settings/accessibility/RemoveAnimationsPreferenceTest.kt +++ b/tests/robotests/src/com/android/settings/accessibility/RemoveAnimationsPreferenceTest.kt @@ -20,10 +20,11 @@ import android.content.Context import androidx.preference.SwitchPreferenceCompat import androidx.test.core.app.ApplicationProvider 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.TOGGLE_ANIMATION_KEYS 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 org.junit.Test import org.junit.runner.RunWith @@ -33,53 +34,59 @@ class RemoveAnimationsPreferenceTest { private val appContext: Context = ApplicationProvider.getApplicationContext() - private val removeAnimationsPreference = - RemoveAnimationsPreference() - - private fun getSwitchPreferenceCompat(): SwitchPreferenceCompat = - removeAnimationsPreference.createAndBindWidget(appContext) + private fun getRemoveAnimationsSwitchPreference(): SwitchPreferenceCompat = + PreferenceScreenFactory(appContext).let { + val preferenceScreen = it.inflate(R.xml.accessibility_color_and_motion)!! + it.preferenceManager.setPreferences(preferenceScreen) + PreferenceScreenBindingHelper.bind(preferenceScreen) + preferenceScreen.findPreference(RemoveAnimationsPreference.KEY)!! + } @Test fun animationOff_switchPreferenceIsChecked() { RemoveAnimationsPreference.setAnimationEnabled(appContext, false) - assertThat(getSwitchPreferenceCompat().isChecked).isTrue() + assertThat(getRemoveAnimationsSwitchPreference().isChecked).isTrue() } @Test fun animationOn_switchPreferenceIsNotChecked() { RemoveAnimationsPreference.setAnimationEnabled(appContext, true) - assertThat(getSwitchPreferenceCompat().isChecked).isFalse() + assertThat(getRemoveAnimationsSwitchPreference().isChecked).isFalse() } @Test fun oneAnimationValueOn_switchPreferenceIsNotChecked() { // Animation is disabled, except for one value. 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 - fun storageSetTrue_turnsOffAnimation() { + fun toggleOnSwitch_turnsOffAnimation() { RemoveAnimationsPreference.setAnimationEnabled(appContext, true) - storageSetValue(true) + val switchPreference = getRemoveAnimationsSwitchPreference() + assertThat(switchPreference.isChecked).isFalse() + switchPreference.performClick() + assertThat(switchPreference.isChecked).isTrue() assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isFalse() } @Test - fun storageSetFalse_turnsOnAnimation() { + fun toggleOffSwitch_turnsOnAnimation() { RemoveAnimationsPreference.setAnimationEnabled(appContext, false) - storageSetValue(false) + val switchPreference = getRemoveAnimationsSwitchPreference() + assertThat(switchPreference.isChecked).isTrue() + switchPreference.performClick() + assertThat(switchPreference.isChecked).isFalse() assertThat(RemoveAnimationsPreference.isAnimationEnabled(appContext)).isTrue() } - - private fun storageSetValue(enabled: Boolean) = removeAnimationsPreference.storage(appContext) - .setValue(RemoveAnimationsPreference.KEY, Boolean::class.javaObjectType, enabled) -} \ No newline at end of file +}