diff --git a/src/com/android/settings/accessibility/DisableAnimationsPreferenceController.java b/src/com/android/settings/accessibility/DisableAnimationsPreferenceController.java index 5630dd91175..2ec1d70da70 100644 --- a/src/com/android/settings/accessibility/DisableAnimationsPreferenceController.java +++ b/src/com/android/settings/accessibility/DisableAnimationsPreferenceController.java @@ -16,40 +16,66 @@ package com.android.settings.accessibility; +import android.content.ContentResolver; import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; +import android.os.Looper; +import android.os.UserHandle; import android.provider.Settings; -import android.text.TextUtils; import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; -public class DisableAnimationsPreferenceController extends TogglePreferenceController { +import java.util.Arrays; +import java.util.List; + +/** A toggle preference controller for disable animations. */ +public class DisableAnimationsPreferenceController extends TogglePreferenceController implements + LifecycleObserver, OnStart, OnStop { @VisibleForTesting - static final String ANIMATION_ON_VALUE = "1"; + static final float ANIMATION_ON_VALUE = 1.0f; @VisibleForTesting - static final String ANIMATION_OFF_VALUE = "0"; + static final float ANIMATION_OFF_VALUE = 0.0f; // Settings that should be changed when toggling animations @VisibleForTesting - static final String[] TOGGLE_ANIMATION_TARGETS = { + static final List TOGGLE_ANIMATION_TARGETS = Arrays.asList( Settings.Global.WINDOW_ANIMATION_SCALE, Settings.Global.TRANSITION_ANIMATION_SCALE, Settings.Global.ANIMATOR_DURATION_SCALE + ); + + private final ContentObserver mSettingsContentObserver = new ContentObserver( + new Handler(Looper.getMainLooper())){ + @Override + public void onChange(boolean selfChange) { + updateState(mPreference); + } }; + private final ContentResolver mContentResolver; + private SwitchPreference mPreference; + public DisableAnimationsPreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); + mContentResolver = context.getContentResolver(); } @Override public boolean isChecked() { boolean allAnimationsDisabled = true; for (String animationSetting : TOGGLE_ANIMATION_TARGETS) { - if (!TextUtils.equals( - Settings.Global.getString(mContext.getContentResolver(), animationSetting), - ANIMATION_OFF_VALUE)) { + final float value = Settings.Global.getFloat(mContentResolver, animationSetting, + ANIMATION_ON_VALUE); + if (value > ANIMATION_OFF_VALUE) { allAnimationsDisabled = false; break; } @@ -59,11 +85,11 @@ public class DisableAnimationsPreferenceController extends TogglePreferenceContr @Override public boolean setChecked(boolean isChecked) { - final String newAnimationValue = isChecked ? ANIMATION_OFF_VALUE : ANIMATION_ON_VALUE; + final float newAnimationValue = isChecked ? ANIMATION_OFF_VALUE : ANIMATION_ON_VALUE; boolean allAnimationSet = true; for (String animationPreference : TOGGLE_ANIMATION_TARGETS) { - allAnimationSet &= Settings.Global.putString(mContext.getContentResolver(), - animationPreference, newAnimationValue); + allAnimationSet &= Settings.Global.putFloat(mContentResolver, animationPreference, + newAnimationValue); } return allAnimationSet; } @@ -77,4 +103,23 @@ public class DisableAnimationsPreferenceController extends TogglePreferenceContr public int getSliceHighlightMenuRes() { return R.string.menu_key_accessibility; } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public void onStart() { + for (String key : TOGGLE_ANIMATION_TARGETS) { + mContentResolver.registerContentObserver(Settings.Global.getUriFor(key), + false, mSettingsContentObserver, UserHandle.USER_ALL); + } + } + + @Override + public void onStop() { + mContentResolver.unregisterContentObserver(mSettingsContentObserver); + } } diff --git a/tests/unit/src/com/android/settings/accessibility/DisableAnimationsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/accessibility/DisableAnimationsPreferenceControllerTest.java index 57060088a63..29330556579 100644 --- a/tests/unit/src/com/android/settings/accessibility/DisableAnimationsPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/accessibility/DisableAnimationsPreferenceControllerTest.java @@ -23,8 +23,11 @@ import static com.android.settings.accessibility.DisableAnimationsPreferenceCont import static com.google.common.truth.Truth.assertThat; import android.content.Context; +import android.os.Looper; import android.provider.Settings; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -38,15 +41,27 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class DisableAnimationsPreferenceControllerTest { - private Context mContext; + private static final String TEST_PREFERENCE_KEY = "disable_animation"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + + private PreferenceScreen mScreen; private SwitchPreference mPreference; private DisableAnimationsPreferenceController mController; @Before public void setUp() { - mContext = ApplicationProvider.getApplicationContext(); - mPreference = new SwitchPreference(mContext); - mController = new DisableAnimationsPreferenceController(mContext, "disable_animation"); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + final SwitchPreference preference = new SwitchPreference(mContext); + preference.setKey(TEST_PREFERENCE_KEY); + mScreen.addPreference(preference); + + mController = new DisableAnimationsPreferenceController(mContext, TEST_PREFERENCE_KEY); + mController.displayPreference(mScreen); + mPreference = mScreen.findPreference(TEST_PREFERENCE_KEY); } @Test @@ -57,10 +72,7 @@ public class DisableAnimationsPreferenceControllerTest { @Test public void isChecked_enabledAnimation_shouldReturnFalse() { - for (String animationPreference : TOGGLE_ANIMATION_TARGETS) { - Settings.Global.putString(mContext.getContentResolver(), animationPreference, - ANIMATION_ON_VALUE); - } + setAnimationScale(ANIMATION_ON_VALUE); mController.updateState(mPreference); @@ -70,10 +82,7 @@ public class DisableAnimationsPreferenceControllerTest { @Test public void isChecked_disabledAnimation_shouldReturnTrue() { - for (String animationPreference : TOGGLE_ANIMATION_TARGETS) { - Settings.Global.putString(mContext.getContentResolver(), animationPreference, - ANIMATION_OFF_VALUE); - } + setAnimationScale(ANIMATION_OFF_VALUE); mController.updateState(mPreference); @@ -86,8 +95,9 @@ public class DisableAnimationsPreferenceControllerTest { mController.setChecked(true); for (String animationSetting : TOGGLE_ANIMATION_TARGETS) { - assertThat(Settings.Global.getString(mContext.getContentResolver(), animationSetting)) - .isEqualTo(ANIMATION_OFF_VALUE); + final float value = Settings.Global.getFloat(mContext.getContentResolver(), + animationSetting, /* def= */ -1.0f); + assertThat(Float.compare(value, ANIMATION_OFF_VALUE)).isEqualTo(0); } } @@ -96,8 +106,47 @@ public class DisableAnimationsPreferenceControllerTest { mController.setChecked(false); for (String animationSetting : TOGGLE_ANIMATION_TARGETS) { - assertThat(Settings.Global.getString(mContext.getContentResolver(), animationSetting)) - .isEqualTo(ANIMATION_ON_VALUE); + final float value = Settings.Global.getFloat(mContext.getContentResolver(), + animationSetting, /* def= */ -1.0f); + assertThat(Float.compare(value, ANIMATION_ON_VALUE)).isEqualTo(0); } } -} + + @Test + public void onStart_enabledAnimation_shouldReturnFalse() { + mController.onStart(); + + setAnimationScale(ANIMATION_ON_VALUE); + + assertThat(mController.isChecked()).isFalse(); + assertThat(mPreference.isChecked()).isFalse(); + } + + @Test + public void onStart_disabledAnimation_shouldReturnTrue() { + mController.onStart(); + + setAnimationScale(ANIMATION_OFF_VALUE); + + assertThat(mController.isChecked()).isTrue(); + assertThat(mPreference.isChecked()).isTrue(); + } + + @Test + public void onStop_shouldNotUpdateTargets() { + mPreference.setChecked(true); + mController.onStart(); + mController.onStop(); + + setAnimationScale(ANIMATION_ON_VALUE); + + assertThat(mPreference.isChecked()).isTrue(); + } + + private void setAnimationScale(float newValue) { + for (String animationPreference : TOGGLE_ANIMATION_TARGETS) { + Settings.Global.putFloat(mContext.getContentResolver(), animationPreference, + newValue); + } + } +} \ No newline at end of file