DO NOT MERGE Don't set screen state until boot is completed

Setting the screen state of non-default displays during boot removes the static logo and results in either a black screen (if the display is off) or the boot animation with an incorrect size (if the display is on).

Bug: 267484164
Bug: 270129433
Test: atest com.android.server.display
Change-Id: Ic65dd18a212edba0e32f03c072ec85bb29e9a5f1
(cherry picked from commit c2aba03600)
This commit is contained in:
Piotr Wilczyński
2023-02-03 15:56:17 +00:00
parent 94f5918459
commit a4124ecb82
6 changed files with 117 additions and 10 deletions

View File

@@ -466,6 +466,8 @@ public final class DisplayManagerService extends SystemService {
private boolean mIsDocked; private boolean mIsDocked;
private boolean mIsDreaming; private boolean mIsDreaming;
private boolean mBootCompleted = false;
private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() { private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() {
@Override @Override
public void onReceive(Context context, Intent intent) { public void onReceive(Context context, Intent intent) {
@@ -602,6 +604,12 @@ public final class DisplayManagerService extends SystemService {
} }
} }
} else if (phase == PHASE_BOOT_COMPLETED) { } else if (phase == PHASE_BOOT_COMPLETED) {
synchronized (mSyncRoot) {
mBootCompleted = true;
for (int i = 0; i < mDisplayPowerControllers.size(); i++) {
mDisplayPowerControllers.valueAt(i).onBootCompleted();
}
}
mDisplayModeDirector.onBootCompleted(); mDisplayModeDirector.onBootCompleted();
mLogicalDisplayMapper.onBootCompleted(); mLogicalDisplayMapper.onBootCompleted();
} }
@@ -2998,12 +3006,12 @@ public final class DisplayManagerService extends SystemService {
displayPowerController = new DisplayPowerController2( displayPowerController = new DisplayPowerController2(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler, mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting, mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
() -> handleBrightnessChange(display), hbmMetadata); () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted);
} else { } else {
displayPowerController = new DisplayPowerController( displayPowerController = new DisplayPowerController(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler, mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting, mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
() -> handleBrightnessChange(display), hbmMetadata); () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted);
} }
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController); mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
} }

View File

@@ -139,6 +139,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_BRIGHTNESS_RAMP_DONE = 12; private static final int MSG_BRIGHTNESS_RAMP_DONE = 12;
private static final int MSG_STATSD_HBM_BRIGHTNESS = 13; private static final int MSG_STATSD_HBM_BRIGHTNESS = 13;
private static final int MSG_SWITCH_USER = 14; private static final int MSG_SWITCH_USER = 14;
private static final int MSG_BOOT_COMPLETED = 15;
private static final int PROXIMITY_UNKNOWN = -1; private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0; private static final int PROXIMITY_NEGATIVE = 0;
@@ -518,6 +519,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers = private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
new SparseArray<>(); new SparseArray<>();
private boolean mBootCompleted;
/** /**
* Creates the display power controller. * Creates the display power controller.
*/ */
@@ -525,7 +528,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
DisplayPowerCallbacks callbacks, Handler handler, DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay, SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting, BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) { Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
boolean bootCompleted) {
mInjector = injector != null ? injector : new Injector(); mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock(); mClock = mInjector.getClock();
@@ -662,6 +666,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mBootCompleted = bootCompleted;
} }
private void applyReduceBrightColorsSplineAdjustment() { private void applyReduceBrightColorsSplineAdjustment() {
@@ -1448,7 +1453,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Initialize things the first time the power state is changed. // Initialize things the first time the power state is changed.
if (mustInitialize) { if (mustInitialize) {
initialize(state); initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
} }
// Animate the screen state change unless already animating. // Animate the screen state change unless already animating.
@@ -2154,7 +2159,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} }
} }
if (!reportOnly && mPowerState.getScreenState() != state) { if (!reportOnly && mPowerState.getScreenState() != state
&& readyToUpdateDisplayState()) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state); Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation // TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state)); SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -2567,6 +2573,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessSetting.setBrightness(brightnessValue); mBrightnessSetting.setBrightness(brightnessValue);
} }
@Override
public void onBootCompleted() {
Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
private void updateScreenBrightnessSetting(float brightnessValue) { private void updateScreenBrightnessSetting(float brightnessValue) {
if (!isValidBrightnessValue(brightnessValue) if (!isValidBrightnessValue(brightnessValue)
|| brightnessValue == mCurrentScreenBrightnessSetting) { || brightnessValue == mCurrentScreenBrightnessSetting) {
@@ -2712,6 +2724,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
} }
}; };
/**
* Indicates whether the display state is ready to update. If this is the default display, we
* want to update it right away so that we can draw the boot animation on it. If it is not
* the default display, drawing the boot animation on it would look incorrect, so we need
* to wait until boot is completed.
* @return True if the display state is ready to update
*/
private boolean readyToUpdateDisplayState() {
return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
}
@Override @Override
public void dump(final PrintWriter pw) { public void dump(final PrintWriter pw) {
synchronized (mLock) { synchronized (mLock) {
@@ -3235,6 +3258,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
case MSG_SWITCH_USER: case MSG_SWITCH_USER:
handleOnSwitchUser(msg.arg1); handleOnSwitchUser(msg.arg1);
break; break;
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
updatePowerState();
break;
} }
} }
} }

