From 1d26b6d898dc9f8b7482c5a433c30c7503a8d5e9 Mon Sep 17 00:00:00 2001 From: menghanli Date: Wed, 29 Jun 2022 08:22:59 +0800 Subject: [PATCH] Refactor CaptionPropertiesFragment to improve maintainability MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: There is a bunch of different logic of preferences in CaptionPropertiesFragment. It’s hard to implement new features and hard to maintain and hard to be testable. Solution: Move out different logic of CaptionPropertiesFragment into controllers to reduce the complexity of the relationship between preference and fragment. Bug: 197695932 Test: make RunSettingsRoboTests ROBOTEST_FILTER=CaptionPropertiesFragmentTest CaptionTogglePreferenceControllerTest Change-Id: I7013a7aa284b587c329c2e678dbb079e553ea94d --- res/xml/captioning_settings.xml | 4 +- .../CaptionPropertiesFragment.java | 77 +-------- .../CaptionTogglePreferenceController.java | 82 +++++++++ .../CaptionPropertiesFragmentTest.java | 50 ++++++ ...CaptionTogglePreferenceControllerTest.java | 163 ++++++++++++++++++ 5 files changed, 298 insertions(+), 78 deletions(-) create mode 100644 src/com/android/settings/accessibility/CaptionTogglePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/CaptionPropertiesFragmentTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/CaptionTogglePreferenceControllerTest.java diff --git a/res/xml/captioning_settings.xml b/res/xml/captioning_settings.xml index f9e9948c6dc..806a256a69f 100644 --- a/res/xml/captioning_settings.xml +++ b/res/xml/captioning_settings.xml @@ -36,8 +36,8 @@ + android:title="@string/accessibility_caption_primary_switch_title" + settings:controller="com.android.settings.accessibility.CaptionTogglePreferenceController"/> mPreferenceList = new ArrayList<>(); @Override public int getMetricsCategory() { return SettingsEnums.ACCESSIBILITY_CAPTION_PROPERTIES; } - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - super.onCreatePreferences(savedInstanceState, rootKey); - - mCaptioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE); - - initializeAllPreferences(); - installUpdateListeners(); - } - - @Override - public void onResume() { - super.onResume(); - mSwitch.setChecked(mCaptioningManager.isEnabled()); - } - @Override protected int getPreferenceScreenResId() { return R.xml.captioning_settings; @@ -86,32 +44,6 @@ public class CaptionPropertiesFragment extends DashboardFragment return TAG; } - private void initializeAllPreferences() { - mSwitch = (SettingsMainSwitchPreference) findPreference(PREF_SWITCH); - mTextAppearance = (Preference) findPreference(PREF_TEXT); - mMoreOptions = (Preference) findPreference(PREF_MORE); - - mPreferenceList.add(mTextAppearance); - mPreferenceList.add(mMoreOptions); - } - - private void installUpdateListeners() { - mSwitch.setOnPreferenceChangeListener(this); - mSwitch.addOnSwitchChangeListener(this); - - } - - @Override - public boolean onPreferenceChange(Preference preference, Object value) { - final ContentResolver cr = getActivity().getContentResolver(); - if (mSwitch == preference) { - Settings.Secure.putInt( - cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, (boolean) value ? 1 : 0); - } - - return true; - } - @Override public int getHelpResource() { return R.string.help_url_caption; @@ -119,11 +51,4 @@ public class CaptionPropertiesFragment extends DashboardFragment public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.captioning_settings); - - @Override - public void onSwitchChanged(Switch switchView, boolean isChecked) { - final ContentResolver cr = getActivity().getContentResolver(); - Settings.Secure.putInt( - cr, Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, isChecked ? 1 : 0); - } } diff --git a/src/com/android/settings/accessibility/CaptionTogglePreferenceController.java b/src/com/android/settings/accessibility/CaptionTogglePreferenceController.java new file mode 100644 index 00000000000..d0ea1f953ca --- /dev/null +++ b/src/com/android/settings/accessibility/CaptionTogglePreferenceController.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2022 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.settings.accessibility; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + +import android.content.Context; +import android.provider.Settings; +import android.view.accessibility.CaptioningManager; +import android.widget.Switch; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; +import com.android.settings.widget.SettingsMainSwitchPreference; +import com.android.settingslib.widget.OnMainSwitchChangeListener; + +/** Preference controller for caption more options. */ +public class CaptionTogglePreferenceController extends TogglePreferenceController + implements OnMainSwitchChangeListener { + + private final CaptioningManager mCaptioningManager; + + public CaptionTogglePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mCaptioningManager = context.getSystemService(CaptioningManager.class); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public boolean isChecked() { + return mCaptioningManager.isEnabled(); + } + + @Override + public boolean setChecked(boolean isChecked) { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, isChecked ? ON : OFF); + return true; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + SettingsMainSwitchPreference pref = screen.findPreference(getPreferenceKey()); + pref.addOnSwitchChangeListener(this); + pref.setChecked(isChecked()); + } + + @Override + public void onSwitchChanged(Switch switchView, boolean isChecked) { + if (isChecked != isChecked()) { + setChecked(isChecked); + } + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_accessibility; + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionPropertiesFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionPropertiesFragmentTest.java new file mode 100644 index 00000000000..f041edc3f21 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/CaptionPropertiesFragmentTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2022 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.settings.accessibility; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; +import com.android.settings.testutils.XmlTestUtils; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +import java.util.List; + +/** Tests for {@link CaptionPropertiesFragment}. */ +@RunWith(RobolectricTestRunner.class) +public class CaptionPropertiesFragmentTest { + + private final Context mContext = ApplicationProvider.getApplicationContext(); + + @Test + public void getNonIndexableKeys_existInXmlLayout() { + final List niks = CaptionPropertiesFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final List keys = + XmlTestUtils.getKeysFromPreferenceXml(mContext, + R.xml.captioning_settings); + + assertThat(keys).containsAtLeastElementsIn(niks); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionTogglePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionTogglePreferenceControllerTest.java new file mode 100644 index 00000000000..1980df2acde --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/CaptionTogglePreferenceControllerTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2022 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.settings.accessibility; + +import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; +import static com.android.settings.accessibility.AccessibilityUtil.State.ON; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.provider.Settings; +import android.view.accessibility.CaptioningManager; + +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.core.BasePreferenceController; +import com.android.settings.widget.SettingsMainSwitchPreference; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowCaptioningManager; + +/** Tests for {@link CaptionTogglePreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class CaptionTogglePreferenceControllerTest { + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private PreferenceScreen mScreen; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private CaptionTogglePreferenceController mController; + private SettingsMainSwitchPreference mSwitchPreference; + private ShadowCaptioningManager mShadowCaptioningManager; + + @Before + public void setUp() { + mController = new CaptionTogglePreferenceController(mContext, + "captioning_preference_switch"); + mSwitchPreference = new SettingsMainSwitchPreference(mContext); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mSwitchPreference); + CaptioningManager captioningManager = mContext.getSystemService(CaptioningManager.class); + mShadowCaptioningManager = Shadow.extract(captioningManager); + } + + @After + public void tearDown() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, OFF); + } + + @Test + public void getAvailabilityStatus_shouldReturnAvailable() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void displayPreference_captionEnabled_shouldSetChecked() { + mShadowCaptioningManager.setEnabled(true); + + mController.displayPreference(mScreen); + + assertThat(mSwitchPreference.isChecked()).isTrue(); + } + + @Test + public void displayPreference_captionDisabled_shouldSetUnchecked() { + mShadowCaptioningManager.setEnabled(false); + + mController.displayPreference(mScreen); + + assertThat(mSwitchPreference.isChecked()).isFalse(); + } + + @Test + public void performClick_captionEnabled_shouldSetCaptionDisabled() { + mShadowCaptioningManager.setEnabled(true); + mController.displayPreference(mScreen); + + mSwitchPreference.performClick(); + + assertThat(mSwitchPreference.isChecked()).isFalse(); + assertThat(isCaptionEnabled()).isFalse(); + } + + @Test + public void performClick_captionDisabled_shouldSetCaptionEnabled() { + mShadowCaptioningManager.setEnabled(false); + mController.displayPreference(mScreen); + + mSwitchPreference.performClick(); + + assertThat(mSwitchPreference.isChecked()).isTrue(); + assertThat(isCaptionEnabled()).isTrue(); + } + + @Test + public void setChecked_switchChecked_shouldSetCaptionEnabled() { + mController.displayPreference(mScreen); + + mController.setChecked(/* isChecked= */ true); + + assertThat(isCaptionEnabled()).isTrue(); + } + + @Test + public void setChecked_switchUnchecked_shouldSetCaptionDisabled() { + mController.displayPreference(mScreen); + + mController.setChecked(/* isChecked= */ false); + + assertThat(isCaptionEnabled()).isFalse(); + } + + @Test + public void onSwitchChanged_switchChecked_shouldSetCaptionEnabled() { + mController.displayPreference(mScreen); + + mController.onSwitchChanged(/* switchView= */ null, /* isChecked= */ true); + + assertThat(isCaptionEnabled()).isTrue(); + } + + @Test + public void onSwitchChanged_switchUnchecked_shouldSetCaptionDisabled() { + mController.displayPreference(mScreen); + + mController.onSwitchChanged(/* switchView= */ null, /* isChecked= */ false); + + assertThat(isCaptionEnabled()).isFalse(); + } + + private boolean isCaptionEnabled() { + return Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_CAPTIONING_ENABLED, OFF) == ON; + } +}