PowerManager.java revision 36e52dce7f63881dd8061b6d4a6bed7c0721911e
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 17package android.os; 18 19import 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 * 101 */ 102public class PowerManager 103{ 104 private static final String TAG = "PowerManager"; 105 106 /** 107 * These internal values define the underlying power elements that we might 108 * want to control individually. Eventually we'd like to expose them. 109 */ 110 private static final int WAKE_BIT_CPU_STRONG = 1; 111 private static final int WAKE_BIT_CPU_WEAK = 2; 112 private static final int WAKE_BIT_SCREEN_DIM = 4; 113 private static final int WAKE_BIT_SCREEN_BRIGHT = 8; 114 private static final int WAKE_BIT_KEYBOARD_BRIGHT = 16; 115 private static final int WAKE_BIT_PROXIMITY_SCREEN_OFF = 32; 116 117 private static final int LOCK_MASK = WAKE_BIT_CPU_STRONG 118 | WAKE_BIT_CPU_WEAK 119 | WAKE_BIT_SCREEN_DIM 120 | WAKE_BIT_SCREEN_BRIGHT 121 | WAKE_BIT_KEYBOARD_BRIGHT 122 | WAKE_BIT_PROXIMITY_SCREEN_OFF; 123 124 /** 125 * Wake lock that ensures that the CPU is running. The screen might 126 * not be on. 127 */ 128 public static final int PARTIAL_WAKE_LOCK = WAKE_BIT_CPU_STRONG; 129 130 /** 131 * Wake lock that ensures that the screen and keyboard are on at 132 * full brightness. 133 */ 134 public static final int FULL_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT 135 | WAKE_BIT_KEYBOARD_BRIGHT; 136 137 /** 138 * Wake lock that ensures that the screen is on at full brightness; 139 * the keyboard backlight will be allowed to go off. 140 */ 141 public static final int SCREEN_BRIGHT_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_BRIGHT; 142 143 /** 144 * Wake lock that ensures that the screen is on (but may be dimmed); 145 * the keyboard backlight will be allowed to go off. 146 */ 147 public static final int SCREEN_DIM_WAKE_LOCK = WAKE_BIT_CPU_WEAK | WAKE_BIT_SCREEN_DIM; 148 149 /** 150 * Wake lock that turns the screen off when the proximity sensor activates. 151 * Since not all devices have proximity sensors, use 152 * {@link #getSupportedWakeLockFlags() getSupportedWakeLockFlags()} to determine if 153 * this wake lock mode is supported. 154 * 155 * {@hide} 156 */ 157 public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = WAKE_BIT_PROXIMITY_SCREEN_OFF; 158 159 /** 160 * Flag for {@link WakeLock#release release(int)} to defer releasing a 161 * {@link #WAKE_BIT_PROXIMITY_SCREEN_OFF} wakelock until the proximity sensor returns 162 * a negative value. 163 * 164 * {@hide} 165 */ 166 public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1; 167 168 /** 169 * Normally wake locks don't actually wake the device, they just cause 170 * it to remain on once it's already on. Think of the video player 171 * app as the normal behavior. Notifications that pop up and want 172 * the device to be on are the exception; use this flag to be like them. 173 * <p> 174 * Does not work with PARTIAL_WAKE_LOCKs. 175 */ 176 public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000; 177 178 /** 179 * When this wake lock is released, poke the user activity timer 180 * so the screen stays on for a little longer. 181 * <p> 182 * Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP} 183 * if you want that. 184 * <p> 185 * Does not work with PARTIAL_WAKE_LOCKs. 186 */ 187 public static final int ON_AFTER_RELEASE = 0x20000000; 188 189 /** 190 * Class lets you say that you need to have the device on. 191 * 192 * <p>Call release when you are done and don't need the lock anymore. 193 */ 194 public class WakeLock 195 { 196 static final int RELEASE_WAKE_LOCK = 1; 197 198 Runnable mReleaser = new Runnable() { 199 public void run() { 200 release(); 201 } 202 }; 203 204 int mFlags; 205 String mTag; 206 IBinder mToken; 207 int mCount = 0; 208 boolean mRefCounted = true; 209 boolean mHeld = false; 210 WorkSource mWorkSource; 211 212 WakeLock(int flags, String tag) 213 { 214 switch (flags & LOCK_MASK) { 215 case PARTIAL_WAKE_LOCK: 216 case SCREEN_DIM_WAKE_LOCK: 217 case SCREEN_BRIGHT_WAKE_LOCK: 218 case FULL_WAKE_LOCK: 219 case PROXIMITY_SCREEN_OFF_WAKE_LOCK: 220 break; 221 default: 222 throw new IllegalArgumentException(); 223 } 224 225 mFlags = flags; 226 mTag = tag; 227 mToken = new Binder(); 228 } 229 230 /** 231 * Sets whether this WakeLock is ref counted. 232 * 233 * <p>Wake locks are reference counted by default. 234 * 235 * @param value true for ref counted, false for not ref counted. 236 */ 237 public void setReferenceCounted(boolean value) 238 { 239 mRefCounted = value; 240 } 241 242 /** 243 * Makes sure the device is on at the level you asked when you created 244 * the wake lock. 245 */ 246 public void acquire() 247 { 248 synchronized (mToken) { 249 if (!mRefCounted || mCount++ == 0) { 250 try { 251 mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource); 252 } catch (RemoteException e) { 253 } 254 mHeld = true; 255 } 256 } 257 } 258 259 /** 260 * Makes sure the device is on at the level you asked when you created 261 * the wake lock. The lock will be released after the given timeout. 262 * 263 * @param timeout Release the lock after the give timeout in milliseconds. 264 */ 265 public void acquire(long timeout) { 266 acquire(); 267 mHandler.postDelayed(mReleaser, timeout); 268 } 269 270 271 /** 272 * Release your claim to the CPU or screen being on. 273 * 274 * <p> 275 * It may turn off shortly after you release it, or it may not if there 276 * are other wake locks held. 277 */ 278 public void release() 279 { 280 release(0); 281 } 282 283 /** 284 * Release your claim to the CPU or screen being on. 285 * @param flags Combination of flag values to modify the release behavior. 286 * Currently only {@link #WAIT_FOR_PROXIMITY_NEGATIVE} is supported. 287 * 288 * <p> 289 * It may turn off shortly after you release it, or it may not if there 290 * are other wake locks held. 291 * 292 * {@hide} 293 */ 294 public void release(int flags) 295 { 296 synchronized (mToken) { 297 if (!mRefCounted || --mCount == 0) { 298 try { 299 mService.releaseWakeLock(mToken, flags); 300 } catch (RemoteException e) { 301 } 302 mHeld = false; 303 } 304 if (mCount < 0) { 305 throw new RuntimeException("WakeLock under-locked " + mTag); 306 } 307 } 308 } 309 310 public boolean isHeld() 311 { 312 synchronized (mToken) { 313 return mHeld; 314 } 315 } 316 317 public void setWorkSource(WorkSource ws) { 318 synchronized (mToken) { 319 if (ws != null && ws.size() == 0) { 320 ws = null; 321 } 322 boolean changed = true; 323 if (ws == null) { 324 mWorkSource = null; 325 } else if (mWorkSource == null) { 326 changed = mWorkSource != null; 327 mWorkSource = new WorkSource(ws); 328 } else { 329 changed = mWorkSource.diff(ws); 330 if (changed) { 331 mWorkSource.set(ws); 332 } 333 } 334 if (changed && mHeld) { 335 try { 336 mService.updateWakeLockWorkSource(mToken, mWorkSource); 337 } catch (RemoteException e) { 338 } 339 } 340 } 341 } 342 343 public String toString() { 344 synchronized (mToken) { 345 return "WakeLock{" 346 + Integer.toHexString(System.identityHashCode(this)) 347 + " held=" + mHeld + ", refCount=" + mCount + "}"; 348 } 349 } 350 351 @Override 352 protected void finalize() throws Throwable 353 { 354 synchronized (mToken) { 355 if (mHeld) { 356 Log.wtf(TAG, "WakeLock finalized while still held: " + mTag); 357 try { 358 mService.releaseWakeLock(mToken, 0); 359 } catch (RemoteException e) { 360 } 361 } 362 } 363 } 364 } 365 366 /** 367 * Get a wake lock at the level of the flags parameter. Call 368 * {@link WakeLock#acquire() acquire()} on the object to acquire the 369 * wake lock, and {@link WakeLock#release release()} when you are done. 370 * 371 * {@samplecode 372 *PowerManager pm = (PowerManager)mContext.getSystemService( 373 * Context.POWER_SERVICE); 374 *PowerManager.WakeLock wl = pm.newWakeLock( 375 * PowerManager.SCREEN_DIM_WAKE_LOCK 376 * | PowerManager.ON_AFTER_RELEASE, 377 * TAG); 378 *wl.acquire(); 379 * // ... 380 *wl.release(); 381 * } 382 * 383 * @param flags Combination of flag values defining the requested behavior of the WakeLock. 384 * @param tag Your class name (or other tag) for debugging purposes. 385 * 386 * @see WakeLock#acquire() 387 * @see WakeLock#release() 388 */ 389 public WakeLock newWakeLock(int flags, String tag) 390 { 391 if (tag == null) { 392 throw new NullPointerException("tag is null in PowerManager.newWakeLock"); 393 } 394 return new WakeLock(flags, tag); 395 } 396 397 /** 398 * User activity happened. 399 * <p> 400 * Turns the device from whatever state it's in to full on, and resets 401 * the auto-off timer. 402 * 403 * @param when is used to order this correctly with the wake lock calls. 404 * This time should be in the {@link SystemClock#uptimeMillis 405 * SystemClock.uptimeMillis()} time base. 406 * @param noChangeLights should be true if you don't want the lights to 407 * turn on because of this event. This is set when the power 408 * key goes down. We want the device to stay on while the button 409 * is down, but we're about to turn off. Otherwise the lights 410 * flash on and then off and it looks weird. 411 */ 412 public void userActivity(long when, boolean noChangeLights) 413 { 414 try { 415 mService.userActivity(when, noChangeLights); 416 } catch (RemoteException e) { 417 } 418 } 419 420 /** 421 * Force the device to go to sleep. Overrides all the wake locks that are 422 * held. 423 * 424 * @param time is used to order this correctly with the wake lock calls. 425 * The time should be in the {@link SystemClock#uptimeMillis 426 * SystemClock.uptimeMillis()} time base. 427 */ 428 public void goToSleep(long time) 429 { 430 try { 431 mService.goToSleep(time); 432 } catch (RemoteException e) { 433 } 434 } 435 436 /** 437 * sets the brightness of the backlights (screen, keyboard, button). 438 * 439 * @param brightness value from 0 to 255 440 * 441 * {@hide} 442 */ 443 public void setBacklightBrightness(int brightness) 444 { 445 try { 446 mService.setBacklightBrightness(brightness); 447 } catch (RemoteException e) { 448 } 449 } 450 451 /** 452 * Returns the set of flags for {@link #newWakeLock(int, String) newWakeLock()} 453 * that are supported on the device. 454 * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK} 455 * is supported: 456 * 457 * {@samplecode 458 * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 459 * int supportedFlags = pm.getSupportedWakeLockFlags(); 460 * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) 461 * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK); 462 * } 463 * 464 * @return the set of supported WakeLock flags. 465 * 466 * {@hide} 467 */ 468 public int getSupportedWakeLockFlags() 469 { 470 try { 471 return mService.getSupportedWakeLockFlags(); 472 } catch (RemoteException e) { 473 return 0; 474 } 475 } 476 477 /** 478 * Returns whether the screen is currently on. The screen could be bright 479 * or dim. 480 * 481 * {@samplecode 482 * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); 483 * boolean isScreenOn = pm.isScreenOn(); 484 * } 485 * 486 * @return whether the screen is on (bright or dim). 487 */ 488 public boolean isScreenOn() 489 { 490 try { 491 return mService.isScreenOn(); 492 } catch (RemoteException e) { 493 return false; 494 } 495 } 496 497 /** 498 * Reboot the device. Will not return if the reboot is 499 * successful. Requires the {@link android.Manifest.permission#REBOOT} 500 * permission. 501 * 502 * @param reason code to pass to the kernel (e.g., "recovery") to 503 * request special boot modes, or null. 504 */ 505 public void reboot(String reason) 506 { 507 try { 508 mService.reboot(reason); 509 } catch (RemoteException e) { 510 } 511 } 512 513 private PowerManager() 514 { 515 } 516 517 /** 518 * {@hide} 519 */ 520 public PowerManager(IPowerManager service, Handler handler) 521 { 522 mService = service; 523 mHandler = handler; 524 } 525 526 /** 527 * TODO: It would be nice to be able to set the poke lock here, 528 * but I'm not sure what would be acceptable as an interface - 529 * either a PokeLock object (like WakeLock) or, possibly just a 530 * method call to set the poke lock. 531 */ 532 533 IPowerManager mService; 534 Handler mHandler; 535} 536