Merge "Extract common render callback interfaces." into main
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt
new file mode 100644
index 0000000..d50979c
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/PaintDrawCallback.kt
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2024 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.surfaceeffects
+
+import android.graphics.Paint
+import android.graphics.RenderEffect
+
+/**
+ * A callback with a [Paint] object that contains shader info, which is triggered every frame while
+ * animation is playing. Note that the [Paint] object here is always the same instance.
+ *
+ * This approach is more performant than other ones because [RenderEffect] forces an intermediate
+ * render pass of the View to a texture to feed into it.
+ *
+ * The usage of this callback is as follows:
+ * <pre>{@code
+ *     private var paint: Paint? = null
+ *     // Override [View.onDraw].
+ *     override fun onDraw(canvas: Canvas) {
+ *         // RuntimeShader requires hardwareAcceleration.
+ *         if (!canvas.isHardwareAccelerated) return
+ *
+ *         paint?.let { canvas.drawPaint(it) }
+ *     }
+ *
+ *     // Given that this is called [PaintDrawCallback.onDraw]
+ *     fun draw(paint: Paint) {
+ *         this.paint = paint
+ *
+ *         // Must call invalidate to trigger View#onDraw
+ *         invalidate()
+ *     }
+ * }</pre>
+ *
+ * Please refer to [RenderEffectDrawCallback] for alternative approach.
+ */
+interface PaintDrawCallback {
+    fun onDraw(paint: Paint)
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt
new file mode 100644
index 0000000..db7ee58
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/RenderEffectDrawCallback.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.surfaceeffects
+
+import android.graphics.RenderEffect
+
+/**
+ * A callback with a [RenderEffect] object that contains shader info, which is triggered every frame
+ * while animation is playing. Note that the [RenderEffect] instance is different each time to
+ * update shader uniforms.
+ *
+ * The usage of this callback is as follows:
+ * <pre>{@code
+ *     private val xEffectDrawingCallback = RenderEffectDrawCallback() {
+ *         val myOtherRenderEffect = createOtherRenderEffect()
+ *         val chainEffect = RenderEffect.createChainEffect(renderEffect, myOtherRenderEffect)
+ *         myView.setRenderEffect(chainEffect)
+ *     }
+ *
+ *     private val xEffect = XEffect(config, xEffectDrawingCallback)
+ * }</pre>
+ */
+interface RenderEffectDrawCallback {
+    fun onDraw(renderEffect: RenderEffect)
+}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
index 1c763e8..211b84f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffect.kt
@@ -22,6 +22,8 @@
 import android.graphics.Paint
 import android.graphics.RenderEffect
 import android.view.View
+import com.android.systemui.surfaceeffects.PaintDrawCallback
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader
 
@@ -334,52 +336,31 @@
         )
     }
 
