PowerManager.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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 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 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 * Normally wake locks don't actually wake the device, they just cause 151 * it to remain on once it's already on. Think of the video player 152 * app as the normal behavior. Notifications that pop up and want 153 * the device to be on are the exception; use this flag to be like them. 154 * <p> 155 * Does not work with PARTIAL_WAKE_LOCKs. 156 */ 157 public static final int ACQUIRE_CAUSES_WAKEUP = 0x10000000; 158 159 /** 160 * When this wake lock is released, poke the user activity timer 161 * so the screen stays on for a little longer. 162 * <p> 163 * Will not turn the screen on if it is not already on. See {@link #ACQUIRE_CAUSES_WAKEUP} 164 * if you want that. 165 * <p> 166 * Does not work with PARTIAL_WAKE_LOCKs. 167 */ 168 public static final int ON_AFTER_RELEASE = 0x20000000; 169 170 /** 171 * Class lets you say that you need to have the device on. 172 * 173 * <p>Call release when you are done and don't need the lock anymore. 174 */ 175 public class WakeLock 176 { 177 static final int RELEASE_WAKE_LOCK = 1; 178 179 Runnable mReleaser = new Runnable() { 180 public void run() { 181 release(); 182 } 183 }; 184 185 int mFlags; 186 String mTag; 187 IBinder mToken; 188 int mCount = 0; 189 boolean mRefCounted = true; 190 boolean mHeld = false; 191 192 WakeLock(int flags, String tag) 193 { 194 switch (flags & LOCK_MASK) { 195 case PARTIAL_WAKE_LOCK: 196 case SCREEN_DIM_WAKE_LOCK: 197 case SCREEN_BRIGHT_WAKE_LOCK: 198 case FULL_WAKE_LOCK: 199 break; 200 default: 201 throw new IllegalArgumentException(); 202 } 203 204 mFlags = flags; 205 mTag = tag; 206 mToken = new Binder(); 207 } 208 209 /** 210 * Sets whether this WakeLock is ref counted. 211 * 212 * @param value true for ref counted, false for not ref counted. 213 */ 214 public void setReferenceCounted(boolean value) 215 { 216 mRefCounted = value; 217 } 218 219 /** 220 * Makes sure the device is on at the level you asked when you created 221 * the wake lock. 222 */ 223 public void acquire() 224 { 225 synchronized (mToken) { 226 if (!mRefCounted || mCount++ == 0) { 227 try { 228 mService.acquireWakeLock(mFlags, mToken, mTag); 229 } catch (RemoteException e) { 230 } 231 mHeld = true; 232 } 233 } 234 } 235 236 /** 237 * Makes sure the device is on at the level you asked when you created 238 * the wake lock. The lock will be released after the given timeout. 239 * 240 * @param timeout Release the lock after the give timeout in milliseconds. 241 */ 242 public void acquire(long timeout) { 243 acquire(); 244 mHandler.postDelayed(mReleaser, timeout); 245 } 246 247 248 /** 249 * Release your claim to the CPU or screen being on. 250 * 251 * <p> 252 * It may turn off shortly after you release it, or it may not if there 253 * are other wake locks held. 254 */ 255 public void release() 256 { 257 synchronized (mToken) { 258 if (!mRefCounted || --mCount == 0) { 259 try { 260 mService.releaseWakeLock(mToken); 261 } catch (RemoteException e) { 262 } 263 mHeld = false; 264 } 265 if (mCount < 0) { 266 throw new RuntimeException("WakeLock under-locked " + mTag); 267 } 268 } 269 } 270 271 public boolean isHeld() 272 { 273 synchronized (mToken) { 274 return mHeld; 275 } 276 } 277 278 public String toString() { 279 synchronized (mToken) { 280 return "WakeLock{" 281 + Integer.toHexString(System.identityHashCode(this)) 282 + " held=" + mHeld + ", refCount=" + mCount + "}"; 283 } 284 } 285 286 @Override 287 protected void finalize() throws Throwable 288 { 289 synchronized (mToken) { 290 if (mHeld) { 291 try { 292 mService.releaseWakeLock(mToken); 293 } catch (RemoteException e) { 294 } 295 RuntimeInit.crash(TAG, new Exception( 296 "WakeLock finalized while still held: "+mTag)); 297 } 298 } 299 } 300 } 301 302 /** 303 * Get a wake lock at the level of the flags parameter. Call 304 * {@link WakeLock#acquire() acquire()} on the object to acquire the 305 * wake lock, and {@link WakeLock#release release()} when you are done. 306 * 307 * {@samplecode 308 *PowerManager pm = (PowerManager)mContext.getSystemService( 309 * Context.POWER_SERVICE); 310 *PowerManager.WakeLock wl = pm.newWakeLock( 311 * PowerManager.SCREEN_DIM_WAKE_LOCK 312 * | PowerManager.ON_AFTER_RELEASE, 313 * TAG); 314 *wl.acquire(); 315 * // ... 316 *wl.release(); 317 * } 318 * 319 * @param flags Combination of flag values defining the requested behavior of the WakeLock. 320 * @param tag Your class name (or other tag) for debugging purposes. 321 * 322 * @see WakeLock#acquire() 323 * @see WakeLock#release() 324 */ 325 public WakeLock newWakeLock(int flags, String tag) 326 { 327 return new WakeLock(flags, tag); 328 } 329 330 /** 331 * User activity happened. 332 * <p> 333 * Turns the device from whatever state it's in to full on, and resets 334 * the auto-off timer. 335 * 336 * @param when is used to order this correctly with the wake lock calls. 337 * This time should be in the {@link SystemClock#uptimeMillis 338 * SystemClock.uptimeMillis()} time base. 339 * @param noChangeLights should be true if you don't want the lights to 340 * turn on because of this event. This is set when the power 341 * key goes down. We want the device to stay on while the button 342 * is down, but we're about to turn off. Otherwise the lights 343 * flash on and then off and it looks weird. 344 */ 345 public void userActivity(long when, boolean noChangeLights) 346 { 347 try { 348 mService.userActivity(when, noChangeLights); 349 } catch (RemoteException e) { 350 } 351 } 352 353 /** 354 * Force the device to go to sleep. Overrides all the wake locks that are 355 * held. 356 * 357 * @param time is used to order this correctly with the wake lock calls. 358 * The time should be in the {@link SystemClock#uptimeMillis 359 * SystemClock.uptimeMillis()} time base. 360 */ 361 public void goToSleep(long time) 362 { 363 try { 364 mService.goToSleep(time); 365 } catch (RemoteException e) { 366 } 367 } 368 369 private PowerManager() 370 { 371 } 372 373 /** 374 * {@hide} 375 */ 376 public PowerManager(IPowerManager service, Handler handler) 377 { 378 mService = service; 379 mHandler = handler; 380 } 381 382 /** 383 * TODO: It would be nice to be able to set the poke lock here, 384 * but I'm not sure what would be acceptable as an interface - 385 * either a PokeLock object (like WakeLock) or, possibly just a 386 * method call to set the poke lock. 387 */ 388 389 IPowerManager mService; 390 Handler mHandler; 391} 392 393