diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index 115f44f0c14..2b9729e7c67 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -28,6 +28,7 @@ import android.icu.text.CaseMap; import android.os.Bundle; import android.os.Handler; import android.provider.Settings; +import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -56,6 +57,7 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF implements ShortcutPreference.OnClickCallback { private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; + protected static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow"; protected static final int NOT_SET = -1; // Save user's shortcutType value when savedInstance has value (e.g. device rotated). protected int mSavedCheckBoxValue = NOT_SET; @@ -66,6 +68,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF private AccessibilitySettingsContentObserver mSettingsContentObserver; private CheckBox mSoftwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox; + private AccessibilityQuickSettingsTooltipWindow mTooltipWindow; + private boolean mNeedsQSTooltipReshow = false; /** Returns the accessibility component name. */ protected abstract ComponentName getComponentName(); @@ -73,14 +77,25 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF /** Returns the accessibility feature name. */ protected abstract CharSequence getLabelName(); + /** Returns the accessibility tile component name. */ + protected abstract ComponentName getTileComponentName(); + + /** Returns the accessibility tile feature name. */ + protected abstract CharSequence getTileName(); + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Restore the user shortcut type. - if (savedInstanceState != null && savedInstanceState.containsKey( - KEY_SAVED_USER_SHORTCUT_TYPE)) { - mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, NOT_SET); + // Restore the user shortcut type and tooltip. + if (savedInstanceState != null) { + if (savedInstanceState.containsKey(KEY_SAVED_USER_SHORTCUT_TYPE)) { + mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, + NOT_SET); + } + if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) { + mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW); + } } final int resId = getPreferenceScreenResId(); @@ -123,6 +138,16 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF return super.onCreateView(inflater, container, savedInstanceState); } + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + // Reshow tooltips when activity recreate, such as rotate device. + if (mNeedsQSTooltipReshow) { + getView().post(this::showQuickSettingsTooltipIfNeeded); + } + } + @Override public void onResume() { super.onResume(); @@ -149,6 +174,9 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF if (value != NOT_SET) { outState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE, value); } + if (mTooltipWindow != null) { + outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, mTooltipWindow.isShowing()); + } super.onSaveInstanceState(outState); } @@ -423,4 +451,33 @@ public abstract class AccessibilityShortcutPreferenceFragment extends DashboardF getComponentName())); mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); } + + protected void showQuickSettingsTooltipIfNeeded() { + final ComponentName tileComponentName = getTileComponentName(); + if (tileComponentName == null) { + // Returns if no tile service assigned. + return; + } + + if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences( + getContext(), tileComponentName)) { + // Returns if quick settings tooltip only show once. + return; + } + + final CharSequence tileName = getTileName(); + if (TextUtils.isEmpty(tileName)) { + // Returns if no title of tile service assigned. + return; + } + + final String title = + getString(R.string.accessibility_service_quick_settings_tooltips_content, tileName); + mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); + mTooltipWindow.setup(title); + mTooltipWindow.showAtTopCenter(getView()); + AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(), + tileComponentName); + mNeedsQSTooltipReshow = false; + } } diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java index 9666fe9354d..00f280440a9 100644 --- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java +++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java @@ -114,6 +114,16 @@ public class LaunchAccessibilityActivityPreferenceFragment extends ToggleFeature mComponentName); } + @Override + ComponentName getTileComponentName() { + return null; + } + + @Override + CharSequence getTileName() { + return null; + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { // Do not call super. We don't want to see the "Help & feedback" option on this page so as diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 0632d3f84bb..a1c98cdc0c4 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -241,6 +241,16 @@ public class ToggleAccessibilityServicePreferenceFragment extends mComponentName); } + @Override + ComponentName getTileComponentName() { + return null; + } + + @Override + CharSequence getTileName() { + return null; + } + @Override protected void updateSwitchBarToggleSwitch() { final boolean checked = isAccessibilityServiceEnabled(); diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java index e65c9c5b2bb..679e28424e3 100644 --- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java @@ -17,11 +17,13 @@ package com.android.settings.accessibility; import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME; +import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME; import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logAccessibilityServiceEnabled; import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; import static com.android.settings.accessibility.AccessibilityUtil.State.ON; import android.app.settings.SettingsEnums; +import android.content.ComponentName; import android.content.ContentResolver; import android.net.Uri; import android.os.Bundle; @@ -48,6 +50,7 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { + super.onPreferenceToggled(preferenceKey, enabled); logAccessibilityServiceEnabled(mComponentName, enabled); Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? ON : OFF); } @@ -131,6 +134,16 @@ public class ToggleColorInversionPreferenceFragment extends ToggleFeaturePrefere mComponentName); } + @Override + ComponentName getTileComponentName() { + return COLOR_INVERSION_TILE_COMPONENT_NAME; + } + + @Override + CharSequence getTileName() { + return getText(R.string.accessibility_display_inversion_preference_title); + } + @Override protected void updateSwitchBarToggleSwitch() { final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON; diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java index f0a4f0a151e..5d9cbe57ee1 100644 --- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java @@ -17,11 +17,13 @@ package com.android.settings.accessibility; import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME; +import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_TILE_COMPONENT_NAME; import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logAccessibilityServiceEnabled; import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; import static com.android.settings.accessibility.AccessibilityUtil.State.ON; import android.app.settings.SettingsEnums; +import android.content.ComponentName; import android.content.Context; import android.content.res.Resources; import android.os.Bundle; @@ -155,6 +157,7 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { + super.onPreferenceToggled(preferenceKey, enabled); logAccessibilityServiceEnabled(mComponentName, enabled); Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? ON : OFF); } @@ -181,6 +184,16 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe mComponentName); } + @Override + ComponentName getTileComponentName() { + return DALTONIZER_TILE_COMPONENT_NAME; + } + + @Override + CharSequence getTileName() { + return getText(R.string.accessibility_display_daltonizer_preference_title); + } + @Override protected void updateSwitchBarToggleSwitch() { final boolean checked = Settings.Secure.getInt(getContentResolver(), ENABLED, OFF) == ON; diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index cba5d83150a..0cc1f1c1662 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -96,6 +96,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference protected static final String KEY_HTML_DESCRIPTION_PREFERENCE = "html_description"; private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; + protected static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow"; protected static final String KEY_ANIMATED_IMAGE = "animated_image"; private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener; @@ -104,6 +105,9 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference private CheckBox mSoftwareTypeCheckBox; private CheckBox mHardwareTypeCheckBox; + private AccessibilityQuickSettingsTooltipWindow mTooltipWindow; + private boolean mNeedsQSTooltipReshow = false; + public static final int NOT_SET = -1; // Save user's shortcutType value when savedInstance has value (e.g. device rotated). protected int mSavedCheckBoxValue = NOT_SET; @@ -129,10 +133,15 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // Restore the user shortcut type. - if (savedInstanceState != null && savedInstanceState.containsKey( - KEY_SAVED_USER_SHORTCUT_TYPE)) { - mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, NOT_SET); + // Restore the user shortcut type and tooltip. + if (savedInstanceState != null) { + if (savedInstanceState.containsKey(KEY_SAVED_USER_SHORTCUT_TYPE)) { + mSavedCheckBoxValue = savedInstanceState.getInt(KEY_SAVED_USER_SHORTCUT_TYPE, + NOT_SET); + } + if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) { + mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW); + } } setupDefaultShortcutIfNecessary(getPrefContext()); @@ -198,6 +207,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference switchBar.hide(); updatePreferenceOrder(); + + // Reshow tooltips when activity recreate, such as rotate device. + if (mNeedsQSTooltipReshow) { + getView().post(this::showQuickSettingsTooltipIfNeeded); + } } @Override @@ -231,6 +245,9 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference if (value != NOT_SET) { outState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE, value); } + if (mTooltipWindow != null) { + outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, mTooltipWindow.isShowing()); + } super.onSaveInstanceState(outState); } @@ -296,6 +313,12 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference */ abstract int getUserShortcutTypes(); + /** Returns the accessibility tile component name. */ + abstract ComponentName getTileComponentName(); + + /** Returns the accessibility tile feature name. */ + abstract CharSequence getTileName(); + protected void updateToggleServiceTitle(SettingsMainSwitchPreference switchPreference) { final CharSequence title = getString(R.string.accessibility_service_primary_switch_title, mPackageName); @@ -307,7 +330,11 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference shortcutPreference.setTitle(title); } - protected abstract void onPreferenceToggled(String preferenceKey, boolean enabled); + protected void onPreferenceToggled(String preferenceKey, boolean enabled) { + if (enabled) { + showQuickSettingsTooltipIfNeeded(); + } + } protected void onInstallSwitchPreferenceToggleSwitch() { // Implement this to set a checked listener. @@ -770,4 +797,37 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference mComponentName.flattenToString(), type); PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); } + + /** + * Shows the quick settings tooltip if the quick settings service is assigned. The tooltip only + * shows once. + */ + protected void showQuickSettingsTooltipIfNeeded() { + final ComponentName tileComponentName = getTileComponentName(); + if (tileComponentName == null) { + // Returns if no tile service assigned. + return; + } + + if (!mNeedsQSTooltipReshow && AccessibilityQuickSettingUtils.hasValueInSharedPreferences( + getContext(), tileComponentName)) { + // Returns if quick settings tooltip only show once. + return; + } + + final CharSequence tileName = getTileName(); + if (TextUtils.isEmpty(tileName)) { + // Returns if no title of tile service assigned. + return; + } + + final String title = + getString(R.string.accessibility_service_quick_settings_tooltips_content, tileName); + mTooltipWindow = new AccessibilityQuickSettingsTooltipWindow(getContext()); + mTooltipWindow.setup(title); + mTooltipWindow.showAtTopCenter(getView()); + AccessibilityQuickSettingUtils.optInValueToSharedPreferences(getContext(), + tileComponentName); + mNeedsQSTooltipReshow = false; + } } diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java index feb41a19463..973e27cd616 100644 --- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java @@ -16,7 +16,12 @@ package com.android.settings.accessibility; +import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME; +import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME; +import static com.android.settings.accessibility.AccessibilityStatsLogUtils.logAccessibilityServiceEnabled; + import android.app.settings.SettingsEnums; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.hardware.display.ColorDisplayManager; @@ -30,7 +35,6 @@ import android.view.ViewGroup; import androidx.preference.PreferenceCategory; import androidx.preference.SwitchPreference; -import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.settings.R; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.SeekBarPreference; @@ -61,7 +65,7 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre .authority(getPrefContext().getPackageName()) .appendPath(String.valueOf(R.raw.extra_dim_banner)) .build(); - mComponentName = AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME; + mComponentName = REDUCE_BRIGHT_COLORS_COMPONENT_NAME; mPackageName = getText(R.string.reduce_bright_colors_preference_title); mHtmlDescription = getText(R.string.reduce_bright_colors_preference_subtitle); mRbcIntensityPreferenceController = @@ -142,7 +146,8 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { - AccessibilityStatsLogUtils.logAccessibilityServiceEnabled(mComponentName, enabled); + super.onPreferenceToggled(preferenceKey, enabled); + logAccessibilityServiceEnabled(mComponentName, enabled); mColorDisplayManager.setReduceBrightColorsActivated(enabled); } @@ -169,6 +174,16 @@ public class ToggleReduceBrightColorsPreferenceFragment extends ToggleFeaturePre mComponentName); } + @Override + ComponentName getTileComponentName() { + return REDUCE_BRIGHT_COLORS_TILE_SERVICE_COMPONENT_NAME; + } + + @Override + CharSequence getTileName() { + return getText(R.string.reduce_bright_colors_preference_title); + } + @Override protected void updateSwitchBarToggleSwitch() { final boolean checked = mColorDisplayManager.isReduceBrightColorsActivated(); diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java index 5f76d5a0a85..62f42820401 100644 --- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java @@ -23,6 +23,7 @@ import static com.android.settings.accessibility.AccessibilityUtil.State.ON; import android.app.Dialog; import android.app.settings.SettingsEnums; +import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; @@ -398,6 +399,16 @@ public class ToggleScreenMagnificationPreferenceFragment extends return getUserShortcutTypeFromSettings(getPrefContext()); } + @Override + ComponentName getTileComponentName() { + return null; + } + + @Override + CharSequence getTileName() { + return null; + } + @Override protected void onPreferenceToggled(String preferenceKey, boolean enabled) { if (enabled && TextUtils.equals( diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java index 1310789bc68..38258968738 100644 --- a/src/com/android/settings/gestures/OneHandedSettings.java +++ b/src/com/android/settings/gestures/OneHandedSettings.java @@ -29,6 +29,7 @@ import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragmen import com.android.settings.accessibility.ShortcutPreference; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.widget.IllustrationPreference; +import com.android.settingslib.widget.MainSwitchPreference; /** * Fragment for One-handed mode settings @@ -40,6 +41,8 @@ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { private static final String ONE_HANDED_SHORTCUT_KEY = "one_handed_shortcuts_preference"; private static final String ONE_HANDED_ILLUSTRATION_KEY = "one_handed_header"; + protected static final String ONE_HANDED_MAIN_SWITCH_KEY = + "gesture_one_handed_mode_enabled_main_switch"; private String mFeatureName; private OneHandedSettingsUtils mUtils; @@ -48,16 +51,22 @@ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { OneHandedSettingsUtils.setUserId(UserHandle.myUserId()); super.updatePreferenceStates(); - final IllustrationPreference preference = - (IllustrationPreference) getPreferenceScreen().findPreference( - ONE_HANDED_ILLUSTRATION_KEY); - if (preference != null) { - final boolean isSwipeDownNotification = - OneHandedSettingsUtils.isSwipeDownNotificationEnabled(getContext()); - preference.setLottieAnimationResId( - isSwipeDownNotification ? R.raw.lottie_swipe_for_notifications - : R.raw.lottie_one_hand_mode); - } + final IllustrationPreference illustrationPreference = + getPreferenceScreen().findPreference(ONE_HANDED_ILLUSTRATION_KEY); + final boolean isSwipeDownNotification = + OneHandedSettingsUtils.isSwipeDownNotificationEnabled(getContext()); + illustrationPreference.setLottieAnimationResId( + isSwipeDownNotification ? R.raw.lottie_swipe_for_notifications + : R.raw.lottie_one_hand_mode); + + final MainSwitchPreference mainSwitchPreference = + getPreferenceScreen().findPreference(ONE_HANDED_MAIN_SWITCH_KEY); + mainSwitchPreference.addOnSwitchChangeListener((switchView, isChecked) -> { + switchView.setChecked(isChecked); + if (isChecked) { + showQuickSettingsTooltipIfNeeded(); + } + }); } @Override @@ -115,6 +124,16 @@ public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { return mFeatureName; } + @Override + protected ComponentName getTileComponentName() { + return AccessibilityShortcutController.ONE_HANDED_TILE_COMPONENT_NAME; + } + + @Override + protected CharSequence getTileName() { + return mFeatureName; + } + @Override protected int getPreferenceScreenResId() { return R.xml.one_handed_settings; diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java index 48d344a65ea..06a046b9aed 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java @@ -16,11 +16,14 @@ package com.android.settings.accessibility; +import static com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW; import static com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment.KEY_SAVED_USER_SHORTCUT_TYPE; +import static com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import static com.google.common.truth.Truth.assertThat; 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; @@ -30,6 +33,10 @@ import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.provider.Settings; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; @@ -48,6 +55,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowApplication; /** Tests for {@link AccessibilityShortcutPreferenceFragment} */ @RunWith(RobolectricTestRunner.class) @@ -55,8 +64,12 @@ public class AccessibilityShortcutPreferenceFragmentTest { private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example"; private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder"; + private static final String PLACEHOLDER_TILE_CLASS_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName( PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME); + private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( + PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); private static final String PLACEHOLDER_DIALOG_TITLE = "title"; private static final String SOFTWARE_SHORTCUT_KEY = @@ -89,10 +102,9 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.updateShortcutPreferenceData(); final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext, - mFragment.getComponentName().flattenToString(), - AccessibilityUtil.UserShortcutType.SOFTWARE); + mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE); // Compare to default UserShortcutType - assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.SOFTWARE); + assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE); } @Test @@ -103,25 +115,21 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.updateShortcutPreferenceData(); final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext, - mFragment.getComponentName().flattenToString(), - AccessibilityUtil.UserShortcutType.SOFTWARE); - assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.SOFTWARE - | AccessibilityUtil.UserShortcutType.HARDWARE); + mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE); + assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE); } @Test public void updateShortcutPreferenceData_hasValueInSharedPreference_assignToVariable() { final PreferredShortcut hardwareShortcut = new PreferredShortcut( - PLACEHOLDER_COMPONENT_NAME.flattenToString(), - AccessibilityUtil.UserShortcutType.HARDWARE); + PLACEHOLDER_COMPONENT_NAME.flattenToString(), UserShortcutType.HARDWARE); putUserShortcutTypeIntoSharedPreference(mContext, hardwareShortcut); mFragment.updateShortcutPreferenceData(); final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext, - mFragment.getComponentName().flattenToString(), - AccessibilityUtil.UserShortcutType.SOFTWARE); - assertThat(expectedType).isEqualTo(AccessibilityUtil.UserShortcutType.HARDWARE); + mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE); + assertThat(expectedType).isEqualTo(UserShortcutType.HARDWARE); } @Test @@ -139,7 +147,7 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.setupEditShortcutDialog(dialog); final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue(); - assertThat(checkboxValue).isEqualTo(AccessibilityUtil.UserShortcutType.EMPTY); + assertThat(checkboxValue).isEqualTo(UserShortcutType.EMPTY); } @Test @@ -152,8 +160,7 @@ public class AccessibilityShortcutPreferenceFragmentTest { final ShortcutPreference shortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); final PreferredShortcut hardwareShortcut = new PreferredShortcut( - PLACEHOLDER_COMPONENT_NAME.flattenToString(), - AccessibilityUtil.UserShortcutType.HARDWARE); + PLACEHOLDER_COMPONENT_NAME.flattenToString(), UserShortcutType.HARDWARE); mFragment.mShortcutPreference = shortcutPreference; PreferredShortcuts.saveUserShortcutType(mContext, hardwareShortcut); @@ -161,12 +168,12 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.setupEditShortcutDialog(dialog); final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue(); - assertThat(checkboxValue).isEqualTo(AccessibilityUtil.UserShortcutType.HARDWARE); + assertThat(checkboxValue).isEqualTo(UserShortcutType.HARDWARE); } @Test @Config(shadows = ShadowFragment.class) - public void restoreValueFromSavedInstanceState_assignToVariable() { + public void restoreValueFromSavedInstanceState_assignShortcutTypeToVariable() { mContext.setTheme(R.style.Theme_AppCompat); final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog( mContext, AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC, @@ -178,8 +185,7 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.mShortcutPreference = shortcutPreference; savedInstanceState.putInt(KEY_SAVED_USER_SHORTCUT_TYPE, - AccessibilityUtil.UserShortcutType.SOFTWARE - | AccessibilityUtil.UserShortcutType.HARDWARE); + UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE); mFragment.onAttach(mContext); mFragment.onCreate(savedInstanceState); mFragment.setupEditShortcutDialog(dialog); @@ -187,11 +193,25 @@ public class AccessibilityShortcutPreferenceFragmentTest { mFragment.saveNonEmptyUserShortcutType(value); final int expectedType = PreferredShortcuts.retrieveUserShortcutType(mContext, - mFragment.getComponentName().flattenToString(), - AccessibilityUtil.UserShortcutType.SOFTWARE); - assertThat(expectedType).isEqualTo( - AccessibilityUtil.UserShortcutType.SOFTWARE - | AccessibilityUtil.UserShortcutType.HARDWARE); + mFragment.getComponentName().flattenToString(), UserShortcutType.SOFTWARE); + assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE); + } + + @Test + @Config(shadows = ShadowFragment.class) + public void restoreValueFromSavedInstanceState_showTooltipView() { + mContext.setTheme(R.style.Theme_AppCompat); + mFragment.showQuickSettingsTooltipIfNeeded(); + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + + final Bundle savedInstanceState = new Bundle(); + savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true); + mFragment.onAttach(mContext); + mFragment.onCreate(savedInstanceState); + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); + mFragment.onViewCreated(mFragment.getView(), savedInstanceState); + + assertThat(getLatestPopupWindow().isShowing()).isTrue(); } @Test @@ -221,8 +241,26 @@ public class AccessibilityShortcutPreferenceFragmentTest { PreferredShortcuts.saveUserShortcutType(context, shortcut); } + private static PopupWindow getLatestPopupWindow() { + final ShadowApplication shadowApplication = + Shadow.extract(ApplicationProvider.getApplicationContext()); + return shadowApplication.getLatestPopupWindow(); + } + public static class TestAccessibilityShortcutPreferenceFragment extends AccessibilityShortcutPreferenceFragment { + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return mock(View.class); + } + + @Override + public void onViewCreated(View view, Bundle savedInstanceState) { + // do nothing + } + @Override protected ComponentName getComponentName() { return PLACEHOLDER_COMPONENT_NAME; @@ -233,6 +271,16 @@ public class AccessibilityShortcutPreferenceFragmentTest { return PLACEHOLDER_PACKAGE_NAME; } + @Override + protected ComponentName getTileComponentName() { + return PLACEHOLDER_TILE_COMPONENT_NAME; + } + + @Override + protected CharSequence getTileName() { + return PLACEHOLDER_PACKAGE_NAME; + } + @Override public int getUserShortcutTypes() { return 0; @@ -263,5 +311,10 @@ public class AccessibilityShortcutPreferenceFragmentTest { protected String getLogTag() { return null; } + + @Override + public View getView() { + return mock(View.class); + } }; } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java index 4584b159b20..5ea4edc8a8d 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java @@ -16,6 +16,7 @@ package com.android.settings.accessibility; +import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_RESHOW; import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_USER_SHORTCUT_TYPE; import static com.google.common.truth.Truth.assertThat; @@ -37,6 +38,7 @@ import android.provider.Settings; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.PopupWindow; import androidx.annotation.XmlRes; import androidx.appcompat.app.AlertDialog; @@ -58,6 +60,8 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.shadows.ShadowApplication; import org.robolectric.shadows.androidx.fragment.FragmentController; /** Tests for {@link ToggleFeaturePreferenceFragment} */ @@ -68,6 +72,12 @@ public class ToggleFeaturePreferenceFragmentTest { private static final String PLACEHOLDER_CLASS_NAME = PLACEHOLDER_PACKAGE_NAME + ".placeholder"; private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName( PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME); + private static final String PLACEHOLDER_TILE_CLASS_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; + private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName( + PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME); + private static final String PLACEHOLDER_TILE_NAME = + PLACEHOLDER_PACKAGE_NAME + "tile.placeholder"; private static final String PLACEHOLDER_DIALOG_TITLE = "title"; private static final String DEFAULT_SUMMARY = "default summary"; private static final String DEFAULT_DESCRIPTION = "default description"; @@ -211,7 +221,7 @@ public class ToggleFeaturePreferenceFragmentTest { @Test @Config(shadows = ShadowFragment.class) - public void restoreValueFromSavedInstanceState_assignToVariable() { + public void restoreValueFromSavedInstanceState_assignShortcutTypeToVariable() { mContext.setTheme(R.style.Theme_AppCompat); final AlertDialog dialog = AccessibilityDialogUtils.showEditShortcutDialog( mContext, DialogType.EDIT_SHORTCUT_GENERIC, PLACEHOLDER_DIALOG_TITLE, @@ -234,6 +244,55 @@ public class ToggleFeaturePreferenceFragmentTest { assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE); } + @Test + @Config(shadows = ShadowFragment.class) + public void onPreferenceToggledOnDisabledService_notShowTooltipView() { + mContext.setTheme(R.style.Theme_AppCompat); + + mFragment.onPreferenceToggled(mFragment.KEY_USE_SERVICE_PREFERENCE, /* enabled= */ false); + + assertThat(getLatestPopupWindow()).isNull(); + } + + @Test + @Config(shadows = ShadowFragment.class) + public void onPreferenceToggledOnEnabledService_showTooltipView() { + mContext.setTheme(R.style.Theme_AppCompat); + + mFragment.onPreferenceToggled(mFragment.KEY_USE_SERVICE_PREFERENCE, /* enabled= */ true); + + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + } + + @Test + @Config(shadows = ShadowFragment.class) + public void onPreferenceToggledOnEnabledService_tooltipViewShown_notShowTooltipView() { + mContext.setTheme(R.style.Theme_AppCompat); + mFragment.onPreferenceToggled(mFragment.KEY_USE_SERVICE_PREFERENCE, /* enabled= */ true); + getLatestPopupWindow().dismiss(); + + mFragment.onPreferenceToggled(mFragment.KEY_USE_SERVICE_PREFERENCE, /* enabled= */ true); + + assertThat(getLatestPopupWindow().isShowing()).isFalse(); + } + + @Test + @Config(shadows = ShadowFragment.class) + public void restoreValueFromSavedInstanceState_showTooltipView() { + mContext.setTheme(R.style.Theme_AppCompat); + mFragment.onPreferenceToggled(mFragment.KEY_USE_SERVICE_PREFERENCE, /* enabled= */ true); + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + + final Bundle savedInstanceState = new Bundle(); + savedInstanceState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true); + mFragment.onCreate(savedInstanceState); + mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY); + mFragment.onViewCreated(mFragment.getView(), savedInstanceState); + mFragment.onAttach(mContext); + + assertThat(getLatestPopupWindow().isShowing()).isTrue(); + } + @Test public void createFooterPreference_shouldSetAsExpectedValue() { mFragment.createFooterPreference(mFragment.getPreferenceScreen(), @@ -258,13 +317,15 @@ public class ToggleFeaturePreferenceFragmentTest { private void callEmptyOnClicked(DialogInterface dialog, int which) {} + private static PopupWindow getLatestPopupWindow() { + final ShadowApplication shadowApplication = + Shadow.extract(ApplicationProvider.getApplicationContext()); + return shadowApplication.getLatestPopupWindow(); + } + public static class TestToggleFeaturePreferenceFragment extends ToggleFeaturePreferenceFragment { - @Override - protected void onPreferenceToggled(String preferenceKey, boolean enabled) { - } - @Override public int getMetricsCategory() { return 0; @@ -275,6 +336,16 @@ public class ToggleFeaturePreferenceFragmentTest { return 0; } + @Override + ComponentName getTileComponentName() { + return PLACEHOLDER_TILE_COMPONENT_NAME; + } + + @Override + CharSequence getTileName() { + return PLACEHOLDER_TILE_NAME; + } + @Override public int getPreferenceScreenResId() { return R.xml.placeholder_prefs; @@ -306,5 +377,9 @@ public class ToggleFeaturePreferenceFragmentTest { // UI related function, do nothing in tests } + @Override + public View getView() { + return mock(View.class); + } } }