From bd502db5026e931c04e743c6f2dad88b2d23a87c Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Tue, 10 Jan 2023 16:11:28 +0100 Subject: [PATCH] Statusbar charging animation chip when plugging in device Bug: 197638244 Test: Separate CL (ag/20982130) Change-Id: I93b8bb4e0eb277e9491e7667de0142f6b1501fea --- .../res/drawable/statusbar_chip_bg.xml | 23 ++++++ ...p_bg.xml => statusbar_privacy_chip_bg.xml} | 0 .../res/layout/battery_status_chip.xml | 43 +++++++++++ .../res/layout/ongoing_privacy_chip.xml | 4 +- .../systemui/battery/BatteryMeterView.java | 9 ++- .../src/com/android/systemui/flags/Flags.kt | 3 + .../systemui/privacy/OngoingPrivacyChip.kt | 2 +- .../systemui/statusbar/BatteryStatusChip.kt | 73 +++++++++++++++++++ .../systemui/statusbar/events/StatusEvent.kt | 16 ++-- .../SystemEventChipAnimationController.kt | 34 +++++++-- .../events/SystemEventCoordinator.kt | 28 +++---- .../events/SystemStatusAnimationScheduler.kt | 16 ++-- .../fragment/StatusBarSystemEventAnimator.kt | 8 +- 13 files changed, 214 insertions(+), 45 deletions(-) create mode 100644 packages/SystemUI/res/drawable/statusbar_chip_bg.xml rename packages/SystemUI/res/drawable/{privacy_chip_bg.xml => statusbar_privacy_chip_bg.xml} (100%) create mode 100644 packages/SystemUI/res/layout/battery_status_chip.xml create mode 100644 packages/SystemUI/src/com/android/systemui/statusbar/BatteryStatusChip.kt diff --git a/packages/SystemUI/res/drawable/statusbar_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml new file mode 100644 index 0000000000000..d7de16d7c5bb7 --- /dev/null +++ b/packages/SystemUI/res/drawable/statusbar_chip_bg.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/drawable/privacy_chip_bg.xml b/packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml similarity index 100% rename from packages/SystemUI/res/drawable/privacy_chip_bg.xml rename to packages/SystemUI/res/drawable/statusbar_privacy_chip_bg.xml diff --git a/packages/SystemUI/res/layout/battery_status_chip.xml b/packages/SystemUI/res/layout/battery_status_chip.xml new file mode 100644 index 0000000000000..ff68ac0f9a71e --- /dev/null +++ b/packages/SystemUI/res/layout/battery_status_chip.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml index d1a2cf4c24b21..245e73541e709 100644 --- a/packages/SystemUI/res/layout/ongoing_privacy_chip.xml +++ b/packages/SystemUI/res/layout/ongoing_privacy_chip.xml @@ -22,10 +22,8 @@ android:layout_height="match_parent" android:layout_width="wrap_content" android:layout_gravity="center_vertical|end" - android:focusable="true" android:clipChildren="false" android:clipToPadding="false" - android:paddingStart="8dp" > BackgroundAnimatableView @@ -73,17 +72,16 @@ class BGImageView( } } -class BatteryEvent : StatusEvent { +class BatteryEvent(@IntRange(from = 0, to = 100) val batteryLevel: Int) : StatusEvent { override val priority = 50 override val forceVisible = false override val showAnimation = true override var contentDescription: String? = "" - override val viewCreator: (context: Context) -> BGImageView = { context -> - val iv = BGImageView(context) - iv.setImageDrawable(ThemedBatteryDrawable(context, Color.WHITE)) - iv.setBackgroundDrawable(ColorDrawable(Color.GREEN)) - iv + override val viewCreator: ViewCreator = { context -> + BatteryStatusChip(context).apply { + setBatteryLevel(batteryLevel) + } } override fun toString(): String { 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 8405aea218f01..b498107752e00 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventChipAnimationController.kt @@ -117,16 +117,21 @@ class SystemEventChipAnimationController @Inject constructor( interpolator = null addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float } } + currentAnimatedView?.contentView?.alpha = 0f + val contentAlphaIn = ValueAnimator.ofFloat(0f, 1f).apply { + startDelay = 10.frames + duration = 10.frames + interpolator = null + addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float } + } val moveIn = ValueAnimator.ofInt(chipMinWidth, chipWidth).apply { startDelay = 7.frames duration = 23.frames interpolator = STATUS_BAR_X_MOVE_IN - addUpdateListener { - updateAnimatedViewBoundsWidth(animatedValue as Int) - } + addUpdateListener { updateAnimatedViewBoundsWidth(animatedValue as Int) } } val animSet = AnimatorSet() - animSet.playTogether(alphaIn, moveIn) + animSet.playTogether(alphaIn, contentAlphaIn, moveIn) return animSet } @@ -210,15 +215,32 @@ class SystemEventChipAnimationController @Inject constructor( } private fun createMoveOutAnimationDefault(): Animator { + val alphaOut = ValueAnimator.ofFloat(1f, 0f).apply { + startDelay = 6.frames + duration = 6.frames + interpolator = null + addUpdateListener { currentAnimatedView?.view?.alpha = animatedValue as Float } + } + + val contentAlphaOut = ValueAnimator.ofFloat(1f, 0f).apply { + duration = 5.frames + interpolator = null + addUpdateListener { currentAnimatedView?.contentView?.alpha = animatedValue as Float } + } + val moveOut = ValueAnimator.ofInt(chipWidth, chipMinWidth).apply { duration = 23.frames + interpolator = STATUS_BAR_X_MOVE_OUT addUpdateListener { currentAnimatedView?.apply { updateAnimatedViewBoundsWidth(it.animatedValue as Int) } } } - return moveOut + + val animSet = AnimatorSet() + animSet.playTogether(alphaOut, contentAlphaOut, moveOut) + return animSet } private fun init() { @@ -296,6 +318,8 @@ class SystemEventChipAnimationController @Inject constructor( interface BackgroundAnimatableView { val view: View // Since this can't extend View, add a view prop get() = this as View + val contentView: View? // This will be alpha faded during appear and disappear animation + get() = null val chipWidth: Int get() = view.measuredWidth fun setBoundsForAnimation(l: Int, t: Int, r: Int, b: Int) 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 fde5d39db7e3e..225ced5f10582 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemEventCoordinator.kt @@ -16,11 +16,14 @@ package com.android.systemui.statusbar.events +import android.annotation.IntRange 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.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.privacy.PrivacyChipBuilder import com.android.systemui.privacy.PrivacyItem import com.android.systemui.privacy.PrivacyItemController @@ -37,21 +40,18 @@ class SystemEventCoordinator @Inject constructor( private val systemClock: SystemClock, private val batteryController: BatteryController, private val privacyController: PrivacyItemController, - private val context: Context + private val context: Context, + private val featureFlags: FeatureFlags ) { private lateinit var scheduler: SystemStatusAnimationScheduler fun startObserving() { - /* currently unused batteryController.addCallback(batteryStateListener) - */ privacyController.addCallback(privacyStateListener) } fun stopObserving() { - /* currently unused batteryController.removeCallback(batteryStateListener) - */ privacyController.removeCallback(privacyStateListener) } @@ -59,8 +59,10 @@ class SystemEventCoordinator @Inject constructor( this.scheduler = s } - fun notifyPluggedIn() { - scheduler.onStatusEvent(BatteryEvent()) + fun notifyPluggedIn(@IntRange(from = 0, to = 100) batteryLevel: Int) { + if (featureFlags.isEnabled(Flags.PLUG_IN_STATUS_BAR_CHIP)) { + scheduler.onStatusEvent(BatteryEvent(batteryLevel)) + } } fun notifyPrivacyItemsEmpty() { @@ -79,25 +81,25 @@ class SystemEventCoordinator @Inject constructor( } private val batteryStateListener = object : BatteryController.BatteryStateChangeCallback { - var plugged = false - var stateKnown = false + private var plugged = false + private var stateKnown = false override fun onBatteryLevelChanged(level: Int, pluggedIn: Boolean, charging: Boolean) { if (!stateKnown) { stateKnown = true plugged = pluggedIn - notifyListeners() + notifyListeners(level) return } if (plugged != pluggedIn) { plugged = pluggedIn - notifyListeners() + notifyListeners(level) } } - private fun notifyListeners() { + private fun notifyListeners(@IntRange(from = 0, to = 100) batteryLevel: Int) { // We only care about the plugged in status - if (plugged) notifyPluggedIn() + if (plugged) notifyPluggedIn(batteryLevel) } } 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 197cf5608cf58..3c35e4bbc8410 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/events/SystemStatusAnimationScheduler.kt @@ -66,7 +66,8 @@ open class SystemStatusAnimationScheduler @Inject constructor( companion object { private const val PROPERTY_ENABLE_IMMERSIVE_INDICATOR = "enable_immersive_indicator" } - public fun isImmersiveIndicatorEnabled(): Boolean { + + fun isImmersiveIndicatorEnabled(): Boolean { return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_PRIVACY, PROPERTY_ENABLE_IMMERSIVE_INDICATOR, true) } @@ -80,11 +81,7 @@ open class SystemStatusAnimationScheduler @Inject constructor( private var scheduledEvent: StatusEvent? = null private var cancelExecutionRunnable: Runnable? = null - private val listeners = mutableSetOf() - - fun getListeners(): MutableSet { - return listeners - } + val listeners = mutableSetOf() init { coordinator.attachScheduler(this) @@ -99,9 +96,8 @@ open 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) && - animationState != ANIMATING_OUT && - (animationState != SHOWING_PERSISTENT_DOT && event.forceVisible)) { + if ((event.priority > (scheduledEvent?.priority ?: -1)) && + animationState != ANIMATING_OUT && animationState != SHOWING_PERSISTENT_DOT) { // events can only be scheduled if a higher priority or no other event is in progress if (DEBUG) { Log.d(TAG, "scheduling event $event") @@ -143,7 +139,7 @@ open class SystemStatusAnimationScheduler @Inject constructor( } } - public fun isTooEarly(): Boolean { + fun isTooEarly(): Boolean { return systemClock.uptimeMillis() - Process.getStartUptimeMillis() < MIN_UPTIME } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt index fe69f75075034..5772fca59beb0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/StatusBarSystemEventAnimator.kt @@ -64,14 +64,14 @@ class StatusBarSystemEventAnimator( override fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator { animatedView.translationX = translationXOut.toFloat() - val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(28.frames) - moveIn.startDelay = 2.frames + val moveIn = ValueAnimator.ofFloat(1f, 0f).setDuration(23.frames) + moveIn.startDelay = 7.frames moveIn.interpolator = STATUS_BAR_X_MOVE_IN moveIn.addUpdateListener { animation: ValueAnimator -> animatedView.translationX = translationXOut * animation.animatedValue as Float } - val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(10.frames) - alphaIn.startDelay = 4.frames + val alphaIn = ValueAnimator.ofFloat(0f, 1f).setDuration(5.frames) + alphaIn.startDelay = 11.frames alphaIn.interpolator = null alphaIn.addUpdateListener { animation: ValueAnimator -> animatedView.alpha = animation.animatedValue as Float