From 4684223acf45799d9a4e8eb72b71d1ea7c8877b0 Mon Sep 17 00:00:00 2001 From: Rhed Jao Date: Mon, 12 Nov 2018 14:37:20 +0800 Subject: [PATCH] Update VolumeDialog to use a11y api for ui timeout value. Using api introduced by A11yManager to get recommended ui timeout value, and remove redundant logic of computing a11y timeout in VolumeDialog. Bug: 119284208 Test: atest VolumeDialogImplTest Change-Id: I7611538e28be64ccceb5c75888a2f9105e624942 --- .../policy/AccessibilityManagerWrapper.java | 9 +-- .../systemui/volume/VolumeDialogImpl.java | 68 +++++-------------- .../systemui/volume/VolumeDialogImplTest.java | 48 ++++++++++++- 3 files changed, 66 insertions(+), 59 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java index d85e18c172525..67da8a54b68ad 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java @@ -14,14 +14,11 @@ package com.android.systemui.statusbar.policy; -import android.accessibilityservice.AccessibilityServiceInfo; import android.content.Context; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; -import java.util.List; - /** * For mocking because AccessibilityManager is final for some reason... */ @@ -62,8 +59,8 @@ public class AccessibilityManagerWrapper implements mAccessibilityManager.sendAccessibilityEvent(event); } - public List getEnabledAccessibilityServiceList( - int feedbackTypeFlags) { - return mAccessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags); + /** Returns a recommended ui timeout value in milliseconds. */ + public int getRecommendedTimeoutMillis(int originalTimeout, int uiContentFlags) { + return mAccessibilityManager.getRecommendedTimeoutMillis(originalTimeout, uiContentFlags); } } diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 798f8bcd79382..b5883052c9a27 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -16,8 +16,6 @@ package com.android.systemui.volume; -import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_ALL_MASK; -import static android.accessibilityservice.AccessibilityServiceInfo.FEEDBACK_GENERIC; import static android.app.ActivityManager.LOCK_TASK_MODE_NONE; import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; @@ -32,7 +30,6 @@ import static android.view.View.VISIBLE; import static com.android.systemui.volume.Events.DISMISS_REASON_SETTINGS_CLICKED; -import android.accessibilityservice.AccessibilityServiceInfo; import android.animation.ObjectAnimator; import android.annotation.SuppressLint; import android.app.ActivityManager; @@ -68,13 +65,12 @@ import android.view.ContextThemeWrapper; import android.view.MotionEvent; import android.view.View; import android.view.View.AccessibilityDelegate; -import android.view.View.OnAttachStateChangeListener; import android.view.ViewGroup; import android.view.ViewPropertyAnimator; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener; +import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; @@ -113,6 +109,10 @@ public class VolumeDialogImpl implements VolumeDialog { private static final long USER_ATTEMPT_GRACE_PERIOD = 1000; private static final int UPDATE_ANIMATION_DURATION = 80; + static final int DIALOG_TIMEOUT_MILLIS = 3000; + static final int DIALOG_SAFETYWARNING_TIMEOUT_MILLIS = 5000; + static final int DIALOG_HOVERING_TIMEOUT_MILLIS = 16000; + private final Context mContext; private final H mHandler = new H(); private final VolumeDialogController mController; @@ -170,7 +170,6 @@ public class VolumeDialogImpl implements VolumeDialog { @Override public void destroy() { - mAccessibility.destroy(); mController.removeCallback(mControllerCallbackH); mHandler.removeCallbacksAndMessages(null); } @@ -356,8 +355,6 @@ public class VolumeDialogImpl implements VolumeDialog { writer.print(" mDynamic: "); writer.println(mDynamic); writer.print(" mAutomute: "); writer.println(mAutomute); writer.print(" mSilentMode: "); writer.println(mSilentMode); - writer.print(" mAccessibility.mFeedbackEnabled: "); - writer.println(mAccessibility.mFeedbackEnabled); } private static int getImpliedLevel(SeekBar seekBar, int progress) { @@ -571,10 +568,18 @@ public class VolumeDialogImpl implements VolumeDialog { } private int computeTimeoutH() { - if (mAccessibility.mFeedbackEnabled) return 20000; - if (mHovering) return 16000; - if (mSafetyWarning != null) return 5000; - return 3000; + if (mHovering) { + return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_HOVERING_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + if (mSafetyWarning != null) { + return mAccessibilityMgr.getRecommendedTimeoutMillis( + DIALOG_SAFETYWARNING_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_TEXT + | AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + return mAccessibilityMgr.getRecommendedTimeoutMillis(DIALOG_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); } protected void dismissH(int reason) { @@ -1261,28 +1266,8 @@ public class VolumeDialogImpl implements VolumeDialog { } private final class Accessibility extends AccessibilityDelegate { - private boolean mFeedbackEnabled; - public void init() { - mDialogView.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { - @Override - public void onViewDetachedFromWindow(View v) { - if (D.BUG) Log.d(TAG, "onViewDetachedFromWindow"); - } - - @Override - public void onViewAttachedToWindow(View v) { - if (D.BUG) Log.d(TAG, "onViewAttachedToWindow"); - updateFeedbackEnabled(); - } - }); mDialogView.setAccessibilityDelegate(this); - mAccessibilityMgr.addCallback(mListener); - updateFeedbackEnabled(); - } - - public void destroy() { - mAccessibilityMgr.removeCallback(mListener); } @Override @@ -1298,25 +1283,6 @@ public class VolumeDialogImpl implements VolumeDialog { rescheduleTimeoutH(); return super.onRequestSendAccessibilityEvent(host, child, event); } - - private void updateFeedbackEnabled() { - mFeedbackEnabled = computeFeedbackEnabled(); - } - - private boolean computeFeedbackEnabled() { - // are there any enabled non-generic a11y services? - final List services = - mAccessibilityMgr.getEnabledAccessibilityServiceList(FEEDBACK_ALL_MASK); - for (AccessibilityServiceInfo asi : services) { - if (asi.feedbackType != 0 && asi.feedbackType != FEEDBACK_GENERIC) { - return true; - } - } - return false; - } - - private final AccessibilityServicesStateChangeListener mListener = - enabled -> updateFeedbackEnabled(); } private static class VolumeRow { diff --git a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java index c536dca68def6..5f02fad06b50c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/volume/VolumeDialogImplTest.java @@ -27,18 +27,23 @@ import static com.android.systemui.volume.VolumeDialogControllerImpl.STREAMS; import static junit.framework.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.KeyguardManager; import android.media.AudioManager; +import android.os.SystemClock; import android.support.test.filters.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.text.TextUtils; +import android.view.InputDevice; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.accessibility.AccessibilityManager; import android.widget.ImageView; import com.android.systemui.R; @@ -48,10 +53,11 @@ import com.android.systemui.plugins.VolumeDialogController.State; import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.function.Predicate; @@ -59,7 +65,6 @@ import java.util.function.Predicate; @SmallTest @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper -@Ignore public class VolumeDialogImplTest extends SysuiTestCase { VolumeDialogImpl mDialog; @@ -113,6 +118,45 @@ public class VolumeDialogImplTest extends SysuiTestCase { + " failed test", condition.test(view)); } } + + @Test + public void testComputeTimeout() { + Mockito.reset(mAccessibilityMgr); + mDialog.rescheduleTimeoutH(); + verify(mAccessibilityMgr).getRecommendedTimeoutMillis( + VolumeDialogImpl.DIALOG_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + + @Test + public void testComputeTimeout_withHovering() { + Mockito.reset(mAccessibilityMgr); + View dialog = mDialog.getDialogView(); + long uptimeMillis = SystemClock.uptimeMillis(); + MotionEvent event = MotionEvent.obtain(uptimeMillis, uptimeMillis, + MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0); + event.setSource(InputDevice.SOURCE_TOUCHSCREEN); + dialog.dispatchGenericMotionEvent(event); + event.recycle(); + verify(mAccessibilityMgr).getRecommendedTimeoutMillis( + VolumeDialogImpl.DIALOG_HOVERING_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + + @Test + public void testComputeTimeout_withSafetyWarningOn() { + Mockito.reset(mAccessibilityMgr); + ArgumentCaptor controllerCallbackCapture = + ArgumentCaptor.forClass(VolumeDialogController.Callbacks.class); + verify(mController).addCallback(controllerCallbackCapture.capture(), any()); + VolumeDialogController.Callbacks callbacks = controllerCallbackCapture.getValue(); + callbacks.onShowSafetyWarning(AudioManager.FLAG_SHOW_UI); + verify(mAccessibilityMgr).getRecommendedTimeoutMillis( + VolumeDialogImpl.DIALOG_SAFETYWARNING_TIMEOUT_MILLIS, + AccessibilityManager.FLAG_CONTENT_TEXT + | AccessibilityManager.FLAG_CONTENT_CONTROLS); + } + /* @Test public void testContentDescriptions() {