diff options
-rw-r--r-- | core/java/android/os/IPowerManager.aidl | 1 | ||||
-rw-r--r-- | core/java/android/os/PowerManager.java | 43 | ||||
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 67 |
3 files changed, 107 insertions, 4 deletions
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl index 5486920..188e7ff 100644 --- a/core/java/android/os/IPowerManager.aidl +++ b/core/java/android/os/IPowerManager.aidl @@ -26,6 +26,7 @@ interface IPowerManager void userActivity(long when, boolean noChangeLights); void userActivityWithForce(long when, boolean noChangeLights, boolean force); void setPokeLock(int pokey, IBinder lock, String tag); + int getSupportedWakeLockFlags(); void setStayOnSetting(int val); long getScreenOnTime(); void preventScreenOn(boolean prevent); diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index bfcf2fc..d5934102 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -114,12 +114,14 @@ public class PowerManager private static final int WAKE_BIT_SCREEN_DIM = 4; private static final int WAKE_BIT_SCREEN_BRIGHT = 8; private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16; + private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32; private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG | WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM | WAKE_BIT_SCREEN_BRIGHT - | WAKE_BIT_KEYBOARD_BRIGHT; + | WAKE_BIT_KEYBOARD_BRIGHT + | WAKE_BIT_PROXIMITY_SCREEN_OFF; /** * Wake lock that ensures that the CPU is running. The screen might @@ -147,6 +149,16 @@ public class PowerManager public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM; /** + * Wake lock that turns the screen off when the proximity sensor activates. + * Since not all devices have proximity sensors, use + * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if + * this wake lock mode is supported. + * + * {@hide} + */ + public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF; + + /** * Normally wake locks don't actually wake the device, they just cause * it to remain on once it's already on. Think of the video player * app as the normal behavior. Notifications that pop up and want @@ -196,6 +208,7 @@ public class PowerManager case SCREEN_DIM_WAKE_LOCK: case SCREEN_BRIGHT_WAKE_LOCK: case FULL_WAKE_LOCK: + case PROXIMITY_SCREEN_OFF_WAKE_LOCK: break; default: throw new IllegalArgumentException(); @@ -365,7 +378,33 @@ public class PowerManager } catch (RemoteException e) { } } - + + /** + * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()} + * that are supported on the device. + * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} + * is supported: + * + * {@samplecode + * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); + * int supportedFlags = pm.getSupportedWakeLockFlags(); + * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) + * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK); + * } + * + * @return the set of supported WakeLock flags. + * + * {@hide} + */ + public int getSupportedWakeLockFlags() + { + try { + return mService.getSupportedWakeLockFlags(); + } catch (RemoteException e) { + return 0; + } + } + private PowerManager() { } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 79d78ad..a3c3436 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -29,6 +29,10 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.database.Cursor; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; import android.os.BatteryStats; import android.os.Binder; import android.os.Handler; @@ -58,7 +62,8 @@ import java.util.HashMap; import java.util.Observable; import java.util.Observer; -class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor { +class PowerManagerService extends IPowerManager.Stub + implements LocalPowerManager,Watchdog.Monitor, SensorEventListener { private static final String TAG = "PowerManagerService"; static final String PARTIAL_NAME = "PowerManagerService"; @@ -72,7 +77,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.SCREEN_BRIGHT_WAKE_LOCK - | PowerManager.FULL_WAKE_LOCK; + | PowerManager.FULL_WAKE_LOCK + | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK; // time since last state: time since last event: // The short keylight delay comes from Gservices; this is the default. @@ -138,6 +144,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private int[] mBroadcastQueue = new int[] { -1, -1, -1 }; private int[] mBroadcastWhy = new int[3]; private int mPartialCount = 0; + private int mProximityCount = 0; private int mPowerState; private boolean mOffBecauseOfUser; private int mUserState; @@ -175,6 +182,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private IActivityManager mActivityService; private IBatteryStats mBatteryStats; private BatteryService mBatteryService; + private SensorManager mSensorManager; + private Sensor mProximitySensor; private boolean mDimScreen = true; private long mNextTimeout; private volatile int mPokey = 0; @@ -536,6 +545,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage wl.minState = SCREEN_DIM; break; case PowerManager.PARTIAL_WAKE_LOCK: + case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: break; default: // just log and bail. we're in the server, so don't @@ -583,6 +593,11 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } } Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME); + } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) { + mProximityCount++; + if (mProximityCount == 1) { + enableProximityLockLocked(); + } } if (newlock) { acquireUid = wl.uid; @@ -639,6 +654,11 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag); Power.releaseWakeLock(PARTIAL_NAME); } + } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) { + mProximityCount--; + if (mProximityCount == 0) { + disableProximityLockLocked(); + } } // Unlink the lock from the binder. wl.binder.unlinkToDeath(wl, 0); @@ -1996,4 +2016,47 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage public void monitor() { synchronized (mLocks) { } } + + public int getSupportedWakeLockFlags() { + int result = PowerManager.PARTIAL_WAKE_LOCK + | PowerManager.FULL_WAKE_LOCK + | PowerManager.SCREEN_DIM_WAKE_LOCK; + + // call getSensorManager() to make sure mProximitySensor is initialized + getSensorManager(); + if (mProximitySensor != null) { + result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK; + } + + return result; + } + + private SensorManager getSensorManager() { + if (mSensorManager == null) { + mSensorManager = new SensorManager(mHandlerThread.getLooper()); + mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); + } + return mSensorManager; + } + + private void enableProximityLockLocked() { + mSensorManager.registerListener(this, mProximitySensor, SensorManager.SENSOR_DELAY_NORMAL); + } + + private void disableProximityLockLocked() { + mSensorManager.unregisterListener(this); + } + + public void onSensorChanged(SensorEvent event) { + long milliseconds = event.timestamp / 1000000; + if (event.values[0] == 0.0) { + goToSleep(milliseconds); + } else { + userActivity(milliseconds, false); + } + } + + public void onAccuracyChanged(Sensor sensor, int accuracy) { + // ignore + } } |