Merge "Accessibility for privacy status animations" into sc-dev
This commit is contained in:
@@ -497,7 +497,12 @@ class PrivacyDotViewController @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (state.designatedCorner != currentViewState.designatedCorner) {
|
if (state.designatedCorner != currentViewState.designatedCorner) {
|
||||||
|
currentViewState.designatedCorner?.contentDescription = null
|
||||||
|
state.designatedCorner?.contentDescription = state.contentDescription
|
||||||
|
|
||||||
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
|
updateDesignatedCorner(state.designatedCorner, state.shouldShowDot())
|
||||||
|
} else if (state.contentDescription != currentViewState.contentDescription) {
|
||||||
|
state.designatedCorner?.contentDescription = state.contentDescription
|
||||||
}
|
}
|
||||||
|
|
||||||
val shouldShow = state.shouldShowDot()
|
val shouldShow = state.shouldShowDot()
|
||||||
@@ -514,9 +519,13 @@ class PrivacyDotViewController @Inject constructor(
|
|||||||
|
|
||||||
private val systemStatusAnimationCallback: SystemStatusAnimationCallback =
|
private val systemStatusAnimationCallback: SystemStatusAnimationCallback =
|
||||||
object : SystemStatusAnimationCallback {
|
object : SystemStatusAnimationCallback {
|
||||||
override fun onSystemStatusAnimationTransitionToPersistentDot(): Animator? {
|
override fun onSystemStatusAnimationTransitionToPersistentDot(
|
||||||
|
contentDescr: String?
|
||||||
|
): Animator? {
|
||||||
synchronized(lock) {
|
synchronized(lock) {
|
||||||
nextViewState = nextViewState.copy(systemPrivacyEventIsActive = true)
|
nextViewState = nextViewState.copy(
|
||||||
|
systemPrivacyEventIsActive = true,
|
||||||
|
contentDescription = contentDescr)
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
@@ -620,7 +629,9 @@ private data class ViewState(
|
|||||||
val rotation: Int = 0,
|
val rotation: Int = 0,
|
||||||
val height: Int = 0,
|
val height: Int = 0,
|
||||||
val cornerIndex: Int = -1,
|
val cornerIndex: Int = -1,
|
||||||
val designatedCorner: View? = null
|
val designatedCorner: View? = null,
|
||||||
|
|
||||||
|
val contentDescription: String? = null
|
||||||
) {
|
) {
|
||||||
fun shouldShowDot(): Boolean {
|
fun shouldShowDot(): Boolean {
|
||||||
return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded
|
return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ interface StatusEvent {
|
|||||||
// Whether or not to show an animation for this event
|
// Whether or not to show an animation for this event
|
||||||
val showAnimation: Boolean
|
val showAnimation: Boolean
|
||||||
val viewCreator: (context: Context) -> View
|
val viewCreator: (context: Context) -> View
|
||||||
|
var contentDescription: String?
|
||||||
|
|
||||||
// Update this event with values from another event.
|
// Update this event with values from another event.
|
||||||
fun updateFromEvent(other: StatusEvent?) {
|
fun updateFromEvent(other: StatusEvent?) {
|
||||||
@@ -50,6 +51,7 @@ class BatteryEvent : StatusEvent {
|
|||||||
override val priority = 50
|
override val priority = 50
|
||||||
override val forceVisible = false
|
override val forceVisible = false
|
||||||
override val showAnimation = true
|
override val showAnimation = true
|
||||||
|
override var contentDescription: String? = ""
|
||||||
|
|
||||||
override val viewCreator: (context: Context) -> View = { context ->
|
override val viewCreator: (context: Context) -> View = { context ->
|
||||||
val iv = ImageView(context)
|
val iv = ImageView(context)
|
||||||
@@ -62,7 +64,9 @@ class BatteryEvent : StatusEvent {
|
|||||||
return javaClass.simpleName
|
return javaClass.simpleName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
|
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
|
||||||
|
override var contentDescription: String? = null
|
||||||
override val priority = 100
|
override val priority = 100
|
||||||
override val forceVisible = true
|
override val forceVisible = true
|
||||||
var privacyItems: List<PrivacyItem> = listOf()
|
var privacyItems: List<PrivacyItem> = listOf()
|
||||||
@@ -72,6 +76,7 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
|
|||||||
val v = LayoutInflater.from(context)
|
val v = LayoutInflater.from(context)
|
||||||
.inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip
|
.inflate(R.layout.ongoing_privacy_chip, null) as OngoingPrivacyChip
|
||||||
v.privacyList = privacyItems
|
v.privacyList = privacyItems
|
||||||
|
v.contentDescription = contentDescription
|
||||||
privacyChip = v
|
privacyChip = v
|
||||||
v
|
v
|
||||||
}
|
}
|
||||||
@@ -81,7 +86,9 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldUpdateFromEvent(other: StatusEvent?): Boolean {
|
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?) {
|
override fun updateFromEvent(other: StatusEvent?) {
|
||||||
@@ -90,6 +97,9 @@ class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
privacyItems = other.privacyItems
|
privacyItems = other.privacyItems
|
||||||
|
contentDescription = other.contentDescription
|
||||||
|
|
||||||
|
privacyChip?.contentDescription = other.contentDescription
|
||||||
privacyChip?.privacyList = other.privacyItems
|
privacyChip?.privacyList = other.privacyItems
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ import com.android.systemui.statusbar.phone.StatusBarWindowView
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* //TODO: this _probably_ doesn't control a window anymore
|
* Controls the view for system event animations.
|
||||||
* Controls the window for system event animations.
|
|
||||||
*/
|
*/
|
||||||
class SystemEventChipAnimationController @Inject constructor(
|
class SystemEventChipAnimationController @Inject constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
|||||||
@@ -16,9 +16,12 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.events
|
package com.android.systemui.statusbar.events
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.provider.DeviceConfig
|
import android.provider.DeviceConfig
|
||||||
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
|
import android.provider.DeviceConfig.NAMESPACE_PRIVACY
|
||||||
|
import com.android.systemui.R
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.privacy.PrivacyChipBuilder
|
||||||
import com.android.systemui.privacy.PrivacyItem
|
import com.android.systemui.privacy.PrivacyItem
|
||||||
import com.android.systemui.privacy.PrivacyItemController
|
import com.android.systemui.privacy.PrivacyItemController
|
||||||
import com.android.systemui.statusbar.policy.BatteryController
|
import com.android.systemui.statusbar.policy.BatteryController
|
||||||
@@ -33,7 +36,8 @@ import javax.inject.Inject
|
|||||||
class SystemEventCoordinator @Inject constructor(
|
class SystemEventCoordinator @Inject constructor(
|
||||||
private val systemClock: SystemClock,
|
private val systemClock: SystemClock,
|
||||||
private val batteryController: BatteryController,
|
private val batteryController: BatteryController,
|
||||||
private val privacyController: PrivacyItemController
|
private val privacyController: PrivacyItemController,
|
||||||
|
private val context: Context
|
||||||
) {
|
) {
|
||||||
private lateinit var scheduler: SystemStatusAnimationScheduler
|
private lateinit var scheduler: SystemStatusAnimationScheduler
|
||||||
|
|
||||||
@@ -66,6 +70,11 @@ class SystemEventCoordinator @Inject constructor(
|
|||||||
fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) {
|
fun notifyPrivacyItemsChanged(showAnimation: Boolean = true) {
|
||||||
val event = PrivacyEvent(showAnimation)
|
val event = PrivacyEvent(showAnimation)
|
||||||
event.privacyItems = privacyStateListener.currentPrivacyItems
|
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)
|
scheduler.onStatusEvent(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,17 +100,20 @@ class SystemStatusAnimationScheduler @Inject constructor(
|
|||||||
|
|
||||||
// Don't deal with threading for now (no need let's be honest)
|
// Don't deal with threading for now (no need let's be honest)
|
||||||
Assert.isMainThread()
|
Assert.isMainThread()
|
||||||
if (event.priority > scheduledEvent?.priority ?: -1 ||
|
if ((event.priority > scheduledEvent?.priority ?: -1) &&
|
||||||
scheduledEvent?.shouldUpdateFromEvent(event) == true) {
|
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) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "scheduling event $event")
|
Log.d(TAG, "scheduling event $event")
|
||||||
}
|
}
|
||||||
if (event.showAnimation) {
|
|
||||||
scheduleEvent(event)
|
scheduleEvent(event)
|
||||||
} else if (event.forceVisible) {
|
} else if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
|
||||||
hasPersistentDot = true
|
if (DEBUG) {
|
||||||
notifyTransitionToPersistentDot()
|
Log.d(TAG, "updating current event from: $event")
|
||||||
}
|
}
|
||||||
|
scheduledEvent?.updateFromEvent(event)
|
||||||
} else {
|
} else {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "ignoring event $event")
|
Log.d(TAG, "ignoring event $event")
|
||||||
@@ -142,24 +145,18 @@ class SystemStatusAnimationScheduler @Inject constructor(
|
|||||||
* Clear the scheduled event (if any) and schedule a new one
|
* Clear the scheduled event (if any) and schedule a new one
|
||||||
*/
|
*/
|
||||||
private fun scheduleEvent(event: StatusEvent) {
|
private fun scheduleEvent(event: StatusEvent) {
|
||||||
if (animationState == ANIMATING_OUT ||
|
scheduledEvent = event
|
||||||
(animationState == SHOWING_PERSISTENT_DOT && event.forceVisible)) {
|
|
||||||
// do not schedule an event or change the current one
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we are showing the chip, possibly update the current event, rather than replacing
|
if (event.forceVisible) {
|
||||||
if (scheduledEvent?.shouldUpdateFromEvent(event) == true) {
|
|
||||||
scheduledEvent?.updateFromEvent(event)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
scheduledEvent = event
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduledEvent!!.forceVisible) {
|
|
||||||
hasPersistentDot = true
|
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
|
// Schedule the animation to start after a debounce period
|
||||||
cancelExecutionRunnable = executor.executeDelayed({
|
cancelExecutionRunnable = executor.executeDelayed({
|
||||||
cancelExecutionRunnable = null
|
cancelExecutionRunnable = null
|
||||||
@@ -218,7 +215,7 @@ class SystemStatusAnimationScheduler @Inject constructor(
|
|||||||
|
|
||||||
private fun notifyTransitionToPersistentDot(): Animator? {
|
private fun notifyTransitionToPersistentDot(): Animator? {
|
||||||
val anims: List<Animator> = listeners.mapNotNull {
|
val anims: List<Animator> = listeners.mapNotNull {
|
||||||
it.onSystemStatusAnimationTransitionToPersistentDot()
|
it.onSystemStatusAnimationTransitionToPersistentDot(scheduledEvent?.contentDescription)
|
||||||
}
|
}
|
||||||
if (anims.isNotEmpty()) {
|
if (anims.isNotEmpty()) {
|
||||||
val aSet = AnimatorSet()
|
val aSet = AnimatorSet()
|
||||||
@@ -346,7 +343,10 @@ interface SystemStatusAnimationCallback {
|
|||||||
@JvmDefault fun onSystemChromeAnimationEnd() {}
|
@JvmDefault fun onSystemChromeAnimationEnd() {}
|
||||||
|
|
||||||
// Best method name, change my mind
|
// 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 }
|
@JvmDefault fun onHidePersistentDot(): Animator? { return null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user