blob: e7d6eba1dcb3096e0017b2bbfde553acb30949de [file] [log] [blame]
/*
* 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 android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
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;
import javax.inject.Singleton;
/**
* Controller which handles all the doze animations of the scrims.
*/
@Singleton
public class DozeScrimController implements StateListener {
private static final String TAG = "DozeScrimController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
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 boolean mFullyPulsing;
private final ScrimController.Callback mScrimCallback = new ScrimController.Callback() {
@Override
public void onDisplayBlanked() {
if (DEBUG) {
Log.d(TAG, "Pulse in, mDozing=" + mDozing + " mPulseReason="
+ DozeLog.reasonToString(mPulseReason));
}
if (!mDozing) {
return;
}
// Signal that the pulse is ready to turn the screen on and draw.
pulseStarted();
}
@Override
public void onFinished() {
if (DEBUG) {
Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
}
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());
}
mFullyPulsing = true;
}
/**
* Transition was aborted before it was over.
*/
@Override
public void onCancelled() {
pulseFinished();
}
};
@Inject
public DozeScrimController(DozeParameters dozeParameters, DozeLog dozeLog) {
mDozeParameters = dozeParameters;
//Never expected to be destroyed
Dependency.get(StatusBarStateController.class).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) {
if (DEBUG) {
Log.d(TAG, "Pulse supressed. Dozing: " + mDozeParameters + " had callback? "
+ (mPulseCallback != null));
}
// Pulse suppressed.
callback.onPulseFinished();
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() {
if (mPulseCallback != null && mFullyPulsing) {
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) {
if (DEBUG) Log.d(TAG, "Cancel pulsing");
mFullyPulsing = false;
mHandler.removeCallbacks(mPulseOut);
mHandler.removeCallbacks(mPulseOutExtended);
pulseFinished();
}
}
private void pulseStarted() {
mDozeLog.tracePulseStart(mPulseReason);
if (mPulseCallback != null) {
mPulseCallback.onPulseStarted();
}
}
private void pulseFinished() {
mDozeLog.tracePulseFinish();
if (mPulseCallback != null) {
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() {
mFullyPulsing = false;
mHandler.removeCallbacks(mPulseOut);
mHandler.removeCallbacks(mPulseOutExtended);
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
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) {
setDozing(isDozing);
}
}