diff --git a/res/xml/captioning_appearance.xml b/res/xml/captioning_appearance.xml index b29d5a71104..fa574d1ff04 100644 --- a/res/xml/captioning_appearance.xml +++ b/res/xml/captioning_appearance.xml @@ -43,7 +43,8 @@ + android:title="@string/captioning_custom_options_title" + settings:controller="com.android.settings.accessibility.CaptionCustomController"> CAPTIONING_FEATURE_KEYS = Arrays.asList( - Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET - ); - - private final Handler mHandler = new Handler(Looper.getMainLooper()); - @VisibleForTesting - AccessibilitySettingsContentObserver mSettingsContentObserver; - private CaptioningManager mCaptioningManager; - private PreferenceCategory mCustom; @Override public int getMetricsCategory() { return SettingsEnums.ACCESSIBILITY_CAPTION_APPEARANCE; } - @Override - public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { - super.onCreatePreferences(savedInstanceState, rootKey); - mCaptioningManager = getContext().getSystemService(CaptioningManager.class); - mSettingsContentObserver = new AccessibilitySettingsContentObserver(mHandler); - mSettingsContentObserver.registerKeysToObserverCallback(CAPTIONING_FEATURE_KEYS, - key -> refreshShowingCustom()); - mCustom = findPreference(PREF_CUSTOM); - refreshShowingCustom(); - } - - @Override - public void onStart() { - super.onStart(); - mSettingsContentObserver.register(getContext().getContentResolver()); - } - - @Override - public void onStop() { - super.onStop(); - getContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver); - } - @Override protected int getPreferenceScreenResId() { return R.xml.captioning_appearance; @@ -96,12 +49,6 @@ public class CaptionAppearanceFragment extends DashboardFragment { return R.string.help_url_caption; } - private void refreshShowingCustom() { - final boolean isCustomPreset = - mCaptioningManager.getRawUserStyle() == CaptionStyle.PRESET_CUSTOM; - mCustom.setVisible(isCustomPreset); - } - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.captioning_appearance); } diff --git a/src/com/android/settings/accessibility/CaptionCustomController.java b/src/com/android/settings/accessibility/CaptionCustomController.java new file mode 100644 index 00000000000..e1674a2d3ce --- /dev/null +++ b/src/com/android/settings/accessibility/CaptionCustomController.java @@ -0,0 +1,96 @@ +/* + * 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 android.content.ContentResolver; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; +import android.view.accessibility.CaptioningManager; + +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; +import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.core.lifecycle.events.OnStart; +import com.android.settingslib.core.lifecycle.events.OnStop; + +import java.util.Arrays; +import java.util.List; + +/** Preference controller for caption custom visibility. */ +public class CaptionCustomController extends BasePreferenceController + implements LifecycleObserver, OnStart, OnStop { + + private Preference mCustom; + private final CaptionHelper mCaptionHelper; + private final ContentResolver mContentResolver; + private final Handler mHandler = new Handler(Looper.getMainLooper()); + @VisibleForTesting + AccessibilitySettingsContentObserver mSettingsContentObserver; + @VisibleForTesting + static final List CAPTIONING_FEATURE_KEYS = Arrays.asList( + Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET + ); + + public CaptionCustomController(Context context, String preferenceKey) { + super(context, preferenceKey); + mCaptionHelper = new CaptionHelper(context); + mContentResolver = context.getContentResolver(); + mSettingsContentObserver = new AccessibilitySettingsContentObserver(mHandler); + mSettingsContentObserver.registerKeysToObserverCallback(CAPTIONING_FEATURE_KEYS, + key -> refreshShowingCustom()); + } + + @VisibleForTesting + CaptionCustomController(Context context, String preferenceKey, + AccessibilitySettingsContentObserver contentObserver) { + this(context, preferenceKey); + mSettingsContentObserver = contentObserver; + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mCustom = screen.findPreference(getPreferenceKey()); + refreshShowingCustom(); + } + + @Override + public void onStart() { + mSettingsContentObserver.register(mContentResolver); + } + + @Override + public void onStop() { + mSettingsContentObserver.unregister(mContentResolver); + } + + private void refreshShowingCustom() { + final boolean isCustomPreset = + mCaptionHelper.getRawUserStyle() == CaptioningManager.CaptionStyle.PRESET_CUSTOM; + mCustom.setVisible(isCustomPreset); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionAppearanceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionAppearanceFragmentTest.java index 3c320e2c6c6..b180f228634 100644 --- a/tests/robotests/src/com/android/settings/accessibility/CaptionAppearanceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/CaptionAppearanceFragmentTest.java @@ -18,37 +18,18 @@ package com.android.settings.accessibility; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import android.app.settings.SettingsEnums; -import android.content.ContentResolver; import android.content.Context; -import android.os.Bundle; -import android.provider.Settings; -import android.view.accessibility.CaptioningManager.CaptionStyle; -import androidx.preference.PreferenceCategory; -import androidx.preference.PreferenceManager; -import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; -import com.android.settings.SettingsActivity; import com.android.settings.testutils.XmlTestUtils; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; -import org.robolectric.util.ReflectionHelpers; import java.util.List; @@ -56,76 +37,12 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) public class CaptionAppearanceFragmentTest { - @Rule - public MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Mock - private SettingsActivity mActivity; - @Mock - private PreferenceScreen mScreen; - @Mock - private PreferenceManager mPreferenceManager; - @Mock - private ContentResolver mContentResolver; - @Mock - private PreferenceCategory mCustomPref; - @Spy - private Context mContext = ApplicationProvider.getApplicationContext(); - private TestCaptionAppearanceFragment mFragment; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private CaptionAppearanceFragment mFragment; @Before public void setUp() { - mFragment = spy(new TestCaptionAppearanceFragment()); - doReturn(mActivity).when(mFragment).getActivity(); - doReturn(mContext).when(mFragment).getContext(); - doReturn(mCustomPref).when(mFragment).findPreference(mFragment.PREF_CUSTOM); - when(mPreferenceManager.getPreferenceScreen()).thenReturn(mScreen); - ReflectionHelpers.setField(mFragment, "mPreferenceManager", mPreferenceManager); - } - - @Test - public void onCreatePreferences_shouldPreferenceIsInvisible() { - mFragment.onAttach(mContext); - - mFragment.onCreatePreferences(Bundle.EMPTY, /* rootKey */ null); - - verify(mCustomPref).setVisible(false); - } - - @Test - public void onCreatePreferences_customValue_shouldPreferenceIsVisible() { - Settings.Secure.putInt(mContext.getContentResolver(), - Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, CaptionStyle.PRESET_CUSTOM); - mFragment.onAttach(mContext); - - mFragment.onCreatePreferences(Bundle.EMPTY, /* rootKey */ null); - - verify(mCustomPref).setVisible(true); - } - - @Test - public void onStart_registerSpecificContentObserverForSpecificKeys() { - when(mContext.getContentResolver()).thenReturn(mContentResolver); - mFragment.onAttach(mContext); - mFragment.onCreatePreferences(Bundle.EMPTY, /* rootKey */ null); - - mFragment.onStart(); - - for (String key : mFragment.CAPTIONING_FEATURE_KEYS) { - verify(mContentResolver).registerContentObserver(Settings.Secure.getUriFor(key), - /* notifyForDescendants= */ false, mFragment.mSettingsContentObserver); - } - } - - @Test - public void onStop_unregisterContentObserver() { - when(mContext.getContentResolver()).thenReturn(mContentResolver); - mFragment.onAttach(mContext); - mFragment.onCreatePreferences(Bundle.EMPTY, /* rootKey */ null); - mFragment.onStart(); - - mFragment.onStop(); - - verify(mContentResolver).unregisterContentObserver(mFragment.mSettingsContentObserver); + mFragment = new CaptionAppearanceFragment(); } @Test @@ -134,11 +51,21 @@ public class CaptionAppearanceFragmentTest { SettingsEnums.ACCESSIBILITY_CAPTION_APPEARANCE); } + @Test + public void getPreferenceScreenResId_returnsCorrectXml() { + assertThat(mFragment.getPreferenceScreenResId()).isEqualTo(R.xml.captioning_appearance); + } + @Test public void getLogTag_returnsCorrectTag() { assertThat(mFragment.getLogTag()).isEqualTo("CaptionAppearanceFragment"); } + @Test + public void getHelpResource_returnsCorrectHelpResource() { + assertThat(mFragment.getHelpResource()).isEqualTo(R.string.help_url_caption); + } + @Test public void getNonIndexableKeys_existInXmlLayout() { final List niks = CaptionAppearanceFragment.SEARCH_INDEX_DATA_PROVIDER @@ -148,12 +75,4 @@ public class CaptionAppearanceFragmentTest { assertThat(keys).containsAtLeastElementsIn(niks); } - - private static class TestCaptionAppearanceFragment extends CaptionAppearanceFragment { - - @Override - public int getPreferenceScreenResId() { - return R.xml.placeholder_prefs; - } - } } diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionCustomControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionCustomControllerTest.java new file mode 100644 index 00000000000..783a9fc2725 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/CaptionCustomControllerTest.java @@ -0,0 +1,107 @@ +/* + * 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 static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.provider.Settings; +import android.view.accessibility.CaptioningManager.CaptionStyle; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.core.BasePreferenceController; + +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; + +/** Tests for {@link CaptionCustomController}. */ +@RunWith(RobolectricTestRunner.class) +public class CaptionCustomControllerTest { + + private static final String PREF_KEY = "custom"; + + @Rule + public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private PreferenceScreen mScreen; + @Mock + private AccessibilitySettingsContentObserver mAccessibilitySettingsContentObserver; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private ContentResolver mContentResolver; + private CaptionCustomController mController; + private Preference mPreference; + + @Before + public void setUp() { + mContentResolver = mContext.getContentResolver(); + mController = new CaptionCustomController(mContext, PREF_KEY, + mAccessibilitySettingsContentObserver); + mPreference = new Preference(mContext); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + } + + @Test + public void getAvailabilityStatus_shouldReturnAvailable() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + + @Test + public void displayPreference_byDefault_shouldIsInvisible() { + mController.displayPreference(mScreen); + + assertThat(mPreference.isVisible()).isFalse(); + } + + @Test + public void displayPreference_customValue_shouldIsVisible() { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_CAPTIONING_PRESET, CaptionStyle.PRESET_CUSTOM); + + mController.displayPreference(mScreen); + + assertThat(mPreference.isVisible()).isTrue(); + } + + @Test + public void onStart_registerSpecificContentObserverForSpecificKeys() { + mController.onStart(); + + verify(mAccessibilitySettingsContentObserver).register(mContentResolver); + } + + @Test + public void onStop_unregisterContentObserver() { + mController.onStop(); + + verify(mAccessibilitySettingsContentObserver).unregister(mContentResolver); + } +}