blob: a17983a0fd37adb67875f1469946459d5ffc35fe [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.os;
18
19import android.util.Log;
20
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021/**
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 *
Kenny Rootd710fb52011-03-15 17:39:45 -0700100 * 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.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 */
103public 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;
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700116 private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
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
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700122 | WAKE_BIT_KEYBOARD_BRIGHT
123 | WAKE_BIT_PROXIMITY_SCREEN_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124
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.
Dianne Hackborn9567a662011-04-19 18:44:03 -0700134 *
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>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139 */
140 public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT
141 | WAKE_BIT_KEYBOARD_BRIGHT;
142
143 /**
Dianne Hackborn9567a662011-04-19 18:44:03 -0700144 * @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 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800149 * Wake lock that ensures that the screen is on at full brightness;
150 * the keyboard backlight will be allowed to go off.
151 */
Dianne Hackborn9567a662011-04-19 18:44:03 -0700152 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 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 /**
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700162 * 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 /**
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500172 * 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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800181 * 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.
Kenny Rootd710fb52011-03-15 17:39:45 -0700203 * <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.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 */
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;
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700225 WorkSource mWorkSource;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226
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:
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700234 case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 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 *
Joe Onorato8310b422010-09-22 16:54:36 -0700248 * <p>Wake locks are reference counted by default.
249 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 * @param value true for ref counted, false for not ref counted.
251 */
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 */
261 public void acquire()
262 {
263 synchronized (mToken) {
Joe Onoratod7350e32011-05-04 18:10:19 -0700264 acquireLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800265 }
266 }
Joe Onoratod7350e32011-05-04 18:10:19 -0700267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 /**
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 */
274 public void acquire(long timeout) {
Joe Onoratod7350e32011-05-04 18:10:19 -0700275 synchronized (mToken) {
276 acquireLocked();
277 mHandler.postDelayed(mReleaser, timeout);
278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800279 }
280
Joe Onoratod7350e32011-05-04 18:10:19 -0700281 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 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
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 */
Joe Onoratod7350e32011-05-04 18:10:19 -0700299 public void release() {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500300 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 */
Joe Onoratod7350e32011-05-04 18:10:19 -0700314 public void release(int flags) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 synchronized (mToken) {
Joe Onoratod7350e32011-05-04 18:10:19 -0700316 mHandler.removeCallbacks(mReleaser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800317 if (!mRefCounted || --mCount == 0) {
318 try {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500319 mService.releaseWakeLock(mToken, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 } catch (RemoteException e) {
321 }
322 mHeld = false;
323 }
324 if (mCount < 0) {
325 throw new RuntimeException("WakeLock under-locked " + mTag);
326 }
327 }
328 }
329
330 public boolean isHeld()
331 {
332 synchronized (mToken) {
333 return mHeld;
334 }
335 }
336
Dianne Hackborn7e9f4eb2010-09-10 18:43:00 -0700337 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 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
372 protected void finalize() throws Throwable
373 {
374 synchronized (mToken) {
375 if (mHeld) {
Dan Egnor60d87622009-12-16 16:32:58 -0800376 Log.wtf(TAG, "WakeLock finalized while still held: " + mTag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 try {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500378 mService.releaseWakeLock(mToken, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 } catch (RemoteException e) {
380 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800381 }
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 *
Dianne Hackborn9567a662011-04-19 18:44:03 -0700403 * <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 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 * @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 */
414 public WakeLock newWakeLock(int flags, String tag)
415 {
Mike Lockwoodf5bd0922010-03-22 17:10:15 -0400416 if (tag == null) {
417 throw new NullPointerException("tag is null in PowerManager.newWakeLock");
418 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 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 */
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 */
453 public void goToSleep(long time)
454 {
455 try {
456 mService.goToSleep(time);
457 } catch (RemoteException e) {
458 }
459 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700460
Mike Lockwood237a2992009-09-15 14:42:16 -0400461 /**
462 * sets the brightness of the backlights (screen, keyboard, button).
463 *
464 * @param brightness value from 0 to 255
465 *
466 * {@hide}
467 */
468 public void setBacklightBrightness(int brightness)
469 {
470 try {
471 mService.setBacklightBrightness(brightness);
472 } catch (RemoteException e) {
473 }
474 }
475
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700476 /**
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 */
493 public int getSupportedWakeLockFlags()
494 {
495 try {
496 return mService.getSupportedWakeLockFlags();
497 } catch (RemoteException e) {
498 return 0;
499 }
500 }
501
Charles Mendis322591c2009-10-29 11:06:59 -0700502 /**
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 */
513 public boolean isScreenOn()
514 {
515 try {
516 return mService.isScreenOn();
517 } catch (RemoteException e) {
518 return false;
519 }
520 }
521
Doug Zongker50a21f42009-11-19 12:49:53 -0800522 /**
523 * Reboot the device. Will not return if the reboot is
Doug Zongker6fd4e762009-11-19 18:17:15 -0800524 * successful. Requires the {@link android.Manifest.permission#REBOOT}
Doug Zongker50a21f42009-11-19 12:49:53 -0800525 * permission.
526 *
527 * @param reason code to pass to the kernel (e.g., "recovery") to
528 * request special boot modes, or null.
529 */
530 public void reboot(String reason)
531 {
532 try {
533 mService.reboot(reason);
534 } catch (RemoteException e) {
535 }
536 }
537
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 private PowerManager()
539 {
540 }
541
542 /**
543 * {@hide}
544 */
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}