| /* |
| * 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; |
| |
| /** |
| * 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><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"); |
| * wl.acquire(); |
| * ..screen will stay on during this section.. |
| * wl.release(); |
| * } |
| * </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> |
| * </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><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> |
| * |
| * <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> |
| * </p><p> |
| * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK} |
| * permission in an {@code <uses-permission>} element of the application's manifest. |
| * </p> |
| */ |
| 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 << 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 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 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} 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 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. |
| */ |
| @Deprecated |
| public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT; |
| |
| /** |
| * 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 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} |
| */ |
| public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF; |
| |
| /** |
| * Flag for {@link WakeLock#release release(int)} to defer releasing a |
| * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wake lock until the proximity sensor returns |
| * a negative value. |
| * |
| * {@hide} |
| */ |
| 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 |
| * 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><p> |
| * Cannot be used with {@link #PARTIAL_WAKE_LOCK}. |
| * </p> |
| */ |
| public static final int ACQUIRE_CAUSES_WAKEUP = 1 << 28; |
| |
| /** |
| * 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><p> |
| * Cannot be used with {@link #PARTIAL_WAKE_LOCK}. |
| * </p> |
| */ |
| public static final int ON_AFTER_RELEASE = 1 << 29; |
| |
| /** |
| * Brightness value to use when battery is low. |
| * @hide |
| */ |
| public static final int BRIGHTNESS_LOW_BATTERY = 10; |
| |
| /** |
| * Brightness value for fully on. |
| * @hide |
| */ |
| public static final int BRIGHTNESS_ON = 255; |
| |
| /** |
| * Brightness value for dim backlight. |
| * @hide |
| */ |
| public static final int BRIGHTNESS_DIM = 20; |
| |
| /** |
| * Brightness value for fully off. |
| * @hide |
| */ |
| public static final int BRIGHTNESS_OFF = 0; |
| |
| final IPowerManager mService; |
| final Handler mHandler; |
| |
| /** |
| * {@hide} |
| */ |
| public PowerManager(IPowerManager service, Handler handler) { |
| mService = service; |
| mHandler = handler; |
| } |
| |
| /** |
| * Creates a new wake lock with the specified level and flags. |
| * <p> |
| * 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 <uses-permission>} 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 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; |
| |
| private final Runnable mReleaser = new Runnable() { |
| public void run() { |
| release(); |
| } |
| }; |
| |
| WakeLock(int flags, String tag) { |
| mFlags = flags; |
| mTag = tag; |
| mToken = new Binder(); |
| } |
| |
| @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) { |
| } |
| } |
| } |
| } |
| |
| /** |
| * 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; |
| } |
| } |
| |
| /** |
| * 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) { |
| // Do this even if the wake lock is already thought to be held (mHeld == true) |
| // because non-reference counted wake locks are not always properly released. |
| // For example, the keyguard's wake lock might be forcibly released by the |
| // power manager without the keyguard knowing. A subsequent call to acquire |
| // should immediately acquire the wake lock once again despite never having |
| // been explicitly released by the keyguard. |
| mHandler.removeCallbacks(mReleaser); |
| 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 + "}"; |
| } |
| } |
| } |
| } |