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