| /* |
| * 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 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> |
| * |
| * 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. |
| */ |
| 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 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 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. |
| * |
| * <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> |
| */ |
| public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT |
| | WAKE_BIT_KEYBOARD_BRIGHT; |
| |
| /** |
| * @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); |
| * 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; |
| |
| /** |
| * 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. |
| * <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. |
| */ |
| 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: |
| 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) { |
| 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 |
| { |
| 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(); |
| * } |
| * |
| * <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"); |
| } |
| 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; |
| } |