View File

@@ -137,6 +137,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
private static final int MSG_BRIGHTNESS_RAMP_DONE = 10; private static final int MSG_BRIGHTNESS_RAMP_DONE = 10;
private static final int MSG_STATSD_HBM_BRIGHTNESS = 11; private static final int MSG_STATSD_HBM_BRIGHTNESS = 11;
private static final int MSG_SWITCH_USER = 12; private static final int MSG_SWITCH_USER = 12;
private static final int MSG_BOOT_COMPLETED = 13;
private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500; private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
@@ -425,6 +426,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
private SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers = private SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
new SparseArray(); new SparseArray();
private boolean mBootCompleted;
/** /**
* Creates the display power controller. * Creates the display power controller.
*/ */
@@ -432,7 +435,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
DisplayPowerCallbacks callbacks, Handler handler, DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay, SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting, BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) { Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
boolean bootCompleted) {
mInjector = injector != null ? injector : new Injector(); mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock(); mClock = mInjector.getClock();
@@ -555,6 +559,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT; mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mBootCompleted = bootCompleted;
} }
private void applyReduceBrightColorsSplineAdjustment() { private void applyReduceBrightColorsSplineAdjustment() {
@@ -1190,7 +1195,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
// Initialize things the first time the power state is changed. // Initialize things the first time the power state is changed.
if (mustInitialize) { if (mustInitialize) {
initialize(state); initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
} }
// Animate the screen state change unless already animating. // Animate the screen state change unless already animating.
@@ -1720,6 +1725,12 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
} }
} }
@Override
public void onBootCompleted() {
Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
private boolean saveBrightnessInfo(float brightness) { private boolean saveBrightnessInfo(float brightness) {
return saveBrightnessInfo(brightness, brightness); return saveBrightnessInfo(brightness, brightness);
} }
@@ -1861,7 +1872,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
} }
} }
if (!reportOnly && mPowerState.getScreenState() != state) { if (!reportOnly && mPowerState.getScreenState() != state
&& readyToUpdateDisplayState()) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state); Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation // TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state)); SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -2519,6 +2531,17 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
} }
} }
/**
* Indicates whether the display state is ready to update. If this is the default display, we
* want to update it right away so that we can draw the boot animation on it. If it is not
* the default display, drawing the boot animation on it would look incorrect, so we need
* to wait until boot is completed.
* @return True if the display state is ready to update
*/
private boolean readyToUpdateDisplayState() {
return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
}
// Return bucket index of range_[left]_[right] where // Return bucket index of range_[left]_[right] where
// left <= nits < right // left <= nits < right
private int nitsToRangeIndex(float nits) { private int nitsToRangeIndex(float nits) {
@@ -2738,6 +2761,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
case MSG_SWITCH_USER: case MSG_SWITCH_USER:
handleOnSwitchUser(msg.arg1); handleOnSwitchUser(msg.arg1);
break; break;
case MSG_BOOT_COMPLETED:
mBootCompleted = true;
updatePowerState();
break;
} }
} }
} }

View File

@@ -206,4 +206,9 @@ public interface DisplayPowerControllerInterface {
* @param follower The DPC to remove from the followers list * @param follower The DPC to remove from the followers list
*/ */
void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower); void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
/**
* Indicate that boot has been completed and the screen is ready to update.
*/
void onBootCompleted();
} }

View File

@@ -460,6 +460,25 @@ public final class DisplayPowerController2Test {
verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
} }
@Test
public void testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted() {
// We should still set screen state for the default display
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
mHolder = createDisplayPowerController(42, UNIQUE_ID);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
mHolder.dpc.onBootCompleted();
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId, private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) { String uniqueId) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
@@ -487,7 +506,7 @@ public final class DisplayPowerController2Test {
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, display, mSensorManagerMock, mDisplayBlankerMock, display,
mBrightnessTrackerMock, brightnessSetting, () -> {}, mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata); hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator, return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
automaticBrightnessController, wakelockController); automaticBrightnessController, wakelockController);

View File

@@ -464,6 +464,25 @@ public final class DisplayPowerControllerTest {
verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat()); verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
} }
@Test
public void testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted() {
// We should still set screen state for the default display
DisplayPowerRequest dpr = new DisplayPowerRequest();
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
mHolder = createDisplayPowerController(42, UNIQUE_ID);
mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
advanceTime(1);
verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
mHolder.dpc.onBootCompleted();
advanceTime(1);
verify(mHolder.displayPowerState).setScreenState(anyInt());
}
private DisplayPowerControllerHolder createDisplayPowerController(int displayId, private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) { String uniqueId) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class); final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
@@ -489,7 +508,7 @@ public final class DisplayPowerControllerTest {
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler, mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, display, mSensorManagerMock, mDisplayBlankerMock, display,
mBrightnessTrackerMock, brightnessSetting, () -> {}, mBrightnessTrackerMock, brightnessSetting, () -> {},
hbmMetadata); hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator, return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
automaticBrightnessController); automaticBrightnessController);