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