/**
* Wake lock level: Turns the screen off when the proximity sensor activates.
* <p>
+ * If the proximity sensor detects that an object is nearby, the screen turns off
+ * immediately. Shortly after the object moves away, the screen turns on again.
+ * </p><p>
+ * A proximity wake lock does not prevent the device from falling asleep
+ * unlike {@link #FULL_WAKE_LOCK}, {@link #SCREEN_BRIGHT_WAKE_LOCK} and
+ * {@link #SCREEN_DIM_WAKE_LOCK}. If there is no user activity and no other
+ * wake locks are held, then the device will fall asleep (and lock) as usual.
+ * However, the device will not fall asleep while the screen has been turned off
+ * by the proximity sensor because it effectively counts as ongoing user activity.
+ * </p><p>
* Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
* to determine whether this wake lock level is supported.
* </p>
private static final int PROXIMITY_NEGATIVE = 0;
private static final int PROXIMITY_POSITIVE = 1;
- // Proximity sensor debounce delay in milliseconds.
- private static final int PROXIMITY_SENSOR_DEBOUNCE_DELAY = 250;
+ // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
+ private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
+ private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 500;
// Trigger proximity if distance is less than 5 cm.
private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
if (!mScreenOffBecauseOfProximity
&& mProximity == PROXIMITY_POSITIVE) {
mScreenOffBecauseOfProximity = true;
+ sendOnProximityPositive();
setScreenOn(false);
}
} else if (mWaitingForNegativeProximity
// Only accept a proximity sensor reading if it remains
// stable for the entire debounce delay.
mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
- mPendingProximity = positive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE;
- mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_DEBOUNCE_DELAY;
+ if (positive) {
+ mPendingProximity = PROXIMITY_POSITIVE;
+ mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY;
+ } else {
+ mPendingProximity = PROXIMITY_NEGATIVE;
+ mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY;
+ }
debounceProximitySensor();
}
}
};
+ private void sendOnProximityPositive() {
+ mCallbackHandler.post(mOnProximityPositiveRunnable);
+ }
+
+ private final Runnable mOnProximityPositiveRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mCallbacks.onProximityPositive();
+ }
+ };
+
private void sendOnProximityNegative() {
mCallbackHandler.post(mOnProximityNegativeRunnable);
}
*/
public interface Callbacks {
void onStateChanged();
+ void onProximityPositive();
void onProximityNegative();
}
private static final int DIRTY_STAY_ON = 1 << 7;
// Dirty bit: battery state changed
private static final int DIRTY_BATTERY_STATE = 1 << 8;
+ // Dirty bit: proximity state changed
+ private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
// Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
// The screen should be off or in the process of being turned off by the display controller.
// True if the device should stay on.
private boolean mStayOn;
+ // True if the proximity sensor reads a positive result.
+ private boolean mProximityPositive;
+
// Screen brightness setting limits.
private int mScreenBrightnessSettingMinimum;
private int mScreenBrightnessSettingMaximum;
*/
private void updateStayOnLocked(int dirty) {
if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
+ final boolean wasStayOn = mStayOn;
if (mStayOnWhilePluggedInSetting != 0
&& !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);
} else {
mStayOn = false;
}
+
+ if (mStayOn != wasStayOn) {
+ mDirty |= DIRTY_STAY_ON;
+ }
}
}
private boolean updateWakefulnessLocked(int dirty) {
boolean changed = false;
if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
- | DIRTY_WAKEFULNESS | DIRTY_STAY_ON)) != 0) {
+ | DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
* to being fully awake or else go to sleep for good.
*/
private boolean isItBedTimeYetLocked() {
- return mBootCompleted && !isScreenBeingKeptOnLocked();
+ return mBootCompleted && !isBeingKeptAwakeLocked();
}
/**
- * Returns true if the screen is being kept on by a wake lock, user activity
+ * Returns true if the device is being kept awake by a wake lock, user activity
* or the stay on while powered setting.
*/
- private boolean isScreenBeingKeptOnLocked() {
+ private boolean isBeingKeptAwakeLocked() {
return mStayOn
- || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
- | WAKE_LOCK_PROXIMITY_SCREEN_OFF)) != 0
+ || mProximityPositive
+ || (mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
| USER_ACTIVITY_SCREEN_DIM)) != 0;
}
| DIRTY_SETTINGS
| DIRTY_IS_POWERED
| DIRTY_STAY_ON
+ | DIRTY_PROXIMITY_POSITIVE
| DIRTY_BATTERY_STATE)) != 0) {
scheduleSandmanLocked();
}
&& mDreamsEnabledSetting
&& mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF
&& mBootCompleted
- && (mIsPowered || isScreenBeingKeptOnLocked());
+ && (mIsPowered || isBeingKeptAwakeLocked());
}
/**
}
@Override
+ public void onProximityPositive() {
+ mProximityPositive = true;
+ mDirty |= DIRTY_PROXIMITY_POSITIVE;
+ updatePowerStateLocked();
+ }
+
+ @Override
public void onProximityNegative() {
+ mProximityPositive = false;
+ mDirty |= DIRTY_PROXIMITY_POSITIVE;
userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
pw.println(" mIsPowered=" + mIsPowered);
pw.println(" mPlugType=" + mPlugType);
pw.println(" mStayOn=" + mStayOn);
+ pw.println(" mProximityPositive=" + mProximityPositive);
pw.println(" mBootCompleted=" + mBootCompleted);
pw.println(" mSystemReady=" + mSystemReady);
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));