1 /* 2 * Copyright (C) 2024 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 17 package com.android.systemui.surfaceeffects.loadingeffect 18 19 import android.graphics.Paint 20 import android.graphics.RenderEffect 21 import android.testing.TestableLooper 22 import androidx.test.ext.junit.runners.AndroidJUnit4 23 import androidx.test.filters.SmallTest 24 import com.android.systemui.SysuiTestCase 25 import com.android.systemui.animation.AnimatorTestRule 26 import com.android.systemui.surfaceeffects.PaintDrawCallback 27 import com.android.systemui.surfaceeffects.RenderEffectDrawCallback 28 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseAnimationConfig 29 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseShader 30 import com.google.common.truth.Truth.assertThat 31 import org.junit.Rule 32 import org.junit.Test 33 import org.junit.runner.RunWith 34 35 @SmallTest 36 @RunWith(AndroidJUnit4::class) 37 @TestableLooper.RunWithLooper(setAsMainLooper = true) 38 class LoadingEffectTest : SysuiTestCase() { 39 40 @get:Rule val animatorTestRule = AnimatorTestRule(this) 41 42 @Test play_paintCallback_triggersDrawCallbacknull43 fun play_paintCallback_triggersDrawCallback() { 44 var paintFromCallback: Paint? = null 45 val drawCallback = 46 object : PaintDrawCallback { 47 override fun onDraw(paint: Paint) { 48 paintFromCallback = paint 49 } 50 } 51 val loadingEffect = 52 LoadingEffect( 53 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 54 TurbulenceNoiseAnimationConfig(), 55 paintCallback = drawCallback, 56 animationStateChangedCallback = null 57 ) 58 59 assertThat(paintFromCallback).isNull() 60 61 loadingEffect.play() 62 animatorTestRule.advanceTimeBy(500L) 63 64 assertThat(paintFromCallback).isNotNull() 65 } 66 67 @Test play_renderEffectCallback_triggersDrawCallbacknull68 fun play_renderEffectCallback_triggersDrawCallback() { 69 var renderEffectFromCallback: RenderEffect? = null 70 val drawCallback = 71 object : RenderEffectDrawCallback { 72 override fun onDraw(renderEffect: RenderEffect) { 73 renderEffectFromCallback = renderEffect 74 } 75 } 76 val loadingEffect = 77 LoadingEffect( 78 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 79 TurbulenceNoiseAnimationConfig(), 80 renderEffectCallback = drawCallback, 81 animationStateChangedCallback = null 82 ) 83 84 assertThat(renderEffectFromCallback).isNull() 85 86 loadingEffect.play() 87 animatorTestRule.advanceTimeBy(500L) 88 89 assertThat(renderEffectFromCallback).isNotNull() 90 } 91 92 @Test play_animationStateChangesInOrdernull93 fun play_animationStateChangesInOrder() { 94 val config = TurbulenceNoiseAnimationConfig() 95 val states = mutableListOf(LoadingEffect.AnimationState.NOT_PLAYING) 96 val stateChangedCallback = 97 object : LoadingEffect.AnimationStateChangedCallback { 98 override fun onStateChanged( 99 oldState: LoadingEffect.AnimationState, 100 newState: LoadingEffect.AnimationState 101 ) { 102 states.add(newState) 103 } 104 } 105 val drawCallback = 106 object : PaintDrawCallback { 107 override fun onDraw(paint: Paint) {} 108 } 109 val loadingEffect = 110 LoadingEffect( 111 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 112 config, 113 paintCallback = drawCallback, 114 stateChangedCallback 115 ) 116 117 loadingEffect.play() 118 119 // Execute all the animators by advancing each duration with some buffer. 120 animatorTestRule.advanceAnimationDuration(config.easeInDuration.toLong()) 121 animatorTestRule.advanceAnimationDuration(config.maxDuration.toLong()) 122 animatorTestRule.advanceAnimationDuration(config.easeOutDuration.toLong()) 123 animatorTestRule.advanceTimeBy(500) 124 125 assertThat(states) 126 .containsExactly( 127 LoadingEffect.AnimationState.NOT_PLAYING, 128 LoadingEffect.AnimationState.EASE_IN, 129 LoadingEffect.AnimationState.MAIN, 130 LoadingEffect.AnimationState.EASE_OUT, 131 LoadingEffect.AnimationState.NOT_PLAYING 132 ) 133 } 134 135 @Test play_alreadyPlaying_playsOnlyOncenull136 fun play_alreadyPlaying_playsOnlyOnce() { 137 val config = TurbulenceNoiseAnimationConfig() 138 var numPlay = 0 139 val stateChangedCallback = 140 object : LoadingEffect.AnimationStateChangedCallback { 141 override fun onStateChanged( 142 oldState: LoadingEffect.AnimationState, 143 newState: LoadingEffect.AnimationState 144 ) { 145 if ( 146 oldState == LoadingEffect.AnimationState.NOT_PLAYING && 147 newState == LoadingEffect.AnimationState.EASE_IN 148 ) { 149 numPlay++ 150 } 151 } 152 } 153 val drawCallback = 154 object : PaintDrawCallback { 155 override fun onDraw(paint: Paint) {} 156 } 157 val loadingEffect = 158 LoadingEffect( 159 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 160 config, 161 paintCallback = drawCallback, 162 stateChangedCallback 163 ) 164 165 assertThat(numPlay).isEqualTo(0) 166 167 loadingEffect.play() 168 loadingEffect.play() 169 loadingEffect.play() 170 loadingEffect.play() 171 loadingEffect.play() 172 173 assertThat(numPlay).isEqualTo(1) 174 } 175 176 @Test finish_finishesLoadingEffectnull177 fun finish_finishesLoadingEffect() { 178 val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f) 179 val drawCallback = 180 object : PaintDrawCallback { 181 override fun onDraw(loadingPaint: Paint) {} 182 } 183 var isFinished = false 184 val stateChangedCallback = 185 object : LoadingEffect.AnimationStateChangedCallback { 186 override fun onStateChanged( 187 oldState: LoadingEffect.AnimationState, 188 newState: LoadingEffect.AnimationState 189 ) { 190 if ( 191 oldState == LoadingEffect.AnimationState.EASE_OUT && 192 newState == LoadingEffect.AnimationState.NOT_PLAYING 193 ) { 194 isFinished = true 195 } 196 } 197 } 198 val loadingEffect = 199 LoadingEffect( 200 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 201 config, 202 paintCallback = drawCallback, 203 stateChangedCallback 204 ) 205 206 assertThat(isFinished).isFalse() 207 208 loadingEffect.play() 209 animatorTestRule.advanceAnimationDuration(config.easeInDuration.toLong() + 500L) 210 211 assertThat(isFinished).isFalse() 212 213 loadingEffect.finish() 214 animatorTestRule.advanceAnimationDuration(config.easeOutDuration.toLong() + 500L) 215 216 assertThat(isFinished).isTrue() 217 } 218 219 @Test finish_notMainState_hasNoEffectnull220 fun finish_notMainState_hasNoEffect() { 221 val config = TurbulenceNoiseAnimationConfig(maxDuration = 1000f) 222 val drawCallback = 223 object : PaintDrawCallback { 224 override fun onDraw(paint: Paint) {} 225 } 226 var isFinished = false 227 val stateChangedCallback = 228 object : LoadingEffect.AnimationStateChangedCallback { 229 override fun onStateChanged( 230 oldState: LoadingEffect.AnimationState, 231 newState: LoadingEffect.AnimationState 232 ) { 233 if ( 234 oldState == LoadingEffect.AnimationState.MAIN && 235 newState == LoadingEffect.AnimationState.NOT_PLAYING 236 ) { 237 isFinished = true 238 } 239 } 240 } 241 val loadingEffect = 242 LoadingEffect( 243 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 244 config, 245 paintCallback = drawCallback, 246 stateChangedCallback 247 ) 248 249 assertThat(isFinished).isFalse() 250 251 loadingEffect.finish() 252 253 assertThat(isFinished).isFalse() 254 } 255 256 @Test getNoiseOffset_returnsNoiseOffsetnull257 fun getNoiseOffset_returnsNoiseOffset() { 258 val expectedNoiseOffset = arrayOf(0.1f, 0.2f, 0.3f) 259 val config = 260 TurbulenceNoiseAnimationConfig( 261 noiseOffsetX = expectedNoiseOffset[0], 262 noiseOffsetY = expectedNoiseOffset[1], 263 noiseOffsetZ = expectedNoiseOffset[2] 264 ) 265 val drawCallback = 266 object : PaintDrawCallback { 267 override fun onDraw(paint: Paint) {} 268 } 269 val loadingEffect = 270 LoadingEffect( 271 baseType = TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE, 272 config, 273 paintCallback = drawCallback, 274 animationStateChangedCallback = null 275 ) 276 277 assertThat(loadingEffect.getNoiseOffset()).isEqualTo(expectedNoiseOffset) 278 } 279 } 280