Support OHM quick settings tooltips when feature on

Bug: 210356011
Test: make RunSettingsRoboTests ROBOTEST_FILTER=AccessibilityShortcutPreferenceFragmentTest
Change-Id: I3b35d9bb347b7e516db94a4b801a4484f6f38ca8
This commit is contained in:
menghanli
2022-01-25 05:58:33 +08:00
parent 6892e89775
commit 95eba64f85
3 changed files with 167 additions and 38 deletions

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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);
}
};
}