From e3b3abee30466966cc9403957f02a661c47c0754 Mon Sep 17 00:00:00 2001 From: Shan Huang Date: Fri, 19 Mar 2021 22:11:41 +0800 Subject: [PATCH] Add charging ripple to wireless charging animation. This cl adds the ripple effect to the WirelessChargingLayout. It also removes the cross fade effect that happens on lock screen and AOD. Next steps: - Apply distortion to the ripple. - Remove the dots and percentage text to match the new design. Demo videos: https://drive.google.com/drive/folders/1wOi53MSjh5hOwkLVTDJglXbRK2Cdw9zL?usp=sharing Test: Manually Test: SysUITests Bug: 183382912 Change-Id: Ib4dbb04bf263e3e46a6cb55cc077b6ee9902ebe3 --- .../res/layout/wireless_charging_layout.xml | 5 +++ .../charging/WirelessChargingAnimation.java | 7 ++- .../charging/WirelessChargingLayout.java | 26 ++++++++++- .../statusbar/charging/ChargingRippleView.kt | 19 ++++---- .../statusbar/charging/RippleShader.kt | 4 +- .../charging/WiredChargingRippleController.kt | 29 +++++++----- .../systemui/statusbar/phone/StatusBar.java | 45 +++++-------------- .../WiredChargingRippleControllerTest.kt | 4 +- 8 files changed, 76 insertions(+), 63 deletions(-) diff --git a/packages/SystemUI/res/layout/wireless_charging_layout.xml b/packages/SystemUI/res/layout/wireless_charging_layout.xml index 730f24ff9dd2c..d82151d30b9e6 100644 --- a/packages/SystemUI/res/layout/wireless_charging_layout.xml +++ b/packages/SystemUI/res/layout/wireless_charging_layout.xml @@ -22,6 +22,11 @@ android:layout_width="match_parent" android:layout_height="match_parent"> + + val now = animator.currentPlayTime val phase = now / 30000f diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt index 5547c1e78cc4e..d400205af50ba 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/RippleShader.kt @@ -53,7 +53,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) { float s = 0.0; for (float i = 0; i < 4; i += 1) { float l = i * 0.25; - float h = l + 0.025; + float h = l + 0.005; float o = abs(sin(0.1 * PI * (t + i))); s += threshold(n + o, l, h); } @@ -97,7 +97,7 @@ class RippleShader internal constructor() : RuntimeShader(SHADER, false) { float fadeRipple = min(fadeIn, 1.-fadeOutRipple); float rippleAlpha = softRing(p, in_origin, radius, 0.5) * fadeRipple * in_color.a; - vec4 ripple = in_color * max(circle, rippleAlpha) * 0.4; + vec4 ripple = in_color * max(circle, rippleAlpha) * 0.3; return mix(ripple, vec4(sparkle), sparkle * in_sparkle_strength); }""" private const val SHADER = SHADER_UNIFORMS + SHADER_LIB + SHADER_MAIN diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt index b567ad4ccfc23..2900462c69248 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.charging import android.content.Context import android.content.res.Configuration +import android.graphics.PointF import android.util.DisplayMetrics import android.view.View import android.view.ViewGroupOverlay @@ -31,6 +32,7 @@ import com.android.systemui.statusbar.policy.BatteryController import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import java.io.PrintWriter +import java.lang.Integer.max import javax.inject.Inject /*** @@ -46,7 +48,7 @@ class WiredChargingRippleController @Inject constructor( private val context: Context, private val keyguardStateController: KeyguardStateController ) { - private var pluggedIn: Boolean? = null + private var charging: Boolean? = null private val rippleEnabled: Boolean = featureFlags.isChargingRippleEnabled @VisibleForTesting var rippleView: ChargingRippleView = ChargingRippleView(context, attrs = null) @@ -55,16 +57,18 @@ class WiredChargingRippleController @Inject constructor( val batteryStateChangeCallback = object : BatteryController.BatteryStateChangeCallback { override fun onBatteryLevelChanged( level: Int, - nowPluggedIn: Boolean, - charging: Boolean + pluggedIn: Boolean, + nowCharging: Boolean ) { - if (!rippleEnabled) { + // Suppresses the ripple when it's disabled, or when the state change comes + // from wireless charging. + if (!rippleEnabled || batteryController.isWirelessCharging) { return } - val wasPluggedIn = pluggedIn - pluggedIn = nowPluggedIn + val wasCharging = charging + charging = nowCharging // Only triggers when the keyguard is active and the device is just plugged in. - if (wasPluggedIn == false && nowPluggedIn && keyguardStateController.isShowing) { + if (wasCharging == false && nowCharging && keyguardStateController.isShowing) { rippleView.startRipple() } } @@ -113,10 +117,13 @@ class WiredChargingRippleController @Inject constructor( val width = displayMetrics.widthPixels val height = displayMetrics.heightPixels if (width != rippleView.width || height != rippleView.height) { - rippleView.measure( - View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), - View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)) - rippleView.layout(0, 0, width, height) + rippleView.apply { + measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY)) + layout(0, 0, width, height) + origin = PointF(width / 2f, height.toFloat()) + radius = max(width, height).toFloat() + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 0e1fe22b2454c..f584030027281 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -184,7 +184,6 @@ import com.android.systemui.statusbar.AutoHideUiElement; import com.android.systemui.statusbar.BackDropView; import com.android.systemui.statusbar.CircleReveal; import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.CrossFadeHelper; import com.android.systemui.statusbar.FeatureFlags; import com.android.systemui.statusbar.GestureRecorder; import com.android.systemui.statusbar.KeyboardShortcuts; @@ -2469,39 +2468,19 @@ public class StatusBar extends SystemUI implements DemoMode, protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel, long animationDelay) { - if (mDozing || mKeyguardManager.isKeyguardLocked()) { - // on ambient or lockscreen, hide notification panel - WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, - transmittingBatteryLevel, batteryLevel, - new WirelessChargingAnimation.Callback() { - @Override - public void onAnimationStarting() { - mNotificationShadeWindowController.setRequestTopUi(true, TAG); - CrossFadeHelper.fadeOut(mNotificationPanelViewController.getView(), 1); - } + WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, + transmittingBatteryLevel, batteryLevel, + new WirelessChargingAnimation.Callback() { + @Override + public void onAnimationStarting() { + mNotificationShadeWindowController.setRequestTopUi(true, TAG); + } - @Override - public void onAnimationEnded() { - CrossFadeHelper.fadeIn(mNotificationPanelViewController.getView()); - mNotificationShadeWindowController.setRequestTopUi(false, TAG); - } - }, mDozing).show(animationDelay); - } else { - // workspace - WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null, - transmittingBatteryLevel, batteryLevel, - new WirelessChargingAnimation.Callback() { - @Override - public void onAnimationStarting() { - mNotificationShadeWindowController.setRequestTopUi(true, TAG); - } - - @Override - public void onAnimationEnded() { - mNotificationShadeWindowController.setRequestTopUi(false, TAG); - } - }, false).show(animationDelay); - } + @Override + public void onAnimationEnded() { + mNotificationShadeWindowController.setRequestTopUi(false, TAG); + } + }, false).show(animationDelay); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt index 3701b91271160..9ce72414d7513 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt @@ -93,8 +93,8 @@ class WiredChargingRippleControllerTest : SysuiTestCase() { captor.value.onBatteryLevelChanged( unusedBatteryLevel, - true /* plugged in */, - false /* charging */) + false /* plugged in */, + true /* charging */) verify(rippleView).startRipple() }