1 /*
2  * Copyright (C) 2023 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.statusbar.events
18 
19 import android.annotation.IntDef
20 import androidx.core.animation.Animator
21 import androidx.core.animation.AnimatorSet
22 import androidx.core.animation.PathInterpolator
23 import com.android.systemui.Dumpable
24 import com.android.systemui.statusbar.policy.CallbackController
25 
26 interface SystemStatusAnimationScheduler :
27         CallbackController<SystemStatusAnimationCallback>, Dumpable {
28 
29     @SystemAnimationState fun getAnimationState(): Int
30 
31     fun onStatusEvent(event: StatusEvent)
32 
33     fun removePersistentDot()
34 }
35 
36 /**
37  * The general idea here is that this scheduler will run two value animators, and provide
38  * animator-like callbacks for each kind of animation. The SystemChrome animation is expected to
39  * create space for the chip animation to display. This means hiding the system elements in the
40  * status bar and keyguard.
41  *
42  * The value animators themselves are simple animators from 0.0 to 1.0. Listeners can apply any
43  * interpolation they choose but realistically these are most likely to be simple alpha transitions
44  */
45 interface SystemStatusAnimationCallback {
46     /** Implement this method to return an [Animator] or [AnimatorSet] that presents the chip */
47     fun onSystemEventAnimationBegin(): Animator? { return null }
48     /** Implement this method to return an [Animator] or [AnimatorSet] that hides the chip */
49     fun onSystemEventAnimationFinish(hasPersistentDot: Boolean): Animator? { return null }
50 
51     // Best method name, change my mind
52     @JvmDefault
53     fun onSystemStatusAnimationTransitionToPersistentDot(contentDescription: String?): Animator? {
54         return null
55     }
56     @JvmDefault fun onHidePersistentDot(): Animator? { return null }
57 }
58 
59 
60 /**
61  * Animation state IntDef
62  */
63 @Retention(AnnotationRetention.SOURCE)
64 @IntDef(
65         value = [
66             IDLE,
67             ANIMATION_QUEUED,
68             ANIMATING_IN,
69             RUNNING_CHIP_ANIM,
70             ANIMATING_OUT,
71             SHOWING_PERSISTENT_DOT
72         ]
73 )
74 annotation class SystemAnimationState
75 
76 /** No animation is in progress */
77 @SystemAnimationState const val IDLE = 0
78 /** An animation is queued, and awaiting the debounce period */
79 const val ANIMATION_QUEUED = 1
80 /** System is animating out, and chip is animating in */
81 const val ANIMATING_IN = 2
82 /** Chip has animated in and is awaiting exit animation, and optionally playing its own animation */
83 const val RUNNING_CHIP_ANIM = 3
84 /** Chip is animating away and system is animating back */
85 const val ANIMATING_OUT = 4
86 /** Chip has animated away, and the persistent dot is showing */
87 const val SHOWING_PERSISTENT_DOT = 5
88 
89 /** Commonly-needed interpolators can go here */
90 @JvmField val STATUS_BAR_X_MOVE_OUT = PathInterpolator(0.33f, 0f, 0f, 1f)
91 @JvmField val STATUS_BAR_X_MOVE_IN = PathInterpolator(0f, 0f, 0f, 1f)
92 /**
93  * Status chip animation to dot have multiple stages of motion, the _1 and _2 interpolators should
94  * be used in succession
95  */
96 val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_1 = PathInterpolator(0.44f, 0f, 0.25f, 1f)
97 val STATUS_CHIP_WIDTH_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0.26f, 1f)
98 val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_1 = PathInterpolator(0.4f, 0f, 0.17f, 1f)
99 val STATUS_CHIP_HEIGHT_TO_DOT_KEYFRAME_2 = PathInterpolator(0.3f, 0f, 0f, 1f)
100 val STATUS_CHIP_MOVE_TO_DOT = PathInterpolator(0f, 0f, 0.05f, 1f)
101 
102 internal const val DEBOUNCE_DELAY = 100L
103 
104 /**
105  * The total time spent on the chip animation is 1500ms, broken up into 3 sections:
106  * - 500ms to animate the chip in (including animating system icons away)
107  * - 500ms holding the chip on screen
108  * - 500ms to animate the chip away (and system icons back)
109  */
110 internal const val APPEAR_ANIMATION_DURATION = 500L
111 internal const val DISPLAY_LENGTH = 3000L
112 internal const val DISAPPEAR_ANIMATION_DURATION = 500L
113 
114 internal const val MIN_UPTIME: Long = 5 * 1000