@@ -130,11 +130,22 @@ public final class PowerManagerService extends IPowerManager.Stub
130130 private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000 ;
131131 private static final int MINIMUM_SCREEN_OFF_TIMEOUT = 10 * 1000 ;
132132
133- // The screen dim duration, in seconds .
133+ // The screen dim duration, in milliseconds .
134134 // This is subtracted from the end of the screen off timeout so the
135135 // minimum screen off timeout should be longer than this.
136136 private static final int SCREEN_DIM_DURATION = 7 * 1000 ;
137137
138+ // The maximum screen dim time expressed as a ratio relative to the screen
139+ // off timeout. If the screen off timeout is very short then we want the
140+ // dim timeout to also be quite short so that most of the time is spent on.
141+ // Otherwise the user won't get much screen on time before dimming occurs.
142+ private static final float MAXIMUM_SCREEN_DIM_RATIO = 0.2f ;
143+
144+ // Upper bound on the battery charge percentage in order to consider turning
145+ // the screen on when the device starts charging wirelessly.
146+ // See point of use for more details.
147+ private static final int WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT = 95 ;
148+
138149 private Context mContext ;
139150 private LightsService mLightsService ;
140151 private BatteryService mBatteryService ;
@@ -218,6 +229,9 @@ public final class PowerManagerService extends IPowerManager.Stub
218229 // True if the device is plugged into a power source.
219230 private boolean mIsPowered ;
220231
232+ // The current plug type, such as BatteryManager.BATTERY_PLUGGED_WIRELESS.
233+ private int mPlugType ;
234+
221235 // True if the device should wake up when plugged or unplugged.
222236 private boolean mWakeUpWhenPluggedOrUnpluggedConfig ;
223237
@@ -1013,15 +1027,19 @@ private void sendPendingNotificationsLocked() {
10131027 */
10141028 private void updateIsPoweredLocked (int dirty ) {
10151029 if ((dirty & DIRTY_BATTERY_STATE ) != 0 ) {
1016- boolean wasPowered = mIsPowered ;
1030+ final boolean wasPowered = mIsPowered ;
1031+ final int oldPlugType = mPlugType ;
10171032 mIsPowered = mBatteryService .isPowered (BatteryManager .BATTERY_PLUGGED_ANY );
1033+ mPlugType = mBatteryService .getPlugType ();
10181034
10191035 if (DEBUG ) {
10201036 Slog .d (TAG , "updateIsPoweredLocked: wasPowered=" + wasPowered
1021- + ", mIsPowered=" + mIsPowered );
1037+ + ", mIsPowered=" + mIsPowered
1038+ + ", oldPlugType=" + oldPlugType
1039+ + ", mPlugType=" + mPlugType );
10221040 }
10231041
1024- if (wasPowered != mIsPowered ) {
1042+ if (wasPowered != mIsPowered || oldPlugType != mPlugType ) {
10251043 mDirty |= DIRTY_IS_POWERED ;
10261044
10271045 // Treat plugging and unplugging the devices as a user activity.
@@ -1030,7 +1048,7 @@ private void updateIsPoweredLocked(int dirty) {
10301048 // Some devices also wake the device when plugged or unplugged because
10311049 // they don't have a charging LED.
10321050 final long now = SystemClock .uptimeMillis ();
1033- if (mWakeUpWhenPluggedOrUnpluggedConfig ) {
1051+ if (shouldWakeUpWhenPluggedOrUnpluggedLocked ( wasPowered , oldPlugType ) ) {
10341052 wakeUpNoUpdateLocked (now );
10351053 }
10361054 userActivityNoUpdateLocked (
@@ -1039,6 +1057,44 @@ private void updateIsPoweredLocked(int dirty) {
10391057 }
10401058 }
10411059
1060+ private boolean shouldWakeUpWhenPluggedOrUnpluggedLocked (boolean wasPowered , int oldPlugType ) {
1061+ if (mWakeUpWhenPluggedOrUnpluggedConfig ) {
1062+ // FIXME: Need more accurate detection of wireless chargers.
1063+ //
1064+ // We are unable to accurately detect whether the device is resting on the
1065+ // charger unless it is actually receiving power. This causes us some grief
1066+ // because the device might not appear to be plugged into the wireless charger
1067+ // unless it actually charging.
1068+ //
1069+ // To avoid spuriously waking the screen, we apply a special policy to
1070+ // wireless chargers.
1071+ //
1072+ // 1. Don't wake the device when unplugged from wireless charger because
1073+ // it might be that the device is still resting on the wireless charger
1074+ // but is not receiving power anymore because the battery is full.
1075+ //
1076+ // 2. Don't wake the device when plugged into a wireless charger if the
1077+ // battery already appears to be mostly full. This situation may indicate
1078+ // that the device was resting on the charger the whole time and simply
1079+ // wasn't receiving power because the battery was full. We can't tell
1080+ // whether the device was just placed on the charger or whether it has
1081+ // been there for half of the night slowly discharging until it hit
1082+ // the point where it needed to start charging again.
1083+ if (wasPowered && !mIsPowered
1084+ && oldPlugType == BatteryManager .BATTERY_PLUGGED_WIRELESS ) {
1085+ return false ;
1086+ }
1087+ if (!wasPowered && mIsPowered
1088+ && mPlugType == BatteryManager .BATTERY_PLUGGED_WIRELESS
1089+ && mBatteryService .getBatteryLevel () >=
1090+ WIRELESS_CHARGER_TURN_ON_BATTERY_LEVEL_LIMIT ) {
1091+ return false ;
1092+ }
1093+ return true ;
1094+ }
1095+ return false ;
1096+ }
1097+
10421098 /**
10431099 * Updates the value of mStayOn.
10441100 * Sets DIRTY_STAY_ON if a change occurred.
@@ -1118,7 +1174,7 @@ private void updateUserActivitySummaryLocked(long now, int dirty) {
11181174 long nextTimeout = 0 ;
11191175 if (mWakefulness != WAKEFULNESS_ASLEEP ) {
11201176 final int screenOffTimeout = getScreenOffTimeoutLocked ();
1121- final int screenDimDuration = getScreenDimDurationLocked ();
1177+ final int screenDimDuration = getScreenDimDurationLocked (screenOffTimeout );
11221178
11231179 mUserActivitySummary = 0 ;
11241180 if (mLastUserActivityTime >= mLastWakeTime ) {
@@ -1192,8 +1248,9 @@ private int getScreenOffTimeoutLocked() {
11921248 return Math .max (timeout , MINIMUM_SCREEN_OFF_TIMEOUT );
11931249 }
11941250
1195- private int getScreenDimDurationLocked () {
1196- return SCREEN_DIM_DURATION ;
1251+ private int getScreenDimDurationLocked (int screenOffTimeout ) {
1252+ return Math .min (SCREEN_DIM_DURATION ,
1253+ (int )(screenOffTimeout * MAXIMUM_SCREEN_DIM_RATIO ));
11971254 }
11981255
11991256 /**
@@ -1891,6 +1948,7 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
18911948 pw .println (" mDirty=0x" + Integer .toHexString (mDirty ));
18921949 pw .println (" mWakefulness=" + wakefulnessToString (mWakefulness ));
18931950 pw .println (" mIsPowered=" + mIsPowered );
1951+ pw .println (" mPlugType=" + mPlugType );
18941952 pw .println (" mStayOn=" + mStayOn );
18951953 pw .println (" mBootCompleted=" + mBootCompleted );
18961954 pw .println (" mSystemReady=" + mSystemReady );
@@ -1936,6 +1994,12 @@ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
19361994 pw .println (" mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum );
19371995 pw .println (" mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault );
19381996
1997+ final int screenOffTimeout = getScreenOffTimeoutLocked ();
1998+ final int screenDimDuration = getScreenDimDurationLocked (screenOffTimeout );
1999+ pw .println ();
2000+ pw .println ("Screen off timeout: " + screenOffTimeout + " ms" );
2001+ pw .println ("Screen dim duration: " + screenDimDuration + " ms" );
2002+
19392003 pw .println ();
19402004 pw .println ("Wake Locks: size=" + mWakeLocks .size ());
19412005 for (WakeLock wl : mWakeLocks ) {
0 commit comments