From 70fe4d60312582938410625a4e26db4bb3ee4985 Mon Sep 17 00:00:00 2001 From: Riley Jones Date: Fri, 28 Oct 2022 22:48:27 +0000 Subject: [PATCH] Fix for potential race condition in Spinners Added measure to try & ensure popups have time to collapse before trying to send TYPE_VIEW_SELECTED Bug: 256048559 Test: Test in topic Change-Id: I8ef5ff37ca08a4adb8c7ffda53a7ac810ba2763d --- core/api/test-current.txt | 1 + core/java/android/widget/AdapterView.java | 3 ++- core/java/android/widget/Spinner.java | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/core/api/test-current.txt b/core/api/test-current.txt index e9f9136c768c8..6263a809dcbd4 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -3252,6 +3252,7 @@ package android.widget { public class Spinner extends android.widget.AbsSpinner implements android.content.DialogInterface.OnClickListener { method public boolean isPopupShowing(); + method public void onClick(int); } @android.widget.RemoteViews.RemoteView public class TextClock extends android.widget.TextView { diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index 52658404548cc..e6379cfb27cf4 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -968,7 +968,8 @@ public abstract class AdapterView extends ViewGroup { final int position = getSelectedItemPosition(); if (position >= 0) { // we fire selection events here not in View - sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); + // posting the event should delay it long enough for UI changes to take effect. + post(() -> sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED)); } } diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java index ba6fa197f1645..ad431efc0bd2b 100644 --- a/core/java/android/widget/Spinner.java +++ b/core/java/android/widget/Spinner.java @@ -802,6 +802,21 @@ public class Spinner extends AbsSpinner implements OnClickListener { dialog.dismiss(); } + /** + * Sets selection and dismisses the spinner's popup if it can be dismissed. + * For ease of use in tests, where publicly obtaining the spinner's popup is difficult. + * + * @param which index of the item to be selected. + * @hide + */ + @TestApi + public void onClick(int which) { + setSelection(which); + if (mPopup != null && mPopup.isShowing()) { + mPopup.dismiss(); + } + } + @Override public CharSequence getAccessibilityClassName() { return Spinner.class.getName();