1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.systemui.surfaceeffects.turbulencenoise
17 
18 import android.view.View
19 import androidx.annotation.VisibleForTesting
20 
21 /** Plays [TurbulenceNoiseView] in ease-in, main (no easing), and ease-out order. */
22 class TurbulenceNoiseController(private val turbulenceNoiseView: TurbulenceNoiseView) {
23 
24     companion object {
25         /**
26          * States of the turbulence noise animation.
27          *
28          * <p>The state is designed to be follow the order below: [AnimationState.EASE_IN],
29          * [AnimationState.MAIN], [AnimationState.EASE_OUT].
30          */
31         enum class AnimationState {
32             EASE_IN,
33             MAIN,
34             EASE_OUT,
35             NOT_PLAYING
36         }
37     }
38 
39     /** Current state of the animation. */
40     @VisibleForTesting
41     var state: AnimationState = AnimationState.NOT_PLAYING
42         set(value) {
43             field = value
44             if (state == AnimationState.NOT_PLAYING) {
45                 turbulenceNoiseView.visibility = View.INVISIBLE
46                 turbulenceNoiseView.clearConfig()
47             } else {
48                 turbulenceNoiseView.visibility = View.VISIBLE
49             }
50         }
51 
52     init {
53         turbulenceNoiseView.visibility = View.INVISIBLE
54     }
55 
56     /** Updates the color of the noise. */
updateNoiseColornull57     fun updateNoiseColor(color: Int) {
58         if (state == AnimationState.NOT_PLAYING) {
59             return
60         }
61         turbulenceNoiseView.updateColor(color)
62     }
63 
64     /**
65      * Plays [TurbulenceNoiseView] with the given config.
66      *
67      * <p>It plays ease-in, main, and ease-out animations in sequence.
68      */
playnull69     fun play(
70         baseType: TurbulenceNoiseShader.Companion.Type,
71         config: TurbulenceNoiseAnimationConfig
72     ) {
73         if (state != AnimationState.NOT_PLAYING) {
74             return // Ignore if any of the animation is playing.
75         }
76 
77         turbulenceNoiseView.initShader(baseType, config)
78         playEaseInAnimation()
79     }
80 
81     // TODO(b/237282226): Support force finish.
82     /** Finishes the main animation, which triggers the ease-out animation. */
finishnull83     fun finish() {
84         if (state == AnimationState.MAIN) {
85             turbulenceNoiseView.finish(nextAnimation = this::playEaseOutAnimation)
86         }
87     }
88 
playEaseInAnimationnull89     private fun playEaseInAnimation() {
90         if (state != AnimationState.NOT_PLAYING) {
91             return
92         }
93         state = AnimationState.EASE_IN
94 
95         turbulenceNoiseView.playEaseIn(this::playMainAnimation)
96     }
97 
playMainAnimationnull98     private fun playMainAnimation() {
99         if (state != AnimationState.EASE_IN) {
100             return
101         }
102         state = AnimationState.MAIN
103 
104         turbulenceNoiseView.play(this::playEaseOutAnimation)
105     }
106 
playEaseOutAnimationnull107     private fun playEaseOutAnimation() {
108         if (state != AnimationState.MAIN) {
109             return
110         }
111         state = AnimationState.EASE_OUT
112 
113         turbulenceNoiseView.playEaseOut(onAnimationEnd = { state = AnimationState.NOT_PLAYING })
114     }
115 }
116