diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 7ca42f7d70159..b5ac9405be0c0 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -142,6 +142,9 @@
+
+
+
diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
index 14ba63a2738ff..f37ef828ebdd8 100644
--- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt
@@ -22,10 +22,13 @@ import android.os.PowerManager
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
+import android.view.View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
+import android.view.View.ACCESSIBILITY_LIVE_REGION_NONE
import android.view.ViewGroup
import android.view.WindowManager
import android.view.accessibility.AccessibilityManager
import android.widget.TextView
+import androidx.annotation.IdRes
import com.android.internal.widget.CachingIconView
import com.android.systemui.Gefingerpoken
import com.android.systemui.R
@@ -113,6 +116,8 @@ open class ChipbarCoordinator @Inject constructor(
}
)
+ currentView.setTag(INFO_TAG, newInfo)
+
// Detect falsing touches on the chip.
parent = currentView.requireViewById(R.id.chipbar_root_view)
parent.touchHandler = object : Gefingerpoken {
@@ -165,8 +170,11 @@ open class ChipbarCoordinator @Inject constructor(
} else {
""
}
- currentView.requireViewById(R.id.chipbar_inner).contentDescription =
- "$loadedIconDesc${newInfo.text.loadText(context)}"
+
+ val chipInnerView = currentView.getInnerView()
+ chipInnerView.contentDescription = "$loadedIconDesc${newInfo.text.loadText(context)}"
+ chipInnerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_ASSERTIVE
+ maybeGetAccessibilityFocus(newInfo, currentView)
// ---- Haptics ----
newInfo.vibrationEffect?.let {
@@ -174,23 +182,37 @@ open class ChipbarCoordinator @Inject constructor(
}
}
+ private fun maybeGetAccessibilityFocus(info: ChipbarInfo?, view: ViewGroup) {
+ // Don't steal focus unless the chipbar has something interactable.
+ // (The chipbar is marked as a live region, so its content will be announced whenever the
+ // content changes.)
+ if (info?.endItem is ChipbarEndItem.Button) {
+ view.getInnerView().requestAccessibilityFocus()
+ } else {
+ view.getInnerView().clearAccessibilityFocus()
+ }
+ }
+
override fun animateViewIn(view: ViewGroup) {
- val chipInnerView = view.requireViewById(R.id.chipbar_inner)
ViewHierarchyAnimator.animateAddition(
- chipInnerView,
+ view.getInnerView(),
ViewHierarchyAnimator.Hotspot.TOP,
Interpolators.EMPHASIZED_DECELERATE,
duration = ANIMATION_IN_DURATION,
includeMargins = true,
includeFadeIn = true,
// We can only request focus once the animation finishes.
- onAnimationEnd = { chipInnerView.requestAccessibilityFocus() },
+ onAnimationEnd = {
+ maybeGetAccessibilityFocus(view.getTag(INFO_TAG) as ChipbarInfo?, view)
+ },
)
}
override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) {
+ val innerView = view.getInnerView()
+ innerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_NONE
ViewHierarchyAnimator.animateRemoval(
- view.requireViewById(R.id.chipbar_inner),
+ innerView,
ViewHierarchyAnimator.Hotspot.TOP,
Interpolators.EMPHASIZED_ACCELERATE,
ANIMATION_OUT_DURATION,
@@ -199,6 +221,10 @@ open class ChipbarCoordinator @Inject constructor(
)
}
+ private fun ViewGroup.getInnerView(): ViewGroup {
+ return requireViewById(R.id.chipbar_inner)
+ }
+
override fun start() {}
override fun getTouchableRegion(view: View, outRect: Rect) {
@@ -216,3 +242,4 @@ open class ChipbarCoordinator @Inject constructor(
private const val ANIMATION_IN_DURATION = 500L
private const val ANIMATION_OUT_DURATION = 250L
+@IdRes private val INFO_TAG = R.id.tag_chipbar_info