• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.os.Handler;
21 
22 import com.android.internal.annotations.VisibleForTesting;
23 import com.android.systemui.dagger.SysUISingleton;
24 import com.android.systemui.doze.DozeHost;
25 import com.android.systemui.doze.DozeLog;
26 import com.android.systemui.plugins.statusbar.StatusBarStateController;
27 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
28 import com.android.systemui.scene.shared.flag.SceneContainerFlag;
29 
30 import javax.inject.Inject;
31 
32 /**
33  * Controller which handles all the doze animations of the scrims.
34  */
35 @SysUISingleton
36 public class DozeScrimController implements StateListener {
37     private final DozeLog mDozeLog;
38     private final DozeParameters mDozeParameters;
39     private final Handler mHandler = new Handler();
40 
41     private boolean mDozing;
42     private DozeHost.PulseCallback mPulseCallback;
43     private int mPulseReason;
44 
45     private final ScrimController.Callback mScrimCallback = new ScrimController.Callback() {
46         @Override
47         public void onDisplayBlanked() {
48             if (!mDozing) {
49                 mDozeLog.tracePulseDropped("onDisplayBlanked - not dozing");
50                 return;
51             }
52 
53             if (mPulseCallback != null) {
54                 // Signal that the pulse is ready to turn the screen on and draw.
55                 mDozeLog.tracePulseStart(mPulseReason);
56                 mPulseCallback.onPulseStarted();
57             }
58         }
59 
60         @Override
61         public void onFinished() {
62             mDozeLog.tracePulseEvent("scrimCallback-onFinished", mDozing, mPulseReason);
63 
64             if (!mDozing) {
65                 return;
66             }
67             // Notifications should time out on their own.  Pulses due to notifications should
68             // instead be managed externally based off the notification's lifetime.
69             // Dock also controls the time out by self.
70             if (mPulseReason != DozeLog.PULSE_REASON_NOTIFICATION
71                     && mPulseReason != DozeLog.PULSE_REASON_DOCKING) {
72                 mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration());
73                 mHandler.postDelayed(mPulseOutExtended,
74                         mDozeParameters.getPulseVisibleDurationExtended());
75             }
76         }
77 
78         /**
79          * Transition was aborted before it was over.
80          */
81         @Override
82         public void onCancelled() {
83             pulseFinished();
84         }
85     };
86 
87     @Inject
DozeScrimController( DozeParameters dozeParameters, DozeLog dozeLog, StatusBarStateController statusBarStateController )88     public DozeScrimController(
89             DozeParameters dozeParameters,
90             DozeLog dozeLog,
91             StatusBarStateController statusBarStateController
92     ) {
93         mDozeParameters = dozeParameters;
94         // Never expected to be destroyed
95         statusBarStateController.addCallback(this);
96         mDozeLog = dozeLog;
97     }
98 
99     @VisibleForTesting
setDozing(boolean dozing)100     public void setDozing(boolean dozing) {
101         if (mDozing == dozing) return;
102         mDozing = dozing;
103         if (!mDozing) {
104             cancelPulsing();
105         }
106     }
107 
108     /** When dozing, fade screen contents in and out using the front scrim. */
pulse(@onNull DozeHost.PulseCallback callback, int reason)109     public void pulse(@NonNull DozeHost.PulseCallback callback, int reason) {
110         if (callback == null) {
111             throw new IllegalArgumentException("callback must not be null");
112         }
113 
114         if (!mDozing || mPulseCallback != null) {
115             // Pulse suppressed.
116             callback.onPulseFinished();
117             if (!mDozing) {
118                 mDozeLog.tracePulseDropped("pulse - device isn't dozing");
119             } else {
120                 mDozeLog.tracePulseDropped("pulse - already has pulse callback mPulseCallback="
121                         + mPulseCallback);
122             }
123             return;
124         }
125 
126         // Begin pulse. Note that it's very important that the pulse finished callback
127         // be invoked when we're done so that the caller can drop the pulse wakelock.
128         if (SceneContainerFlag.isEnabled()) {
129             // ScrimController.Callback#onDisplayBlanked is no longer triggered when flexiglass is
130             // on, but we still need to signal that pulsing has started.
131             callback.onPulseStarted();
132         }
133         mPulseCallback = callback;
134         mPulseReason = reason;
135     }
136 
pulseOutNow()137     public void pulseOutNow() {
138         mPulseOut.run();
139     }
140 
isPulsing()141     public boolean isPulsing() {
142         return mPulseCallback != null;
143     }
144 
isDozing()145     public boolean isDozing() {
146         return mDozing;
147     }
148 
extendPulse()149     public void extendPulse() {
150         mHandler.removeCallbacks(mPulseOut);
151     }
152 
153     /**
154      * When pulsing, cancel any timeouts that would take you out of the pulsing state.
155      */
cancelPendingPulseTimeout()156     public void cancelPendingPulseTimeout() {
157         mHandler.removeCallbacks(mPulseOut);
158         mHandler.removeCallbacks(mPulseOutExtended);
159     }
160 
cancelPulsing()161     private void cancelPulsing() {
162         if (mPulseCallback != null) {
163             mDozeLog.tracePulseEvent("cancel", mDozing, mPulseReason);
164             mHandler.removeCallbacks(mPulseOut);
165             mHandler.removeCallbacks(mPulseOutExtended);
166             pulseFinished();
167         }
168     }
169 
pulseFinished()170     private void pulseFinished() {
171         if (mPulseCallback != null) {
172             mDozeLog.tracePulseFinish();
173             mPulseCallback.onPulseFinished();
174             mPulseCallback = null;
175         }
176     }
177 
178     private final Runnable mPulseOutExtended = new Runnable() {
179         @Override
180         public void run() {
181             mHandler.removeCallbacks(mPulseOut);
182             mPulseOut.run();
183         }
184     };
185 
186     private final Runnable mPulseOut = new Runnable() {
187         @Override
188         public void run() {
189             mHandler.removeCallbacks(mPulseOut);
190             mHandler.removeCallbacks(mPulseOutExtended);
191             mDozeLog.tracePulseEvent("out", mDozing, mPulseReason);
192             if (!mDozing) return;
193             pulseFinished();
194         }
195     };
196 
getScrimCallback()197     public ScrimController.Callback getScrimCallback() {
198         return mScrimCallback;
199     }
200 
201     @Override
onStateChanged(int newState)202     public void onStateChanged(int newState) {
203         // don't care
204     }
205 
206     @Override
onDozingChanged(boolean isDozing)207     public void onDozingChanged(boolean isDozing) {
208         if (mDozing != isDozing) {
209             mDozeLog.traceDozingChanged(isDozing);
210         }
211 
212         setDozing(isDozing);
213     }
214 }