-    companion object {
+    /**
+     * States of the loading effect animation.
+     *
+     * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
+     * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't necessarily
+     * mean the acceleration and deceleration in the animation curve. They simply mean each stage of
+     * the animation. (i.e. Intro, core, and rest)
+     */
+    enum class AnimationState {
+        EASE_IN,
+        MAIN,
+        EASE_OUT,
+        NOT_PLAYING
+    }
+
+    /** Optional callback that is triggered when the animation state changes. */
+    interface AnimationStateChangedCallback {
         /**
-         * States of the loading effect animation.
-         *
-         * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
-         * [AnimationState.MAIN], [AnimationState.EASE_OUT]. Note that ease in and out don't
-         * necessarily mean the acceleration and deceleration in the animation curve. They simply
-         * mean each stage of the animation. (i.e. Intro, core, and rest)
+         * A callback that's triggered when the [AnimationState] changes. Example usage is
+         * performing a cleanup when [AnimationState] becomes [NOT_PLAYING].
          */
-        enum class AnimationState {
-            EASE_IN,
-            MAIN,
-            EASE_OUT,
-            NOT_PLAYING
-        }
+        fun onStateChanged(oldState: AnimationState, newState: AnimationState) {}
+    }
 
-        /** Client must implement one of the draw callbacks. */
-        interface PaintDrawCallback {
-            /**
-             * A callback with a [Paint] object that contains shader info, which is triggered every
-             * frame while animation is playing. Note that the [Paint] object here is always the
-             * same instance.
-             */
-            fun onDraw(loadingPaint: Paint)
-        }
-
-        interface RenderEffectDrawCallback {
-            /**
-             * A callback with a [RenderEffect] object that contains shader info, which is triggered
-             * every frame while animation is playing. Note that the [RenderEffect] instance is
-             * different each time to update shader uniforms.
-             */
-            fun onDraw(loadingRenderEffect: RenderEffect)
-        }
-
-        /** Optional callback that is triggered when the animation state changes. */
-        interface AnimationStateChangedCallback {
-            /**
-             * A callback that's triggered when the [AnimationState] changes. Example usage is
-             * performing a cleanup when [AnimationState] becomes [NOT_PLAYING].
-             */
-            fun onStateChanged(oldState: AnimationState, newState: AnimationState) {}
-        }
-
+    private companion object {
         private const val MS_TO_SEC = 0.001f
-
-        private val TAG = LoadingEffect::class.java.simpleName
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
index 899b9ed..ca898e6 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaControlPanel.java
@@ -118,8 +118,9 @@
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.surfaceeffects.PaintDrawCallback;
 import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect;
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState;
+import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.AnimationState;
 import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleController;
 import com.android.systemui.surfaceeffects.ripple.MultiRippleView;
@@ -264,15 +265,15 @@
     private boolean mWasPlaying = false;
     private boolean mButtonClicked = false;
 
-    private final LoadingEffect.Companion.PaintDrawCallback mNoiseDrawCallback =
-            new LoadingEffect.Companion.PaintDrawCallback() {
+    private final PaintDrawCallback mNoiseDrawCallback =
+            new PaintDrawCallback() {
                 @Override
-                public void onDraw(@NonNull Paint loadingPaint) {
-                    mMediaViewHolder.getLoadingEffectView().draw(loadingPaint);
+                public void onDraw(@NonNull Paint paint) {
+                    mMediaViewHolder.getLoadingEffectView().draw(paint);
                 }
             };
-    private final LoadingEffect.Companion.AnimationStateChangedCallback mStateChangedCallback =
-            new LoadingEffect.Companion.AnimationStateChangedCallback() {
+    private final LoadingEffect.AnimationStateChangedCallback mStateChangedCallback =
+            new LoadingEffect.AnimationStateChangedCallback() {
                 @Override
                 public void onStateChanged(@NonNull AnimationState oldState,
                         @NonNull AnimationState newState) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
index 7a83cfe..6f58941 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/loadingeffect/LoadingEffectTest.kt
@@ -23,14 +23,8 @@
 import androidx.test.filters.SmallTest
 import com.android.systemui.animation.AnimatorTestRule
 import com.android.systemui.model.SysUiStateTest
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_IN
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.EASE_OUT
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.MAIN
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationState.NOT_PLAYING
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.AnimationStateChangedCallback
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.PaintDrawCallback
-import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffect.Companion.RenderEffectDrawCallback
+import com.android.systemui.surfaceeffects.PaintDrawCallback
+import com.android.systemui.surfaceeffects.RenderEffectDrawCallback
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader
 import com.google.common.truth.Truth.assertThat
@@ -50,8 +44,8 @@
         var paintFromCallback: Paint? = null
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {
-                    paintFromCallback = loadingPaint
+                override fun onDraw(paint: Paint) {
+                    paintFromCallback = paint
                 }
             }
         val loadingEffect =
@@ -75,8 +69,8 @@
         var renderEffectFromCallback: RenderEffect? = null
         val drawCallback =
             object : RenderEffectDrawCallback {
-                override fun onDraw(loadingRenderEffect: RenderEffect) {
-                    renderEffectFromCallback = loadingRenderEffect
+                override fun onDraw(renderEffect: RenderEffect) {
+                    renderEffectFromCallback = renderEffect
                 }
             }
         val loadingEffect =
@@ -98,16 +92,19 @@
     @Test
     fun play_animationStateChangesInOrder() {
         val config = TurbulenceNoiseAnimationConfig()
-        val states = mutableListOf(NOT_PLAYING)
+        val states = mutableListOf(LoadingEffect.AnimationState.NOT_PLAYING)
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
                     states.add(newState)
                 }
             }
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(
@@ -125,7 +122,14 @@
         animatorTestRule.advanceTimeBy(config.easeOutDuration.toLong())
         animatorTestRule.advanceTimeBy(500)
 
-        assertThat(states).containsExactly(NOT_PLAYING, EASE_IN, MAIN, EASE_OUT, NOT_PLAYING)
+        assertThat(states)
+            .containsExactly(
+                LoadingEffect.AnimationState.NOT_PLAYING,
+                LoadingEffect.AnimationState.EASE_IN,
+                LoadingEffect.AnimationState.MAIN,
+                LoadingEffect.AnimationState.EASE_OUT,
+                LoadingEffect.AnimationState.NOT_PLAYING
+            )
     }
 
     @Test
@@ -133,16 +137,22 @@
         val config = TurbulenceNoiseAnimationConfig()
         var numPlay = 0
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == NOT_PLAYING && newState == EASE_IN) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.NOT_PLAYING &&
+                            newState == LoadingEffect.AnimationState.EASE_IN
+                    ) {
                         numPlay++
                     }
                 }
             }
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(
@@ -172,9 +182,15 @@
             }
         var isFinished = false
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == EASE_OUT && newState == NOT_PLAYING) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.EASE_OUT &&
+                            newState == LoadingEffect.AnimationState.NOT_PLAYING
+                    ) {
                         isFinished = true
                     }
                 }
@@ -205,13 +221,19 @@
         val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f)
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         var isFinished = false
         val stateChangedCallback =
-            object : AnimationStateChangedCallback {
-                override fun onStateChanged(oldState: AnimationState, newState: AnimationState) {
-                    if (oldState == MAIN && newState == NOT_PLAYING) {
+            object : LoadingEffect.AnimationStateChangedCallback {
+                override fun onStateChanged(
+                    oldState: LoadingEffect.AnimationState,
+                    newState: LoadingEffect.AnimationState
+                ) {
+                    if (
+                        oldState == LoadingEffect.AnimationState.MAIN &&
+                            newState == LoadingEffect.AnimationState.NOT_PLAYING
+                    ) {
                         isFinished = true
                     }
                 }
@@ -242,7 +264,7 @@
             )
         val drawCallback =
             object : PaintDrawCallback {
-                override fun onDraw(loadingPaint: Paint) {}
+                override fun onDraw(paint: Paint) {}
             }
         val loadingEffect =
             LoadingEffect(