summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Laird <evanlaird@google.com>2021-08-04 11:50:07 -0400
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-08-17 22:54:04 +0000
commit421a14f3bce7c69040ac0482cae450f1bb68ba2d (patch)
tree3e9ba4790561f2167d26abce67ff61a138919a47
parentfb0db2652a8ec3d631c439b47075f52a4dc15de1 (diff)
downloadbase-421a14f3bce7c69040ac0482cae450f1bb68ba2d.tar.gz
Accessibility for privacy status animations
This CL adds contentDescriptions to the privacy event chip and the ongoing privacy dot views. This is a partial fix which allows talkback for the ongoing privacy chip, and allows talkback scrolling to the privacy dot. However, due to the fact that the dot lives in a different window, the privacy dot shows up in the wrong part of the accesibility tree and still needs to be virtually placed in the status bar. Bug: 187197696 Test: manual Change-Id: I6210e18c75a1aab61cbcf619a9a31c459fffe544 (cherry picked from commit c14dd63160ee9fb303e3cd92ff63825a1303362a)
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt44
5 files changed, 58 insertions, 29 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
index 29cfb07a14f9..1037e576f263 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt
@@ -497,7 +497,12 @@ class PrivacyDotViewController @Inject constructor(
}
if (state.designatedCorner != currentViewState.designatedCorner) {
+ currentViewState.designatedCorner?.contentDescription = null
+ state.designatedCorner?.contentDescription = state.contentDescription
+
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
+ } else if (state.contentDescription != currentViewState.contentDescription) {
+ state.designatedCorner?.contentDescription = state.contentDescription
}
val shouldShow = state.shouldShowDot()
@@ -514,9 +519,13 @@ class PrivacyDotViewController @Inject constructor(
private val systemStatusAnimationCallback: SystemStatusAnimationCallback =
object : SystemStatusAnimationCallback {
- override fun onSystemStatusAnimationTransitionToPersistentDot(): Animator? {
+ override fun onSystemStatusAnimationTransitionToPersistentDot(
+ contentDescr: String?
+ ): Animator? {
synchronized(lock) {
- nextViewState = nextViewState.copy(systemPrivacyEventIsActive = true)
+ nextViewState = nextViewState.copy(
+ systemPrivacyEventIsActive = true,
+ contentDescription = contentDescr)
}
return null
@@ -620,7 +629,9 @@ private data class ViewState(
val rotation: Int = 0,
val height: Int = 0,
val cornerIndex: Int = -1,
- val designatedCorner: View? = null
+ val designatedCorner: View? = null,
+
+ val contentDescription: String? = null
) {
fun shouldShowDot(): Boolean {
return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
index 539020d52db5..d4d84c138b20 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/StatusEvent.kt
@@ -34,6 +34,7 @@ interface StatusEvent {
// Whether or not to show an animation for this event
val showAnimation: Boolean
val viewCreator: (context: Context) -> View
+ var contentDescription: String?
// Update this event with values from another event.
fun updateFromEvent(other: StatusEvent?) {
@@ -50,6 +51,7 @@ class BatteryEvent : StatusEvent {
override val priority = 50
override val forceVisible = false
override val showAnimation = true
+ override var contentDescription: String? = ""
override val viewCreator: (context: Context) -> View = { context ->
val iv = ImageView(context)
@@ -62,7 +64,9 @@ class BatteryEvent : StatusEvent {
return javaClass.simpleName
}
}
+
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
+ override var contentDescription: String? = null
override val priority = 100
override val forceVisible = true
var privacyItems: List<PrivacyItem> = listOf()
@@ -72,6 +76,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
val v = LayoutInflater.from(context)
.inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip
v.privacyList = privacyItems
+ v.contentDescription = contentDescription
privacyChip = v
v
}
@@ -81,7 +86,9 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
}
override fun shouldUpdateFromEvent(other: StatusEvent?): Boolean {
- return other is PrivacyEvent && other.privacyItems != privacyItems
+ return other is PrivacyEvent &&
+ (other.privacyItems != privacyItems ||
+ other.contentDescription != contentDescription)
}
override fun updateFromEvent(other: StatusEvent?) {
@@ -90,6 +97,9 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
}
privacyItems = other.privacyItems
+ contentDescription = other.contentDescription
+
+ privacyChip?.contentDescription = other.contentDescription
privacyChip?.privacyList = other.privacyItems
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
index b861c1db9b8b..7291b5a8be3b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt
@@ -34,8 +34,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowView
import javax.inject.Inject
/**
- * //TODO: this _probably_ doesn't control a window anymore
- * Controls the window for system event animations.
+ * Controls the view for system event animations.
*/
class SystemEventChipAnimationController @Inject constructor(
private val context: Context,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
index ba50659f5567..04f7492e8562 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt
@@ -16,9 +16,12 @@
package com.android.systemui.statusbar.events
+import android.content.Context
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
+import com.android.systemui.R
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.privacy.PrivacyChipBuilder
import com.android.systemui.privacy.PrivacyItem
import com.android.systemui.privacy.PrivacyItemController
import com.android.systemui.statusbar.policy.BatteryController
@@ -33,7 +36,8 @@ import javax.inject.Inject
class SystemEventCoordinator @Inject constructor(
private val systemClock: SystemClock,
private val batteryController: BatteryController,
- private val privacyController: PrivacyItemController
+ private val privacyController: PrivacyItemController,
+ private val context: Context
) {
private lateinit var scheduler: SystemStatusAnimationScheduler
@@ -66,6 +70,11 @@ class SystemEventCoordinator @Inject constructor(
fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) {
val event = PrivacyEvent(showAnimation)
event.privacyItems = privacyStateListener.currentPrivacyItems
+ event.contentDescription = {
+ val items = PrivacyChipBuilder(context, event.privacyItems).joinTypes()
+ context.getString(
+ R.string.ongoing_privacy_chip_content_multiple_apps, items)
+ }()
scheduler.onStatusEvent(event)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
index f30010cf4d1c..f1610d866f34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt
@@ -100,17 +100,20 @@ class SystemStatusAnimationScheduler @Inject constructor(
// Don't deal with threading for now (no need let's be honest)
Assert.isMainThread()
- if (event.priority > scheduledEvent?.priority ?: -1 ||
- scheduledEvent?.shouldUpdateFromEvent(event) == true) {
+ if ((event.priority > scheduledEvent?.priority ?: -1) &&
+ animationState != ANIMATING_OUT &&
+ (animationState != SHOWING_PERSISTENT_DOT && event.forceVisible)) {
+ // events can only be scheduled if a higher priority or no other event is in progress
if (DEBUG) {
Log.d(TAG, "scheduling event $event")
}
- if (event.showAnimation) {
- scheduleEvent(event)
- } else if (event.forceVisible) {
- hasPersistentDot = true
- notifyTransitionToPersistentDot()
+
+ scheduleEvent(event)
+ } else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
+ if (DEBUG) {
+ Log.d(TAG, "updating current event from: $event")
}
+ scheduledEvent?.updateFromEvent(event)
} else {
if (DEBUG) {
Log.d(TAG, "ignoring event $event")
@@ -142,22 +145,16 @@ class SystemStatusAnimationScheduler @Inject constructor(
* Clear the scheduled event (if any) and schedule a new one
*/
private fun scheduleEvent(event: StatusEvent) {
- if (animationState == ANIMATING_OUT ||
- (animationState == SHOWING_PERSISTENT_DOT && event.forceVisible)) {
- // do not schedule an event or change the current one
- return
- }
+ scheduledEvent = event
- // If we are showing the chip, possibly update the current event, rather than replacing
- if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
- scheduledEvent?.updateFromEvent(event)
- return
- } else {
- scheduledEvent = event
+ if (event.forceVisible) {
+ hasPersistentDot = true
}
- if (scheduledEvent!!.forceVisible) {
- hasPersistentDot = true
+ // If animations are turned off, we'll transition directly to the dot
+ if (!event.showAnimation && event.forceVisible) {
+ notifyTransitionToPersistentDot()
+ return
}
// Schedule the animation to start after a debounce period
@@ -218,7 +215,7 @@ class SystemStatusAnimationScheduler @Inject constructor(
private fun notifyTransitionToPersistentDot(): Animator? {
val anims: List<Animator> = listeners.mapNotNull {
- it.onSystemStatusAnimationTransitionToPersistentDot()
+ it.onSystemStatusAnimationTransitionToPersistentDot(scheduledEvent?.contentDescription)
}
if (anims.isNotEmpty()) {
val aSet = AnimatorSet()
@@ -346,7 +343,10 @@ interface SystemStatusAnimationCallback {
@JvmDefault fun onSystemChromeAnimationEnd() {}
// Best method name, change my mind
- @JvmDefault fun onSystemStatusAnimationTransitionToPersistentDot(): Animator? { return null }
+ @JvmDefault
+ fun onSystemStatusAnimationTransitionToPersistentDot(contentDescription: String?): Animator? {
+ return null
+ }
@JvmDefault fun onHidePersistentDot(): Animator? { return null }
}