• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WakeLock(int flags, String tag)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          */
setReferenceCounted(boolean value)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          */
acquire()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          */
acquire(long timeout)298         public void acquire(long timeout) {
299             synchronized (mToken) {
300                 acquireLocked();
301                 mHandler.postDelayed(mReleaser, timeout);
302             }
303         }
304 
acquireLocked()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          */
release()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          */
release(int flags)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 
isHeld()354         public boolean isHeld()
355         {
356             synchronized (mToken) {
357                 return mHeld;
358             }
359         }
360 
setWorkSource(WorkSource ws)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 
toString()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
finalize()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      */
newWakeLock(int flags, String tag)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      */
userActivity(long when, boolean noChangeLights)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      */
goToSleep(long time)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      */
setBacklightBrightness(int brightness)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      */
getSupportedWakeLockFlags()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       */
isScreenOn()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      */
reboot(String reason)554     public void reboot(String reason)
555     {
556         try {
557             mService.reboot(reason);
558         } catch (RemoteException e) {
559         }
560     }
561 
PowerManager()562     private PowerManager()
563     {
564     }
565 
566     /**
567      * {@hide}
568      */
PowerManager(IPowerManager service, Handler handler)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