From beae3bd6d34472d27ac5698f8d9bcbc12d0cf4f0 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Wed, 21 Sep 2011 10:55:12 -0700 Subject: Improvements to power manager turning on screen. The keyguard/window manager recently got a facility to report when it is okay to turn the screen on, when it knows the lock screen is displayed. The power manager was using this wrong, just using it to drive the flags given to the input system. Duh. This change now uses the information to determine when to turn the screen brightness up from 0. For an OLED screen, this is the time when the user can actually see anything on the screen. For LCD screens this may not be optimal, because the LCD may start running before its backlight is turned on, so if you look carefully you may see stuff before it is lit up. On the other hand, it is good to turn on the display as early as possible (before waiting for the keyguard) because it can take a little bit of time to get that and the touch screen going. By only waiting on the display brightness, we allow turning on the screen in the kernel to proceed in parallel with ensuring the keyguard is displayed. Change-Id: I7ee4ce19fd4efd5b51872b855af6263f53cd6c30 --- .../com/android/server/PowerManagerService.java | 128 ++++++++++++++++----- 1 file changed, 97 insertions(+), 31 deletions(-) diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 0934cd02f8bd..785db9829992 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -79,6 +79,8 @@ public class PowerManagerService extends IPowerManager.Stub 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 @@ public class PowerManagerService extends IPowerManager.Stub 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 @@ public class PowerManagerService extends IPowerManager.Stub 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 @@ public class PowerManagerService extends IPowerManager.Stub + " " + ((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 @@ public class PowerManagerService extends IPowerManager.Stub } } - 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 @@ public class PowerManagerService extends IPowerManager.Stub // 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 @@ public class PowerManagerService extends IPowerManager.Stub 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 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, mBroadcastWakeLock.mCount); - updateNativePowerStateLocked(); + updateLightsLocked(mPowerState, SCREEN_ON_BIT); mBroadcastWakeLock.release(); } } @@ -1646,6 +1664,11 @@ public class PowerManagerService extends IPowerManager.Stub }; 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 @@ public class PowerManagerService extends IPowerManager.Stub } else { newState &= ~BATTERY_LOW_BIT; } - if (newState == mPowerState) { + if (newState == mPowerState && mInitialized) { return; } @@ -1722,10 +1745,7 @@ public class PowerManagerService extends IPowerManager.Stub + " 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 @@ public class PowerManagerService extends IPowerManager.Stub 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 @@ public class PowerManagerService extends IPowerManager.Stub 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