Merge "Clean up PowerManager API."

This commit is contained in:
Jeff Brown
2012-06-19 18:48:20 -07:00
committed by Android (Google) Code Review
3 changed files with 474 additions and 399 deletions

View File

@@ -19,19 +19,21 @@ package android.os;
import android.util.Log;
/**
* This class gives you control of the power state of the device.
*
* <p><b>Device battery life will be significantly affected by the use of this API.</b> Do not
* acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
* to release it as soon as you can.
*
* <p>You can obtain an instance of this class by calling
* This class gives you control of the power state of the device.
*
* <p>
* <b>Device battery life will be significantly affected by the use of this API.</b>
* Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
* possible, and be sure to release them as soon as possible.
* </p><p>
* You can obtain an instance of this class by calling
* {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
*
* <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}. This will
* create a {@link PowerManager.WakeLock} object. You can then use methods on this object to
* control the power state of the device. In practice it's quite simple:
*
* </p><p>
* The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
* This will create a {@link PowerManager.WakeLock} object. You can then use methods
* on the wake lock object to control the power state of the device.
* </p><p>
* In practice it's quite simple:
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
@@ -39,11 +41,11 @@ import android.util.Log;
* ..screen will stay on during this section..
* wl.release();
* }
*
* <p>The following flags are defined, with varying effects on system power. <i>These flags are
* mutually exclusive - you may only specify one of them.</i>
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* </p><p>
* The following flags are defined, with varying effects on system power.
* <i>These flags are mutually exclusive - you may only specify one of them.</i>
*
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* <thead>
* <tr><th>Flag Value</th>
* <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
@@ -67,15 +69,16 @@ import android.util.Log;
* </tr>
* </tbody>
* </table>
*
* <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers
* and even after the user presses the power button. In all other wakelocks, the CPU will run, but
* the user can still put the device to sleep using the power button.</i>
*
* <p>In addition, you can add two more flags, which affect behavior of the screen only. <i>These
* flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* </p><p>
* *<i>If you hold a partial wake lock, the CPU will continue to run, regardless of any
* display timeouts or the state of the screen and even after the user presses the power button.
* In all other wake locks, the CPU will run, but the user can still put the device to sleep
* using the power button.</i>
* </p><p>
* In addition, you can add two more flags, which affect behavior of the screen only.
* <i>These flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
*
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* <thead>
* <tr><th>Flag Value</th> <th>Description</th></tr>
* </thead>
@@ -96,73 +99,77 @@ import android.util.Log;
* </tr>
* </tbody>
* </table>
*
* </p><p>
* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
* permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
* </p>
*/
public class PowerManager
{
public final class PowerManager {
private static final String TAG = "PowerManager";
/**
/*
* These internal values define the underlying power elements that we might
* want to control individually. Eventually we'd like to expose them.
*/
private static final int WAKE_BIT_CPU_STRONG = 1;
private static final int WAKE_BIT_CPU_WEAK = 2;
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 WAKE_BIT_CPU_STRONG = 1 << 0;
private static final int WAKE_BIT_CPU_WEAK = 1 << 1;
private static final int WAKE_BIT_SCREEN_DIM = 1 << 2;
private static final int WAKE_BIT_SCREEN_BRIGHT = 1 << 3;
private static final int WAKE_BIT_KEYBOARD_BRIGHT = 1 << 4;
private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 1 << 5;
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_PROXIMITY_SCREEN_OFF;
| WAKE_BIT_CPU_WEAK
| WAKE_BIT_SCREEN_DIM
| WAKE_BIT_SCREEN_BRIGHT
| WAKE_BIT_KEYBOARD_BRIGHT
| WAKE_BIT_PROXIMITY_SCREEN_OFF;
/**
* Wake lock that ensures that the CPU is running. The screen might
* not be on.
* Wake lock level: Ensures that the CPU is running; the screen and keyboard
* backlight will be allowed to go off.
*/
public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
/**
* Wake lock that ensures that the screen and keyboard are on at
* Wake lock level: Ensures that the screen and keyboard backlight are on at
* full brightness.
*
* <p class="note">Most applications should strongly consider using
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
* This window flag will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.</p>
* <p class="note">
* Most applications should strongly consider using
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
* of managing their own wake locks. This window flag will be correctly managed
* by the platform as the user moves between applications and doesn't require
* a special permission.
* </p>
*/
public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
| WAKE_BIT_KEYBOARD_BRIGHT;
| WAKE_BIT_KEYBOARD_BRIGHT;
/**
* Wake lock level: Ensures that the screen is on at full brightness;
* the keyboard backlight will be allowed to go off.
*
* @deprecated Most applications should use
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead
* of this type of wake lock, as it will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.
*
* Wake lock that ensures that the screen is on at full brightness;
* the keyboard backlight will be allowed to go off.
*/
@Deprecated
public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
/**
* Wake lock that ensures that the screen is on (but may be dimmed);
* Wake lock level: Ensures that the screen is on (but may be dimmed);
* the keyboard backlight will be allowed to go off.
*/
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.
* Wake lock level: Turns the screen off when the proximity sensor activates.
* <p>
* Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags()}
* to determine whether this wake lock level is supported.
* </p>
*
* {@hide}
*/
@@ -170,7 +177,7 @@ public class PowerManager
/**
* Flag for {@link WakeLock#release release(int)} to defer releasing a
* {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
* {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns
* a negative value.
*
* {@hide}
@@ -178,25 +185,29 @@ public class PowerManager
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
/**
* Wake lock flag: Turn the screen on when the wake lock is acquired.
* <p>
* 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
* the screen to remain on once it's already on. Think of the video player
* application as the normal behavior. Notifications that pop up and want
* the device to be on are the exception; use this flag to be like them.
* <p>
* Does not work with PARTIAL_WAKE_LOCKs.
* </p><p>
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
* </p>
*/
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
public static final int ACQUIRE_CAUSES_WAKEUP = 1 << 28;
/**
* When this wake lock is released, poke the user activity timer
* Wake lock flag: When this wake lock is released, poke the user activity timer
* so the screen stays on for a little longer.
* <p>
* Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP}
* if you want that.
* <p>
* Does not work with PARTIAL_WAKE_LOCKs.
* Will not turn the screen on if it is not already on.
* See {@link #ACQUIRE_CAUSES_WAKEUP} if you want that.
* </p><p>
* Cannot be used with {@link #PARTIAL_WAKE_LOCK}.
* </p>
*/
public static final int ON_AFTER_RELEASE = 0x20000000;
public static final int ON_AFTER_RELEASE = 1 << 29;
/**
* Brightness value to use when battery is low.
@@ -222,179 +233,253 @@ public class PowerManager
*/
public static final int BRIGHTNESS_OFF = 0;
final IPowerManager mService;
final Handler mHandler;
/**
* Class lets you say that you need to have the device on.
* {@hide}
*/
public PowerManager(IPowerManager service, Handler handler) {
mService = service;
mHandler = handler;
}
/**
* Creates a new wake lock with the specified level and flags.
* <p>
* Call release when you are done and don't need the lock anymore.
* The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
* combined using the logical OR operator.
* </p><p>
* The wake lock levels are: {@link #PARTIAL_WAKE_LOCK},
* {@link #FULL_WAKE_LOCK}, {@link #SCREEN_DIM_WAKE_LOCK}
* and {@link #SCREEN_BRIGHT_WAKE_LOCK}. Exactly one wake lock level must be
* specified as part of the {@code levelAndFlags} parameter.
* </p><p>
* The wake lock flags are: {@link #ACQUIRE_CAUSES_WAKEUP}
* and {@link #ON_AFTER_RELEASE}. Multiple flags can be combined as part of the
* {@code levelAndFlags} parameters.
* </p><p>
* Call {@link WakeLock#acquire() acquire()} on the object to acquire the
* wake lock, and {@link WakeLock#release release()} when you are done.
* </p><p>
* {@samplecode
* PowerManager pm = (PowerManager)mContext.getSystemService(
* Context.POWER_SERVICE);
* PowerManager.WakeLock wl = pm.newWakeLock(
* PowerManager.SCREEN_DIM_WAKE_LOCK
* | PowerManager.ON_AFTER_RELEASE,
* TAG);
* wl.acquire();
* // ... do work...
* wl.release();
* }
* </p><p>
* Although a wake lock can be created without special permissions,
* the {@link android.Manifest.permission#WAKE_LOCK} permission is
* required to actually acquire or release the wake lock that is returned.
* </p><p class="note">
* If using this to keep the screen on, you should strongly consider using
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
* This window flag will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.
* </p>
*
* @param levelAndFlags Combination of wake lock level and flag values defining
* the requested behavior of the WakeLock.
* @param tag Your class name (or other tag) for debugging purposes.
*
* @see WakeLock#acquire()
* @see WakeLock#release()
* @see #PARTIAL_WAKE_LOCK
* @see #FULL_WAKE_LOCK
* @see #SCREEN_DIM_WAKE_LOCK
* @see #SCREEN_BRIGHT_WAKE_LOCK
* @see #ACQUIRE_CAUSES_WAKEUP
* @see #ON_AFTER_RELEASE
*/
public WakeLock newWakeLock(int levelAndFlags, String tag) {
switch (levelAndFlags & LOCK_MASK) {
case PARTIAL_WAKE_LOCK:
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("Must specify a wake lock level.");
}
if (tag == null) {
throw new IllegalArgumentException("The tag must not be null.");
}
return new WakeLock(levelAndFlags, tag);
}
/**
* Notifies the power manager that user activity happened.
* <p>
* Turns the device from whatever state it's in to full on, and resets
* the auto-off timer.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param when The time of the user activity, in the {@link SystemClock#uptimeMillis()}
* time base. This timestamp is used to correctly order the user activity with
* other power management functions. It should be set
* to the timestamp of the input event that caused the user activity.
* @param noChangeLights If true, does not cause the keyboard backlight to turn on
* because of this event. This is set when the power key is pressed.
* We want the device to stay on while the button is down, but we're about
* to turn off the screen so we don't want the keyboard backlight to turn on again.
* Otherwise the lights flash on and then off and it looks weird.
*/
public void userActivity(long when, boolean noChangeLights) {
try {
mService.userActivity(when, noChangeLights);
} catch (RemoteException e) {
}
}
/**
* Forces the device to go to sleep.
* <p>
* Overrides all the wake locks that are held. This is what happen when the power
* key is pressed to turn off the screen.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param time The time when the request to go to sleep was issued, in the
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
* order the user activity with other power management functions. It should be set
* to the timestamp of the input event that caused the request to go to sleep.
*/
public void goToSleep(long time) {
try {
mService.goToSleep(time);
} catch (RemoteException e) {
}
}
/**
* Sets the brightness of the backlights (screen, keyboard, button).
* <p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
*
* @param brightness The brightness value from 0 to 255.
*
* {@hide}
*/
public void setBacklightBrightness(int brightness) {
try {
mService.setBacklightBrightness(brightness);
} catch (RemoteException e) {
}
}
/**
* Returns the set of wake lock levels and flags for {@link #newWakeLock}
* that are supported on the device.
* <p>
* 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);
* }
* </p>
*
* @return The set of supported WakeLock flags.
*
* {@hide}
*/
public int getSupportedWakeLockFlags() {
try {
return mService.getSupportedWakeLockFlags();
} catch (RemoteException e) {
return 0;
}
}
/**
* Returns whether the screen is currently on.
* <p>
* Only indicates whether the screen is on. The screen could be either bright or dim.
* </p><p>
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* boolean isScreenOn = pm.isScreenOn();
* }
* </p>
*
* @return whether the screen is on (bright or dim).
*/
public boolean isScreenOn() {
try {
return mService.isScreenOn();
} catch (RemoteException e) {
return false;
}
}
/**
* Reboot the device. Will not return if the reboot is successful.
* <p>
* Requires the {@link android.Manifest.permission#REBOOT} permission.
* </p>
*
* @param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
*/
public void reboot(String reason) {
try {
mService.reboot(reason);
} catch (RemoteException e) {
}
}
/**
* A wake lock is a mechanism to indicate that your application needs
* to have the device stay on.
* <p>
* Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
* permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
* Obtain a wake lock by calling {@link PowerManager#newWakeLock(int, String)}.
* </p><p>
* Call {@link #acquire()} to acquire the wake lock and force the device to stay
* on at the level that was requested when the wake lock was created.
* </p><p>
* Call {@link #release()} when you are done and don't need the lock anymore.
* It is very important to do this as soon as possible to avoid running down the
* device's battery excessively.
* </p>
*/
public class WakeLock
{
static final int RELEASE_WAKE_LOCK = 1;
public final class WakeLock {
private final int mFlags;
private final String mTag;
private final IBinder mToken;
private int mCount;
private boolean mRefCounted = true;
private boolean mHeld;
private WorkSource mWorkSource;
Runnable mReleaser = new Runnable() {
private final Runnable mReleaser = new Runnable() {
public void run() {
release();
}
};
int mFlags;
String mTag;
IBinder mToken;
int mCount = 0;
boolean mRefCounted = true;
boolean mHeld = false;
WorkSource mWorkSource;
WakeLock(int flags, String tag)
{
switch (flags & LOCK_MASK) {
case PARTIAL_WAKE_LOCK:
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();
}
WakeLock(int flags, String tag) {
mFlags = flags;
mTag = tag;
mToken = new Binder();
}
/**
* Sets whether this WakeLock is ref counted.
*
* <p>Wake locks are reference counted by default.
*
* @param value true for ref counted, false for not ref counted.
*/
public void setReferenceCounted(boolean value)
{
mRefCounted = value;
}
/**
* Makes sure the device is on at the level you asked when you created
* the wake lock.
*/
public void acquire()
{
synchronized (mToken) {
acquireLocked();
}
}
/**
* Makes sure the device is on at the level you asked when you created
* the wake lock. The lock will be released after the given timeout.
*
* @param timeout Release the lock after the give timeout in milliseconds.
*/
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
mHandler.removeCallbacks(mReleaser);
try {
mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
}
}
/**
* Release your claim to the CPU or screen being on.
*
* <p>
* It may turn off shortly after you release it, or it may not if there
* are other wake locks held.
*/
public void release() {
release(0);
}
/**
* Release your claim to the CPU or screen being on.
* @param flags Combination of flag values to modify the release behavior.
* Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
*
* <p>
* It may turn off shortly after you release it, or it may not if there
* are other wake locks held.
*
* {@hide}
*/
public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
public boolean isHeld()
{
synchronized (mToken) {
return mHeld;
}
}
public void setWorkSource(WorkSource ws) {
synchronized (mToken) {
if (ws != null && ws.size() == 0) {
ws = null;
}
boolean changed = true;
if (ws == null) {
mWorkSource = null;
} else if (mWorkSource == null) {
changed = mWorkSource != null;
mWorkSource = new WorkSource(ws);
} else {
changed = mWorkSource.diff(ws);
if (changed) {
mWorkSource.set(ws);
}
}
if (changed && mHeld) {
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource);
} catch (RemoteException e) {
}
}
}
}
public String toString() {
synchronized (mToken) {
return "WakeLock{"
+ Integer.toHexString(System.identityHashCode(this))
+ " held=" + mHeld + ", refCount=" + mCount + "}";
}
}
@Override
protected void finalize() throws Throwable
{
protected void finalize() throws Throwable {
synchronized (mToken) {
if (mHeld) {
Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
@@ -405,180 +490,170 @@ public class PowerManager
}
}
}
}
/**
* Get a wake lock at the level of the flags parameter. Call
* {@link WakeLock#acquire() acquire()} on the object to acquire the
* wake lock, and {@link WakeLock#release release()} when you are done.
*
* {@samplecode
*PowerManager pm = (PowerManager)mContext.getSystemService(
* Context.POWER_SERVICE);
*PowerManager.WakeLock wl = pm.newWakeLock(
* PowerManager.SCREEN_DIM_WAKE_LOCK
* | PowerManager.ON_AFTER_RELEASE,
* TAG);
*wl.acquire();
* // ...
*wl.release();
* }
*
* <p class="note">If using this to keep the screen on, you should strongly consider using
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
* This window flag will be correctly managed by the platform
* as the user moves between applications and doesn't require a special permission.</p>
*
* @param flags Combination of flag values defining the requested behavior of the WakeLock.
* @param tag Your class name (or other tag) for debugging purposes.
*
* @see WakeLock#acquire()
* @see WakeLock#release()
*/
public WakeLock newWakeLock(int flags, String tag)
{
if (tag == null) {
throw new NullPointerException("tag is null in PowerManager.newWakeLock");
/**
* Sets whether this WakeLock is reference counted.
* <p>
* Wake locks are reference counted by default. If a wake lock is
* reference counted, then each call to {@link #acquire()} must be
* balanced by an equal number of calls to {@link #release()}. If a wake
* lock is not reference counted, then one call to {@link #release()} is
* sufficient to undo the effect of all previous calls to {@link #acquire()}.
* </p>
*
* @param value True to make the wake lock reference counted, false to
* make the wake lock non-reference counted.
*/
public void setReferenceCounted(boolean value) {
synchronized (mToken) {
mRefCounted = value;
}
}
return new WakeLock(flags, tag);
}
/**
* User activity happened.
* <p>
* Turns the device from whatever state it's in to full on, and resets
* the auto-off timer.
*
* @param when is used to order this correctly with the wake lock calls.
* This time should be in the {@link SystemClock#uptimeMillis
* SystemClock.uptimeMillis()} time base.
* @param noChangeLights should be true if you don't want the lights to
* turn on because of this event. This is set when the power
* key goes down. We want the device to stay on while the button
* is down, but we're about to turn off. Otherwise the lights
* flash on and then off and it looks weird.
*/
public void userActivity(long when, boolean noChangeLights)
{
try {
mService.userActivity(when, noChangeLights);
} catch (RemoteException e) {
/**
* Acquires the wake lock.
* <p>
* Ensures that the device is on at the level requested when
* the wake lock was created.
* </p>
*/
public void acquire() {
synchronized (mToken) {
acquireLocked();
}
}
/**
* Acquires the wake lock with a timeout.
* <p>
* Ensures that the device is on at the level requested when
* the wake lock was created. The lock will be released after the given timeout
* expires.
* </p>
*
* @param timeout The timeout after which to release the wake lock, in milliseconds.
*/
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
private void acquireLocked() {
if (!mRefCounted || mCount++ == 0) {
mHandler.removeCallbacks(mReleaser);
if (!mHeld) {
try {
mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
}
}
}
/**
* Releases the wake lock.
* <p>
* This method releases your claim to the CPU or screen being on.
* The screen may turn off shortly after you release the wake lock, or it may
* not if there are other wake locks still held.
* </p>
*/
public void release() {
release(0);
}
/**
* Releases the wake lock with flags to modify the release behavior.
* <p>
* This method releases your claim to the CPU or screen being on.
* The screen may turn off shortly after you release the wake lock, or it may
* not if there are other wake locks still held.
* </p>
*
* @param flags Combination of flag values to modify the release behavior.
* Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
*
* {@hide}
*/
public void release(int flags) {
synchronized (mToken) {
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser);
if (mHeld) {
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}
if (mCount < 0) {
throw new RuntimeException("WakeLock under-locked " + mTag);
}
}
}
/**
* Returns true if the wake lock has been acquired but not yet released.
*
* @return True if the wake lock is held.
*/
public boolean isHeld() {
synchronized (mToken) {
return mHeld;
}
}
/**
* Sets the work source associated with the wake lock.
* <p>
* The work source is used to determine on behalf of which application
* the wake lock is being held. This is useful in the case where a
* service is performing work on behalf of an application so that the
* cost of that work can be accounted to the application.
* </p>
*
* @param ws The work source, or null if none.
*/
public void setWorkSource(WorkSource ws) {
synchronized (mToken) {
if (ws != null && ws.size() == 0) {
ws = null;
}
final boolean changed;
if (ws == null) {
changed = mWorkSource != null;
mWorkSource = null;
} else if (mWorkSource == null) {
changed = true;
mWorkSource = new WorkSource(ws);
} else {
changed = mWorkSource.diff(ws);
if (changed) {
mWorkSource.set(ws);
}
}
if (changed && mHeld) {
try {
mService.updateWakeLockWorkSource(mToken, mWorkSource);
} catch (RemoteException e) {
}
}
}
}
@Override
public String toString() {
synchronized (mToken) {
return "WakeLock{"
+ Integer.toHexString(System.identityHashCode(this))
+ " held=" + mHeld + ", refCount=" + mCount + "}";
}
}
}
/**
* Force the device to go to sleep. Overrides all the wake locks that are
* held.
*
* @param time is used to order this correctly with the wake lock calls.
* The time should be in the {@link SystemClock#uptimeMillis
* SystemClock.uptimeMillis()} time base.
*/
public void goToSleep(long time)
{
try {
mService.goToSleep(time);
} catch (RemoteException e) {
}
}
/**
* sets the brightness of the backlights (screen, keyboard, button).
*
* @param brightness value from 0 to 255
*
* {@hide}
*/
public void setBacklightBrightness(int brightness)
{
try {
mService.setBacklightBrightness(brightness);
} 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;
}
}
/**
* Returns whether the screen is currently on. The screen could be bright
* or dim.
*
* {@samplecode
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
* boolean isScreenOn = pm.isScreenOn();
* }
*
* @return whether the screen is on (bright or dim).
*/
public boolean isScreenOn()
{
try {
return mService.isScreenOn();
} catch (RemoteException e) {
return false;
}
}
/**
* Reboot the device. Will not return if the reboot is
* successful. Requires the {@link android.Manifest.permission#REBOOT}
* permission.
*
* @param reason code to pass to the kernel (e.g., "recovery") to
* request special boot modes, or null.
*/
public void reboot(String reason)
{
try {
mService.reboot(reason);
} catch (RemoteException e) {
}
}
private PowerManager()
{
}
/**
* {@hide}
*/
public PowerManager(IPowerManager service, Handler handler)
{
mService = service;
mHandler = handler;
}
/**
* TODO: It would be nice to be able to set the poke lock here,
* but I'm not sure what would be acceptable as an interface -
* either a PokeLock object (like WakeLock) or, possibly just a
* method call to set the poke lock.
*/
IPowerManager mService;
Handler mHandler;
}