blob: 2efc23041038fe83c2bcbedb1b8189163f02ac69 [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
21import 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 */
104public 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;
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700117 private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118
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
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700123 | WAKE_BIT_KEYBOARD_BRIGHT
124 | WAKE_BIT_PROXIMITY_SCREEN_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125
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 /**
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700152 * 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 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 * Normally wake locks don't actually wake the device, they just cause
163 * it to remain on once it's already on. Think of the video player
164 * app as the normal behavior. Notifications that pop up and want
165 * the device to be on are the exception; use this flag to be like them.
166 * <p>
167 * Does not work with PARTIAL_WAKE_LOCKs.
168 */
169 public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000;
170
171 /**
172 * When this wake lock is released, poke the user activity timer
173 * so the screen stays on for a little longer.
174 * <p>
175 * Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP}
176 * if you want that.
177 * <p>
178 * Does not work with PARTIAL_WAKE_LOCKs.
179 */
180 public static final int ON_AFTER_RELEASE = 0x20000000;
181
182 /**
183 * Class lets you say that you need to have the device on.
184 *
185 * <p>Call release when you are done and don't need the lock anymore.
186 */
187 public class WakeLock
188 {
189 static final int RELEASE_WAKE_LOCK = 1;
190
191 Runnable mReleaser = new Runnable() {
192 public void run() {
193 release();
194 }
195 };
196
197 int mFlags;
198 String mTag;
199 IBinder mToken;
200 int mCount = 0;
201 boolean mRefCounted = true;
202 boolean mHeld = false;
203
204 WakeLock(int flags, String tag)
205 {
206 switch (flags & LOCK_MASK) {
207 case PARTIAL_WAKE_LOCK:
208 case SCREEN_DIM_WAKE_LOCK:
209 case SCREEN_BRIGHT_WAKE_LOCK:
210 case FULL_WAKE_LOCK:
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700211 case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 break;
213 default:
214 throw new IllegalArgumentException();
215 }
216
217 mFlags = flags;
218 mTag = tag;
219 mToken = new Binder();
220 }
221
222 /**
223 * Sets whether this WakeLock is ref counted.
224 *
225 * @param value true for ref counted, false for not ref counted.
226 */
227 public void setReferenceCounted(boolean value)
228 {
229 mRefCounted = value;
230 }
231
232 /**
233 * Makes sure the device is on at the level you asked when you created
234 * the wake lock.
235 */
236 public void acquire()
237 {
238 synchronized (mToken) {
239 if (!mRefCounted || mCount++ == 0) {
240 try {
241 mService.acquireWakeLock(mFlags, mToken, mTag);
242 } catch (RemoteException e) {
243 }
244 mHeld = true;
245 }
246 }
247 }
248
249 /**
250 * Makes sure the device is on at the level you asked when you created
251 * the wake lock. The lock will be released after the given timeout.
252 *
253 * @param timeout Release the lock after the give timeout in milliseconds.
254 */
255 public void acquire(long timeout) {
256 acquire();
257 mHandler.postDelayed(mReleaser, timeout);
258 }
259
260
261 /**
262 * Release your claim to the CPU or screen being on.
263 *
264 * <p>
265 * It may turn off shortly after you release it, or it may not if there
266 * are other wake locks held.
267 */
268 public void release()
269 {
270 synchronized (mToken) {
271 if (!mRefCounted || --mCount == 0) {
272 try {
273 mService.releaseWakeLock(mToken);
274 } catch (RemoteException e) {
275 }
276 mHeld = false;
277 }
278 if (mCount < 0) {
279 throw new RuntimeException("WakeLock under-locked " + mTag);
280 }
281 }
282 }
283
284 public boolean isHeld()
285 {
286 synchronized (mToken) {
287 return mHeld;
288 }
289 }
290
291 public String toString() {
292 synchronized (mToken) {
293 return "WakeLock{"
294 + Integer.toHexString(System.identityHashCode(this))
295 + " held=" + mHeld + ", refCount=" + mCount + "}";
296 }
297 }
298
299 @Override
300 protected void finalize() throws Throwable
301 {
302 synchronized (mToken) {
303 if (mHeld) {
304 try {
305 mService.releaseWakeLock(mToken);
306 } catch (RemoteException e) {
307 }
308 RuntimeInit.crash(TAG, new Exception(
309 "WakeLock finalized while still held: "+mTag));
310 }
311 }
312 }
313 }
314
315 /**
316 * Get a wake lock at the level of the flags parameter. Call
317 * {@link WakeLock#acquire() acquire()} on the object to acquire the
318 * wake lock, and {@link WakeLock#release release()} when you are done.
319 *
320 * {@samplecode
321 *PowerManager pm = (PowerManager)mContext.getSystemService(
322 * Context.POWER_SERVICE);
323 *PowerManager.WakeLock wl = pm.newWakeLock(
324 * PowerManager.SCREEN_DIM_WAKE_LOCK
325 * | PowerManager.ON_AFTER_RELEASE,
326 * TAG);
327 *wl.acquire();
328 * // ...
329 *wl.release();
330 * }
331 *
332 * @param flags Combination of flag values defining the requested behavior of the WakeLock.
333 * @param tag Your class name (or other tag) for debugging purposes.
334 *
335 * @see WakeLock#acquire()
336 * @see WakeLock#release()
337 */
338 public WakeLock newWakeLock(int flags, String tag)
339 {
340 return new WakeLock(flags, tag);
341 }
342
343 /**
344 * User activity happened.
345 * <p>
346 * Turns the device from whatever state it's in to full on, and resets
347 * the auto-off timer.
348 *
349 * @param when is used to order this correctly with the wake lock calls.
350 * This time should be in the {@link SystemClock#uptimeMillis
351 * SystemClock.uptimeMillis()} time base.
352 * @param noChangeLights should be true if you don't want the lights to
353 * turn on because of this event. This is set when the power
354 * key goes down. We want the device to stay on while the button
355 * is down, but we're about to turn off. Otherwise the lights
356 * flash on and then off and it looks weird.
357 */
358 public void userActivity(long when, boolean noChangeLights)
359 {
360 try {
361 mService.userActivity(when, noChangeLights);
362 } catch (RemoteException e) {
363 }
364 }
365
366 /**
367 * Force the device to go to sleep. Overrides all the wake locks that are
368 * held.
369 *
370 * @param time is used to order this correctly with the wake lock calls.
371 * The time should be in the {@link SystemClock#uptimeMillis
372 * SystemClock.uptimeMillis()} time base.
373 */
374 public void goToSleep(long time)
375 {
376 try {
377 mService.goToSleep(time);
378 } catch (RemoteException e) {
379 }
380 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700381
Mike Lockwood237a2992009-09-15 14:42:16 -0400382 /**
383 * sets the brightness of the backlights (screen, keyboard, button).
384 *
385 * @param brightness value from 0 to 255
386 *
387 * {@hide}
388 */
389 public void setBacklightBrightness(int brightness)
390 {
391 try {
392 mService.setBacklightBrightness(brightness);
393 } catch (RemoteException e) {
394 }
395 }
396
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700397 /**
398 * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()}
399 * that are supported on the device.
400 * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
401 * is supported:
402 *
403 * {@samplecode
404 * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
405 * int supportedFlags = pm.getSupportedWakeLockFlags();
406 * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
407 * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
408 * }
409 *
410 * @return the set of supported WakeLock flags.
411 *
412 * {@hide}
413 */
414 public int getSupportedWakeLockFlags()
415 {
416 try {
417 return mService.getSupportedWakeLockFlags();
418 } catch (RemoteException e) {
419 return 0;
420 }
421 }
422
Charles Mendis322591c2009-10-29 11:06:59 -0700423 /**
424 * Returns whether the screen is currently on. The screen could be bright
425 * or dim.
426 *
427 * {@samplecode
428 * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
429 * boolean isScreenOn = pm.isScreenOn();
430 * }
431 *
432 * @return whether the screen is on (bright or dim).
433 */
434 public boolean isScreenOn()
435 {
436 try {
437 return mService.isScreenOn();
438 } catch (RemoteException e) {
439 return false;
440 }
441 }
442
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800443 private PowerManager()
444 {
445 }
446
447 /**
448 * {@hide}
449 */
450 public PowerManager(IPowerManager service, Handler handler)
451 {
452 mService = service;
453 mHandler = handler;
454 }
455
456 /**
457 * TODO: It would be nice to be able to set the poke lock here,
458 * but I'm not sure what would be acceptable as an interface -
459 * either a PokeLock object (like WakeLock) or, possibly just a
460 * method call to set the poke lock.
461 */
462
463 IPowerManager mService;
464 Handler mHandler;
465}
466