Support OHM quick settings tooltips when feature on
Bug: 210356011
Test: make RunSettingsRoboTests ROBOTEST_FILTER=AccessibilityShortcutPreferenceFragmentTest
Change-Id: I3b35d9bb347b7e516db94a4b801a4484f6f38ca8
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
index 115f44f..2b9729e 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -28,6 +28,7 @@
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 @@
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 @@
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 @@
/** 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();
@@ -124,6 +139,16 @@
}
@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();
final AccessibilityManager am = getPrefContext().getSystemService(
@@ -149,6 +174,9 @@
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 @@
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/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java
index 1310789..3825896 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.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 @@
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 @@
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
@@ -116,6 +125,16 @@
}
@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 48d344a..06a046b 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.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.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 @@
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 @@
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 @@
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 @@
mFragment.setupEditShortcutDialog(dialog);
final int checkboxValue = mFragment.getShortcutTypeCheckBoxValue();
- assertThat(checkboxValue).isEqualTo(AccessibilityUtil.UserShortcutType.EMPTY);
+ assertThat(checkboxValue).isEqualTo(UserShortcutType.EMPTY);
}
@Test
@@ -152,8 +160,7 @@
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 @@
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 @@
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 @@
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 @@
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;
@@ -234,6 +272,16 @@
}
@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 @@
protected String getLogTag() {
return null;
}
+
+ @Override
+ public View getView() {
+ return mock(View.class);
+ }
};
}