From 238639c494164de9ba02ea0cdd2a3315b7ab0822 Mon Sep 17 00:00:00 2001 From: menghanli Date: Wed, 19 Jan 2022 09:29:13 +0800 Subject: [PATCH] Allow users dismiss accessibility quick settings tooltips when clicked Problem: When Talkback on, users cannot use double tap or swipe to move focus on the next window. Solution: Talkback speaks out "double tap to dismiss" to allow dismissing this tooltips. Bug: 215656141 Test: make RunSettingsRoboTests ROBOTEST_FILTER=AccessibilityQuickSettingsTooltipWindowTest Change-Id: I8f7066a805ec963f9f0f8fee1b81ad008418c4a6 --- res/values/strings.xml | 2 + ...cessibilityQuickSettingsTooltipWindow.java | 28 +++++++++- ...ibilityQuickSettingsTooltipWindowTest.java | 55 ++++++++++++------- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index ec72321ced8..b75ede4599c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5481,6 +5481,8 @@ Open %1$s Swipe down to quickly turn %1$s on or off in quick settings + + Dismiss Use color correction diff --git a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java index a4986a0beb2..f24934fbbd1 100644 --- a/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java +++ b/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindow.java @@ -19,10 +19,14 @@ package com.android.settings.accessibility; import android.content.Context; import android.content.res.Resources; import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; import android.os.Handler; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; +import android.view.View.AccessibilityDelegate; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; @@ -49,6 +53,25 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { this.mContext = context; } + private final AccessibilityDelegate mAccessibilityDelegate = new AccessibilityDelegate() { + @Override + public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) { + super.onInitializeAccessibilityNodeInfo(host, info); + final AccessibilityAction clickAction = new AccessibilityAction( + AccessibilityNodeInfo.ACTION_CLICK, + mContext.getString(R.string.accessibility_quick_settings_tooltips_dismiss)); + info.addAction(clickAction); + } + + @Override + public boolean performAccessibilityAction(View host, int action, Bundle args) { + if (action == AccessibilityNodeInfo.ACTION_CLICK) { + dismiss(); + return true; + } + return super.performAccessibilityAction(host, action, args); + } + }; /** * Sets up {@link #AccessibilityQuickSettingsTooltipWindow}'s layout and content. * @@ -74,13 +97,16 @@ public class AccessibilityQuickSettingsTooltipWindow extends PopupWindow { final LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class); final View popupView = inflater.inflate(R.layout.accessibility_qs_tooltips, /* root= */ null); + popupView.setFocusable(/* focusable= */ true); + popupView.setAccessibilityDelegate(mAccessibilityDelegate); setContentView(popupView); + final TextView textView = getContentView().findViewById(R.id.qs_content); textView.setText(text); - setWidth(getWindowWidthWith(textView)); setHeight(LinearLayout.LayoutParams.WRAP_CONTENT); setFocusable(/* focusable= */ true); + setOutsideTouchable(/* touchable= */ true); } /** diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java index f1e1121b78e..be67977c520 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityQuickSettingsTooltipWindowTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; import android.widget.PopupWindow; import androidx.test.core.app.ApplicationProvider; @@ -53,52 +54,68 @@ public class AccessibilityQuickSettingsTooltipWindowTest { private static final String TEST_PACKAGE_NAME = "com.test.package"; private final Context mContext = ApplicationProvider.getApplicationContext(); - private AccessibilityQuickSettingsTooltipWindow mToolTipView; + private AccessibilityQuickSettingsTooltipWindow mTooltipView; private View mView; @Before public void setUp() { - mToolTipView = new AccessibilityQuickSettingsTooltipWindow(mContext); + mTooltipView = new AccessibilityQuickSettingsTooltipWindow(mContext); mView = new View(RuntimeEnvironment.application); } @Test - public void initToolTipView_atMostAvailableTextWidth() { + public void initTooltipView_atMostAvailableTextWidth() { final String quickSettingsTooltipsContent = mContext.getString( R.string.accessibility_service_quick_settings_tooltips_content, TEST_PACKAGE_NAME); - mToolTipView.setup(quickSettingsTooltipsContent); + mTooltipView.setup(quickSettingsTooltipsContent); - final int getMaxWidth = mToolTipView.getAvailableWindowWidth(); - assertThat(mToolTipView.getWidth()).isAtMost(getMaxWidth); + final int getMaxWidth = mTooltipView.getAvailableWindowWidth(); + assertThat(mTooltipView.getWidth()).isAtMost(getMaxWidth); } @Test - public void showToolTipView_success() { - mToolTipView.setup(TEST_PACKAGE_NAME); + public void showTooltipView_success() { + mTooltipView.setup(TEST_PACKAGE_NAME); assertThat(getLatestPopupWindow()).isNull(); - mToolTipView.showAtTopCenter(mView); + mTooltipView.showAtTopCenter(mView); - assertThat(getLatestPopupWindow()).isSameInstanceAs(mToolTipView); + assertThat(getLatestPopupWindow()).isSameInstanceAs(mTooltipView); } @Test - public void dismiss_toolTipViewShown_shouldInvokeCallbackAndNotShowing() { - mToolTipView.setup(TEST_PACKAGE_NAME); - mToolTipView.setOnDismissListener(mMockOnDismissListener); - mToolTipView.showAtTopCenter(mView); + public void accessibilityClickActionOnTooltipViewShown_shouldInvokeCallbackAndNotShowing() { + mTooltipView.setup(TEST_PACKAGE_NAME); + mTooltipView.setOnDismissListener(mMockOnDismissListener); + mTooltipView.showAtTopCenter(mView); - mToolTipView.dismiss(); + final boolean isActionPerformed = + mTooltipView.getContentView().performAccessibilityAction( + AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK.getId(), + /* arguments= */ null); + + assertThat(isActionPerformed).isTrue(); + verify(mMockOnDismissListener).onDismiss(); + assertThat(getLatestPopupWindow().isShowing()).isFalse(); + } + + @Test + public void dismiss_tooltipViewShown_shouldInvokeCallbackAndNotShowing() { + mTooltipView.setup(TEST_PACKAGE_NAME); + mTooltipView.setOnDismissListener(mMockOnDismissListener); + mTooltipView.showAtTopCenter(mView); + + mTooltipView.dismiss(); verify(mMockOnDismissListener).onDismiss(); assertThat(getLatestPopupWindow().isShowing()).isFalse(); } @Test - public void waitAutoCloseDelayTime_toolTipViewShown_shouldInvokeCallbackAndNotShowing() { - mToolTipView.setup(TEST_PACKAGE_NAME, /* closeDelayTimeMillis= */ 1); - mToolTipView.setOnDismissListener(mMockOnDismissListener); - mToolTipView.showAtTopCenter(mView); + public void waitAutoCloseDelayTime_tooltipViewShown_shouldInvokeCallbackAndNotShowing() { + mTooltipView.setup(TEST_PACKAGE_NAME, /* closeDelayTimeMillis= */ 1); + mTooltipView.setOnDismissListener(mMockOnDismissListener); + mTooltipView.showAtTopCenter(mView); ShadowLooper.runUiThreadTasksIncludingDelayedTasks();