From 991b70c7205c4276def350664565f2b83769ac1d Mon Sep 17 00:00:00 2001 From: menghanli Date: Mon, 13 Feb 2023 17:18:40 +0800 Subject: [PATCH] Add a done button to vision setting pages in setup flow Root cause: User feels confused because the particular screen doesn't have a back button but at that moment of the setup flow the regular UI gestures didn't even work. Solution: Add a done button to the vision settings pages for clearer navigation. This change combines parts of commit 5e931b2c2371417de75ed98f0342a90ed7601574 and commit dd2ec775c8bc7e03bfb269cf55e6284b37396ebd. Bug: 262995569 Test: make RunSettingsRoboTests ROBOTEST_FILTER=FragmentForSetupWizardTest Change-Id: Id3a0d78389e0e6c11b5b5cf016b37673fde7f286 Merged-In: Id3a0d78389e0e6c11b5b5cf016b37673fde7f286 (cherry picked from commit dd2ec775c8bc7e03bfb269cf55e6284b37396ebd) --- .../AccessibilitySettingsForSetupWizard.java | 28 ++- .../AccessibilitySetupWizardUtils.java | 49 ++++- .../TextReadingPreferenceFragment.java | 24 +-- ...adingPreferenceFragmentForSetupWizard.java | 28 +-- .../TextReadingResetController.java | 7 + ...ationPreferenceFragmentForSetupWizard.java | 10 + ...eaderPreferenceFragmentForSetupWizard.java | 9 + ...SpeakPreferenceFragmentForSetupWizard.java | 9 + ...cessibilitySettingsForSetupWizardTest.java | 198 ++++++++++++++++++ ...gPreferenceFragmentForSetupWizardTest.java | 52 ++++- ...nPreferenceFragmentForSetupWizardTest.java | 144 +++++++++++++ ...rPreferenceFragmentForSetupWizardTest.java | 133 ++++++++++++ ...kPreferenceFragmentForSetupWizardTest.java | 133 ++++++++++++ 13 files changed, 782 insertions(+), 42 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java index a365566a6fb..5e9f8071d4c 100644 --- a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java +++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java @@ -16,6 +16,8 @@ package com.android.settings.accessibility; +import static android.app.Activity.RESULT_CANCELED; + import static com.android.settings.Utils.getAdaptiveIcon; import static com.android.settings.accessibility.AccessibilityUtil.AccessibilityServiceFragmentType.VOLUME_SHORTCUT_TOGGLE; import static com.android.settingslib.widget.TwoTargetPreference.ICON_SIZE_MEDIUM; @@ -34,6 +36,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; +import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.recyclerview.widget.RecyclerView; @@ -41,6 +44,7 @@ import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settingslib.RestrictedPreference; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; import java.util.List; @@ -59,17 +63,21 @@ public class AccessibilitySettingsForSetupWizard extends DashboardFragment private static final String SELECT_TO_SPEAK_PREFERENCE = "select_to_speak_preference"; // Package names and service names used to identify screen reader and SelectToSpeak services. - private static final String SCREEN_READER_PACKAGE_NAME = "com.google.android.marvin.talkback"; - private static final String SCREEN_READER_SERVICE_NAME = + @VisibleForTesting + static final String SCREEN_READER_PACKAGE_NAME = "com.google.android.marvin.talkback"; + @VisibleForTesting + static final String SCREEN_READER_SERVICE_NAME = "com.google.android.marvin.talkback.TalkBackService"; - private static final String SELECT_TO_SPEAK_PACKAGE_NAME = "com.google.android.marvin.talkback"; - private static final String SELECT_TO_SPEAK_SERVICE_NAME = + @VisibleForTesting + static final String SELECT_TO_SPEAK_PACKAGE_NAME = "com.google.android.marvin.talkback"; + @VisibleForTesting + static final String SELECT_TO_SPEAK_SERVICE_NAME = "com.google.android.accessibility.selecttospeak.SelectToSpeakService"; // Preference controls. - private Preference mDisplayMagnificationPreference; - private RestrictedPreference mScreenReaderPreference; - private RestrictedPreference mSelectToSpeakPreference; + protected Preference mDisplayMagnificationPreference; + protected RestrictedPreference mScreenReaderPreference; + protected RestrictedPreference mSelectToSpeakPreference; @Override public int getMetricsCategory() { @@ -86,6 +94,12 @@ public class AccessibilitySettingsForSetupWizard extends DashboardFragment final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility); AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, description, icon); + + final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); + AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> { + setResult(RESULT_CANCELED); + finish(); + }); } @Override diff --git a/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java b/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java index c5302143182..b7a3439162d 100644 --- a/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java +++ b/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java @@ -19,8 +19,13 @@ import android.content.Context; import android.graphics.drawable.Drawable; import android.widget.LinearLayout; +import androidx.annotation.StringRes; + import com.android.settings.R; +import com.google.android.setupcompat.template.FooterBarMixin; +import com.google.android.setupcompat.template.FooterButton; +import com.google.android.setupcompat.template.Mixin; import com.google.android.setupdesign.GlifPreferenceLayout; import com.google.android.setupdesign.util.ThemeHelper; @@ -30,7 +35,7 @@ class AccessibilitySetupWizardUtils { private AccessibilitySetupWizardUtils(){} /** - * Update the {@link GlifPreferenceLayout} attributes if they have previously been initialized. + * Updates the {@link GlifPreferenceLayout} attributes if they have previously been initialized. * When the SetupWizard supports the extended partner configs, it means the material layout * would be applied. It should set a different padding/margin in views to align Settings style * for accessibility feature pages. @@ -55,4 +60,46 @@ class AccessibilitySetupWizardUtils { } } } + + /** + * Sets primary button for footer of the {@link GlifPreferenceLayout}. + * + *

