diff options
| author | 2022-12-21 20:17:43 +0000 | |
|---|---|---|
| committer | 2022-12-21 20:17:43 +0000 | |
| commit | abd81830d40ff956c49ab5b481f921232a23d19a (patch) | |
| tree | bb732bc765320226d3d1493962eda51a486e75f2 | |
| parent | bcd5cf6f1310f25cb14999a4de3a38f4ec74a813 (diff) | |
| parent | d287d1d6bb76f8606aadcfeddeed4a50ff34d746 (diff) | |
Merge "[Media TTT] Apply ripple effect for new states" into tm-qpr-dev am: d287d1d6bb
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20668089
Change-Id: Ib89a4f05a80937b6c82e7bb3575892f6827371d4
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
11 files changed, 97 insertions, 17 deletions
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt index f55fb97a9a97..90585109643a 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt @@ -169,11 +169,9 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : setFloatUniform("in_progress", value) val curvedProg = 1 - (1 - value) * (1 - value) * (1 - value) - setFloatUniform( - "in_size", - /* width= */ maxSize.x * curvedProg, - /* height= */ maxSize.y * curvedProg - ) + currentWidth = maxSize.x * curvedProg + currentHeight = maxSize.y * curvedProg + setFloatUniform("in_size", /* width= */ currentWidth, /* height= */ currentHeight) setFloatUniform("in_thickness", maxSize.y * curvedProg * 0.5f) // radius should not exceed width and height values. setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * curvedProg) @@ -237,4 +235,10 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) : * False for a ring effect. */ var rippleFill: Boolean = false + + var currentWidth: Float = 0f + private set + + var currentHeight: Float = 0f + private set } diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt index ae28a8b6dc2e..b37c73417119 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt @@ -36,7 +36,7 @@ import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape */ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) { - private lateinit var rippleShader: RippleShader + protected lateinit var rippleShader: RippleShader lateinit var rippleShape: RippleShape private set diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index fbf413bc55fe..1f80b5a99c60 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -315,6 +315,10 @@ object Flags { // TODO(b/261734857): Tracking Bug @JvmField val UMO_TURBULENCE_NOISE = unreleasedFlag(909, "umo_turbulence_noise") + // TODO(b/263272731): Tracking Bug + val MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE = + unreleasedFlag(910, "media_ttt_receiver_success_ripple", teamfood = true) + // 1000 - dock val SIMULATE_DOCK_THROUGH_CHARGING = releasedFlag(1000, "simulate_dock_through_charging") diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt index 03bc9350674b..8a565fa86b35 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt @@ -26,4 +26,8 @@ import javax.inject.Inject class MediaTttFlags @Inject constructor(private val featureFlags: FeatureFlags) { /** */ fun isMediaTttEnabled(): Boolean = featureFlags.isEnabled(Flags.MEDIA_TAP_TO_TRANSFER) + + /** Check whether the flag for the receiver success state is enabled. */ + fun isMediaTttReceiverSuccessRippleEnabled(): Boolean = + featureFlags.isEnabled(Flags.MEDIA_TTT_RECEIVER_SUCCESS_RIPPLE) } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 358534c25a1e..889147b598b5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -114,6 +114,9 @@ open class MediaTttChipControllerReceiver @Inject constructor( } } + private var maxRippleWidth: Float = 0f + private var maxRippleHeight: Float = 0f + private fun updateMediaTapToTransferReceiverDisplay( @StatusBarManager.MediaTransferReceiverState displayState: Int, routeInfo: MediaRoute2Info, @@ -216,7 +219,7 @@ open class MediaTttChipControllerReceiver @Inject constructor( expandRipple(view.requireViewById(R.id.ripple)) } - override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { + override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) { val appIconView = view.getAppIconView() appIconView.animate() .translationYBy(getTranslationAmount().toFloat()) @@ -226,7 +229,14 @@ open class MediaTttChipControllerReceiver @Inject constructor( .alpha(0f) .setDuration(ICON_ALPHA_ANIM_DURATION) .start() - (view.requireViewById(R.id.ripple) as ReceiverChipRippleView).collapseRipple(onAnimationEnd) + + val rippleView: ReceiverChipRippleView = view.requireViewById(R.id.ripple) + if (removalReason == ChipStateReceiver.TRANSFER_TO_RECEIVER_SUCCEEDED.name && + mediaTttFlags.isMediaTttReceiverSuccessRippleEnabled()) { + expandRippleToFull(rippleView, onAnimationEnd) + } else { + rippleView.collapseRipple(onAnimationEnd) + } } override fun getTouchableRegion(view: View, outRect: Rect) { @@ -271,12 +281,19 @@ open class MediaTttChipControllerReceiver @Inject constructor( }) } - private fun layoutRipple(rippleView: ReceiverChipRippleView) { + private fun layoutRipple(rippleView: ReceiverChipRippleView, isFullScreen: Boolean = false) { val windowBounds = windowManager.currentWindowMetrics.bounds val height = windowBounds.height().toFloat() val width = windowBounds.width().toFloat() - rippleView.setMaxSize(width / 2f, height / 2f) + if (isFullScreen) { + maxRippleHeight = height * 2f + maxRippleWidth = width * 2f + } else { + maxRippleHeight = height / 2f + maxRippleWidth = width / 2f + } + rippleView.setMaxSize(maxRippleWidth, maxRippleHeight) // Center the ripple on the bottom of the screen in the middle. rippleView.setCenter(width * 0.5f, height) val color = Utils.getColorAttrDefaultColor(context, R.attr.wallpaperTextColorAccent) @@ -286,6 +303,11 @@ open class MediaTttChipControllerReceiver @Inject constructor( private fun View.getAppIconView(): CachingIconView { return this.requireViewById(R.id.app_icon) } + + private fun expandRippleToFull(rippleView: ReceiverChipRippleView, onAnimationEnd: Runnable?) { + layoutRipple(rippleView, true) + rippleView.expandToFull(maxRippleHeight, onAnimationEnd) + } } val ICON_TRANSLATION_ANIM_DURATION = 30.frames diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt index 6e9fc5c33940..87b2528f93d3 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt @@ -22,6 +22,7 @@ import android.content.Context import android.util.AttributeSet import com.android.systemui.surfaceeffects.ripple.RippleShader import com.android.systemui.surfaceeffects.ripple.RippleView +import kotlin.math.pow /** * An expanding ripple effect for the media tap-to-transfer receiver chip. @@ -59,4 +60,44 @@ class ReceiverChipRippleView(context: Context?, attrs: AttributeSet?) : RippleVi }) animator.reverse() } + + // Expands the ripple to cover full screen. + fun expandToFull(newHeight: Float, onAnimationEnd: Runnable? = null) { + if (!isStarted) { + return + } + // Reset all listeners to animator. + animator.removeAllListeners() + animator.removeAllUpdateListeners() + + // Only show the outline as ripple expands and disappears when animation ends. + setRippleFill(false) + + val startingPercentage = calculateStartingPercentage(newHeight) + animator.addUpdateListener { updateListener -> + val now = updateListener.currentPlayTime + val progress = updateListener.animatedValue as Float + rippleShader.progress = startingPercentage + (progress * (1 - startingPercentage)) + rippleShader.distortionStrength = 1 - rippleShader.progress + rippleShader.pixelDensity = 1 - rippleShader.progress + rippleShader.time = now.toFloat() + invalidate() + } + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationEnd(animation: Animator?) { + animation?.let { visibility = GONE } + onAnimationEnd?.run() + isStarted = false + } + }) + animator.start() + } + + // Calculates the actual starting percentage according to ripple shader progress set method. + // Check calculations in [RippleShader.progress] + fun calculateStartingPercentage(newHeight: Float): Float { + val ratio = rippleShader.currentHeight / newHeight + val remainingPercentage = (1 - ratio).toDouble().pow(1 / 3.toDouble()).toFloat() + return 1 - remainingPercentage + } } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt index 532fbaad1cfd..ad48e218687d 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt @@ -331,7 +331,7 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora return } - removeViewFromWindow(displayInfo) + removeViewFromWindow(displayInfo, removalReason) // Prune anything that's already timed out before determining if we should re-display a // different chipbar. @@ -358,14 +358,14 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora removeViewFromWindow(displayInfo) } - private fun removeViewFromWindow(displayInfo: DisplayInfo) { + private fun removeViewFromWindow(displayInfo: DisplayInfo, removalReason: String? = null) { val view = displayInfo.view if (view == null) { logger.logViewRemovalIgnored(displayInfo.info.id, "View is null") return } displayInfo.view = null // Need other places?? - animateViewOut(view) { + animateViewOut(view, removalReason) { windowManager.removeView(view) displayInfo.wakeLock?.release(displayInfo.info.wakeReason) } @@ -428,7 +428,11 @@ abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : Tempora * * @param onAnimationEnd an action that *must* be run once the animation finishes successfully. */ - internal open fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { + internal open fun animateViewOut( + view: ViewGroup, + removalReason: String? = null, + onAnimationEnd: Runnable + ) { onAnimationEnd.run() } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt index fd2c70565d45..52980c3c1f9b 100644 --- a/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/chipbar/ChipbarCoordinator.kt @@ -211,7 +211,7 @@ open class ChipbarCoordinator @Inject constructor( ) } - override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { + override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) { val innerView = view.getInnerView() innerView.accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_NONE ViewHierarchyAnimator.animateRemoval( diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt index 07a31093b104..9c4e849df738 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/FakeMediaTttChipControllerReceiver.kt @@ -66,7 +66,7 @@ class FakeMediaTttChipControllerReceiver( wakeLockBuilder, systemClock, ) { - override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { + override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) { // Just bypass the animation in tests onAnimationEnd.run() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 03ba3d39f5ea..cefc7424324b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -98,6 +98,7 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) whenever(mediaTttFlags.isMediaTttEnabled()).thenReturn(true) + whenever(mediaTttFlags.isMediaTttReceiverSuccessRippleEnabled()).thenReturn(true) fakeAppIconDrawable = context.getDrawable(R.drawable.ic_cake)!! whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(fakeAppIconDrawable) diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt index b9a5bd7081c4..4ef4e6ca6540 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/chipbar/FakeChipbarCoordinator.kt @@ -64,7 +64,7 @@ class FakeChipbarCoordinator( wakeLockBuilder, systemClock, ) { - override fun animateViewOut(view: ViewGroup, onAnimationEnd: Runnable) { + override fun animateViewOut(view: ViewGroup, removalReason: String?, onAnimationEnd: Runnable) { // Just bypass the animation in tests onAnimationEnd.run() } |