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

Commit a69c13a5 authored by Yein Jo's avatar Yein Jo Committed by Android (Google) Code Review
Browse files

Merge "Extract common render callback interfaces." into main

parents 434d46cc 6f879b8a
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
/*
 * 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)
}
+39 −0
Original line number Diff line number Diff line
/*
 * 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)
}
+24 −43
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.animation.ValueAnimator
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,14 +336,13 @@ private constructor(
        )
    }

    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)
     * [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,
@@ -350,25 +351,6 @@ private constructor(
        NOT_PLAYING
    }

        /** 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 {
        /**
@@ -378,8 +360,7 @@ private constructor(
        fun onStateChanged(oldState: AnimationState, newState: AnimationState) {}
    }

    private companion object {
        private const val MS_TO_SEC = 0.001f

        private val TAG = LoadingEffect::class.java.simpleName
    }
}
+8 −7
Original line number Diff line number Diff line
@@ -118,8 +118,9 @@ import com.android.systemui.res.R;
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 @@ public class MediaControlPanel {
    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) {
+51 −29
Original line number Diff line number Diff line
@@ -23,14 +23,8 @@ import android.testing.TestableLooper
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 @@ class LoadingEffectTest : SysUiStateTest() {
        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 @@ class LoadingEffectTest : SysUiStateTest() {
        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 @@ class LoadingEffectTest : SysUiStateTest() {
    @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 @@ class LoadingEffectTest : SysUiStateTest() {
        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 @@ class LoadingEffectTest : SysUiStateTest() {
        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 @@ class LoadingEffectTest : SysUiStateTest() {
            }
        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 @@ class LoadingEffectTest : SysUiStateTest() {
        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 @@ class LoadingEffectTest : SysUiStateTest() {
            )
        val drawCallback =
            object : PaintDrawCallback {
                override fun onDraw(loadingPaint: Paint) {}
                override fun onDraw(paint: Paint) {}
            }
        val loadingEffect =
            LoadingEffect(