| /* |
| * Copyright (C) 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License |
| */ |
| |
| package com.android.systemui.statusbar.phone; |
| |
| import android.annotation.NonNull; |
| import android.os.Handler; |
| |
| import com.android.internal.annotations.VisibleForTesting; |
| import com.android.systemui.dagger.SysUISingleton; |
| import com.android.systemui.doze.DozeHost; |
| import com.android.systemui.doze.DozeLog; |
| import com.android.systemui.plugins.statusbar.StatusBarStateController; |
| import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; |
| |
| import javax.inject.Inject; |
| |
| /** |
| * Controller which handles all the doze animations of the scrims. |
| */ |
| @SysUISingleton |
| public class DozeScrimController implements StateListener { |
| private final DozeLog mDozeLog; |
| private final DozeParameters mDozeParameters; |
| private final Handler mHandler = new Handler(); |
| |
| private boolean mDozing; |
| private DozeHost.PulseCallback mPulseCallback; |
| private int mPulseReason; |
| |
| private final ScrimController.Callback mScrimCallback = new ScrimController.Callback() { |
| @Override |
| public void onDisplayBlanked() { |
| if (!mDozing) { |
| mDozeLog.tracePulseDropped("onDisplayBlanked - not dozing"); |
| return; |
| } |
| |
| if (mPulseCallback != null) { |
| // Signal that the pulse is ready to turn the screen on and draw. |
| mDozeLog.tracePulseStart(mPulseReason); |
| mPulseCallback.onPulseStarted(); |
| } |
| } |
| |
| @Override |
| public void onFinished() { |
| mDozeLog.tracePulseEvent("scrimCallback-onFinished", mDozing, mPulseReason); |
| |
| if (!mDozing) { |
| return; |
| } |
| // Notifications should time out on their own. Pulses due to notifications should |
| // instead be managed externally based off the notification's lifetime. |
| // Dock also controls the time out by self. |
| if (mPulseReason != DozeLog.PULSE_REASON_NOTIFICATION |
| && mPulseReason != DozeLog.PULSE_REASON_DOCKING) { |
| mHandler.postDelayed(mPulseOut, mDozeParameters.getPulseVisibleDuration()); |
| mHandler.postDelayed(mPulseOutExtended, |
| mDozeParameters.getPulseVisibleDurationExtended()); |
| } |
| } |
| |
| /** |
| * Transition was aborted before it was over. |
| */ |
| @Override |
| public void onCancelled() { |
| pulseFinished(); |
| } |
| }; |
| |
| @Inject |
| public DozeScrimController( |
| DozeParameters dozeParameters, |
| DozeLog dozeLog, |
| StatusBarStateController statusBarStateController |
| ) { |
| mDozeParameters = dozeParameters; |
| // Never expected to be destroyed |
| statusBarStateController.addCallback(this); |
| mDozeLog = dozeLog; |
| } |
| |
| @VisibleForTesting |
| public void setDozing(boolean dozing) { |
| if (mDozing == dozing) return; |
| mDozing = dozing; |
| if (!mDozing) { |
| cancelPulsing(); |
| } |
| } |
| |
| /** When dozing, fade screen contents in and out using the front scrim. */ |
| public void pulse(@NonNull DozeHost.PulseCallback callback, int reason) { |
| if (callback == null) { |
| throw new IllegalArgumentException("callback must not be null"); |
| } |
| |
| if (!mDozing || mPulseCallback != null) { |
| // Pulse suppressed. |
| callback.onPulseFinished(); |
| if (!mDozing) { |
| mDozeLog.tracePulseDropped("pulse - device isn't dozing"); |
| } else { |
| mDozeLog.tracePulseDropped("pulse - already has pulse callback mPulseCallback=" |
| + mPulseCallback); |
| } |
| return; |
| } |
| |
| // Begin pulse. Note that it's very important that the pulse finished callback |
| // be invoked when we're done so that the caller can drop the pulse wakelock. |
| mPulseCallback = callback; |
| mPulseReason = reason; |
| } |
| |
| public void pulseOutNow() { |
| mPulseOut.run(); |
| } |
| |
| public boolean isPulsing() { |
| return mPulseCallback != null; |
| } |
| |
| public boolean isDozing() { |
| return mDozing; |
| } |
| |
| public void extendPulse() { |
| mHandler.removeCallbacks(mPulseOut); |
| } |
| |
| /** |
| * When pulsing, cancel any timeouts that would take you out of the pulsing state. |
| */ |
| public void cancelPendingPulseTimeout() { |
| mHandler.removeCallbacks(mPulseOut); |
| mHandler.removeCallbacks(mPulseOutExtended); |
| } |
| |
| private void cancelPulsing() { |
| if (mPulseCallback != null) { |
| mDozeLog.tracePulseEvent("cancel", mDozing, mPulseReason); |
| mHandler.removeCallbacks(mPulseOut); |
| mHandler.removeCallbacks(mPulseOutExtended); |
| pulseFinished(); |
| } |
| } |
| |
| private void pulseFinished() { |
| if (mPulseCallback != null) { |
| mDozeLog.tracePulseFinish(); |
| mPulseCallback.onPulseFinished(); |
| mPulseCallback = null; |
| } |
| } |
| |
| private final Runnable mPulseOutExtended = new Runnable() { |
| @Override |
| public void run() { |
| mHandler.removeCallbacks(mPulseOut); |
| mPulseOut.run(); |
| } |
| }; |
| |
| private final Runnable mPulseOut = new Runnable() { |
| @Override |
| public void run() { |
| mHandler.removeCallbacks(mPulseOut); |
| mHandler.removeCallbacks(mPulseOutExtended); |
| mDozeLog.tracePulseEvent("out", mDozing, mPulseReason); |
| if (!mDozing) return; |
| pulseFinished(); |
| } |
| }; |
| |
| public ScrimController.Callback getScrimCallback() { |
| return mScrimCallback; |
| } |
| |
| @Override |
| public void onStateChanged(int newState) { |
| // don't care |
| } |
| |
| @Override |
| public void onDozingChanged(boolean isDozing) { |
| if (mDozing != isDozing) { |
| mDozeLog.traceDozingChanged(isDozing); |
| } |
| |
| setDozing(isDozing); |
| } |
| } |