summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dianne Hackborn <hackbod@google.com> 2011-09-21 10:55:12 -0700
committer Dianne Hackborn <hackbod@google.com> 2011-09-21 13:15:02 -0700
commitbeae3bd6d34472d27ac5698f8d9bcbc12d0cf4f0 (patch)
treecc0e7eeb8aa6d53c11412a31bb506e6d5fb274f1
parenta80599f5be394edd9f3918ba03c490850a1d9e7f (diff)
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
-rw-r--r--services/java/com/android/server/PowerManagerService.java128
1 files 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<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 @@ 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.
@@ -1960,6 +2019,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) {