Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 61a46b17 authored by bsears's avatar bsears Committed by Android (Google) Code Review
Browse files

Merge "Accessibility for privacy status animations" into sc-dev

parents 06ca6eed c14dd631
Loading
Loading
Loading
Loading
+14 −3
Original line number Diff line number Diff line
@@ -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
+11 −1
Original line number Diff line number Diff line
@@ -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
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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,
+10 −1
Original line number Diff line number Diff line
@@ -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)
    }

+22 −22
Original line number Diff line number Diff line
@@ -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()
        } 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,24 +145,18 @@ 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
        }

        // 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 (scheduledEvent!!.forceVisible) {
        if (event.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
        cancelExecutionRunnable = executor.executeDelayed({
            cancelExecutionRunnable = null
@@ -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 }
}