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