1 /*
2  * Copyright (C) 2014 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.phone;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.os.Handler;
22 import android.util.Log;
23 
24 import com.android.systemui.doze.DozeHost;
25 import com.android.systemui.doze.DozeLog;
26 
27 /**
28  * Controller which handles all the doze animations of the scrims.
29  */
30 public class DozeScrimController {
31     private static final String TAG = "DozeScrimController";
32     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
33 
34     private final DozeParameters mDozeParameters;
35     private final Handler mHandler = new Handler();
36     private final ScrimController mScrimController;
37 
38     private boolean mDozing;
39     private DozeHost.PulseCallback mPulseCallback;
40     private int mPulseReason;
41     private boolean mFullyPulsing;
42 
43     private final ScrimController.Callback mScrimCallback = new ScrimController.Callback() {
44         @Override
45         public void onDisplayBlanked() {
46             if (DEBUG) {
47                 Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
48                         + DozeLog.pulseReasonToString(mPulseReason));
49             }
50             if (!mDozing) {
51                 return;
52             }
53 
54             // Signal that the pulse is ready to turn the screen on and draw.
55             pulseStarted();
56         }
57 
58         @Override
59         public void onFinished() {
60             if (DEBUG) {
61                 Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
62             }
63             if (!mDozing) {
64                 return;
65             }
66             mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
67             mHandler.postDelayed(mPulseOutExtended,
68                     mDozeParameters.getPulseVisibleDurationExtended());
69             mFullyPulsing = true;
70         }
71 
72         /**
73          * Transition was aborted before it was over.
74          */
75         @Override
76         public void onCancelled() {
77             pulseFinished();
78         }
79     };
80 
DozeScrimController(ScrimController scrimController, Context context, DozeParameters dozeParameters)81     public DozeScrimController(ScrimController scrimController, Context context,
82             DozeParameters dozeParameters) {
83         mScrimController = scrimController;
84         mDozeParameters = dozeParameters;
85     }
86 
setDozing(boolean dozing)87     public void setDozing(boolean dozing) {
88         if (mDozing == dozing) return;
89         mDozing = dozing;
90         if (!mDozing) {
91             cancelPulsing();
92         }
93     }
94 
95     /** When dozing, fade screen contents in and out using the front scrim. */
pulse(@onNull DozeHost.PulseCallback callback, int reason)96     public void pulse(@NonNull DozeHost.PulseCallback callback, int reason) {
97         if (callback == null) {
98             throw new IllegalArgumentException("callback must not be null");
99         }
100 
101         if (!mDozing || mPulseCallback != null) {
102             if (DEBUG) {
103                 Log.d(TAG, "Pulse supressed. Dozing: " + mDozeParameters + " had callback? "
104                         + (mPulseCallback != null));
105             }
106             // Pulse suppressed.
107             callback.onPulseFinished();
108             return;
109         }
110 
111         // Begin pulse. Note that it's very important that the pulse finished callback
112         // be invoked when we're done so that the caller can drop the pulse wakelock.
113         mPulseCallback = callback;
114         mPulseReason = reason;
115 
116         mScrimController.transitionTo(ScrimState.PULSING, mScrimCallback);
117     }
118 
pulseOutNow()119     public void pulseOutNow() {
120         if (mPulseCallback != null && mFullyPulsing) {
121             mPulseOut.run();
122         }
123     }
124 
isPulsing()125     public boolean isPulsing() {
126         return mPulseCallback != null;
127     }
128 
isDozing()129     public boolean isDozing() {
130         return mDozing;
131     }
132 
extendPulse()133     public void extendPulse() {
134         mHandler.removeCallbacks(mPulseOut);
135     }
136 
cancelPulsing()137     private void cancelPulsing() {
138         if (mPulseCallback != null) {
139             if (DEBUG) Log.d(TAG, "Cancel pulsing");
140             mFullyPulsing = false;
141             mHandler.removeCallbacks(mPulseOut);
142             mHandler.removeCallbacks(mPulseOutExtended);
143             pulseFinished();
144         }
145     }
146 
pulseStarted()147     private void pulseStarted() {
148         DozeLog.tracePulseStart(mPulseReason);
149         if (mPulseCallback != null) {
150             mPulseCallback.onPulseStarted();
151         }
152     }
153 
pulseFinished()154     private void pulseFinished() {
155         DozeLog.tracePulseFinish();
156         if (mPulseCallback != null) {
157             mPulseCallback.onPulseFinished();
158             mPulseCallback = null;
159         }
160     }
161 
162     private final Runnable mPulseOutExtended = new Runnable() {
163         @Override
164         public void run() {
165             mHandler.removeCallbacks(mPulseOut);
166             mPulseOut.run();
167         }
168     };
169 
170     private final Runnable mPulseOut = new Runnable() {
171         @Override
172         public void run() {
173             mFullyPulsing = false;
174             mHandler.removeCallbacks(mPulseOut);
175             mHandler.removeCallbacks(mPulseOutExtended);
176             if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
177             if (!mDozing) return;
178             mScrimController.transitionTo(ScrimState.AOD,
179                     new ScrimController.Callback() {
180                         @Override
181                         public void onDisplayBlanked() {
182                             pulseFinished();
183                         }
184                     });
185         }
186     };
187 }