1 /*
2  * Copyright (C) 2021 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.unfold.progress
17 
18 import android.animation.Animator
19 import android.animation.ObjectAnimator
20 import android.util.FloatProperty
21 import com.android.systemui.unfold.UnfoldTransitionProgressProvider
22 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
23 import com.android.systemui.unfold.updates.FOLD_UPDATE_FINISH_CLOSED
24 import com.android.systemui.unfold.updates.FoldStateProvider
25 import com.android.systemui.unfold.updates.FoldStateProvider.FoldUpdate
26 import javax.inject.Inject
27 
28 /** Emits animation progress with fixed timing after unfolding */
29 internal class FixedTimingTransitionProgressProvider
30 @Inject
31 constructor(private val foldStateProvider: FoldStateProvider) :
32     UnfoldTransitionProgressProvider, FoldStateProvider.FoldUpdatesListener {
33 
34     private val animatorListener = AnimatorListener()
35     private val animator =
<lambda>null36         ObjectAnimator.ofFloat(this, AnimationProgressProperty, 0f, 1f).apply {
37             duration = TRANSITION_TIME_MILLIS
38             addListener(animatorListener)
39         }
40 
41     private var transitionProgress: Float = 0.0f
42         set(value) {
<lambda>null43             listeners.forEach { it.onTransitionProgress(value) }
44             field = value
45         }
46 
47     private val listeners: MutableList<TransitionProgressListener> = mutableListOf()
48 
49     init {
50         foldStateProvider.addCallback(this)
51         foldStateProvider.start()
52     }
53 
destroynull54     override fun destroy() {
55         animator.cancel()
56         foldStateProvider.removeCallback(this)
57         foldStateProvider.stop()
58     }
59 
onFoldUpdatenull60     override fun onFoldUpdate(@FoldUpdate update: Int) {
61         if (update == FOLD_UPDATE_FINISH_CLOSED) {
62              animator.cancel()
63         }
64     }
65 
onUnfoldedScreenAvailablenull66     override fun onUnfoldedScreenAvailable() {
67         animator.start()
68     }
69 
addCallbacknull70     override fun addCallback(listener: TransitionProgressListener) {
71         listeners.add(listener)
72     }
73 
removeCallbacknull74     override fun removeCallback(listener: TransitionProgressListener) {
75         listeners.remove(listener)
76     }
77 
78     private object AnimationProgressProperty :
79         FloatProperty<FixedTimingTransitionProgressProvider>("animation_progress") {
80 
setValuenull81         override fun setValue(provider: FixedTimingTransitionProgressProvider, value: Float) {
82             provider.transitionProgress = value
83         }
84 
getnull85         override fun get(provider: FixedTimingTransitionProgressProvider): Float =
86             provider.transitionProgress
87     }
88 
89     private inner class AnimatorListener : Animator.AnimatorListener {
90 
91         override fun onAnimationStart(animator: Animator) {
92             listeners.forEach { it.onTransitionStarted() }
93             listeners.forEach { it.onTransitionFinishing() }
94         }
95 
96         override fun onAnimationEnd(animator: Animator) {
97             listeners.forEach { it.onTransitionFinished() }
98         }
99 
100         override fun onAnimationRepeat(animator: Animator) {}
101 
102         override fun onAnimationCancel(animator: Animator) {}
103     }
104 
105     private companion object {
106         private const val TRANSITION_TIME_MILLIS = 400L
107     }
108 }
109