Home | History | Annotate | Download | only in os
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.os;
     18 
     19 import android.util.Log;
     20 
     21 import com.android.internal.os.RuntimeInit;
     22 
     23 /**
     24  * This class gives you control of the power state of the device.
     25  *
     26  * <p><b>Device battery life will be significantly affected by the use of this API.</b>  Do not
     27  * acquire WakeLocks unless you really need them, use the minimum levels possible, and be sure
     28  * to release it as soon as you can.
     29  *
     30  * <p>You can obtain an instance of this class by calling
     31  * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
     32  *
     33  * <p>The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.  This will
     34  * create a {@link PowerManager.WakeLock} object.  You can then use methods on this object to
     35  * control the power state of the device.  In practice it's quite simple:
     36  *
     37  * {@samplecode
     38  * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
     39  * PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, "My Tag");
     40  * wl.acquire();
     41  *   ..screen will stay on during this section..
     42  * wl.release();
     43  * }
     44  *
     45  * <p>The following flags are defined, with varying effects on system power.  <i>These flags are
     46  * mutually exclusive - you may only specify one of them.</i>
     47  * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
     48  *
     49  *     <thead>
     50  *     <tr><th>Flag Value</th>
     51  *     <th>CPU</th> <th>Screen</th> <th>Keyboard</th></tr>
     52  *     </thead>
     53  *
     54  *     <tbody>
     55  *     <tr><th>{@link #PARTIAL_WAKE_LOCK}</th>
     56  *         <td>On*</td> <td>Off</td> <td>Off</td>
     57  *     </tr>
     58  *
     59  *     <tr><th>{@link #SCREEN_DIM_WAKE_LOCK}</th>
     60  *         <td>On</td> <td>Dim</td> <td>Off</td>
     61  *     </tr>
     62  *
     63  *     <tr><th>{@link #SCREEN_BRIGHT_WAKE_LOCK}</th>
     64  *         <td>On</td> <td>Bright</td> <td>Off</td>
     65  *     </tr>
     66  *
     67  *     <tr><th>{@link #FULL_WAKE_LOCK}</th>
     68  *         <td>On</td> <td>Bright</td> <td>Bright</td>
     69  *     </tr>
     70  *     </tbody>
     71  * </table>
     72  *
     73  * <p>*<i>If you hold a partial wakelock, the CPU will continue to run, irrespective of any timers
     74  * and even after the user presses the power button.  In all other wakelocks, the CPU will run, but
     75  * the user can still put the device to sleep using the power button.</i>
     76  *
     77  * <p>In addition, you can add two more flags, which affect behavior of the screen only.  <i>These
     78  * flags have no effect when combined with a {@link #PARTIAL_WAKE_LOCK}.</i>
     79  * <table border="2" width="85%" align="center" frame="hsides" rules="rows">
     80  *
     81  *     <thead>
     82  *     <tr><th>Flag Value</th> <th>Description</th></tr>
     83  *     </thead>
     84  *
     85  *     <tbody>
     86  *     <tr><th>{@link #ACQUIRE_CAUSES_WAKEUP}</th>
     87  *         <td>Normal wake locks don't actually turn on the illumination.  Instead, they cause
     88  *         the illumination to remain on once it turns on (e.g. from user activity).  This flag
     89  *         will force the screen and/or keyboard to turn on immediately, when the WakeLock is
     90  *         acquired.  A typical use would be for notifications which are important for the user to
     91  *         see immediately.</td>
     92  *     </tr>
     93  *
     94  *     <tr><th>{@link #ON_AFTER_RELEASE}</th>
     95  *         <td>If this flag is set, the user activity timer will be reset when the WakeLock is
     96  *         released, causing the illumination to remain on a bit longer.  This can be used to
     97  *         reduce flicker if you are cycling between wake lock conditions.</td>
     98  *     </tr>
     99  *     </tbody>
    100  * </table>
    101  *
    102  *
    103  */
    104 public class PowerManager
    105 {
    106     private static final String TAG = "PowerManager";
    107 
    108     /**
    109      * These internal values define the underlying power elements that we might
    110      * want to control individually.  Eventually we'd like to expose them.
    111      */
    112     private static final int WAKE_BIT_CPU_STRONG = 1;
    113     private static final int WAKE_BIT_CPU_WEAK = 2;
    114     private static final int WAKE_BIT_SCREEN_DIM = 4;
    115     private static final int WAKE_BIT_SCREEN_BRIGHT = 8;
    116     private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16;
    117     private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
    118 
    119     private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG
    120                                         | WAKE_BIT_CPU_WEAK
    121                                         | WAKE_BIT_SCREEN_DIM
    122                                         | WAKE_BIT_SCREEN_BRIGHT
    123                                         | WAKE_BIT_KEYBOARD_BRIGHT
    124                                         | WAKE_BIT_PROXIMITY_SCREEN_OFF;
    125 
    126     /**
    127      * Wake lock that ensures that the CPU is running.  The screen might
    128      * not be on.
    129      */
    130     public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG;
    131 
    132     /**
    133      * Wake lock that ensures that the screen and keyboard are on at
    134      * full brightness.
    135      */
    136     public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
    137                                             | WAKE_BIT_KEYBOARD_BRIGHT;
    138 
    139     /**
    140      * Wake lock that ensures that the screen is on at full brightness;
    141      * the keyboard backlight will be allowed to go off.
    142      */
    143     public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT;
    144 
    145     /**
    146      * Wake lock that ensures that the screen is on (but may be dimmed);
    147      * the keyboard backlight will be allowed to go off.
    148      */
    149     public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM;
    150 
    151     /**
    152      * Wake lock that turns the screen off when the proximity sensor activates.
    153      * Since not all devices have proximity sensors, use
    154      * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if
    155      * this wake lock mode is supported.
    156      *
    157      * {@hide}
    158      */
    159     public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF;
    160 
    161     /**
    162      * Flag for {@link WakeLock#release release(int)} to defer releasing a
    163      * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns
    164      * a negative value.
    165      *
    166      * {@hide}
    167      */
    168     public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
    169 
    170     /**
    171      * Normally wake locks don't actually wake the device, they just cause
    172      * it to remain on once it's already on.  Think of the video player
    173      * app as the normal behavior.  Notifications that pop up and want
    174      * the device to be on are the exception; use this flag to be like them.
    175      * <p>
    176      * Does not work with PARTIAL_WAKE_LOCKs.
    177      */
    178     public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
    179 
    180     /**
    181      * When this wake lock is released, poke the user activity timer
    182      * so the screen stays on for a little longer.
    183      * <p>
    184      * Will not turn the screen on if it is not already on.  See {@link #ACQUIRE_CAUSES_WAKEUP}
    185      * if you want that.
    186      * <p>
    187      * Does not work with PARTIAL_WAKE_LOCKs.
    188      */
    189     public static final int ON_AFTER_RELEASE = 0x20000000;
    190 
    191     /**
    192      * Class lets you say that you need to have the device on.
    193      *
    194      * <p>Call release when you are done and don't need the lock anymore.
    195      */
    196     public class WakeLock
    197     {
    198         static final int RELEASE_WAKE_LOCK = 1;
    199 
    200         Runnable mReleaser = new Runnable() {
    201             public void run() {
    202                 release();
    203             }
    204         };
    205 
    206         int mFlags;
    207         String mTag;
    208         IBinder mToken;
    209         int mCount = 0;
    210         boolean mRefCounted = true;
    211         boolean mHeld = false;
    212 
    213         WakeLock(int flags, String tag)
    214         {
    215             switch (flags & LOCK_MASK) {
    216             case PARTIAL_WAKE_LOCK:
    217             case SCREEN_DIM_WAKE_LOCK:
    218             case SCREEN_BRIGHT_WAKE_LOCK:
    219             case FULL_WAKE_LOCK:
    220             case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
    221                 break;
    222             default:
    223                 throw new IllegalArgumentException();
    224             }
    225 
    226             mFlags = flags;
    227             mTag = tag;
    228             mToken = new Binder();
    229         }
    230 
    231         /**
    232          * Sets whether this WakeLock is ref counted.
    233          *
    234          * @param value true for ref counted, false for not ref counted.
    235          */
    236         public void setReferenceCounted(boolean value)
    237         {
    238             mRefCounted = value;
    239         }
    240 
    241         /**
    242          * Makes sure the device is on at the level you asked when you created
    243          * the wake lock.
    244          */
    245         public void acquire()
    246         {
    247             synchronized (mToken) {
    248                 if (!mRefCounted || mCount++ == 0) {
    249                     try {
    250                         mService.acquireWakeLock(mFlags, mToken, mTag);
    251                     } catch (RemoteException e) {
    252                     }
    253                     mHeld = true;
    254                 }
    255             }
    256         }
    257 
    258         /**
    259          * Makes sure the device is on at the level you asked when you created
    260          * the wake lock. The lock will be released after the given timeout.
    261          *
    262          * @param timeout Release the lock after the give timeout in milliseconds.
    263          */
    264         public void acquire(long timeout) {
    265             acquire();
    266             mHandler.postDelayed(mReleaser, timeout);
    267         }
    268 
    269 
    270         /**
    271          * Release your claim to the CPU or screen being on.
    272          *
    273          * <p>
    274          * It may turn off shortly after you release it, or it may not if there
    275          * are other wake locks held.
    276          */
    277         public void release()
    278         {
    279             release(0);
    280         }
    281 
    282         /**
    283          * Release your claim to the CPU or screen being on.
    284          * @param flags Combination of flag values to modify the release behavior.
    285          *              Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
    286          *
    287          * <p>
    288          * It may turn off shortly after you release it, or it may not if there
    289          * are other wake locks held.
    290          *
    291          * {@hide}
    292          */
    293         public void release(int flags)
    294         {
    295             synchronized (mToken) {
    296                 if (!mRefCounted || --mCount == 0) {
    297                     try {
    298                         mService.releaseWakeLock(mToken, flags);
    299                     } catch (RemoteException e) {
    300                     }
    301                     mHeld = false;
    302                 }
    303                 if (mCount < 0) {
    304                     throw new RuntimeException("WakeLock under-locked " + mTag);
    305                 }
    306             }
    307         }
    308 
    309         public boolean isHeld()
    310         {
    311             synchronized (mToken) {
    312                 return mHeld;
    313             }
    314         }
    315 
    316         public String toString() {
    317             synchronized (mToken) {
    318                 return "WakeLock{"
    319                     + Integer.toHexString(System.identityHashCode(this))
    320                     + " held=" + mHeld + ", refCount=" + mCount + "}";
    321             }
    322         }
    323 
    324         @Override
    325         protected void finalize() throws Throwable
    326         {
    327             synchronized (mToken) {
    328                 if (mHeld) {
    329                     Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
    330                     try {
    331                         mService.releaseWakeLock(mToken, 0);
    332                     } catch (RemoteException e) {
    333                     }
    334                 }
    335             }
    336         }
    337     }
    338 
    339     /**
    340      * Get a wake lock at the level of the flags parameter.  Call
    341      * {@link WakeLock#acquire() acquire()} on the object to acquire the
    342      * wake lock, and {@link WakeLock#release release()} when you are done.
    343      *
    344      * {@samplecode
    345      *PowerManager pm = (PowerManager)mContext.getSystemService(
    346      *                                          Context.POWER_SERVICE);
    347      *PowerManager.WakeLock wl = pm.newWakeLock(
    348      *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
    349      *                                      | PowerManager.ON_AFTER_RELEASE,
    350      *                                      TAG);
    351      *wl.acquire();
    352      * // ...
    353      *wl.release();
    354      * }
    355      *
    356      * @param flags Combination of flag values defining the requested behavior of the WakeLock.
    357      * @param tag Your class name (or other tag) for debugging purposes.
    358      *
    359      * @see WakeLock#acquire()
    360      * @see WakeLock#release()
    361      */
    362     public WakeLock newWakeLock(int flags, String tag)
    363     {
    364         if (tag == null) {
    365             throw new NullPointerException("tag is null in PowerManager.newWakeLock");
    366         }
    367         return new WakeLock(flags, tag);
    368     }
    369 
    370     /**
    371      * User activity happened.
    372      * <p>
    373      * Turns the device from whatever state it's in to full on, and resets
    374      * the auto-off timer.
    375      *
    376      * @param when is used to order this correctly with the wake lock calls.
    377      *          This time should be in the {@link SystemClock#uptimeMillis
    378      *          SystemClock.uptimeMillis()} time base.
    379      * @param noChangeLights should be true if you don't want the lights to
    380      *          turn on because of this event.  This is set when the power
    381      *          key goes down.  We want the device to stay on while the button
    382      *          is down, but we're about to turn off.  Otherwise the lights
    383      *          flash on and then off and it looks weird.
    384      */
    385     public void userActivity(long when, boolean noChangeLights)
    386     {
    387         try {
    388             mService.userActivity(when, noChangeLights);
    389         } catch (RemoteException e) {
    390         }
    391     }
    392 
    393    /**
    394      * Force the device to go to sleep. Overrides all the wake locks that are
    395      * held.
    396      *
    397      * @param time is used to order this correctly with the wake lock calls.
    398      *          The time  should be in the {@link SystemClock#uptimeMillis
    399      *          SystemClock.uptimeMillis()} time base.
    400      */
    401     public void goToSleep(long time)
    402     {
    403         try {
    404             mService.goToSleep(time);
    405         } catch (RemoteException e) {
    406         }
    407     }
    408 
    409     /**
    410      * sets the brightness of the backlights (screen, keyboard, button).
    411      *
    412      * @param brightness value from 0 to 255
    413      *
    414      * {@hide}
    415      */
    416     public void setBacklightBrightness(int brightness)
    417     {
    418         try {
    419             mService.setBacklightBrightness(brightness);
    420         } catch (RemoteException e) {
    421         }
    422     }
    423 
    424    /**
    425      * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
    426      * that are supported on the device.
    427      * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
    428      * is supported:
    429      *
    430      * {@samplecode
    431      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    432      * int supportedFlags = pm.getSupportedWakeLockFlags();
    433      *  boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
    434      *                                  == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
    435      * }
    436      *
    437      * @return the set of supported WakeLock flags.
    438      *
    439      * {@hide}
    440      */
    441     public int getSupportedWakeLockFlags()
    442     {
    443         try {
    444             return mService.getSupportedWakeLockFlags();
    445         } catch (RemoteException e) {
    446             return 0;
    447         }
    448     }
    449 
    450     /**
    451       * Returns whether the screen is currently on. The screen could be bright
    452       * or dim.
    453       *
    454       * {@samplecode
    455       * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    456       * boolean isScreenOn = pm.isScreenOn();
    457       * }
    458       *
    459       * @return whether the screen is on (bright or dim).
    460       */
    461     public boolean isScreenOn()
    462     {
    463         try {
    464             return mService.isScreenOn();
    465         } catch (RemoteException e) {
    466             return false;
    467         }
    468     }
    469 
    470     /**
    471      * Reboot the device.  Will not return if the reboot is
    472      * successful.  Requires the {@link android.Manifest.permission#REBOOT}
    473      * permission.
    474      *
    475      * @param reason code to pass to the kernel (e.g., "recovery") to
    476      *               request special boot modes, or null.
    477      */
    478     public void reboot(String reason)
    479     {
    480         try {
    481             mService.reboot(reason);
    482         } catch (RemoteException e) {
    483         }
    484     }
    485 
    486     private PowerManager()
    487     {
    488     }
    489 
    490     /**
    491      * {@hide}
    492      */
    493     public PowerManager(IPowerManager service, Handler handler)
    494     {
    495         mService = service;
    496         mHandler = handler;
    497     }
    498 
    499     /**
    500      *  TODO: It would be nice to be able to set the poke lock here,
    501      *  but I'm not sure what would be acceptable as an interface -
    502      *  either a PokeLock object (like WakeLock) or, possibly just a
    503      *  method call to set the poke lock.
    504      */
    505 
    506     IPowerManager mService;
    507     Handler mHandler;
    508 }
    509