1 /*
2  * Copyright (C) 2019 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.glwallpaper;
18 
19 import android.animation.Animator;
20 import android.animation.AnimatorListenerAdapter;
21 import android.animation.ValueAnimator;
22 
23 import com.android.systemui.Interpolators;
24 
25 /**
26  * Use ValueAnimator and appropriate interpolator to control the progress of reveal transition.
27  * The transition will happen while getting awake and quit events.
28  */
29 class ImageRevealHelper {
30     private static final String TAG = ImageRevealHelper.class.getSimpleName();
31     private static final float MAX_REVEAL = 0f;
32     private static final float MIN_REVEAL = 1f;
33 
34     private final ValueAnimator mAnimator;
35     private final RevealStateListener mRevealListener;
36     private float mReveal = MAX_REVEAL;
37     private boolean mAwake = false;
38 
ImageRevealHelper(RevealStateListener listener)39     ImageRevealHelper(RevealStateListener listener) {
40         mRevealListener = listener;
41         mAnimator = ValueAnimator.ofFloat();
42         mAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
43         mAnimator.addUpdateListener(animator -> {
44             mReveal = (float) animator.getAnimatedValue();
45             if (mRevealListener != null) {
46                 mRevealListener.onRevealStateChanged();
47             }
48         });
49         mAnimator.addListener(new AnimatorListenerAdapter() {
50             private boolean mIsCanceled;
51 
52             @Override
53             public void onAnimationCancel(Animator animation) {
54                 mIsCanceled = true;
55             }
56 
57             @Override
58             public void onAnimationEnd(Animator animation) {
59                 if (!mIsCanceled && mRevealListener != null) {
60                     mRevealListener.onRevealEnd();
61                 }
62                 mIsCanceled = false;
63             }
64 
65             @Override
66             public void onAnimationStart(Animator animation) {
67                 if (mRevealListener != null) {
68                     mRevealListener.onRevealStart(true /* animate */);
69                 }
70             }
71         });
72     }
73 
animate()74     private void animate() {
75         mAnimator.cancel();
76         mAnimator.setFloatValues(mReveal, mAwake ? MAX_REVEAL : MIN_REVEAL);
77         mAnimator.start();
78     }
79 
getReveal()80     public float getReveal() {
81         return mReveal;
82     }
83 
updateAwake(boolean awake, long duration)84     void updateAwake(boolean awake, long duration) {
85         mAwake = awake;
86         mAnimator.setDuration(duration);
87         if (duration == 0) {
88             // We are transiting from home to aod or aod to home directly,
89             // we don't need to do transition in these cases.
90             mReveal = mAwake ? MAX_REVEAL : MIN_REVEAL;
91             mRevealListener.onRevealStart(false /* animate */);
92             mRevealListener.onRevealStateChanged();
93             mRevealListener.onRevealEnd();
94         } else {
95             animate();
96         }
97     }
98 
99     /**
100      * A listener to trace value changes of reveal.
101      */
102     public interface RevealStateListener {
103 
104         /**
105          * Called back while reveal status changes.
106          */
onRevealStateChanged()107         void onRevealStateChanged();
108 
109         /**
110          * Called back while reveal starts.
111          */
onRevealStart(boolean animate)112         void onRevealStart(boolean animate);
113 
114         /**
115          * Called back while reveal ends.
116          */
onRevealEnd()117         void onRevealEnd();
118     }
119 }
120