* commit '6907304024f1c31d2d2dcf783588a6dd8865ecd8': Reduce latency from doze to screen on.
This commit is contained in:
@@ -227,6 +227,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
// turning off the screen.
|
||||
private boolean mPendingScreenOff;
|
||||
|
||||
// True if we have unfinished business and are holding a suspend blocker.
|
||||
private boolean mUnfinishedBusiness;
|
||||
|
||||
// The elapsed real time when the screen on was blocked.
|
||||
private long mScreenOnBlockStartRealTime;
|
||||
|
||||
@@ -633,22 +636,42 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mAppliedLowPower = true;
|
||||
}
|
||||
|
||||
// Animate the screen brightness when the screen is on.
|
||||
if (state != Display.STATE_OFF) {
|
||||
animateScreenBrightness(brightness, slowChange
|
||||
? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
|
||||
}
|
||||
|
||||
// Animate the screen state change unless already animating.
|
||||
animateScreenStateChange(state, performScreenOffTransition);
|
||||
|
||||
// Report whether the display is ready for use and all changes have been applied.
|
||||
if (mustNotify
|
||||
&& mPendingScreenOnUnblocker == null
|
||||
// Animate the screen brightness when the screen is on or dozing.
|
||||
// Skip the animation when the screen is off or suspended.
|
||||
final int actualState = mPowerState.getScreenState();
|
||||
if (actualState == Display.STATE_ON || actualState == Display.STATE_DOZE) {
|
||||
animateScreenBrightness(brightness,
|
||||
slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
|
||||
} else {
|
||||
animateScreenBrightness(brightness, 0);
|
||||
}
|
||||
|
||||
// Determine whether the display is ready for use in the newly requested state.
|
||||
// Note that we do not wait for the brightness ramp animation to complete before
|
||||
// reporting the display is ready because we only need to ensure the screen is in the
|
||||
// right power state even as it continues to converge on the desired brightness.
|
||||
final boolean ready = mPendingScreenOnUnblocker == null
|
||||
&& !mColorFadeOnAnimator.isStarted()
|
||||
&& !mColorFadeOffAnimator.isStarted()
|
||||
&& !mScreenBrightnessRampAnimator.isAnimating()
|
||||
&& mPowerState.waitUntilClean(mCleanListener)) {
|
||||
&& mPowerState.waitUntilClean(mCleanListener);
|
||||
final boolean finished = ready
|
||||
&& !mScreenBrightnessRampAnimator.isAnimating();
|
||||
|
||||
// Grab a wake lock if we have unfinished business.
|
||||
if (!finished && !mUnfinishedBusiness) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Unfinished business...");
|
||||
}
|
||||
mCallbacks.acquireSuspendBlocker();
|
||||
mUnfinishedBusiness = true;
|
||||
}
|
||||
|
||||
// Notify the power manager when ready.
|
||||
if (ready && mustNotify) {
|
||||
// Send state change.
|
||||
synchronized (mLock) {
|
||||
if (!mPendingRequestChangedLocked) {
|
||||
mDisplayReadyLocked = true;
|
||||
@@ -660,6 +683,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}
|
||||
sendOnStateChangedWithWakelock();
|
||||
}
|
||||
|
||||
// Release the wake lock when we have no unfinished business.
|
||||
if (finished && mUnfinishedBusiness) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Finished business...");
|
||||
}
|
||||
mUnfinishedBusiness = false;
|
||||
mCallbacks.releaseSuspendBlocker();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -723,6 +755,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}
|
||||
|
||||
private void animateScreenBrightness(int target, int rate) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
|
||||
}
|
||||
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
|
||||
try {
|
||||
mBatteryStats.noteScreenBrightness(target);
|
||||
|
||||
@@ -80,6 +80,7 @@ final class DisplayPowerState {
|
||||
mBacklight = backlight;
|
||||
mColorFade = electronBeam;
|
||||
mPhotonicModulator = new PhotonicModulator();
|
||||
mPhotonicModulator.start();
|
||||
|
||||
// At boot time, we know that the screen is on and the electron beam
|
||||
// animation is not playing. We don't know the screen's brightness though,
|
||||
@@ -336,7 +337,7 @@ final class DisplayPowerState {
|
||||
/**
|
||||
* Updates the state of the screen and backlight asynchronously on a separate thread.
|
||||
*/
|
||||
private final class PhotonicModulator {
|
||||
private final class PhotonicModulator extends Thread {
|
||||
private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
|
||||
private static final int INITIAL_BACKLIGHT = -1; // unknown
|
||||
|
||||
@@ -361,7 +362,7 @@ final class DisplayPowerState {
|
||||
|
||||
if (!mChangeInProgress) {
|
||||
mChangeInProgress = true;
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
|
||||
mLock.notifyAll();
|
||||
}
|
||||
}
|
||||
return !mChangeInProgress;
|
||||
@@ -369,75 +370,78 @@ final class DisplayPowerState {
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println();
|
||||
pw.println("Photonic Modulator State:");
|
||||
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
|
||||
pw.println(" mPendingBacklight=" + mPendingBacklight);
|
||||
pw.println(" mActualState=" + Display.stateToString(mActualState));
|
||||
pw.println(" mActualBacklight=" + mActualBacklight);
|
||||
pw.println(" mChangeInProgress=" + mChangeInProgress);
|
||||
synchronized (mLock) {
|
||||
pw.println();
|
||||
pw.println("Photonic Modulator State:");
|
||||
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
|
||||
pw.println(" mPendingBacklight=" + mPendingBacklight);
|
||||
pw.println(" mActualState=" + Display.stateToString(mActualState));
|
||||
pw.println(" mActualBacklight=" + mActualBacklight);
|
||||
pw.println(" mChangeInProgress=" + mChangeInProgress);
|
||||
}
|
||||
}
|
||||
|
||||
private final Runnable mTask = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Apply pending changes until done.
|
||||
for (;;) {
|
||||
final int state;
|
||||
final boolean stateChanged;
|
||||
final int backlight;
|
||||
final boolean backlightChanged;
|
||||
synchronized (mLock) {
|
||||
state = mPendingState;
|
||||
stateChanged = (state != mActualState);
|
||||
backlight = mPendingBacklight;
|
||||
backlightChanged = (backlight != mActualBacklight);
|
||||
if (!stateChanged && !backlightChanged) {
|
||||
mChangeInProgress = false;
|
||||
break;
|
||||
}
|
||||
mActualState = state;
|
||||
mActualBacklight = backlight;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Updating screen state: state="
|
||||
+ Display.stateToString(state) + ", backlight=" + backlight);
|
||||
}
|
||||
boolean suspending = Display.isSuspendedState(state);
|
||||
if (stateChanged && !suspending) {
|
||||
requestDisplayState(state);
|
||||
}
|
||||
if (backlightChanged) {
|
||||
setBrightness(backlight);
|
||||
}
|
||||
if (stateChanged && suspending) {
|
||||
requestDisplayState(state);
|
||||
@Override
|
||||
public void run() {
|
||||
for (;;) {
|
||||
// Get pending change.
|
||||
final int state;
|
||||
final boolean stateChanged;
|
||||
final int backlight;
|
||||
final boolean backlightChanged;
|
||||
synchronized (mLock) {
|
||||
state = mPendingState;
|
||||
stateChanged = (state != mActualState);
|
||||
backlight = mPendingBacklight;
|
||||
backlightChanged = (backlight != mActualBacklight);
|
||||
if (!stateChanged && !backlightChanged) {
|
||||
// All changed applied, notify outer class and wait for more.
|
||||
mChangeInProgress = false;
|
||||
postScreenUpdateThreadSafe();
|
||||
try {
|
||||
mLock.wait();
|
||||
} catch (InterruptedException ex) { }
|
||||
continue;
|
||||
}
|
||||
mActualState = state;
|
||||
mActualBacklight = backlight;
|
||||
}
|
||||
|
||||
// Let the outer class know that all changes have been applied.
|
||||
postScreenUpdateThreadSafe();
|
||||
}
|
||||
|
||||
private void requestDisplayState(int state) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
|
||||
+ Display.stateToString(state) + ")");
|
||||
try {
|
||||
mBlanker.requestDisplayState(state);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_POWER);
|
||||
// Apply pending change.
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "Updating screen state: state="
|
||||
+ Display.stateToString(state) + ", backlight=" + backlight);
|
||||
}
|
||||
boolean suspending = Display.isSuspendedState(state);
|
||||
if (stateChanged && !suspending) {
|
||||
requestDisplayState(state);
|
||||
}
|
||||
if (backlightChanged) {
|
||||
setBrightness(backlight);
|
||||
}
|
||||
if (stateChanged && suspending) {
|
||||
requestDisplayState(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setBrightness(int backlight) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setBrightness(" + backlight + ")");
|
||||
try {
|
||||
mBacklight.setBrightness(backlight);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_POWER);
|
||||
}
|
||||
private void requestDisplayState(int state) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
|
||||
+ Display.stateToString(state) + ")");
|
||||
try {
|
||||
mBlanker.requestDisplayState(state);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_POWER);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void setBrightness(int backlight) {
|
||||
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setBrightness(" + backlight + ")");
|
||||
try {
|
||||
mBacklight.setBrightness(backlight);
|
||||
} finally {
|
||||
Trace.traceEnd(Trace.TRACE_TAG_POWER);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,20 +50,32 @@ final class RampAnimator<T> {
|
||||
/**
|
||||
* Starts animating towards the specified value.
|
||||
*
|
||||
* If this is the first time the property is being set, the value jumps
|
||||
* directly to the target.
|
||||
* If this is the first time the property is being set or if the rate is 0,
|
||||
* the value jumps directly to the target.
|
||||
*
|
||||
* @param target The target value.
|
||||
* @param rate The convergence rate, in units per second.
|
||||
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
|
||||
* @return True if the target differs from the previous target.
|
||||
*/
|
||||
public boolean animateTo(int target, int rate) {
|
||||
// Immediately jump to the target the first time.
|
||||
if (mFirstTime) {
|
||||
mFirstTime = false;
|
||||
mProperty.setValue(mObject, target);
|
||||
mCurrentValue = target;
|
||||
return true;
|
||||
if (mFirstTime || rate <= 0) {
|
||||
if (mFirstTime || target != mCurrentValue) {
|
||||
mFirstTime = false;
|
||||
mRate = 0;
|
||||
mTargetValue = target;
|
||||
mCurrentValue = target;
|
||||
mProperty.setValue(mObject, target);
|
||||
if (mAnimating) {
|
||||
mAnimating = false;
|
||||
cancelAnimationCallback();
|
||||
}
|
||||
if (mListener != null) {
|
||||
mListener.onAnimationEnd();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust the rate based on the closest target.
|
||||
@@ -88,7 +100,7 @@ final class RampAnimator<T> {
|
||||
mAnimating = true;
|
||||
mAnimatedValue = mCurrentValue;
|
||||
mLastFrameTimeNanos = System.nanoTime();
|
||||
postCallback();
|
||||
postAnimationCallback();
|
||||
}
|
||||
|
||||
return changed;
|
||||
@@ -108,11 +120,15 @@ final class RampAnimator<T> {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
private void postCallback() {
|
||||
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
|
||||
private void postAnimationCallback() {
|
||||
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
|
||||
}
|
||||
|
||||
private final Runnable mCallback = new Runnable() {
|
||||
private void cancelAnimationCallback() {
|
||||
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
|
||||
}
|
||||
|
||||
private final Runnable mAnimationCallback = new Runnable() {
|
||||
@Override // Choreographer callback
|
||||
public void run() {
|
||||
final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
|
||||
@@ -144,7 +160,7 @@ final class RampAnimator<T> {
|
||||
}
|
||||
|
||||
if (mTargetValue != mCurrentValue) {
|
||||
postCallback();
|
||||
postAnimationCallback();
|
||||
} else {
|
||||
mAnimating = false;
|
||||
if (mListener != null) {
|
||||
|
||||
Reference in New Issue
Block a user