Report the display is off when the hardware blanks itself.

Some hardware will blank itself coming out of doze to avoid artifacts
from being shown. In order to perform a graceful transition from doze to
on, tell window manager policy that the display turned off and then
turned on without actually telling the display to enter the off state,
in order to keep the screen on latency low.

Bug: 63531607
Test: manual
Merged-In: I4362905e47d5fb47b639c8701c91d69b50aa1232
Change-Id: I4362905e47d5fb47b639c8701c91d69b50aa1232
This commit is contained in:
Michael Wright
2017-07-25 22:31:03 +01:00
parent 55bc522d0d
commit 410fd1b838
5 changed files with 52 additions and 42 deletions

View File

@@ -1854,9 +1854,8 @@
states. --> states. -->
<bool name="config_dozeAlwaysOnDisplayAvailable">false</bool> <bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
<!-- Whether the display hardware requires we go to the off state before transitioning <!-- Whether the display blanks itself when transitioning from a doze to a non-doze state -->
out of any doze states. --> <bool name="config_displayBlanksAfterDoze">false</bool>
<bool name="config_displayTransitionOffAfterDoze">false</bool>
<!-- Power Management: Specifies whether to decouple the auto-suspend state of the <!-- Power Management: Specifies whether to decouple the auto-suspend state of the

View File

@@ -3052,7 +3052,7 @@
<java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" /> <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
<java-symbol type="integer" name="config_inCallNotificationVolumeRelative" /> <java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" /> <java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
<java-symbol type="bool" name="config_displayTransitionOffAfterDoze" /> <java-symbol type="bool" name="config_displayBlanksAfterDoze" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" /> <java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
<java-symbol type="string" name="config_headlineFontFamily" /> <java-symbol type="string" name="config_headlineFontFamily" />
<java-symbol type="string" name="config_headlineFontFamilyLight" /> <java-symbol type="string" name="config_headlineFontFamilyLight" />

View File

@@ -165,11 +165,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// a stylish color fade animation instead. // a stylish color fade animation instead.
private boolean mColorFadeFadesConfig; private boolean mColorFadeFadesConfig;
// True if we need to transition to the off state when coming out of a doze state. // True if we need to fake a transition to off when coming out of a doze state.
// Some display hardware will show artifacts (flickers, etc) when transitioning from a doze // Some display hardware will blank itself when coming out of doze in order to hide
// to a fully on state. In order to hide these, we first transition to off to let the system // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
// animate the screen on as it normally would, which is a much smoother experience. // blank itself and begin an appropriate power on animation.
private boolean mTransitionOffAfterDozeConfig; private boolean mDisplayBlanksAfterDozeConfig;
// The pending power request. // The pending power request.
// Initially null until the first call to requestPowerState. // Initially null until the first call to requestPowerState.
@@ -416,8 +416,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mColorFadeFadesConfig = resources.getBoolean( mColorFadeFadesConfig = resources.getBoolean(
com.android.internal.R.bool.config_animateScreenLights); com.android.internal.R.bool.config_animateScreenLights);
mTransitionOffAfterDozeConfig = resources.getBoolean( mDisplayBlanksAfterDozeConfig = resources.getBoolean(
com.android.internal.R.bool.config_displayTransitionOffAfterDoze); com.android.internal.R.bool.config_displayBlanksAfterDoze);
if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) { if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
@@ -803,7 +803,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Notify policy about screen turned on. // Notify policy about screen turned on.
if (ready && state != Display.STATE_OFF if (ready && state != Display.STATE_OFF
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) { && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON; setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
mWindowManagerPolicy.screenTurnedOn(); mWindowManagerPolicy.screenTurnedOn();
} }
@@ -886,10 +886,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} }
private boolean setScreenState(int state) { private boolean setScreenState(int state) {
return setScreenState(state, false /*force*/); return setScreenState(state, false /*reportOnly*/);
} }
private boolean setScreenState(int state, boolean force) { private boolean setScreenState(int state, boolean reportOnly) {
final boolean isOff = (state == Display.STATE_OFF); final boolean isOff = (state == Display.STATE_OFF);
if (mPowerState.getScreenState() != state) { if (mPowerState.getScreenState() != state) {
@@ -897,32 +897,24 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// actually turn the screen off. // actually turn the screen off.
if (isOff && !mScreenOffBecauseOfProximity) { if (isOff && !mScreenOffBecauseOfProximity) {
if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) { if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_OFF; setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
blockScreenOff(); blockScreenOff();
mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker); mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
if (force) { unblockScreenOff();
// If we're forcing the power state transition then immediately
// unblock the screen off event. This keeps the lifecycle consistent,
// so WindowManagerPolicy will always see screenTurningOff before
// screenTurnedOff, but we don't actually block on them for the state
// change.
unblockScreenOff();
} else {
return false;
}
} else if (mPendingScreenOffUnblocker != null) { } else if (mPendingScreenOffUnblocker != null) {
// Abort doing the state change until screen off is unblocked. // Abort doing the state change until screen off is unblocked.
return false; return false;
} }
} }
mPowerState.setScreenState(state); if (!reportOnly) {
mPowerState.setScreenState(state);
// Tell battery stats about the transition. // Tell battery stats about the transition.
try { try {
mBatteryStats.noteScreenState(state); mBatteryStats.noteScreenState(state);
} catch (RemoteException ex) { } catch (RemoteException ex) {
// same process // same process
}
} }
} }
@@ -934,7 +926,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// finished drawing underneath. // finished drawing underneath.
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) { && !mScreenOffBecauseOfProximity) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF; setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
unblockScreenOn(); unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff(); mWindowManagerPolicy.screenTurnedOff();
} else if (!isOff } else if (!isOff
@@ -944,10 +936,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Complete the full state transition on -> turningOff -> off. // Complete the full state transition on -> turningOff -> off.
unblockScreenOff(); unblockScreenOff();
mWindowManagerPolicy.screenTurnedOff(); mWindowManagerPolicy.screenTurnedOff();
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF; setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
} }
if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) { if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON; setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) { if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn(); blockScreenOn();
} else { } else {
@@ -960,6 +952,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return mPendingScreenOnUnblocker == null; return mPendingScreenOnUnblocker == null;
} }
private void setReportedScreenState(int state) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
mReportedScreenStateToPolicy = state;
}
private int clampScreenBrightness(int value) { private int clampScreenBrightness(int value) {
return MathUtils.constrain( return MathUtils.constrain(
value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum); value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
@@ -989,15 +986,20 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPendingScreenOff = false; mPendingScreenOff = false;
} }
if (mTransitionOffAfterDozeConfig && if (mDisplayBlanksAfterDozeConfig
Display.isDozeState(mPowerState.getScreenState()) && Display.isDozeState(mPowerState.getScreenState())
&& !Display.isDozeState(target)) { && !Display.isDozeState(target)) {
setScreenState(Display.STATE_OFF, true /*force*/);
// Skip the screen off animation and add a black surface to hide the // Skip the screen off animation and add a black surface to hide the
// contents of the screen. This will also trigger another power state update so that we // contents of the screen.
// end up converging on the target state. mPowerState.prepareColorFade(mContext,
mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
mColorFadeOffAnimator.end(); mColorFadeOffAnimator.end();
return; // Some display hardware will blank itself on the transition between doze and non-doze
// but still on display states. In this case we want to report to policy that the
// display has turned off so it can prepare the appropriate power on animation, but we
// don't want to actually transition to the fully off state since that takes
// significantly longer to transition from.
setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
} }
// If we were in the process of turning off the screen but didn't quite // If we were in the process of turning off the screen but didn't quite
@@ -1295,7 +1297,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mAppliedLowPower=" + mAppliedLowPower); pw.println(" mAppliedLowPower=" + mAppliedLowPower);
pw.println(" mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker); pw.println(" mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
pw.println(" mPendingScreenOff=" + mPendingScreenOff); pw.println(" mPendingScreenOff=" + mPendingScreenOff);
pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy)); pw.println(" mReportedToPolicy=" +
reportedToPolicyToString(mReportedScreenStateToPolicy));
pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" + pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" +
mScreenBrightnessRampAnimator.isAnimating()); mScreenBrightnessRampAnimator.isAnimating());

