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 cancelPulsing()152 private void cancelPulsing() { 153 if (mPulseCallback != null) { 154 if (DEBUG) Log.d(TAG, "Cancel pulsing"); 155 mFullyPulsing = false; 156 mHandler.removeCallbacks(mPulseOut); 157 mHandler.removeCallbacks(mPulseOutExtended); 158 pulseFinished(); 159 } 160 } 161 pulseStarted()162 private void pulseStarted() { 163 DozeLog.tracePulseStart(mPulseReason); 164 if (mPulseCallback != null) { 165 mPulseCallback.onPulseStarted(); 166 } 167 } 168 pulseFinished()169 private void pulseFinished() { 170 DozeLog.tracePulseFinish(); 171 if (mPulseCallback != null) { 172 mPulseCallback.onPulseFinished(); 173 mPulseCallback = null; 174 } 175 } 176 177 private final Runnable mPulseOutExtended = new Runnable() { 178 @Override 179 public void run() { 180 mHandler.removeCallbacks(mPulseOut); 181 mPulseOut.run(); 182 } 183 }; 184 185 private final Runnable mPulseOut = new Runnable() { 186 @Override 187 public void run() { 188 mFullyPulsing = false; 189 mHandler.removeCallbacks(mPulseOut); 190 mHandler.removeCallbacks(mPulseOutExtended); 191 if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing); 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 setDozing(isDozing); 209 } 210 }