diff options
Diffstat (limited to 'services/java/com/android/server/PowerManagerService.java')
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 165 |
1 files changed, 127 insertions, 38 deletions
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index bb21d81..78dbbd6 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 @@ -161,7 +163,9 @@ public class PowerManagerService extends IPowerManager.Stub private int mStayOnConditions = 0; private final int[] mBroadcastQueue = new int[] { -1, -1, -1 }; private final int[] mBroadcastWhy = new int[3]; - private boolean mBroadcastingScreenOff = false; + 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,10 @@ 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(); + mInitialized = true; } } @@ -1122,7 +1130,9 @@ public class PowerManagerService extends IPowerManager.Stub pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now + " " + ((mNextTimeout-now)/1000) + "s from now"); pw.println(" mDimScreen=" + mDimScreen - + " mStayOnConditions=" + mStayOnConditions); + + " mStayOnConditions=" + mStayOnConditions + + " mPreparingForScreenOn=" + mPreparingForScreenOn + + " mSkippedScreenOn=" + mSkippedScreenOn); pw.println(" mScreenOffReason=" + mScreenOffReason + " mUserState=" + mUserState); pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1] @@ -1311,8 +1321,23 @@ 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 (DEBUG_SCREEN_ON) { + RuntimeException here = new RuntimeException("here"); + here.fillInStackTrace(); + Slog.i(TAG, "sendNotificationLocked: " + on, here); + } + if (!on) { mStillNeedSleepNotification = false; } @@ -1341,7 +1366,9 @@ public class PowerManagerService extends IPowerManager.Stub mBroadcastQueue[0] = on ? 1 : 0; mBroadcastQueue[1] = -1; mBroadcastQueue[2] = -1; + EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount); mBroadcastWakeLock.release(); + EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount); mBroadcastWakeLock.release(); index = 0; } @@ -1357,7 +1384,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) { @@ -1371,6 +1400,21 @@ public class PowerManagerService extends IPowerManager.Stub } } + private WindowManagerPolicy.ScreenOnListener mScreenOnListener = + new WindowManagerPolicy.ScreenOnListener() { + @Override public void onScreenOn() { + synchronized (mLocks) { + if (mPreparingForScreenOn) { + mPreparingForScreenOn = false; + updateLightsLocked(mPowerState, SCREEN_ON_BIT); + EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, + 4, mBroadcastWakeLock.mCount); + mBroadcastWakeLock.release(); + } + } + } + }; + private Runnable mNotificationTask = new Runnable() { public void run() @@ -1387,14 +1431,17 @@ public class PowerManagerService extends IPowerManager.Stub mBroadcastWhy[i] = mBroadcastWhy[i+1]; } policy = getPolicyLocked(); - if (value == 0) { - mBroadcastingScreenOff = true; + if (value == 1 && !mPreparingForScreenOn) { + mPreparingForScreenOn = true; + mBroadcastWakeLock.acquire(); + EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, + mBroadcastWakeLock.mCount); } } if (value == 1) { mScreenOnStart = SystemClock.uptimeMillis(); - policy.screenTurnedOn(); + policy.screenTurningOn(mScreenOnListener); try { ActivityManagerNative.getDefault().wakingUp(); } catch (RemoteException e) { @@ -1432,8 +1479,7 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, mBroadcastWakeLock.mCount); - mBroadcastingScreenOff = false; - updateNativePowerStateLocked(); + updateLightsLocked(mPowerState, SCREEN_ON_BIT); mBroadcastWakeLock.release(); } } @@ -1464,10 +1510,6 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount); - synchronized (mLocks) { - mBroadcastingScreenOff = false; - updateNativePowerStateLocked(); - } mBroadcastWakeLock.release(); } } @@ -1630,6 +1672,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); @@ -1680,7 +1727,7 @@ public class PowerManagerService extends IPowerManager.Stub } else { newState &= ~BATTERY_LOW_BIT; } - if (newState == mPowerState) { + if (newState == mPowerState && mInitialized) { return; } @@ -1706,10 +1753,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) { @@ -1761,10 +1805,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; @@ -1787,29 +1845,18 @@ 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(); } } - + private void updateNativePowerStateLocked() { - if ((mPowerState & SCREEN_ON_BIT) != 0) { - // Don't turn screen on if we are currently reporting a screen off. - // This is to avoid letting the screen go on before things like the - // lock screen have been displayed due to it going off. - if (mBroadcastingScreenOff) { - // Currently broadcasting that the screen is off. Don't - // allow screen to go on until that is done. - return; - } - for (int i=0; i<mBroadcastQueue.length; i++) { - if (mBroadcastQueue[i] == 0) { - // A screen off is currently enqueued. - return; - } - } - } nativeSetPowerState( (mPowerState & SCREEN_ON_BIT) != 0, (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT); @@ -1835,8 +1882,43 @@ public class PowerManagerService extends IPowerManager.Stub 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. @@ -1943,6 +2025,13 @@ public class PowerManagerService extends IPowerManager.Stub } 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) { |