View File

@@ -20,6 +20,7 @@ import android.content.Context;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Trace;
import android.util.FloatProperty; import android.util.FloatProperty;
import android.util.IntProperty; import android.util.IntProperty;
import android.util.Slog; import android.util.Slog;
@@ -49,6 +50,7 @@ final class DisplayPowerState {
private static final String TAG = "DisplayPowerState"; private static final String TAG = "DisplayPowerState";
private static boolean DEBUG = false; private static boolean DEBUG = false;
private static String COUNTER_COLOR_FADE = "ColorFadeLevel";
private final Handler mHandler; private final Handler mHandler;
private final Choreographer mChoreographer; private final Choreographer mChoreographer;
@@ -190,6 +192,7 @@ final class DisplayPowerState {
* Dismisses the color fade surface. * Dismisses the color fade surface.
*/ */
public void dismissColorFade() { public void dismissColorFade() {
Trace.traceCounter(Trace.TRACE_TAG_POWER, COUNTER_COLOR_FADE, 100);
mColorFade.dismiss(); mColorFade.dismiss();
mColorFadePrepared = false; mColorFadePrepared = false;
mColorFadeReady = true; mColorFadeReady = true;
@@ -328,6 +331,8 @@ final class DisplayPowerState {
if (mColorFadePrepared) { if (mColorFadePrepared) {
mColorFade.draw(mColorFadeLevel); mColorFade.draw(mColorFadeLevel);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
COUNTER_COLOR_FADE, Math.round(mColorFadeLevel* 100));
} }
mColorFadeReady = true; mColorFadeReady = true;

View File

@@ -515,6 +515,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
try { try {
final int mode = getPowerModeForState(state); final int mode = getPowerModeForState(state);
SurfaceControl.setDisplayPowerMode(token, mode); SurfaceControl.setDisplayPowerMode(token, mode);
Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
} finally { } finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER);
} }
@@ -530,6 +531,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
+ "id=" + displayId + ", brightness=" + brightness + ")"); + "id=" + displayId + ", brightness=" + brightness + ")");
try { try {
mBacklight.setBrightness(brightness); mBacklight.setBrightness(brightness);
Trace.traceCounter(Trace.TRACE_TAG_POWER,
"DisplayBrightness", brightness);
} finally { } finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER); Trace.traceEnd(Trace.TRACE_TAG_POWER);
} }