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 <uses-permission>} 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 <uses-permission>} 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