547 lines
18 KiB
Java
547 lines
18 KiB
Java
|
/*
|
||
|
* Copyright (C) 2007 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.os;
|
||
|
|
||
|
import android.util.Log;
|
||
|
|
||
|
import com.android.internal.os.RuntimeInit;
|
||
|
|
||
|
/**
|
||
|
* 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
|
||
|
* {@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:
|
||
|
*
|
||
|
* {@samplecode
|
||
|
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
|
||
|
* PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
|
||
|
* wl.acquire();
|
||
|
* ..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">
|
||
|
*
|
||
|
* <thead>
|
||
|
* <tr><th>Flag Value</th>
|
||
|
* <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
|
||
|
* </thead>
|
||
|
*
|
||
|
* <tbody>
|
||
|
* <tr><th>{@link #PARTIAL_WAKE_LOCK}</th>
|
||
|
* <td>On*</td> <td>Off</td> <td>Off</td>
|
||
|
* </tr>
|
||
|
*
|
||
|
* <tr><th>{@link #SCREEN_DIM_WAKE_LOCK}</th>
|
||
|
* <td>On</td> <td>Dim</td> <td>Off</td>
|
||
|
* </tr>
|
||
|
*
|
||
|
* <tr><th>{@link #SCREEN_BRIGHT_WAKE_LOCK}</th>
|
||
|
* <td>On</td> <td>Bright</td> <td>Off</td>
|
||
|
* </tr>
|
||
|
*
|
||
|
* <tr><th>{@link #FULL_WAKE_LOCK}</th>
|
||
|
* <td>On</td> <td>Bright</td> <td>Bright</td>
|
||
|
* </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">
|
||
|
*
|
||
|
* <thead>
|
||
|
* <tr><th>Flag Value</th> <th>Description</th></tr>
|
||
|
* </thead>
|
||
|
*
|
||
|
* <tbody>
|
||
|
* <tr><th>{@link #ACQUIRE_CAUSES_WAKEUP}</th>
|
||
|
* <td>Normal wake locks don't actually turn on the illumination. Instead, they cause
|
||
|
* the illumination to remain on once it turns on (e.g. from user activity). This flag
|
||
|
* will force the screen and/or keyboard to turn on immediately, when the WakeLock is
|
||
|
* acquired. A typical use would be for notifications which are important for the user to
|
||
|
* see immediately.</td>
|
||
|
* </tr>
|
||
|
*
|
||
|
* <tr><th>{@link #ON_AFTER_RELEASE}</th>
|
||
|
* <td>If this flag is set, the user activity timer will be reset when the WakeLock is
|
||
|
* released, causing the illumination to remain on a bit longer. This can be used to
|
||
|
* reduce flicker if you are cycling between wake lock conditions.</td>
|
||
|
* </tr>
|
||
|
* </tbody>
|
||
|
* </table>
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
public 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_MAX = 64;
|
||
|
|
||
|
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_MAX;
|
||
|
|
||
|
/**
|
||
|
* Wake lock that ensures that the CPU is running. The screen might
|
||
|
* not be on.
|
||
|
*/
|
||
|
public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
|
||
|
|
||
|
/**
|
||
|
* Wake lock that ensures that the screen and keyboard are on at
|
||
|
* full brightness.
|
||
|
*/
|
||
|
public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
|
||
|
| WAKE_BIT_KEYBOARD_BRIGHT;
|
||
|
|
||
|
/**
|
||
|
* Wake lock that ensures that the screen is on at full brightness;
|
||
|
* the keyboard backlight will be allowed to go off.
|
||
|
*/
|
||
|
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);
|
||
|
* 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.
|
||
|
*
|
||
|
* {@hide}
|
||
|
*/
|
||
|
public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF;
|
||
|
|
||
|
/**
|
||
|
* Wake lock that ensures that the cpu frequency is set to max;
|
||
|
* Will not effect the screen state or cpu's ability to sleep.
|
||
|
*/
|
||
|
public static final int CPU_MAX_WAKE_LOCK = WAKE_BIT_CPU_MAX;
|
||
|
|
||
|
/**
|
||
|
* Flag for {@link WakeLock#release release(int)} to defer releasing a
|
||
|
* {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
|
||
|
* a negative value.
|
||
|
*
|
||
|
* {@hide}
|
||
|
*/
|
||
|
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
|
||
|
|
||
|
/**
|
||
|
* 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 device to be on are the exception; use this flag to be like them.
|
||
|
* <p>
|
||
|
* Does not work with PARTIAL_WAKE_LOCKs.
|
||
|
*/
|
||
|
public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
|
||
|
|
||
|
/**
|
||
|
* 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.
|
||
|
*/
|
||
|
public static final int ON_AFTER_RELEASE = 0x20000000;
|
||
|
|
||
|
/**
|
||
|
* Class lets you say that you need to have the device on.
|
||
|
*
|
||
|
* <p>Call release when you are done and don't need the lock anymore.
|
||
|
*/
|
||
|
public class WakeLock
|
||
|
{
|
||
|
static final int RELEASE_WAKE_LOCK = 1;
|
||
|
|
||
|
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:
|
||
|
case CPU_MAX_WAKE_LOCK:
|
||
|
break;
|
||
|
default:
|
||
|
throw new IllegalArgumentException();
|
||
|
}
|
||
|
|
||
|
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) {
|
||
|
if (!mRefCounted || mCount++ == 0) {
|
||
|
try {
|
||
|
mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
|
||
|
} catch (RemoteException e) {
|
||
|
}
|
||
|
mHeld = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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) {
|
||
|
acquire();
|
||
|
mHandler.postDelayed(mReleaser, timeout);
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* 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) {
|
||
|
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
|
||
|
{
|
||
|
synchronized (mToken) {
|
||
|
if (mHeld) {
|
||
|
Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
|
||
|
try {
|
||
|
mService.releaseWakeLock(mToken, 0);
|
||
|
} catch (RemoteException e) {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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();
|
||
|
* }
|
||
|
*
|
||
|
* @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");
|
||
|
}
|
||
|
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) {
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 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;
|
||
|
}
|