This will be the initial by given material theme style. + * + * @param context A {@link Context} + * @param mixin A {@link Mixin} for managing buttons. + * @param text The {@code text} by resource. + * @param runnable The {@link Runnable} to run. + */ + public static void setPrimaryButton(Context context, FooterBarMixin mixin, @StringRes int text, + Runnable runnable) { + mixin.setPrimaryButton( + new FooterButton.Builder(context) + .setText(text) + .setListener(l -> runnable.run()) + .setButtonType(FooterButton.ButtonType.DONE) + .setTheme(R.style.SudGlifButton_Primary) + .build()); + } + + /** + * Sets secondary button for the footer of the {@link GlifPreferenceLayout}. + * + *

This will be the initial by given material theme style. + * + * @param context A {@link Context} + * @param mixin A {@link Mixin} for managing buttons. + * @param text The {@code text} by resource. + * @param runnable The {@link Runnable} to run. + */ + public static void setSecondaryButton(Context context, FooterBarMixin mixin, + @StringRes int text, Runnable runnable) { + mixin.setSecondaryButton( + new FooterButton.Builder(context) + .setText(text) + .setListener(l -> runnable.run()) + .setButtonType(FooterButton.ButtonType.CLEAR) + .setTheme(R.style.SudGlifButton_Secondary) + .build()); + } } diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java index 4033404cd98..fbcaf4156cf 100644 --- a/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java +++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragment.java @@ -18,11 +18,11 @@ package com.android.settings.accessibility; import static com.android.settings.accessibility.TextReadingResetController.ResetStateListener; +import android.app.Activity; import android.app.Dialog; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; -import android.content.Intent; import android.os.Bundle; import android.widget.Toast; @@ -36,13 +36,13 @@ import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.search.SearchIndexable; +import com.google.android.setupcompat.util.WizardManagerHelper; import com.google.common.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; /** @@ -53,8 +53,7 @@ import java.util.stream.Collectors; public class TextReadingPreferenceFragment extends DashboardFragment { public static final String EXTRA_LAUNCHED_FROM = "launched_from"; private static final String TAG = "TextReadingPreferenceFragment"; - private static final String CATEGORY_FOR_ANYTHING_ELSE = - "com.android.settings.suggested.category.DISPLAY_SETTINGS"; + private static final String SETUP_WIZARD_PACKAGE = "setupwizard"; static final String FONT_SIZE_KEY = "font_size"; static final String DISPLAY_SIZE_KEY = "display_size"; static final String BOLD_TEXT_KEY = "toggle_force_bold_text"; @@ -156,6 +155,7 @@ public class TextReadingPreferenceFragment extends DashboardFragment { new TextReadingResetController(context, RESET_KEY, v -> showDialog(DialogEnums.DIALOG_RESET_SETTINGS)); resetController.setEntryPoint(mEntryPoint); + resetController.setVisible(!WizardManagerHelper.isAnySetupWizard(getIntent())); controllers.add(resetController); return controllers; @@ -193,6 +193,13 @@ public class TextReadingPreferenceFragment extends DashboardFragment { } } + protected boolean isCallingFromAnythingElseEntryPoint() { + final Activity activity = getActivity(); + final String callingPackage = activity != null ? activity.getCallingPackage() : null; + + return callingPackage != null && callingPackage.contains(SETUP_WIZARD_PACKAGE); + } + @VisibleForTesting DisplaySizeData createDisplaySizeData(Context context) { return new DisplaySizeData(context); @@ -205,14 +212,7 @@ public class TextReadingPreferenceFragment extends DashboardFragment { return; } - final Intent intent = getIntent(); - if (intent == null) { - mEntryPoint = EntryPoint.UNKNOWN_ENTRY; - return; - } - - final Set categories = intent.getCategories(); - mEntryPoint = categories != null && categories.contains(CATEGORY_FOR_ANYTHING_ELSE) + mEntryPoint = isCallingFromAnythingElseEntryPoint() ? EntryPoint.SUW_ANYTHING_ELSE : EntryPoint.UNKNOWN_ENTRY; } diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java index 6ead3907a28..f2edf8ed323 100644 --- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java +++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java @@ -16,6 +16,10 @@ package com.android.settings.accessibility; +import static android.app.Activity.RESULT_CANCELED; + +import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums.DIALOG_RESET_SETTINGS; + import android.app.settings.SettingsEnums; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -27,11 +31,9 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; import com.android.settingslib.Utils; -import com.android.settingslib.widget.LayoutPreference; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; -import com.google.android.setupdesign.util.LayoutStyler; - /** * A {@link androidx.preference.PreferenceFragmentCompat} that displays the settings page related @@ -51,7 +53,15 @@ public class TextReadingPreferenceFragmentForSetupWizard extends TextReadingPref AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, /* description= */ null, icon); - updateResetButtonPadding(); + final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); + AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> { + setResult(RESULT_CANCELED); + finish(); + }); + AccessibilitySetupWizardUtils.setSecondaryButton(getContext(), mixin, + R.string.accessibility_text_reading_reset_button_title, + () -> showDialog(DIALOG_RESET_SETTINGS) + ); } @Override @@ -71,14 +81,4 @@ public class TextReadingPreferenceFragmentForSetupWizard extends TextReadingPref // Hides help center in action bar and footer bar in SuW return 0; } - - /** - * Updates the padding of the reset button to meet for SetupWizard style. - */ - private void updateResetButtonPadding() { - final LayoutPreference resetPreference = (LayoutPreference) findPreference(RESET_KEY); - final ViewGroup parentView = - (ViewGroup) resetPreference.findViewById(R.id.reset_button).getParent(); - LayoutStyler.applyPartnerCustomizationLayoutPaddingStyle(parentView); - } } diff --git a/src/com/android/settings/accessibility/TextReadingResetController.java b/src/com/android/settings/accessibility/TextReadingResetController.java index 30a94c2eadd..ed201ad5278 100644 --- a/src/com/android/settings/accessibility/TextReadingResetController.java +++ b/src/com/android/settings/accessibility/TextReadingResetController.java @@ -32,6 +32,7 @@ import com.android.settingslib.widget.LayoutPreference; * The controller of the reset button in the text and reading options page. */ class TextReadingResetController extends BasePreferenceController { + private boolean mIsVisible; private final View.OnClickListener mOnResetClickListener; @EntryPoint @@ -65,6 +66,12 @@ class TextReadingResetController extends BasePreferenceController { AccessibilityStatsLogUtils.convertToEntryPoint(mEntryPoint)); } }); + + setVisible(screen, getPreferenceKey(), mIsVisible); + } + + void setVisible(boolean isVisible) { + mIsVisible = isVisible; } /** diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java index 12a988603d8..a726d8131d5 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java @@ -16,6 +16,8 @@ package com.android.settings.accessibility; +import static android.app.Activity.RESULT_CANCELED; + import android.app.settings.SettingsEnums; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -27,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; public class ToggleScreenMagnificationPreferenceFragmentForSetupWizard @@ -44,6 +47,13 @@ public class ToggleScreenMagnificationPreferenceFragmentForSetupWizard final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility); AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, description, icon); + + final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); + AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> { + setResult(RESULT_CANCELED); + finish(); + }); + hidePreferenceSettingComponents(); } diff --git a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java index f9a1113c054..89dc4376c53 100644 --- a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java +++ b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java @@ -16,6 +16,8 @@ package com.android.settings.accessibility; +import static android.app.Activity.RESULT_CANCELED; + import android.app.settings.SettingsEnums; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -27,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; public class ToggleScreenReaderPreferenceFragmentForSetupWizard @@ -45,6 +48,12 @@ public class ToggleScreenReaderPreferenceFragmentForSetupWizard AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, description, icon); + final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); + AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> { + setResult(RESULT_CANCELED); + finish(); + }); + mToggleSwitchWasInitiallyChecked = mToggleServiceSwitchPreference.isChecked(); if (mTopIntroPreference != null) { mTopIntroPreference.setVisible(false); diff --git a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java index a4604191b81..ff9182e7a5c 100644 --- a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java +++ b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java @@ -16,6 +16,8 @@ package com.android.settings.accessibility; +import static android.app.Activity.RESULT_CANCELED; + import android.app.settings.SettingsEnums; import android.graphics.drawable.Drawable; import android.os.Bundle; @@ -27,6 +29,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.android.settings.R; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; public class ToggleSelectToSpeakPreferenceFragmentForSetupWizard @@ -45,6 +48,12 @@ public class ToggleSelectToSpeakPreferenceFragmentForSetupWizard AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title, description, icon); + final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class); + AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> { + setResult(RESULT_CANCELED); + finish(); + }); + mToggleSwitchWasInitiallyChecked = mToggleServiceSwitchPreference.isChecked(); if (mTopIntroPreference != null) { mTopIntroPreference.setVisible(false); diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java new file mode 100644 index 00000000000..e14e27109e0 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java @@ -0,0 +1,198 @@ +/* + * 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.AccessibilitySettingsForSetupWizard.SCREEN_READER_PACKAGE_NAME; +import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SCREEN_READER_SERVICE_NAME; +import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SELECT_TO_SPEAK_PACKAGE_NAME; +import static com.android.settings.accessibility.AccessibilitySettingsForSetupWizard.SELECT_TO_SPEAK_SERVICE_NAME; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.accessibilityservice.AccessibilityServiceInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.view.accessibility.AccessibilityManager; + +import androidx.fragment.app.FragmentActivity; +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; +import com.android.settingslib.RestrictedPreference; + +import com.google.android.setupcompat.template.FooterBarMixin; +import com.google.android.setupdesign.GlifPreferenceLayout; + +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 java.util.ArrayList; +import java.util.List; + +/** + * Tests for {@link AccessibilitySettingsForSetupWizard}. + */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilitySettingsForSetupWizardTest { + + private static final ComponentName TEST_SCREEN_READER_COMPONENT_NAME = new ComponentName( + SCREEN_READER_PACKAGE_NAME, SCREEN_READER_SERVICE_NAME); + private static final ComponentName TEST_SELECT_TO_SPEAK_COMPONENT_NAME = new ComponentName( + SELECT_TO_SPEAK_PACKAGE_NAME, SELECT_TO_SPEAK_SERVICE_NAME); + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final List mAccessibilityServices = new ArrayList<>(); + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private AccessibilityManager mAccessibilityManager; + @Mock + private FragmentActivity mActivity; + @Mock + private GlifPreferenceLayout mGlifLayoutView; + @Mock + private FooterBarMixin mFooterBarMixin; + private AccessibilitySettingsForSetupWizard mFragment; + + @Before + public void setUp() { + mFragment = spy(new TestAccessibilitySettingsForSetupWizard(mContext)); + doReturn(mAccessibilityManager).when(mActivity).getSystemService( + AccessibilityManager.class); + when(mAccessibilityManager.getInstalledAccessibilityServiceList()).thenReturn( + mAccessibilityServices); + doReturn(mActivity).when(mFragment).getActivity(); + doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class); + } + + @Test + public void onViewCreated_verifyAction() { + mFragment.onViewCreated(mGlifLayoutView, null); + + verify(mGlifLayoutView).setHeaderText( + mContext.getString(R.string.vision_settings_title)); + verify(mGlifLayoutView).setDescriptionText( + mContext.getString(R.string.vision_settings_description)); + verify(mFooterBarMixin).setPrimaryButton(any()); + } + + @Test + public void onResume_accessibilityServiceListInstalled_returnExpectedValue() { + addEnabledServiceInfo(TEST_SCREEN_READER_COMPONENT_NAME, true); + addEnabledServiceInfo(TEST_SELECT_TO_SPEAK_COMPONENT_NAME, true); + mFragment.onAttach(mContext); + mFragment.onViewCreated(mGlifLayoutView, null); + + mFragment.onResume(); + + assertRestrictedPreferenceMatch(mFragment.mScreenReaderPreference, + TEST_SCREEN_READER_COMPONENT_NAME.getPackageName(), + TEST_SCREEN_READER_COMPONENT_NAME.flattenToString()); + assertRestrictedPreferenceMatch(mFragment.mSelectToSpeakPreference, + TEST_SELECT_TO_SPEAK_COMPONENT_NAME.getPackageName(), + TEST_SELECT_TO_SPEAK_COMPONENT_NAME.flattenToString()); + } + + @Test + public void onResume_accessibilityServiceListNotInstalled_returnNull() { + mFragment.onAttach(mContext); + mFragment.onViewCreated(mGlifLayoutView, null); + + mFragment.onResume(); + + assertThat(mFragment.mScreenReaderPreference.getKey()).isNull(); + assertThat(mFragment.mSelectToSpeakPreference.getKey()).isNull(); + } + + private void addEnabledServiceInfo(ComponentName componentName, boolean isAccessibilityTool) { + final AccessibilityServiceInfo a11yServiceInfo = mock(AccessibilityServiceInfo.class); + when(a11yServiceInfo.getComponentName()).thenReturn(componentName); + when(a11yServiceInfo.isAccessibilityTool()).thenReturn(isAccessibilityTool); + final ResolveInfo resolveInfo = mock(ResolveInfo.class); + when(a11yServiceInfo.getResolveInfo()).thenReturn(resolveInfo); + resolveInfo.serviceInfo = mock(ServiceInfo.class); + resolveInfo.serviceInfo.packageName = componentName.getPackageName(); + resolveInfo.serviceInfo.name = componentName.getClassName(); + when(resolveInfo.loadLabel(mActivity.getPackageManager())).thenReturn( + componentName.getPackageName()); + mAccessibilityServices.add(a11yServiceInfo); + } + + private void assertRestrictedPreferenceMatch(RestrictedPreference preference, String title, + String key) { + assertThat(preference.getTitle().toString()).isEqualTo(title); + assertThat(preference.getKey()).isEqualTo(key); + assertThat(preference.getExtras().getString(AccessibilitySettings.EXTRA_TITLE)) + .isEqualTo(title); + assertThat(preference.getExtras().getString(AccessibilitySettings.EXTRA_PREFERENCE_KEY)) + .isEqualTo(key); + } + + private static class TestAccessibilitySettingsForSetupWizard + extends AccessibilitySettingsForSetupWizard { + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestAccessibilitySettingsForSetupWizard(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + mDisplayMagnificationPreference = new Preference(context); + mScreenReaderPreference = new RestrictedPreference(context); + mSelectToSpeakPreference = new RestrictedPreference(context); + } + + @Override + public int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + @Override + public Context getContext() { + return mContext; + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java index bddaed5aa9a..1cd301f98b9 100644 --- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java @@ -18,51 +18,68 @@ package com.android.settings.accessibility; import static com.android.settings.accessibility.TextReadingPreferenceFragment.RESET_KEY; +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; +import android.app.settings.SettingsEnums; import android.content.Context; +import androidx.fragment.app.FragmentActivity; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; import com.android.settingslib.widget.LayoutPreference; +import com.google.android.setupcompat.template.FooterBarMixin; import com.google.android.setupdesign.GlifPreferenceLayout; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; -/** - * Tests for {@link TextReadingPreferenceFragmentForSetupWizard}. - */ +/** Tests for {@link TextReadingPreferenceFragmentForSetupWizard}. */ @RunWith(RobolectricTestRunner.class) public class TextReadingPreferenceFragmentForSetupWizardTest { - private final Context mContext = spy(ApplicationProvider.getApplicationContext()); + @Rule + public final MockitoRule mMockito = MockitoJUnit.rule(); + @Mock private GlifPreferenceLayout mGlifLayoutView; + + @Mock + private FooterBarMixin mFooterBarMixin; + + @Mock + private FragmentActivity mActivity; + + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); private TextReadingPreferenceFragmentForSetupWizard mFragment; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mFragment = spy(new TextReadingPreferenceFragmentForSetupWizard()); final LayoutPreference resetPreference = new LayoutPreference(mContext, R.layout.accessibility_text_reading_reset_button); + doReturn(mContext).when(mFragment).getContext(); doReturn(resetPreference).when(mFragment).findPreference(RESET_KEY); + doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class); } @Test public void setHeaderText_onViewCreated_verifyAction() { final String title = "title"; - doReturn(mContext).when(mFragment).getContext(); doReturn(title).when(mContext).getString( R.string.accessibility_text_reading_options_title); @@ -70,4 +87,23 @@ public class TextReadingPreferenceFragmentForSetupWizardTest { verify(mGlifLayoutView).setHeaderText(title); } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.SUW_ACCESSIBILITY_TEXT_READING_OPTIONS); + } + + @Test + public void getHelpResource_shouldNotHaveHelpResource() { + assertThat(mFragment.getHelpResource()).isEqualTo(0); + } + + @Test + public void onViewCreated_verifyAction() { + mFragment.onViewCreated(mGlifLayoutView, null); + + verify(mFooterBarMixin).setPrimaryButton(any()); + verify(mFooterBarMixin).setSecondaryButton(any()); + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java new file mode 100644 index 00000000000..84783b21a3a --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java @@ -0,0 +1,144 @@ +/* + * 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.ArgumentMatchers.any; +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.Context; + +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; +import com.android.settings.SettingsActivity; +import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment; +import com.android.settings.widget.SettingsMainSwitchBar; +import com.android.settingslib.widget.TopIntroPreference; + +import com.google.android.setupcompat.template.FooterBarMixin; +import com.google.android.setupdesign.GlifPreferenceLayout; + +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.annotation.Config; + +/** Tests for {@link ToggleScreenMagnificationPreferenceFragmentForSetupWizard}. */ +@RunWith(RobolectricTestRunner.class) +@Config(shadows = {ShadowSettingsPreferenceFragment.class}) +public class ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest { + + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private SettingsActivity mActivity; + @Mock + private GlifPreferenceLayout mGlifLayoutView; + @Mock + private SettingsMainSwitchBar mSwitchBar; + @Mock + private FooterBarMixin mFooterBarMixin; + private ToggleScreenMagnificationPreferenceFragmentForSetupWizard mFragment; + + @Before + public void setUp() { + mFragment = + spy(new TestToggleScreenMagnificationPreferenceFragmentForSetupWizard(mContext)); + doReturn(mActivity).when(mFragment).getActivity(); + when(mActivity.getSwitchBar()).thenReturn(mSwitchBar); + doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class); + } + + @Test + public void onViewCreated_verifyAction() { + mFragment.onViewCreated(mGlifLayoutView, null); + + verify(mGlifLayoutView).setHeaderText( + mContext.getString(R.string.accessibility_screen_magnification_title)); + verify(mGlifLayoutView).setDescriptionText( + mContext.getString(R.string.accessibility_screen_magnification_intro_text)); + verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0); + verify(mFooterBarMixin).setPrimaryButton(any()); + assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse(); + assertThat(mFragment.mSettingsPreference.isVisible()).isFalse(); + assertThat(mFragment.mFollowingTypingSwitchPreference.isVisible()).isFalse(); + } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFICATION); + } + + @Test + public void getHelpResource_shouldNotHaveHelpResource() { + assertThat(mFragment.getHelpResource()).isEqualTo(0); + } + + private static class TestToggleScreenMagnificationPreferenceFragmentForSetupWizard + extends ToggleScreenMagnificationPreferenceFragmentForSetupWizard { + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestToggleScreenMagnificationPreferenceFragmentForSetupWizard(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + mTopIntroPreference = new TopIntroPreference(context); + mSettingsPreference = new Preference(context); + mFollowingTypingSwitchPreference = new SwitchPreference(context); + } + + @Override + public int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + @Override + public Context getContext() { + return mContext; + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java new file mode 100644 index 00000000000..727c1603c22 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java @@ -0,0 +1,133 @@ +/* + * 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.ArgumentMatchers.any; +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.Context; +import android.os.Bundle; + +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.widget.SettingsMainSwitchBar; +import com.android.settings.widget.SettingsMainSwitchPreference; +import com.android.settingslib.widget.TopIntroPreference; + +import com.google.android.setupcompat.template.FooterBarMixin; +import com.google.android.setupdesign.GlifPreferenceLayout; + +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 ToggleScreenReaderPreferenceFragmentForSetupWizard}. */ +@RunWith(RobolectricTestRunner.class) +public class ToggleScreenReaderPreferenceFragmentForSetupWizardTest { + + private static final String TEST_TITLE = "test_title"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private SettingsActivity mActivity; + @Mock + private GlifPreferenceLayout mGlifLayoutView; + @Mock + private SettingsMainSwitchBar mSwitchBar; + @Mock + private FooterBarMixin mFooterBarMixin; + private ToggleScreenReaderPreferenceFragmentForSetupWizard mFragment; + + @Before + public void setUp() { + mFragment = spy(new TestToggleScreenReaderPreferenceFragmentForSetupWizard(mContext)); + doReturn(mActivity).when(mFragment).getActivity(); + when(mActivity.getSwitchBar()).thenReturn(mSwitchBar); + doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class); + } + + @Test + public void onViewCreated_verifyAction() { + mFragment.onViewCreated(mGlifLayoutView, null); + verify(mGlifLayoutView).setHeaderText(TEST_TITLE); + verify(mGlifLayoutView).setDescriptionText( + mContext.getString(R.string.talkback_summary)); + verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0); + verify(mFooterBarMixin).setPrimaryButton(any()); + assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse(); + } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SCREEN_READER); + } + + private static class TestToggleScreenReaderPreferenceFragmentForSetupWizard + extends ToggleScreenReaderPreferenceFragmentForSetupWizard { + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestToggleScreenReaderPreferenceFragmentForSetupWizard(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + mTopIntroPreference = new TopIntroPreference(context); + mToggleServiceSwitchPreference = new SettingsMainSwitchPreference(context); + Bundle bundle = new Bundle(); + bundle.putString(AccessibilitySettings.EXTRA_TITLE, TEST_TITLE); + setArguments(bundle); + } + + @Override + public int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + @Override + public Context getContext() { + return mContext; + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java new file mode 100644 index 00000000000..38ede0ea389 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java @@ -0,0 +1,133 @@ +/* + * 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.ArgumentMatchers.any; +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.Context; +import android.os.Bundle; + +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.widget.SettingsMainSwitchBar; +import com.android.settings.widget.SettingsMainSwitchPreference; +import com.android.settingslib.widget.TopIntroPreference; + +import com.google.android.setupcompat.template.FooterBarMixin; +import com.google.android.setupdesign.GlifPreferenceLayout; + +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 ToggleSelectToSpeakPreferenceFragmentForSetupWizard}. */ +@RunWith(RobolectricTestRunner.class) +public class ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest { + + private static final String TEST_TITLE = "test_title"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Mock + private SettingsActivity mActivity; + @Mock + private GlifPreferenceLayout mGlifLayoutView; + @Mock + private SettingsMainSwitchBar mSwitchBar; + @Mock + private FooterBarMixin mFooterBarMixin; + private ToggleSelectToSpeakPreferenceFragmentForSetupWizard mFragment; + + @Before + public void setUp() { + mFragment = spy(new TestToggleSelectToSpeakPreferenceFragmentForSetupWizard(mContext)); + doReturn(mActivity).when(mFragment).getActivity(); + when(mActivity.getSwitchBar()).thenReturn(mSwitchBar); + doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class); + } + + @Test + public void onViewCreated_verifyAction() { + mFragment.onViewCreated(mGlifLayoutView, null); + verify(mGlifLayoutView).setHeaderText(TEST_TITLE); + verify(mGlifLayoutView).setDescriptionText( + mContext.getString(R.string.select_to_speak_summary)); + verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0); + verify(mFooterBarMixin).setPrimaryButton(any()); + assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse(); + } + + @Test + public void getMetricsCategory_returnsCorrectCategory() { + assertThat(mFragment.getMetricsCategory()).isEqualTo( + SettingsEnums.SUW_ACCESSIBILITY_TOGGLE_SELECT_TO_SPEAK); + } + + private static class TestToggleSelectToSpeakPreferenceFragmentForSetupWizard + extends ToggleSelectToSpeakPreferenceFragmentForSetupWizard { + + private final Context mContext; + private final PreferenceManager mPreferenceManager; + + TestToggleSelectToSpeakPreferenceFragmentForSetupWizard(Context context) { + super(); + mContext = context; + mPreferenceManager = new PreferenceManager(context); + mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context)); + mToggleServiceSwitchPreference = new SettingsMainSwitchPreference(context); + mTopIntroPreference = new TopIntroPreference(context); + Bundle bundle = new Bundle(); + bundle.putString(AccessibilitySettings.EXTRA_TITLE, TEST_TITLE); + setArguments(bundle); + } + + @Override + public int getPreferenceScreenResId() { + return R.xml.placeholder_prefs; + } + + @Override + public PreferenceScreen getPreferenceScreen() { + return mPreferenceManager.getPreferenceScreen(); + } + + @Override + public PreferenceManager getPreferenceManager() { + return mPreferenceManager; + } + + @Override + public Context getContext() { + return mContext; + } + } +}