Update TurbulenceNoiseShader and the config.

Removed some unused or non shader related params from the config and
updated the Shader, View accordingly.

Test: MediaControlPanelTest, TurbulenceNoiseShaderTest,
TurbulenceNoiseViewTest, TurbulenceNoiseControllerTest, Inspect UMO and
wallpaper picker visually.
Bug: 282007590
Flag: NA

Change-Id: I477f1c07b683473a3a007ee8107b6c51f81f7f88
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
index 2cd587f..59354c8 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseAnimationConfig.kt
@@ -15,8 +15,8 @@
  */
 package com.android.systemui.surfaceeffects.turbulencenoise
 
-import android.graphics.BlendMode
 import android.graphics.Color
+import java.util.Random
 
 /** Turbulence noise animation configuration. */
 data class TurbulenceNoiseAnimationConfig(
@@ -26,6 +26,11 @@
     /** Multiplier for the noise luma matte. Increase this for brighter effects. */
     val luminosityMultiplier: Float = DEFAULT_LUMINOSITY_MULTIPLIER,
 
+    /** Initial noise offsets. */
+    val noiseOffsetX: Float = random.nextFloat(),
+    val noiseOffsetY: Float = random.nextFloat(),
+    val noiseOffsetZ: Float = random.nextFloat(),
+
     /**
      * Noise move speed variables.
      *
@@ -45,18 +50,15 @@
     val noiseMoveSpeedZ: Float = DEFAULT_NOISE_SPEED_Z,
 
     /** Color of the effect. */
-    var color: Int = DEFAULT_COLOR,
+    val color: Int = DEFAULT_COLOR,
     /** Background color of the effect. */
     val backgroundColor: Int = DEFAULT_BACKGROUND_COLOR,
-    val opacity: Int = DEFAULT_OPACITY,
     val width: Float = 0f,
     val height: Float = 0f,
     val maxDuration: Float = DEFAULT_MAX_DURATION_IN_MILLIS,
     val easeInDuration: Float = DEFAULT_EASING_DURATION_IN_MILLIS,
     val easeOutDuration: Float = DEFAULT_EASING_DURATION_IN_MILLIS,
     val pixelDensity: Float = 1f,
-    val blendMode: BlendMode = DEFAULT_BLEND_MODE,
-    val onAnimationEnd: Runnable? = null,
     /**
      * Variants in noise. Higher number means more contrast; lower number means less contrast but
      * make the noise dimmed. You may want to increase the [lumaMatteBlendFactor] to compensate.
@@ -68,7 +70,9 @@
      * want to use this if you have made the noise softer using [lumaMatteBlendFactor]. Expected
      * range [0, 1].
      */
-    val lumaMatteOverallBrightness: Float = DEFAULT_LUMA_MATTE_OVERALL_BRIGHTNESS
+    val lumaMatteOverallBrightness: Float = DEFAULT_LUMA_MATTE_OVERALL_BRIGHTNESS,
+    /** Whether to flip the luma mask. */
+    val shouldInverseNoiseLuminosity: Boolean = false
 ) {
     companion object {
         const val DEFAULT_MAX_DURATION_IN_MILLIS = 30_000f // Max 30 sec
@@ -76,11 +80,10 @@
         const val DEFAULT_LUMINOSITY_MULTIPLIER = 1f
         const val DEFAULT_NOISE_GRID_COUNT = 1.2f
         const val DEFAULT_NOISE_SPEED_Z = 0.3f
-        const val DEFAULT_OPACITY = 150 // full opacity is 255.
         const val DEFAULT_COLOR = Color.WHITE
         const val DEFAULT_LUMA_MATTE_BLEND_FACTOR = 1f
         const val DEFAULT_LUMA_MATTE_OVERALL_BRIGHTNESS = 0f
         const val DEFAULT_BACKGROUND_COLOR = Color.BLACK
-        val DEFAULT_BLEND_MODE = BlendMode.SRC_OVER
+        private val random = Random()
     }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
index b8f4b27..535c2d3 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseController.kt
@@ -69,12 +69,15 @@
      *
      * <p>It plays ease-in, main, and ease-out animations in sequence.
      */
-    fun play(config: TurbulenceNoiseAnimationConfig) {
+    fun play(
+        baseType: TurbulenceNoiseShader.Companion.Type,
+        config: TurbulenceNoiseAnimationConfig
+    ) {
         if (state != AnimationState.NOT_PLAYING) {
             return // Ignore if any of the animation is playing.
         }
 
-        turbulenceNoiseView.applyConfig(config)
+        turbulenceNoiseView.initShader(baseType, config)
         playEaseInAnimation()
     }
 
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
index d3c57c9..30108ac 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShader.kt
@@ -22,10 +22,10 @@
 /**
  * Shader that renders turbulence simplex noise, by default no octave.
  *
- * @param useFractal whether to use fractal noise (4 octaves).
+ * @param baseType the base [Type] of the shader.
  */
-class TurbulenceNoiseShader(useFractal: Boolean = false) :
-    RuntimeShader(if (useFractal) FRACTAL_NOISE_SHADER else SIMPLEX_NOISE_SHADER) {
+class TurbulenceNoiseShader(val baseType: Type = Type.SIMPLEX_NOISE) :
+    RuntimeShader(getShader(baseType)) {
     // language=AGSL
     companion object {
         private const val UNIFORMS =
@@ -86,11 +86,34 @@
                 return vec4(color * in_opacity, in_opacity);
             }
         """
-
         private const val SIMPLEX_NOISE_SHADER =
             ShaderUtilLibrary.SHADER_LIB + UNIFORMS + SIMPLEX_SHADER
         private const val FRACTAL_NOISE_SHADER =
             ShaderUtilLibrary.SHADER_LIB + UNIFORMS + FRACTAL_SHADER
+        // TODO (b/282007590): Add NOISE_WITH_SPARKLE
+
+        enum class Type {
+            SIMPLEX_NOISE,
+            SIMPLEX_NOISE_FRACTAL,
+        }
+
+        fun getShader(type: Type): String {
+            return when (type) {
+                Type.SIMPLEX_NOISE -> SIMPLEX_NOISE_SHADER
+                Type.SIMPLEX_NOISE_FRACTAL -> FRACTAL_NOISE_SHADER
+            }
+        }
+    }
+
+    /** Convenient way for updating multiple uniform values via config object. */
+    fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
+        setGridCount(config.gridCount)
+        setPixelDensity(config.pixelDensity)
+        setColor(config.color)
+        setBackgroundColor(config.backgroundColor)
+        setSize(config.width, config.height)
+        setLumaMatteFactors(config.lumaMatteBlendFactor, config.lumaMatteOverallBrightness)
+        setInverseNoiseLuminosity(config.shouldInverseNoiseLuminosity)
     }
 
     /** Sets the number of grid for generating noise. */
@@ -107,18 +130,19 @@
         setFloatUniform("in_pixelDensity", pixelDensity)
     }
 
-    /** Sets the noise color of the effect. */
+    /** Sets the noise color of the effect. Alpha is ignored. */
     fun setColor(color: Int) {
         setColorUniform("in_color", color)
     }
 
-    /** Sets the background color of the effect. */
+    /** Sets the background color of the effect. Alpha is ignored. */
     fun setBackgroundColor(color: Int) {
         setColorUniform("in_backgroundColor", color)
     }
 
     /**
-     * Sets the opacity to achieve fade in/ out of the animation.
+     * Sets the opacity of the effect. Not intended to set by the client as it is used for
+     * ease-in/out animations.
      *
      * Expected value range is [1, 0].
      */
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
index 43d6504..c59bc10 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseView.kt
@@ -19,12 +19,12 @@
 import android.animation.AnimatorListenerAdapter
 import android.animation.ValueAnimator
 import android.content.Context
+import android.graphics.BlendMode
 import android.graphics.Canvas
 import android.graphics.Paint
 import android.util.AttributeSet
 import android.view.View
 import androidx.annotation.VisibleForTesting
-import androidx.core.graphics.ColorUtils
 
 /**
  * View that renders turbulence noise effect.
@@ -44,8 +44,8 @@
         private const val MS_TO_SEC = 0.001f
     }
 
-    private val turbulenceNoiseShader = TurbulenceNoiseShader()
-    private val paint = Paint().apply { this.shader = turbulenceNoiseShader }
+    private val paint = Paint()
+    @VisibleForTesting var turbulenceNoiseShader: TurbulenceNoiseShader? = null
     @VisibleForTesting var noiseConfig: TurbulenceNoiseAnimationConfig? = null
     @VisibleForTesting var currentAnimator: ValueAnimator? = null
 
@@ -61,9 +61,7 @@
 
     /** Updates the color during the animation. No-op if there's no animation playing. */
     internal fun updateColor(color: Int) {
-        noiseConfig?.let {
-            turbulenceNoiseShader.setColor(ColorUtils.setAlphaComponent(color, it.opacity))
-        }
+        turbulenceNoiseShader?.setColor(color)
     }
 
     /** Plays the turbulence noise with no easing. */
@@ -73,24 +71,25 @@
             return
         }
         val config = noiseConfig!!
+        val shader = turbulenceNoiseShader!!
 
         val animator = ValueAnimator.ofFloat(0f, 1f)
         animator.duration = config.maxDuration.toLong()
 
         // Animation should start from the initial position to avoid abrupt transition.
-        val initialX = turbulenceNoiseShader.noiseOffsetX
-        val initialY = turbulenceNoiseShader.noiseOffsetY
-        val initialZ = turbulenceNoiseShader.noiseOffsetZ
+        val initialX = shader.noiseOffsetX
+        val initialY = shader.noiseOffsetY
+        val initialZ = shader.noiseOffsetZ
 
         animator.addUpdateListener { updateListener ->
             val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
-            turbulenceNoiseShader.setNoiseMove(
+            shader.setNoiseMove(
                 initialX + timeInSec * config.noiseMoveSpeedX,
                 initialY + timeInSec * config.noiseMoveSpeedY,
                 initialZ + timeInSec * config.noiseMoveSpeedZ
             )
 
-            turbulenceNoiseShader.setOpacity(config.luminosityMultiplier)
+            shader.setOpacity(config.luminosityMultiplier)
 
             invalidate()
         }
@@ -115,27 +114,28 @@
             return
         }
         val config = noiseConfig!!
+        val shader = turbulenceNoiseShader!!
 
         val animator = ValueAnimator.ofFloat(0f, 1f)
         animator.duration = config.easeInDuration.toLong()
 
         // Animation should start from the initial position to avoid abrupt transition.
-        val initialX = turbulenceNoiseShader.noiseOffsetX
-        val initialY = turbulenceNoiseShader.noiseOffsetY
-        val initialZ = turbulenceNoiseShader.noiseOffsetZ
+        val initialX = shader.noiseOffsetX
+        val initialY = shader.noiseOffsetY
+        val initialZ = shader.noiseOffsetZ
 
         animator.addUpdateListener { updateListener ->
             val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
             val progress = updateListener.animatedValue as Float
 
-            turbulenceNoiseShader.setNoiseMove(
+            shader.setNoiseMove(
                 offsetX + initialX + timeInSec * config.noiseMoveSpeedX,
                 offsetY + initialY + timeInSec * config.noiseMoveSpeedY,
                 initialZ + timeInSec * config.noiseMoveSpeedZ
             )
 
             // TODO: Replace it with a better curve.
-            turbulenceNoiseShader.setOpacity(progress * config.luminosityMultiplier)
+            shader.setOpacity(progress * config.luminosityMultiplier)
 
             invalidate()
         }
@@ -160,27 +160,28 @@
             return
         }
         val config = noiseConfig!!
+        val shader = turbulenceNoiseShader!!
 
         val animator = ValueAnimator.ofFloat(0f, 1f)
         animator.duration = config.easeOutDuration.toLong()
 
         // Animation should start from the initial position to avoid abrupt transition.
-        val initialX = turbulenceNoiseShader.noiseOffsetX
-        val initialY = turbulenceNoiseShader.noiseOffsetY
-        val initialZ = turbulenceNoiseShader.noiseOffsetZ
+        val initialX = shader.noiseOffsetX
+        val initialY = shader.noiseOffsetY
+        val initialZ = shader.noiseOffsetZ
 
         animator.addUpdateListener { updateListener ->
             val timeInSec = updateListener.currentPlayTime * MS_TO_SEC
             val progress = updateListener.animatedValue as Float
 
-            turbulenceNoiseShader.setNoiseMove(
+            shader.setNoiseMove(
                 initialX + timeInSec * config.noiseMoveSpeedX,
                 initialY + timeInSec * config.noiseMoveSpeedY,
                 initialZ + timeInSec * config.noiseMoveSpeedZ
             )
 
             // TODO: Replace it with a better curve.
-            turbulenceNoiseShader.setOpacity((1f - progress) * config.luminosityMultiplier)
+            shader.setOpacity((1f - progress) * config.luminosityMultiplier)
 
             invalidate()
         }
@@ -211,18 +212,22 @@
 
     /** Applies shader uniforms. Must be called before playing animation. */
     @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
-    fun applyConfig(config: TurbulenceNoiseAnimationConfig) {
+    fun initShader(
+        baseType: TurbulenceNoiseShader.Companion.Type,
+        config: TurbulenceNoiseAnimationConfig
+    ) {
         noiseConfig = config
-        with(turbulenceNoiseShader) {
-            setGridCount(config.gridCount)
-            setColor(config.color)
-            setBackgroundColor(config.backgroundColor)
-            setSize(config.width, config.height)
-            setPixelDensity(config.pixelDensity)
-            setInverseNoiseLuminosity(inverse = false)
-            setLumaMatteFactors(config.lumaMatteBlendFactor, config.lumaMatteOverallBrightness)
+        if (turbulenceNoiseShader == null || turbulenceNoiseShader?.baseType != baseType) {
+            turbulenceNoiseShader = TurbulenceNoiseShader(baseType)
+
+            paint.shader = turbulenceNoiseShader!!
         }
-        paint.blendMode = config.blendMode
+        turbulenceNoiseShader!!.applyConfig(config)
+    }
+
+    /** Sets the blend mode of the View. */
+    fun setBlendMode(blendMode: BlendMode) {
+        paint.blendMode = blendMode
     }
 
     internal fun clearConfig() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
index 5720cc7..5bfc7e8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java
@@ -118,6 +118,8 @@
 import com.android.systemui.surfaceeffects.ripple.RippleShader;
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig;
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController;
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type;
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView;
 import com.android.systemui.util.ColorUtilKt;
 import com.android.systemui.util.animation.TransitionLayout;
 import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -132,6 +134,7 @@
 import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Random;
 import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
@@ -251,6 +254,8 @@
     private boolean mWasPlaying = false;
     private boolean mButtonClicked = false;
 
+    private final Random mRandom = new Random();
+
     /**
      * Initialize a new control panel
      *
@@ -448,7 +453,10 @@
 
         MultiRippleView multiRippleView = vh.getMultiRippleView();
         mMultiRippleController = new MultiRippleController(multiRippleView);
-        mTurbulenceNoiseController = new TurbulenceNoiseController(vh.getTurbulenceNoiseView());
+
+        TurbulenceNoiseView turbulenceNoiseView = vh.getTurbulenceNoiseView();
+        turbulenceNoiseView.setBlendMode(BlendMode.SCREEN);
+        mTurbulenceNoiseController = new TurbulenceNoiseController(turbulenceNoiseView);
 
         mColorSchemeTransition = new ColorSchemeTransition(
                 mContext, mMediaViewHolder, mMultiRippleController, mTurbulenceNoiseController);
@@ -587,6 +595,7 @@
             }
             // Color will be correctly updated in ColorSchemeTransition.
             mTurbulenceNoiseController.play(
+                    Type.SIMPLEX_NOISE,
                     mTurbulenceNoiseAnimationConfig
             );
             mMainExecutor.executeDelayed(
@@ -1227,22 +1236,23 @@
         return new TurbulenceNoiseAnimationConfig(
                 /* gridCount= */ 2.14f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_LUMINOSITY_MULTIPLIER,
+                /* noiseOffsetX= */ mRandom.nextFloat(),
+                /* noiseOffsetY= */ mRandom.nextFloat(),
+                /* noiseOffsetZ= */ mRandom.nextFloat(),
                 /* noiseMoveSpeedX= */ 0.42f,
                 /* noiseMoveSpeedY= */ 0f,
                 TurbulenceNoiseAnimationConfig.DEFAULT_NOISE_SPEED_Z,
                 /* color= */ mColorSchemeTransition.getAccentPrimary().getCurrentColor(),
                 /* backgroundColor= */ Color.BLACK,
-                /* opacity= */ 51,
                 /* width= */ mMediaViewHolder.getTurbulenceNoiseView().getWidth(),
                 /* height= */ mMediaViewHolder.getTurbulenceNoiseView().getHeight(),
                 TurbulenceNoiseAnimationConfig.DEFAULT_MAX_DURATION_IN_MILLIS,
                 /* easeInDuration= */ 1350f,
                 /* easeOutDuration= */ 1350f,
                 getContext().getResources().getDisplayMetrics().density,
-                BlendMode.SCREEN,
-                /* onAnimationEnd= */ null,
                 /* lumaMatteBlendFactor= */ 0.26f,
-                /* lumaMatteOverallBrightness= */ 0.09f
+                /* lumaMatteOverallBrightness= */ 0.09f,
+                /* shouldInverseNoiseLuminosity= */ false
         );
     }
     private void clearButton(final ImageButton button) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
index 614261d..203096a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseControllerTest.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.EASE_OUT
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.MAIN
 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseController.Companion.AnimationState.NOT_PLAYING
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -47,7 +48,7 @@
         assertThat(turbulenceNoiseController.state).isEqualTo(NOT_PLAYING)
 
         fakeExecutor.execute {
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             assertThat(turbulenceNoiseController.state).isEqualTo(EASE_IN)
 
@@ -75,7 +76,7 @@
 
         fakeExecutor.execute {
             // Request another animation
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             assertThat(turbulenceNoiseController.state).isEqualTo(MAIN)
         }
@@ -89,7 +90,7 @@
             TurbulenceNoiseController(turbulenceNoiseView).also { it.state = MAIN }
 
         fakeExecutor.execute {
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             fakeSystemClock.advanceTime(config.maxDuration.toLong() / 2)
 
@@ -107,7 +108,7 @@
             TurbulenceNoiseController(turbulenceNoiseView).also { it.state = EASE_IN }
 
         fakeExecutor.execute {
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             fakeSystemClock.advanceTime(config.maxDuration.toLong() / 2)
 
@@ -128,7 +129,7 @@
         assertThat(turbulenceNoiseView.noiseConfig).isNull()
 
         fakeExecutor.execute {
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             assertThat(turbulenceNoiseController.state).isEqualTo(EASE_IN)
             assertThat(turbulenceNoiseView.visibility).isEqualTo(VISIBLE)
@@ -156,7 +157,7 @@
         val turbulenceNoiseController = TurbulenceNoiseController(turbulenceNoiseView)
 
         fakeExecutor.execute {
-            turbulenceNoiseController.play(config)
+            turbulenceNoiseController.play(SIMPLEX_NOISE, config)
 
             turbulenceNoiseController.updateNoiseColor(expectedColor)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
index 71bd511..549280a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseShaderTest.kt
@@ -18,6 +18,8 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE_FRACTAL
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -28,12 +30,12 @@
     private lateinit var turbulenceNoiseShader: TurbulenceNoiseShader
 
     @Test
-    fun compliesSimplexNoise() {
-        turbulenceNoiseShader = TurbulenceNoiseShader()
+    fun compilesSimplexNoise() {
+        turbulenceNoiseShader = TurbulenceNoiseShader(baseType = SIMPLEX_NOISE)
     }
 
     @Test
-    fun compliesFractalNoise() {
-        turbulenceNoiseShader = TurbulenceNoiseShader(useFractal = true)
+    fun compilesFractalNoise() {
+        turbulenceNoiseShader = TurbulenceNoiseShader(baseType = SIMPLEX_NOISE_FRACTAL)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
index ce7f2f4..953071c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/turbulencenoise/TurbulenceNoiseViewTest.kt
@@ -15,9 +15,12 @@
  */
 package com.android.systemui.surfaceeffects.turbulencenoise
 
+import android.graphics.Color
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE
+import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE_FRACTAL
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.time.FakeSystemClock
 import com.google.common.truth.Truth.assertThat
@@ -35,7 +38,8 @@
     @Test
     fun play_playsAnimation() {
         val config = TurbulenceNoiseAnimationConfig()
-        val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(SIMPLEX_NOISE, config)
         var onAnimationEndCalled = false
 
         fakeExecutor.execute {
@@ -50,7 +54,8 @@
     @Test
     fun playEaseIn_playsEaseInAnimation() {
         val config = TurbulenceNoiseAnimationConfig()
-        val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(SIMPLEX_NOISE, config)
         var onAnimationEndCalled = false
 
         fakeExecutor.execute {
@@ -65,7 +70,8 @@
     @Test
     fun playEaseOut_playsEaseOutAnimation() {
         val config = TurbulenceNoiseAnimationConfig()
-        val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(SIMPLEX_NOISE, config)
         var onAnimationEndCalled = false
 
         fakeExecutor.execute {
@@ -80,7 +86,8 @@
     @Test
     fun finish_animationPlaying_finishesAnimation() {
         val config = TurbulenceNoiseAnimationConfig()
-        val turbulenceNoiseView = TurbulenceNoiseView(context, null).also { it.applyConfig(config) }
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(SIMPLEX_NOISE, config)
         var onAnimationEndCalled = false
 
         fakeExecutor.execute {
@@ -94,4 +101,51 @@
             assertThat(turbulenceNoiseView.currentAnimator).isNull()
         }
     }
+
+    @Test
+    fun initShader_createsShaderCorrectly() {
+        val config = TurbulenceNoiseAnimationConfig()
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+
+        // To begin with, the shader is not initialized yet.
+        assertThat(turbulenceNoiseView.turbulenceNoiseShader).isNull()
+
+        turbulenceNoiseView.initShader(baseType = SIMPLEX_NOISE, config)
+
+        assertThat(turbulenceNoiseView.turbulenceNoiseShader).isNotNull()
+        assertThat(turbulenceNoiseView.turbulenceNoiseShader!!.baseType).isEqualTo(SIMPLEX_NOISE)
+    }
+
+    @Test
+    fun initShader_changesConfig_doesNotCreateNewShader() {
+        val config = TurbulenceNoiseAnimationConfig(color = Color.RED)
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(baseType = SIMPLEX_NOISE, config)
+
+        val shader = turbulenceNoiseView.turbulenceNoiseShader
+        assertThat(shader).isNotNull()
+
+        val newConfig = TurbulenceNoiseAnimationConfig(color = Color.GREEN)
+        turbulenceNoiseView.initShader(baseType = SIMPLEX_NOISE, newConfig)
+
+        val newShader = turbulenceNoiseView.turbulenceNoiseShader
+        assertThat(newShader).isNotNull()
+        assertThat(newShader).isEqualTo(shader)
+    }
+
+    @Test
+    fun initShader_changesBaseType_createsNewShader() {
+        val config = TurbulenceNoiseAnimationConfig()
+        val turbulenceNoiseView = TurbulenceNoiseView(context, null)
+        turbulenceNoiseView.initShader(baseType = SIMPLEX_NOISE, config)
+
+        val shader = turbulenceNoiseView.turbulenceNoiseShader
+        assertThat(shader).isNotNull()
+
+        turbulenceNoiseView.initShader(baseType = SIMPLEX_NOISE_FRACTAL, config)
+
+        val newShader = turbulenceNoiseView.turbulenceNoiseShader
+        assertThat(newShader).isNotNull()
+        assertThat(newShader).isNotEqualTo(shader)
+    }
 }