Merge "Improvements to power manager turning on screen."
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 0934cd0..785db98 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -79,6 +79,8 @@
private static final String TAG = "PowerManagerService";
static final String PARTIAL_NAME = "PowerManagerService";
+ static final boolean DEBUG_SCREEN_ON = false;
+
private static final boolean LOG_PARTIAL_WL = false;
// Indicates whether touch-down cycles should be logged as part of the
@@ -162,6 +164,8 @@
private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
private final int[] mBroadcastWhy = new int[3];
private boolean mPreparingForScreenOn = false;
+ private boolean mSkippedScreenOn = false;
+ private boolean mInitialized = false;
private int mPartialCount = 0;
private int mPowerState;
// mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
@@ -557,6 +561,9 @@
nativeInit();
synchronized (mLocks) {
updateNativePowerStateLocked();
+ // We make sure to start out with the screen on due to user activity.
+ // (They did just boot their device, after all.)
+ forceUserActivityLocked();
}
}
@@ -1123,7 +1130,8 @@
+ " " + ((mNextTimeout-now)/1000) + "s from now");
pw.println(" mDimScreen=" + mDimScreen
+ " mStayOnConditions=" + mStayOnConditions
- + " mPreparingForScreenOn=" + mPreparingForScreenOn);
+ + " mPreparingForScreenOn=" + mPreparingForScreenOn
+ + " mSkippedScreenOn=" + mSkippedScreenOn);
pw.println(" mScreenOffReason=" + mScreenOffReason
+ " mUserState=" + mUserState);
pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
@@ -1312,8 +1320,16 @@
}
}
- private void sendNotificationLocked(boolean on, int why)
- {
+ private void sendNotificationLocked(boolean on, int why) {
+ if (!mInitialized) {
+ // No notifications sent until first initialization is done.
+ // This is so that when we are moving from our initial state
+ // which looks like the screen was off to it being on, we do not
+ // go through the process of waiting for the higher-level user
+ // space to be ready before turning up the display brightness.
+ // (And also do not send needless broadcasts about the screen.)
+ return;
+ }
if (!on) {
mStillNeedSleepNotification = false;
}
@@ -1360,7 +1376,9 @@
// The broadcast queue has changed; make sure the screen is on if it
// is now possible for it to be.
- updateNativePowerStateLocked();
+ if (mSkippedScreenOn) {
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
+ }
// Now send the message.
if (index >= 0) {
@@ -1380,7 +1398,7 @@
synchronized (mLocks) {
if (mPreparingForScreenOn) {
mPreparingForScreenOn = false;
- updateNativePowerStateLocked();
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
4, mBroadcastWakeLock.mCount);
mBroadcastWakeLock.release();
@@ -1453,7 +1471,7 @@
synchronized (mLocks) {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
mBroadcastWakeLock.mCount);
- updateNativePowerStateLocked();
+ updateLightsLocked(mPowerState, SCREEN_ON_BIT);
mBroadcastWakeLock.release();
}
}
@@ -1646,6 +1664,11 @@
};
private int setScreenStateLocked(boolean on) {
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Set screen state: " + on, e);
+ }
int err = Power.setScreenState(on);
if (err == 0) {
mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
@@ -1696,7 +1719,7 @@
} else {
newState &= ~BATTERY_LOW_BIT;
}
- if (newState == mPowerState) {
+ if (newState == mPowerState && mInitialized) {
return;
}
@@ -1722,10 +1745,7 @@
+ " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
}
- if (mPowerState != newState) {
- updateLightsLocked(newState, 0);
- mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
- }
+ final boolean stateChanged = mPowerState != newState;
if (oldScreenOn != newScreenOn) {
if (newScreenOn) {
@@ -1777,10 +1797,24 @@
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
mTotalTouchDownTime, mTouchCycles);
if (err == 0) {
- mPowerState |= SCREEN_ON_BIT;
sendNotificationLocked(true, -1);
+ // Update the lights *after* taking care of turning the
+ // screen on, so we do this after our notifications are
+ // enqueued and thus will delay turning on the screen light
+ // until the windows are correctly displayed.
+ if (stateChanged) {
+ updateLightsLocked(newState, 0);
+ }
+ mPowerState |= SCREEN_ON_BIT;
}
+
} else {
+ // Update the lights *before* taking care of turning the
+ // screen off, so we can initiate any animations that are desired.
+ if (stateChanged) {
+ updateLightsLocked(newState, 0);
+ }
+
// cancel light sensor task
mHandler.removeCallbacks(mAutoBrightnessTask);
mLightSensorPendingDecrease = false;
@@ -1803,30 +1837,20 @@
mLastTouchDown = 0;
}
}
+ } else if (stateChanged) {
+ // Screen on/off didn't change, but lights may have.
+ updateLightsLocked(newState, 0);
}
-
+
+ mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
+
updateNativePowerStateLocked();
+
+ mInitialized = true;
}
}
-
+
private void updateNativePowerStateLocked() {
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- // Don't turn screen on until we know we are really ready to.
- // This is to avoid letting the screen go on before things like the
- // lock screen have been displayed.
- if (mPreparingForScreenOn) {
- // Currently waiting for confirmation from the policy that it
- // is okay to turn on the screen. Don't allow the screen to go
- // on until that is done.
- return;
- }
- for (int i=0; i<mBroadcastQueue.length; i++) {
- if (mBroadcastQueue[i] == 1) {
- // A screen on is currently enqueued.
- return;
- }
- }
- }
nativeSetPowerState(
(mPowerState & SCREEN_ON_BIT) != 0,
(mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
@@ -1852,8 +1876,43 @@
mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
}
+ private boolean shouldDeferScreenOnLocked() {
+ if (mPreparingForScreenOn) {
+ // Currently waiting for confirmation from the policy that it
+ // is okay to turn on the screen. Don't allow the screen to go
+ // on until that is done.
+ if (DEBUG_SCREEN_ON) Slog.i(TAG,
+ "updateLights: delaying screen on due to mPreparingForScreenOn");
+ return true;
+ } else {
+ // If there is a screen-on command in the notification queue, we
+ // can't turn the screen on until it has been processed (and we
+ // have set mPreparingForScreenOn) or it has been dropped.
+ for (int i=0; i<mBroadcastQueue.length; i++) {
+ if (mBroadcastQueue[i] == 1) {
+ if (DEBUG_SCREEN_ON) Slog.i(TAG,
+ "updateLights: delaying screen on due to notification queue");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
private void updateLightsLocked(int newState, int forceState) {
final int oldState = mPowerState;
+
+ // If the screen is not currently on, we will want to delay actually
+ // turning the lights on if we are still getting the UI put up.
+ if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
+ // Don't turn screen on until we know we are really ready to.
+ // This is to avoid letting the screen go on before things like the
+ // lock screen have been displayed.
+ if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) {
+ newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
+ }
+ }
+
if ((newState & SCREEN_ON_BIT) != 0) {
// Only turn on the buttons or keyboard if the screen is also on.
// We should never see the buttons on but not the screen.
@@ -1960,6 +2019,13 @@
}
mScreenBrightness.setTargetLocked(brightness, steps,
INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ if (DEBUG_SCREEN_ON) {
+ RuntimeException e = new RuntimeException("here");
+ e.fillInStackTrace();
+ Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+ mScreenBrightness.setTargetLocked(brightness, steps,
+ INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
+ }
}
if (mSpew) {