Skip to content

Commit 62434d6

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Reduce latency from doze to screen on." into lmp-dev
2 parents ee33c66 + 0a43477 commit 62434d6

3 files changed

Lines changed: 141 additions & 86 deletions

File tree

services/core/java/com/android/server/display/DisplayPowerController.java

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
227227
// turning off the screen.
228228
private boolean mPendingScreenOff;
229229

230+
// True if we have unfinished business and are holding a suspend blocker.
231+
private boolean mUnfinishedBusiness;
232+
230233
// The elapsed real time when the screen on was blocked.
231234
private long mScreenOnBlockStartRealTime;
232235

@@ -633,22 +636,42 @@ private void updatePowerState() {
633636
mAppliedLowPower = true;
634637
}
635638

636-
// Animate the screen brightness when the screen is on.
637-
if (state != Display.STATE_OFF) {
638-
animateScreenBrightness(brightness, slowChange
639-
? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
640-
}
641-
642639
// Animate the screen state change unless already animating.
643640
animateScreenStateChange(state, performScreenOffTransition);
644641

645-
// Report whether the display is ready for use and all changes have been applied.
646-
if (mustNotify
647-
&& mPendingScreenOnUnblocker == null
642+
// Animate the screen brightness when the screen is on or dozing.
643+
// Skip the animation when the screen is off or suspended.
644+
final int actualState = mPowerState.getScreenState();
645+
if (actualState == Display.STATE_ON || actualState == Display.STATE_DOZE) {
646+
animateScreenBrightness(brightness,
647+
slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
648+
} else {
649+
animateScreenBrightness(brightness, 0);
650+
}
651+
652+
// Determine whether the display is ready for use in the newly requested state.
653+
// Note that we do not wait for the brightness ramp animation to complete before
654+
// reporting the display is ready because we only need to ensure the screen is in the
655+
// right power state even as it continues to converge on the desired brightness.
656+
final boolean ready = mPendingScreenOnUnblocker == null
648657
&& !mColorFadeOnAnimator.isStarted()
649658
&& !mColorFadeOffAnimator.isStarted()
650-
&& !mScreenBrightnessRampAnimator.isAnimating()
651-
&& mPowerState.waitUntilClean(mCleanListener)) {
659+
&& mPowerState.waitUntilClean(mCleanListener);
660+
final boolean finished = ready
661+
&& !mScreenBrightnessRampAnimator.isAnimating();
662+
663+
// Grab a wake lock if we have unfinished business.
664+
if (!finished && !mUnfinishedBusiness) {
665+
if (DEBUG) {
666+
Slog.d(TAG, "Unfinished business...");
667+
}
668+
mCallbacks.acquireSuspendBlocker();
669+
mUnfinishedBusiness = true;
670+
}
671+
672+
// Notify the power manager when ready.
673+
if (ready && mustNotify) {
674+
// Send state change.
652675
synchronized (mLock) {
653676
if (!mPendingRequestChangedLocked) {
654677
mDisplayReadyLocked = true;
@@ -660,6 +683,15 @@ private void updatePowerState() {
660683
}
661684
sendOnStateChangedWithWakelock();
662685
}
686+
687+
// Release the wake lock when we have no unfinished business.
688+
if (finished && mUnfinishedBusiness) {
689+
if (DEBUG) {
690+
Slog.d(TAG, "Finished business...");
691+
}
692+
mUnfinishedBusiness = false;
693+
mCallbacks.releaseSuspendBlocker();
694+
}
663695
}
664696

665697
@Override
@@ -723,6 +755,9 @@ private int clampScreenBrightness(int value) {
723755
}
724756

725757
private void animateScreenBrightness(int target, int rate) {
758+
if (DEBUG) {
759+
Slog.d(TAG, "Animating brightness: target=" + target +", rate=" + rate);
760+
}
726761
if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
727762
try {
728763
mBatteryStats.noteScreenBrightness(target);

services/core/java/com/android/server/display/DisplayPowerState.java

Lines changed: 66 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ public DisplayPowerState(DisplayBlanker blanker, Light backlight, ColorFade elec
8080
mBacklight = backlight;
8181
mColorFade = electronBeam;
8282
mPhotonicModulator = new PhotonicModulator();
83+
mPhotonicModulator.start();
8384

8485
// At boot time, we know that the screen is on and the electron beam
8586
// animation is not playing. We don't know the screen's brightness though,
@@ -336,7 +337,7 @@ public void run() {
336337
/**
337338
* Updates the state of the screen and backlight asynchronously on a separate thread.
338339
*/
339-
private final class PhotonicModulator {
340+
private final class PhotonicModulator extends Thread {
340341
private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
341342
private static final int INITIAL_BACKLIGHT = -1; // unknown
342343

@@ -361,83 +362,86 @@ public boolean setState(int state, int backlight) {
361362

362363
if (!mChangeInProgress) {
363364
mChangeInProgress = true;
364-
AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
365+
mLock.notifyAll();
365366
}
366367
}
367368
return !mChangeInProgress;
368369
}
369370
}
370371

371372
public void dump(PrintWriter pw) {
372-
pw.println();
373-
pw.println("Photonic Modulator State:");
374-
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
375-
pw.println(" mPendingBacklight=" + mPendingBacklight);
376-
pw.println(" mActualState=" + Display.stateToString(mActualState));
377-
pw.println(" mActualBacklight=" + mActualBacklight);
378-
pw.println(" mChangeInProgress=" + mChangeInProgress);
373+
synchronized (mLock) {
374+
pw.println();
375+
pw.println("Photonic Modulator State:");
376+
pw.println(" mPendingState=" + Display.stateToString(mPendingState));
377+
pw.println(" mPendingBacklight=" + mPendingBacklight);
378+
pw.println(" mActualState=" + Display.stateToString(mActualState));
379+
pw.println(" mActualBacklight=" + mActualBacklight);
380+
pw.println(" mChangeInProgress=" + mChangeInProgress);
381+
}
379382
}
380383

381-
private final Runnable mTask = new Runnable() {
382-
@Override
383-
public void run() {
384-
// Apply pending changes until done.
385-
for (;;) {
386-
final int state;
387-
final boolean stateChanged;
388-
final int backlight;
389-
final boolean backlightChanged;
390-
synchronized (mLock) {
391-
state = mPendingState;
392-
stateChanged = (state != mActualState);
393-
backlight = mPendingBacklight;
394-
backlightChanged = (backlight != mActualBacklight);
395-
if (!stateChanged && !backlightChanged) {
396-
mChangeInProgress = false;
397-
break;
398-
}
399-
mActualState = state;
400-
mActualBacklight = backlight;
401-
}
402-
403-
if (DEBUG) {
404-
Slog.d(TAG, "Updating screen state: state="
405-
+ Display.stateToString(state) + ", backlight=" + backlight);
406-
}
407-
boolean suspending = Display.isSuspendedState(state);
408-
if (stateChanged && !suspending) {
409-
requestDisplayState(state);
410-
}
411-
if (backlightChanged) {
412-
setBrightness(backlight);
413-
}
414-
if (stateChanged && suspending) {
415-
requestDisplayState(state);
384+
@Override
385+
public void run() {
386+
for (;;) {
387+
// Get pending change.
388+
final int state;
389+
final boolean stateChanged;
390+
final int backlight;
391+
final boolean backlightChanged;
392+
synchronized (mLock) {
393+
state = mPendingState;
394+
stateChanged = (state != mActualState);
395+
backlight = mPendingBacklight;
396+
backlightChanged = (backlight != mActualBacklight);
397+
if (!stateChanged && !backlightChanged) {
398+
// All changed applied, notify outer class and wait for more.
399+
mChangeInProgress = false;
400+
postScreenUpdateThreadSafe();
401+
try {
402+
mLock.wait();
403+
} catch (InterruptedException ex) { }
404+
continue;
416405
}
406+
mActualState = state;
407+
mActualBacklight = backlight;
417408
}
418409

419-
// Let the outer class know that all changes have been applied.
420-
postScreenUpdateThreadSafe();
410+
// Apply pending change.
411+
if (DEBUG) {
412+
Slog.d(TAG, "Updating screen state: state="
413+
+ Display.stateToString(state) + ", backlight=" + backlight);
414+
}
415+
boolean suspending = Display.isSuspendedState(state);
416+
if (stateChanged && !suspending) {
417+
requestDisplayState(state);
418+
}
419+
if (backlightChanged) {
420+
setBrightness(backlight);
421+
}
422+
if (stateChanged && suspending) {
423+
requestDisplayState(state);
424+
}
421425
}
426+
}
422427

423-
private void requestDisplayState(int state) {
424-
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
425-
+ Display.stateToString(state) + ")");
426-
try {
427-
mBlanker.requestDisplayState(state);
428-
} finally {
429-
Trace.traceEnd(Trace.TRACE_TAG_POWER);
430-
}
428+
private void requestDisplayState(int state) {
429+
Trace.traceBegin(Trace.TRACE_TAG_POWER, "requestDisplayState("
430+
+ Display.stateToString(state) + ")");
431+
try {
432+
mBlanker.requestDisplayState(state);
433+
} finally {
434+
Trace.traceEnd(Trace.TRACE_TAG_POWER);
431435
}
436+
}
432437

433-
private void setBrightness(int backlight) {
434-
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setBrightness(" + backlight + ")");
435-
try {
436-
mBacklight.setBrightness(backlight);
437-
} finally {
438-
Trace.traceEnd(Trace.TRACE_TAG_POWER);
439-
}
438+
private void setBrightness(int backlight) {
439+
Trace.traceBegin(Trace.TRACE_TAG_POWER, "setBrightness(" + backlight + ")");
440+
try {
441+
mBacklight.setBrightness(backlight);
442+
} finally {
443+
Trace.traceEnd(Trace.TRACE_TAG_POWER);
440444
}
441-
};
445+
}
442446
}
443447
}

services/core/java/com/android/server/display/RampAnimator.java

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,32 @@ public RampAnimator(T object, IntProperty<T> property) {
5050
/**
5151
* Starts animating towards the specified value.
5252
*
53-
* If this is the first time the property is being set, the value jumps
54-
* directly to the target.
53+
* If this is the first time the property is being set or if the rate is 0,
54+
* the value jumps directly to the target.
5555
*
5656
* @param target The target value.
57-
* @param rate The convergence rate, in units per second.
57+
* @param rate The convergence rate in units per second, or 0 to set the value immediately.
5858
* @return True if the target differs from the previous target.
5959
*/
6060
public boolean animateTo(int target, int rate) {
6161
// Immediately jump to the target the first time.
62-
if (mFirstTime) {
63-
mFirstTime = false;
64-
mProperty.setValue(mObject, target);
65-
mCurrentValue = target;
66-
return true;
62+
if (mFirstTime || rate <= 0) {
63+
if (mFirstTime || target != mCurrentValue) {
64+
mFirstTime = false;
65+
mRate = 0;
66+
mTargetValue = target;
67+
mCurrentValue = target;
68+
mProperty.setValue(mObject, target);
69+
if (mAnimating) {
70+
mAnimating = false;
71+
cancelAnimationCallback();
72+
}
73+
if (mListener != null) {
74+
mListener.onAnimationEnd();
75+
}
76+
return true;
77+
}
78+
return false;
6779
}
6880

6981
// Adjust the rate based on the closest target.
@@ -88,7 +100,7 @@ public boolean animateTo(int target, int rate) {
88100
mAnimating = true;
89101
mAnimatedValue = mCurrentValue;
90102
mLastFrameTimeNanos = System.nanoTime();
91-
postCallback();
103+
postAnimationCallback();
92104
}
93105

94106
return changed;
@@ -108,11 +120,15 @@ public void setListener(Listener listener) {
108120
mListener = listener;
109121
}
110122

111-
private void postCallback() {
112-
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
123+
private void postAnimationCallback() {
124+
mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
125+
}
126+
127+
private void cancelAnimationCallback() {
128+
mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null);
113129
}
114130

115-
private final Runnable mCallback = new Runnable() {
131+
private final Runnable mAnimationCallback = new Runnable() {
116132
@Override // Choreographer callback
117133
public void run() {
118134
final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
@@ -144,7 +160,7 @@ public void run() {
144160
}
145161

146162
if (mTargetValue != mCurrentValue) {
147-
postCallback();
163+
postAnimationCallback();
148164
} else {
149165
mAnimating = false;
150166
if (mListener != null) {

0 commit comments

Comments
 (0)