• 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      * Class lets you say that you need to have the device on.
203      * <p>
204      * Call release when you are done and don't need the lock anymore.
205      * <p>
206      * Any application using a WakeLock must request the {@code android.permission.WAKE_LOCK}
207      * permission in an {@code &lt;uses-permission&gt;} element of the application's manifest.
208      */
209     public class WakeLock
210     {
211         static final int RELEASE_WAKE_LOCK = 1;
212 
213         Runnable mReleaser = new Runnable() {
214             public void run() {
215                 release();
216             }
217         };
218 
219         int mFlags;
220         String mTag;
221         IBinder mToken;
222         int mCount = 0;
223         boolean mRefCounted = true;
224         boolean mHeld = false;
225         WorkSource mWorkSource;
226 
WakeLock(int flags, String tag)227         WakeLock(int flags, String tag)
228         {
229             switch (flags & LOCK_MASK) {
230             case PARTIAL_WAKE_LOCK:
231             case SCREEN_DIM_WAKE_LOCK:
232             case SCREEN_BRIGHT_WAKE_LOCK:
233             case FULL_WAKE_LOCK:
234             case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
235                 break;
236             default:
237                 throw new IllegalArgumentException();
238             }
239 
240             mFlags = flags;
241             mTag = tag;
242             mToken = new Binder();
243         }
244 
245         /**
246          * Sets whether this WakeLock is ref counted.
247          *
248          * <p>Wake locks are reference counted by default.
249          *
250          * @param value true for ref counted, false for not ref counted.
251          */
setReferenceCounted(boolean value)252         public void setReferenceCounted(boolean value)
253         {
254             mRefCounted = value;
255         }
256 
257         /**
258          * Makes sure the device is on at the level you asked when you created
259          * the wake lock.
260          */
acquire()261         public void acquire()
262         {
263             synchronized (mToken) {
264                 acquireLocked();
265             }
266         }
267 
268         /**
269          * Makes sure the device is on at the level you asked when you created
270          * the wake lock. The lock will be released after the given timeout.
271          *
272          * @param timeout Release the lock after the give timeout in milliseconds.
273          */
acquire(long timeout)274         public void acquire(long timeout) {
275             synchronized (mToken) {
276                 acquireLocked();
277                 mHandler.postDelayed(mReleaser, timeout);
278             }
279         }
280 
acquireLocked()281         private void acquireLocked() {
282             if (!mRefCounted || mCount++ == 0) {
283                 mHandler.removeCallbacks(mReleaser);
284                 try {
285                     mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
286                 } catch (RemoteException e) {
287                 }
288                 mHeld = true;
289             }
290         }
291 
292         /**
293          * Release your claim to the CPU or screen being on.
294          *
295          * <p>
296          * It may turn off shortly after you release it, or it may not if there
297          * are other wake locks held.
298          */
release()299         public void release() {
300             release(0);
301         }
302 
303         /**
304          * Release your claim to the CPU or screen being on.
305          * @param flags Combination of flag values to modify the release behavior.
306          *              Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported.
307          *
308          * <p>
309          * It may turn off shortly after you release it, or it may not if there
310          * are other wake locks held.
311          *
312          * {@hide}
313          */
release(int flags)314         public void release(int flags) {
315             synchronized (mToken) {
316                 if (!mRefCounted || --mCount == 0) {
317                     mHandler.removeCallbacks(mReleaser);
318                     try {
319                         mService.releaseWakeLock(mToken, flags);
320                     } catch (RemoteException e) {
321                     }
322                     mHeld = false;
323                 }
324                 if (mCount < 0) {
325                     throw new RuntimeException("WakeLock under-locked " + mTag);
326                 }
327             }
328         }
329 
isHeld()330         public boolean isHeld()
331         {
332             synchronized (mToken) {
333                 return mHeld;
334             }
335         }
336 
setWorkSource(WorkSource ws)337         public void setWorkSource(WorkSource ws) {
338             synchronized (mToken) {
339                 if (ws != null && ws.size() == 0) {
340                     ws = null;
341                 }
342                 boolean changed = true;
343                 if (ws == null) {
344                     mWorkSource = null;
345                 } else if (mWorkSource == null) {
346                     changed = mWorkSource != null;
347                     mWorkSource = new WorkSource(ws);
348                 } else {
349                     changed = mWorkSource.diff(ws);
350                     if (changed) {
351                         mWorkSource.set(ws);
352                     }
353                 }
354                 if (changed && mHeld) {
355                     try {
356                         mService.updateWakeLockWorkSource(mToken, mWorkSource);
357                     } catch (RemoteException e) {
358                     }
359                 }
360             }
361         }
362 
toString()363         public String toString() {
364             synchronized (mToken) {
365                 return "WakeLock{"
366                     + Integer.toHexString(System.identityHashCode(this))
367                     + " held=" + mHeld + ", refCount=" + mCount + "}";
368             }
369         }
370 
371         @Override
finalize()372         protected void finalize() throws Throwable
373         {
374             synchronized (mToken) {
375                 if (mHeld) {
376                     Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
377                     try {
378                         mService.releaseWakeLock(mToken, 0);
379                     } catch (RemoteException e) {
380                     }
381                 }
382             }
383         }
384     }
385 
386     /**
387      * Get a wake lock at the level of the flags parameter.  Call
388      * {@link WakeLock#acquire() acquire()} on the object to acquire the
389      * wake lock, and {@link WakeLock#release release()} when you are done.
390      *
391      * {@samplecode
392      *PowerManager pm = (PowerManager)mContext.getSystemService(
393      *                                          Context.POWER_SERVICE);
394      *PowerManager.WakeLock wl = pm.newWakeLock(
395      *                                      PowerManager.SCREEN_DIM_WAKE_LOCK
396      *                                      | PowerManager.ON_AFTER_RELEASE,
397      *                                      TAG);
398      *wl.acquire();
399      * // ...
400      *wl.release();
401      * }
402      *
403      * <p class="note">If using this to keep the screen on, you should strongly consider using
404      * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} instead.
405      * This window flag will be correctly managed by the platform
406      * as the user moves between applications and doesn't require a special permission.</p>
407      *
408      * @param flags Combination of flag values defining the requested behavior of the WakeLock.
409      * @param tag Your class name (or other tag) for debugging purposes.
410      *
411      * @see WakeLock#acquire()
412      * @see WakeLock#release()
413      */
newWakeLock(int flags, String tag)414     public WakeLock newWakeLock(int flags, String tag)
415     {
416         if (tag == null) {
417             throw new NullPointerException("tag is null in PowerManager.newWakeLock");
418         }
419         return new WakeLock(flags, tag);
420     }
421 
422     /**
423      * User activity happened.
424      * <p>
425      * Turns the device from whatever state it's in to full on, and resets
426      * the auto-off timer.
427      *
428      * @param when is used to order this correctly with the wake lock calls.
429      *          This time should be in the {@link SystemClock#uptimeMillis
430      *          SystemClock.uptimeMillis()} time base.
431      * @param noChangeLights should be true if you don't want the lights to
432      *          turn on because of this event.  This is set when the power
433      *          key goes down.  We want the device to stay on while the button
434      *          is down, but we're about to turn off.  Otherwise the lights
435      *          flash on and then off and it looks weird.
436      */
userActivity(long when, boolean noChangeLights)437     public void userActivity(long when, boolean noChangeLights)
438     {
439         try {
440             mService.userActivity(when, noChangeLights);
441         } catch (RemoteException e) {
442         }
443     }
444 
445    /**
446      * Force the device to go to sleep. Overrides all the wake locks that are
447      * held.
448      *
449      * @param time is used to order this correctly with the wake lock calls.
450      *          The time  should be in the {@link SystemClock#uptimeMillis
451      *          SystemClock.uptimeMillis()} time base.
452      */
goToSleep(long time)453     public void goToSleep(long time)
454     {
455         try {
456             mService.goToSleep(time);
457         } catch (RemoteException e) {
458         }
459     }
460 
461     /**
462      * sets the brightness of the backlights (screen, keyboard, button).
463      *
464      * @param brightness value from 0 to 255
465      *
466      * {@hide}
467      */
setBacklightBrightness(int brightness)468     public void setBacklightBrightness(int brightness)
469     {
470         try {
471             mService.setBacklightBrightness(brightness);
472         } catch (RemoteException e) {
473         }
474     }
475 
476    /**
477      * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
478      * that are supported on the device.
479      * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
480      * is supported:
481      *
482      * {@samplecode
483      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
484      * int supportedFlags = pm.getSupportedWakeLockFlags();
485      *  boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
486      *                                  == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
487      * }
488      *
489      * @return the set of supported WakeLock flags.
490      *
491      * {@hide}
492      */
getSupportedWakeLockFlags()493     public int getSupportedWakeLockFlags()
494     {
495         try {
496             return mService.getSupportedWakeLockFlags();
497         } catch (RemoteException e) {
498             return 0;
499         }
500     }
501 
502     /**
503       * Returns whether the screen is currently on. The screen could be bright
504       * or dim.
505       *
506       * {@samplecode
507       * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
508       * boolean isScreenOn = pm.isScreenOn();
509       * }
510       *
511       * @return whether the screen is on (bright or dim).
512       */
isScreenOn()513     public boolean isScreenOn()
514     {
515         try {
516             return mService.isScreenOn();
517         } catch (RemoteException e) {
518             return false;
519         }
520     }
521 
522     /**
523      * Reboot the device.  Will not return if the reboot is
524      * successful.  Requires the {@link android.Manifest.permission#REBOOT}
525      * permission.
526      *
527      * @param reason code to pass to the kernel (e.g., "recovery") to
528      *               request special boot modes, or null.
529      */
reboot(String reason)530     public void reboot(String reason)
531     {
532         try {
533             mService.reboot(reason);
534         } catch (RemoteException e) {
535         }
536     }
537 
PowerManager()538     private PowerManager()
539     {
540     }
541 
542     /**
543      * {@hide}
544      */
PowerManager(IPowerManager service, Handler handler)545     public PowerManager(IPowerManager service, Handler handler)
546     {
547         mService = service;
548         mHandler = handler;
549     }
550 
551     /**
552      *  TODO: It would be nice to be able to set the poke lock here,
553      *  but I'm not sure what would be acceptable as an interface -
554      *  either a PokeLock object (like WakeLock) or, possibly just a
555      *  method call to set the poke lock.
556      */
557 
558     IPowerManager mService;
559     Handler mHandler;
560 }
561