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

Commit 688ffd09 authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

Handle replacement of StatusChips in SystemStatusAnimationScheduler

This CL contains a refactoring of SystemStatusAnimationScheduler to allow cancellation of StatusEvents in order to replace them with higher priority status events. Because the DelayableExecutor does not provide any cancellation functionality, I replaced the Executor based logic of scheduling animations with coroutines.

Additionally, prepareChipAnimation() (in SystemEventChipAnimationController) does no longer need to be called one layout pass before the chip appear animation is started. The appear animation can now be started immediately after calling prepareChipAnimation().

Both changes are only in effect when the PLUG_IN_STATUS_BAR_CHIP flag is enabled.

Bug: 197638244
Test: separate CL (ag/20982130)
Change-Id: Ice296b0b9950d6ceac83aa8df7652552acfdf971
parent 6b7afc23
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl;
import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.dagger.StartCentralSurfacesModule;
import com.android.systemui.statusbar.events.StatusBarEventsModule;
import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -101,6 +102,7 @@ import dagger.Provides;
        QSModule.class,
        ReferenceScreenshotModule.class,
        RotationLockModule.class,
        StatusBarEventsModule.class,
        StartCentralSurfacesModule.class,
        VolumeModule.class
})
+5 −0
Original line number Diff line number Diff line
@@ -255,6 +255,11 @@ public abstract class SystemUIModule {
    @BindsOptionalOf
    abstract FingerprintInteractiveToAuthProvider optionalFingerprintInteractiveToAuthProvider();

    @BindsOptionalOf
    //TODO(b/269430792 remove full qualifier. Full qualifier is used to avoid merge conflict.)
    abstract com.android.systemui.statusbar.events.SystemStatusAnimationScheduler
    optionalSystemStatusAnimationScheduler();

    @SysUISingleton
    @Binds
    abstract SystemClock bindSystemClock(SystemClockImpl systemClock);
+71 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.events

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.time.SystemClock
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.CoroutineScope

@Module
interface StatusBarEventsModule {

    companion object {

        @Provides
        @SysUISingleton
        fun provideSystemStatusAnimationScheduler(
                featureFlags: FeatureFlags,
                coordinator: SystemEventCoordinator,
                chipAnimationController: SystemEventChipAnimationController,
                statusBarWindowController: StatusBarWindowController,
                dumpManager: DumpManager,
                systemClock: SystemClock,
                @Application coroutineScope: CoroutineScope,
                @Main executor: DelayableExecutor
        ): SystemStatusAnimationScheduler {
            return if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
                SystemStatusAnimationSchedulerImpl(
                        coordinator,
                        chipAnimationController,
                        statusBarWindowController,
                        dumpManager,
                        systemClock,
                        coroutineScope
                )
            } else {
                SystemStatusAnimationSchedulerLegacyImpl(
                        coordinator,
                        chipAnimationController,
                        statusBarWindowController,
                        dumpManager,
                        systemClock,
                        executor
                )
            }
        }
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ typealias ViewCreator = (context: Context) -> BackgroundAnimatableView
interface StatusEvent {
    val priority: Int
    // Whether or not to force the status bar open and show a dot
    val forceVisible: Boolean
    var forceVisible: Boolean
    // Whether or not to show an animation for this event
    val showAnimation: Boolean
    val viewCreator: ViewCreator
@@ -72,7 +72,7 @@ class BGImageView(

class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : StatusEvent {
    override val priority = 50
    override val forceVisible = false
    override var forceVisible = false
    override val showAnimation = true
    override var contentDescription: String? = ""

@@ -90,7 +90,7 @@ class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : Status
class PrivacyEvent(override val showAnimation: Boolean = true) : StatusEvent {
    override var contentDescription: String? = null
    override val priority = 100
    override val forceVisible = true
    override var forceVisible = true
    var privacyItems: List<PrivacyItem> = listOf()
    private var privacyChip: OngoingPrivacyChip? = null

+38 −24
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import androidx.core.animation.AnimatorListenerAdapter
import androidx.core.animation.AnimatorSet
import androidx.core.animation.ValueAnimator
import com.android.systemui.R
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.window.StatusBarWindowController
import com.android.systemui.util.animation.AnimationUtil.Companion.frames
@@ -43,7 +45,8 @@ import kotlin.math.roundToInt
class SystemEventChipAnimationController @Inject constructor(
    private val context: Context,
    private val statusBarWindowController: StatusBarWindowController,
    private val contentInsetsProvider: StatusBarContentInsetsProvider
    private val contentInsetsProvider: StatusBarContentInsetsProvider,
    private val featureFlags: FeatureFlags
) : SystemStatusAnimationCallback {

    private lateinit var animationWindowView: FrameLayout
@@ -53,12 +56,14 @@ class SystemEventChipAnimationController @Inject constructor(

    // Left for LTR, Right for RTL
    private var animationDirection = LEFT
    private var chipRight = 0
    private var chipLeft = 0
    private var chipWidth = 0
    private var chipBounds = Rect()
    private val chipWidth get() = chipBounds.width()
    private val chipRight get() = chipBounds.right
    private val chipLeft get() = chipBounds.left
    private var chipMinWidth = context.resources.getDimensionPixelSize(
            R.dimen.ongoing_appops_chip_min_animation_width)
    private var dotSize = context.resources.getDimensionPixelSize(

    private val dotSize = context.resources.getDimensionPixelSize(
            R.dimen.ongoing_appops_dot_diameter)
    // Use during animation so that multiple animators can update the drawing rect
    private var animRect = Rect()
@@ -90,21 +95,26 @@ class SystemEventChipAnimationController @Inject constructor(
            it.view.measure(
                    View.MeasureSpec.makeMeasureSpec(
                            (animationWindowView.parent as View).width, AT_MOST),
                    View.MeasureSpec.makeMeasureSpec(animationWindowView.height, AT_MOST))
            chipWidth = it.chipWidth
        }
                    View.MeasureSpec.makeMeasureSpec(
                            (animationWindowView.parent as View).height, AT_MOST))

            // decide which direction we're animating from, and then set some screen coordinates
            val contentRect = contentInsetsProvider.getStatusBarContentAreaForCurrentRotation()
            val chipTop = ((animationWindowView.parent as View).height - it.view.measuredHeight) / 2
            val chipBottom = chipTop + it.view.measuredHeight
            val chipRight: Int
            val chipLeft: Int
            when (animationDirection) {
                LEFT -> {
                    chipRight = contentRect.right
                chipLeft = contentRect.right - chipWidth
                    chipLeft = contentRect.right - it.chipWidth
                }
                else /* RIGHT */ -> {
                    chipLeft = contentRect.left
                chipRight = contentRect.left + chipWidth
                    chipRight = contentRect.left + it.chipWidth
                }
            }
            chipBounds = Rect(chipLeft, chipTop, chipRight, chipBottom)
        }
    }

@@ -261,11 +271,15 @@ class SystemEventChipAnimationController @Inject constructor(
                it.marginEnd = marginEnd
            }

    private fun initializeAnimRect() = animRect.set(
    private fun initializeAnimRect() = if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) {
        animRect.set(chipBounds)
    } else {
        animRect.set(
                chipLeft,
                currentAnimatedView!!.view.top,
                chipRight,
                currentAnimatedView!!.view.bottom)
    }

    /**
     * To be called during an animation, sets the width and updates the current animated chip view
Loading