PowerManagerService.java revision 27c6dd7aa4ff6f57435a3c87d8b9a782cf7c9116
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 com.android.server; 18 19import com.android.internal.app.IBatteryStats; 20import com.android.server.am.BatteryStatsService; 21 22import android.app.ActivityManagerNative; 23import android.app.IActivityManager; 24import android.content.BroadcastReceiver; 25import android.content.ContentQueryMap; 26import android.content.ContentResolver; 27import android.content.Context; 28import android.content.Intent; 29import android.content.IntentFilter; 30import android.content.pm.PackageManager; 31import android.content.res.Resources; 32import android.database.Cursor; 33import android.hardware.Sensor; 34import android.hardware.SensorEvent; 35import android.hardware.SensorEventListener; 36import android.hardware.SensorManager; 37import android.os.BatteryStats; 38import android.os.Binder; 39import android.os.Handler; 40import android.os.HandlerThread; 41import android.os.IBinder; 42import android.os.IPowerManager; 43import android.os.LocalPowerManager; 44import android.os.Power; 45import android.os.PowerManager; 46import android.os.Process; 47import android.os.RemoteException; 48import android.os.SystemClock; 49import android.provider.Settings.SettingNotFoundException; 50import android.provider.Settings; 51import android.util.EventLog; 52import android.util.Log; 53import android.view.WindowManagerPolicy; 54import static android.provider.Settings.System.DIM_SCREEN; 55import static android.provider.Settings.System.SCREEN_BRIGHTNESS; 56import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; 57import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; 58import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT; 59import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN; 60 61import java.io.FileDescriptor; 62import java.io.PrintWriter; 63import java.util.ArrayList; 64import java.util.HashMap; 65import java.util.Observable; 66import java.util.Observer; 67 68class PowerManagerService extends IPowerManager.Stub 69 implements LocalPowerManager, Watchdog.Monitor { 70 71 private static final String TAG = "PowerManagerService"; 72 static final String PARTIAL_NAME = "PowerManagerService"; 73 74 private static final boolean LOG_PARTIAL_WL = false; 75 76 // Indicates whether touch-down cycles should be logged as part of the 77 // LOG_POWER_SCREEN_STATE log events 78 private static final boolean LOG_TOUCH_DOWNS = true; 79 80 private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK 81 | PowerManager.SCREEN_DIM_WAKE_LOCK 82 | PowerManager.SCREEN_BRIGHT_WAKE_LOCK 83 | PowerManager.FULL_WAKE_LOCK 84 | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK; 85 86 // time since last state: time since last event: 87 // The short keylight delay comes from Gservices; this is the default. 88 private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec 89 private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec 90 private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec 91 private static final int LONG_DIM_TIME = 7000; // t+N-5 sec 92 93 // How long to wait to debounce light sensor changes. 94 private static final int LIGHT_SENSOR_DELAY = 1000; 95 96 // trigger proximity if distance is less than 5 cm 97 private static final float PROXIMITY_THRESHOLD = 5.0f; 98 99 // Cached Gservices settings; see updateGservicesValues() 100 private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT; 101 102 // flags for setPowerState 103 private static final int SCREEN_ON_BIT = 0x00000001; 104 private static final int SCREEN_BRIGHT_BIT = 0x00000002; 105 private static final int BUTTON_BRIGHT_BIT = 0x00000004; 106 private static final int KEYBOARD_BRIGHT_BIT = 0x00000008; 107 private static final int BATTERY_LOW_BIT = 0x00000010; 108 109 // values for setPowerState 110 111 // SCREEN_OFF == everything off 112 private static final int SCREEN_OFF = 0x00000000; 113 114 // SCREEN_DIM == screen on, screen backlight dim 115 private static final int SCREEN_DIM = SCREEN_ON_BIT; 116 117 // SCREEN_BRIGHT == screen on, screen backlight bright 118 private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT; 119 120 // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright 121 private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT; 122 123 // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright 124 private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT; 125 126 // used for noChangeLights in setPowerState() 127 private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT; 128 129 static final boolean ANIMATE_SCREEN_LIGHTS = true; 130 static final boolean ANIMATE_BUTTON_LIGHTS = false; 131 static final boolean ANIMATE_KEYBOARD_LIGHTS = false; 132 133 static final int ANIM_STEPS = 60/4; 134 // Slower animation for autobrightness changes 135 static final int AUTOBRIGHTNESS_ANIM_STEPS = 60; 136 137 // These magic numbers are the initial state of the LEDs at boot. Ideally 138 // we should read them from the driver, but our current hardware returns 0 139 // for the initial value. Oops! 140 static final int INITIAL_SCREEN_BRIGHTNESS = 255; 141 static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF; 142 static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF; 143 144 static final int LOG_POWER_SLEEP_REQUESTED = 2724; 145 static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725; 146 static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726; 147 static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727; 148 static final int LOG_POWER_SCREEN_STATE = 2728; 149 static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729; 150 151 private final int MY_UID; 152 153 private boolean mDoneBooting = false; 154 private int mStayOnConditions = 0; 155 private int[] mBroadcastQueue = new int[] { -1, -1, -1 }; 156 private int[] mBroadcastWhy = new int[3]; 157 private int mPartialCount = 0; 158 private int mProximityCount = 0; 159 private int mPowerState; 160 private boolean mOffBecauseOfUser; 161 private int mUserState; 162 private boolean mKeyboardVisible = false; 163 private boolean mUserActivityAllowed = true; 164 private boolean mProximitySensorActive = false; 165 private int mTotalDelaySetting; 166 private int mKeylightDelay; 167 private int mDimDelay; 168 private int mScreenOffDelay; 169 private int mWakeLockState; 170 private long mLastEventTime = 0; 171 private long mScreenOffTime; 172 private volatile WindowManagerPolicy mPolicy; 173 private final LockList mLocks = new LockList(); 174 private Intent mScreenOffIntent; 175 private Intent mScreenOnIntent; 176 private HardwareService mHardware; 177 private Context mContext; 178 private UnsynchronizedWakeLock mBroadcastWakeLock; 179 private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock; 180 private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock; 181 private UnsynchronizedWakeLock mPreventScreenOnPartialLock; 182 private HandlerThread mHandlerThread; 183 private Handler mHandler; 184 private TimeoutTask mTimeoutTask = new TimeoutTask(); 185 private LightAnimator mLightAnimator = new LightAnimator(); 186 private final BrightnessState mScreenBrightness 187 = new BrightnessState(SCREEN_BRIGHT_BIT); 188 private final BrightnessState mKeyboardBrightness 189 = new BrightnessState(KEYBOARD_BRIGHT_BIT); 190 private final BrightnessState mButtonBrightness 191 = new BrightnessState(BUTTON_BRIGHT_BIT); 192 private boolean mStillNeedSleepNotification; 193 private boolean mIsPowered = false; 194 private IActivityManager mActivityService; 195 private IBatteryStats mBatteryStats; 196 private BatteryService mBatteryService; 197 private SensorManager mSensorManager; 198 private Sensor mProximitySensor; 199 private Sensor mLightSensor; 200 private boolean mLightSensorEnabled; 201 private float mLightSensorValue = -1; 202 private float mLightSensorPendingValue = -1; 203 private int mLightSensorBrightness = -1; 204 private boolean mDimScreen = true; 205 private long mNextTimeout; 206 private volatile int mPokey = 0; 207 private volatile boolean mPokeAwakeOnSet = false; 208 private volatile boolean mInitComplete = false; 209 private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>(); 210 private long mScreenOnTime; 211 private long mScreenOnStartTime; 212 private boolean mPreventScreenOn; 213 private int mScreenBrightnessOverride = -1; 214 private boolean mUseSoftwareAutoBrightness; 215 private boolean mAutoBrightessEnabled; 216 private int[] mAutoBrightnessLevels; 217 private int[] mLcdBacklightValues; 218 private int[] mButtonBacklightValues; 219 private int[] mKeyboardBacklightValues; 220 221 // Used when logging number and duration of touch-down cycles 222 private long mTotalTouchDownTime; 223 private long mLastTouchDown; 224 private int mTouchCycles; 225 226 // could be either static or controllable at runtime 227 private static final boolean mSpew = false; 228 private static final boolean mDebugLightSensor = (false || mSpew); 229 230 /* 231 static PrintStream mLog; 232 static { 233 try { 234 mLog = new PrintStream("/data/power.log"); 235 } 236 catch (FileNotFoundException e) { 237 android.util.Log.e(TAG, "Life is hard", e); 238 } 239 } 240 static class Log { 241 static void d(String tag, String s) { 242 mLog.println(s); 243 android.util.Log.d(tag, s); 244 } 245 static void i(String tag, String s) { 246 mLog.println(s); 247 android.util.Log.i(tag, s); 248 } 249 static void w(String tag, String s) { 250 mLog.println(s); 251 android.util.Log.w(tag, s); 252 } 253 static void e(String tag, String s) { 254 mLog.println(s); 255 android.util.Log.e(tag, s); 256 } 257 } 258 */ 259 260 /** 261 * This class works around a deadlock between the lock in PowerManager.WakeLock 262 * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its 263 * mToken object so it can be accessed from any thread, but it calls into here 264 * with its lock held. This class is essentially a reimplementation of 265 * PowerManager.WakeLock, but without that extra synchronized block, because we'll 266 * only call it with our own locks held. 267 */ 268 private class UnsynchronizedWakeLock { 269 int mFlags; 270 String mTag; 271 IBinder mToken; 272 int mCount = 0; 273 boolean mRefCounted; 274 275 UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) { 276 mFlags = flags; 277 mTag = tag; 278 mToken = new Binder(); 279 mRefCounted = refCounted; 280 } 281 282 public void acquire() { 283 if (!mRefCounted || mCount++ == 0) { 284 long ident = Binder.clearCallingIdentity(); 285 try { 286 PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken, 287 MY_UID, mTag); 288 } finally { 289 Binder.restoreCallingIdentity(ident); 290 } 291 } 292 } 293 294 public void release() { 295 if (!mRefCounted || --mCount == 0) { 296 PowerManagerService.this.releaseWakeLockLocked(mToken, false); 297 } 298 if (mCount < 0) { 299 throw new RuntimeException("WakeLock under-locked " + mTag); 300 } 301 } 302 303 public String toString() { 304 return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags) 305 + " mCount=" + mCount + ")"; 306 } 307 } 308 309 private final class BatteryReceiver extends BroadcastReceiver { 310 @Override 311 public void onReceive(Context context, Intent intent) { 312 synchronized (mLocks) { 313 boolean wasPowered = mIsPowered; 314 mIsPowered = mBatteryService.isPowered(); 315 316 if (mIsPowered != wasPowered) { 317 // update mStayOnWhilePluggedIn wake lock 318 updateWakeLockLocked(); 319 320 // treat plugging and unplugging the devices as a user activity. 321 // users find it disconcerting when they unplug the device 322 // and it shuts off right away. 323 // temporarily set mUserActivityAllowed to true so this will work 324 // even when the keyguard is on. 325 synchronized (mLocks) { 326 forceUserActivityLocked(); 327 } 328 } 329 } 330 } 331 } 332 333 /** 334 * Set the setting that determines whether the device stays on when plugged in. 335 * The argument is a bit string, with each bit specifying a power source that, 336 * when the device is connected to that source, causes the device to stay on. 337 * See {@link android.os.BatteryManager} for the list of power sources that 338 * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC} 339 * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB} 340 * @param val an {@code int} containing the bits that specify which power sources 341 * should cause the device to stay on. 342 */ 343 public void setStayOnSetting(int val) { 344 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null); 345 Settings.System.putInt(mContext.getContentResolver(), 346 Settings.System.STAY_ON_WHILE_PLUGGED_IN, val); 347 } 348 349 private class SettingsObserver implements Observer { 350 private int getInt(String name) { 351 return mSettings.getValues(name).getAsInteger(Settings.System.VALUE); 352 } 353 354 public void update(Observable o, Object arg) { 355 synchronized (mLocks) { 356 // STAY_ON_WHILE_PLUGGED_IN 357 mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN); 358 updateWakeLockLocked(); 359 360 // SCREEN_OFF_TIMEOUT 361 mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT); 362 363 // DIM_SCREEN 364 //mDimScreen = getInt(DIM_SCREEN) != 0; 365 366 // SCREEN_BRIGHTNESS_MODE 367 setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE)); 368 369 // recalculate everything 370 setScreenOffTimeoutsLocked(); 371 } 372 } 373 } 374 375 PowerManagerService() 376 { 377 // Hack to get our uid... should have a func for this. 378 long token = Binder.clearCallingIdentity(); 379 MY_UID = Binder.getCallingUid(); 380 Binder.restoreCallingIdentity(token); 381 382 // XXX remove this when the kernel doesn't timeout wake locks 383 Power.setLastUserActivityTimeout(7*24*3600*1000); // one week 384 385 // assume nothing is on yet 386 mUserState = mPowerState = 0; 387 388 // Add ourself to the Watchdog monitors. 389 Watchdog.getInstance().addMonitor(this); 390 mScreenOnStartTime = SystemClock.elapsedRealtime(); 391 } 392 393 private ContentQueryMap mSettings; 394 395 void init(Context context, HardwareService hardware, IActivityManager activity, 396 BatteryService battery) { 397 mHardware = hardware; 398 mContext = context; 399 mActivityService = activity; 400 mBatteryStats = BatteryStatsService.getService(); 401 mBatteryService = battery; 402 403 mHandlerThread = new HandlerThread("PowerManagerService") { 404 @Override 405 protected void onLooperPrepared() { 406 super.onLooperPrepared(); 407 initInThread(); 408 } 409 }; 410 mHandlerThread.start(); 411 412 synchronized (mHandlerThread) { 413 while (!mInitComplete) { 414 try { 415 mHandlerThread.wait(); 416 } catch (InterruptedException e) { 417 // Ignore 418 } 419 } 420 } 421 } 422 423 void initInThread() { 424 mHandler = new Handler(); 425 426 mBroadcastWakeLock = new UnsynchronizedWakeLock( 427 PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true); 428 mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock( 429 PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false); 430 mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock( 431 PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false); 432 mPreventScreenOnPartialLock = new UnsynchronizedWakeLock( 433 PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false); 434 435 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON); 436 mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 437 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF); 438 mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 439 440 Resources resources = mContext.getResources(); 441 442 // read settings for auto-brightness 443 mUseSoftwareAutoBrightness = resources.getBoolean( 444 com.android.internal.R.bool.config_automatic_brightness_available); 445 if (mUseSoftwareAutoBrightness) { 446 mAutoBrightnessLevels = resources.getIntArray( 447 com.android.internal.R.array.config_autoBrightnessLevels); 448 mLcdBacklightValues = resources.getIntArray( 449 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues); 450 mButtonBacklightValues = resources.getIntArray( 451 com.android.internal.R.array.config_autoBrightnessButtonBacklightValues); 452 mKeyboardBacklightValues = resources.getIntArray( 453 com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues); 454 } 455 456 ContentResolver resolver = mContext.getContentResolver(); 457 Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null, 458 "(" + Settings.System.NAME + "=?) or (" 459 + Settings.System.NAME + "=?) or (" 460 + Settings.System.NAME + "=?) or (" 461 + Settings.System.NAME + "=?)", 462 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN, 463 SCREEN_BRIGHTNESS_MODE}, 464 null); 465 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler); 466 SettingsObserver settingsObserver = new SettingsObserver(); 467 mSettings.addObserver(settingsObserver); 468 469 // pretend that the settings changed so we will get their initial state 470 settingsObserver.update(mSettings, null); 471 472 // register for the battery changed notifications 473 IntentFilter filter = new IntentFilter(); 474 filter.addAction(Intent.ACTION_BATTERY_CHANGED); 475 mContext.registerReceiver(new BatteryReceiver(), filter); 476 477 // Listen for Gservices changes 478 IntentFilter gservicesChangedFilter = 479 new IntentFilter(Settings.Gservices.CHANGED_ACTION); 480 mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter); 481 // And explicitly do the initial update of our cached settings 482 updateGservicesValues(); 483 484 if (mUseSoftwareAutoBrightness) { 485 // turn the screen on 486 setPowerState(SCREEN_BRIGHT); 487 } else { 488 // turn everything on 489 setPowerState(ALL_BRIGHT); 490 } 491 492 synchronized (mHandlerThread) { 493 mInitComplete = true; 494 mHandlerThread.notifyAll(); 495 } 496 } 497 498 private class WakeLock implements IBinder.DeathRecipient 499 { 500 WakeLock(int f, IBinder b, String t, int u) { 501 super(); 502 flags = f; 503 binder = b; 504 tag = t; 505 uid = u == MY_UID ? Process.SYSTEM_UID : u; 506 if (u != MY_UID || ( 507 !"KEEP_SCREEN_ON_FLAG".equals(tag) 508 && !"KeyInputQueue".equals(tag))) { 509 monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK 510 ? BatteryStats.WAKE_TYPE_PARTIAL 511 : BatteryStats.WAKE_TYPE_FULL; 512 } else { 513 monitorType = -1; 514 } 515 try { 516 b.linkToDeath(this, 0); 517 } catch (RemoteException e) { 518 binderDied(); 519 } 520 } 521 public void binderDied() { 522 synchronized (mLocks) { 523 releaseWakeLockLocked(this.binder, true); 524 } 525 } 526 final int flags; 527 final IBinder binder; 528 final String tag; 529 final int uid; 530 final int monitorType; 531 boolean activated = true; 532 int minState; 533 } 534 535 private void updateWakeLockLocked() { 536 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { 537 // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set. 538 mStayOnWhilePluggedInScreenDimLock.acquire(); 539 mStayOnWhilePluggedInPartialLock.acquire(); 540 } else { 541 mStayOnWhilePluggedInScreenDimLock.release(); 542 mStayOnWhilePluggedInPartialLock.release(); 543 } 544 } 545 546 private boolean isScreenLock(int flags) 547 { 548 int n = flags & LOCK_MASK; 549 return n == PowerManager.FULL_WAKE_LOCK 550 || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK 551 || n == PowerManager.SCREEN_DIM_WAKE_LOCK; 552 } 553 554 public void acquireWakeLock(int flags, IBinder lock, String tag) { 555 int uid = Binder.getCallingUid(); 556 if (uid != Process.myUid()) { 557 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 558 } 559 long ident = Binder.clearCallingIdentity(); 560 try { 561 synchronized (mLocks) { 562 acquireWakeLockLocked(flags, lock, uid, tag); 563 } 564 } finally { 565 Binder.restoreCallingIdentity(ident); 566 } 567 } 568 569 public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) { 570 int acquireUid = -1; 571 String acquireName = null; 572 int acquireType = -1; 573 574 if (mSpew) { 575 Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag); 576 } 577 578 int index = mLocks.getIndex(lock); 579 WakeLock wl; 580 boolean newlock; 581 if (index < 0) { 582 wl = new WakeLock(flags, lock, tag, uid); 583 switch (wl.flags & LOCK_MASK) 584 { 585 case PowerManager.FULL_WAKE_LOCK: 586 if (mUseSoftwareAutoBrightness) { 587 wl.minState = SCREEN_BRIGHT; 588 } else { 589 wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT); 590 } 591 break; 592 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: 593 wl.minState = SCREEN_BRIGHT; 594 break; 595 case PowerManager.SCREEN_DIM_WAKE_LOCK: 596 wl.minState = SCREEN_DIM; 597 break; 598 case PowerManager.PARTIAL_WAKE_LOCK: 599 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 600 break; 601 default: 602 // just log and bail. we're in the server, so don't 603 // throw an exception. 604 Log.e(TAG, "bad wakelock type for lock '" + tag + "' " 605 + " flags=" + flags); 606 return; 607 } 608 mLocks.addLock(wl); 609 newlock = true; 610 } else { 611 wl = mLocks.get(index); 612 newlock = false; 613 } 614 if (isScreenLock(flags)) { 615 // if this causes a wakeup, we reactivate all of the locks and 616 // set it to whatever they want. otherwise, we modulate that 617 // by the current state so we never turn it more on than 618 // it already is. 619 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) { 620 int oldWakeLockState = mWakeLockState; 621 mWakeLockState = mLocks.reactivateScreenLocksLocked(); 622 if (mSpew) { 623 Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState) 624 + " mWakeLockState=0x" 625 + Integer.toHexString(mWakeLockState) 626 + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState)); 627 } 628 } else { 629 if (mSpew) { 630 Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState) 631 + " mLocks.gatherState()=0x" 632 + Integer.toHexString(mLocks.gatherState()) 633 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)); 634 } 635 mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState(); 636 } 637 setPowerState(mWakeLockState | mUserState); 638 } 639 else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) { 640 if (newlock) { 641 mPartialCount++; 642 if (mPartialCount == 1) { 643 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag); 644 } 645 } 646 Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME); 647 } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) { 648 mProximityCount++; 649 if (mProximityCount == 1) { 650 enableProximityLockLocked(); 651 } 652 } 653 if (newlock) { 654 acquireUid = wl.uid; 655 acquireName = wl.tag; 656 acquireType = wl.monitorType; 657 } 658 659 if (acquireType >= 0) { 660 try { 661 mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType); 662 } catch (RemoteException e) { 663 // Ignore 664 } 665 } 666 } 667 668 public void releaseWakeLock(IBinder lock) { 669 int uid = Binder.getCallingUid(); 670 if (uid != Process.myUid()) { 671 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); 672 } 673 674 synchronized (mLocks) { 675 releaseWakeLockLocked(lock, false); 676 } 677 } 678 679 private void releaseWakeLockLocked(IBinder lock, boolean death) { 680 int releaseUid; 681 String releaseName; 682 int releaseType; 683 684 WakeLock wl = mLocks.removeLock(lock); 685 if (wl == null) { 686 return; 687 } 688 689 if (mSpew) { 690 Log.d(TAG, "releaseWakeLock flags=0x" 691 + Integer.toHexString(wl.flags) + " tag=" + wl.tag); 692 } 693 694 if (isScreenLock(wl.flags)) { 695 mWakeLockState = mLocks.gatherState(); 696 // goes in the middle to reduce flicker 697 if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) { 698 userActivity(SystemClock.uptimeMillis(), false); 699 } 700 setPowerState(mWakeLockState | mUserState); 701 } 702 else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) { 703 mPartialCount--; 704 if (mPartialCount == 0) { 705 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag); 706 Power.releaseWakeLock(PARTIAL_NAME); 707 } 708 } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) { 709 mProximityCount--; 710 if (mProximityCount == 0) { 711 disableProximityLockLocked(); 712 } 713 } 714 // Unlink the lock from the binder. 715 wl.binder.unlinkToDeath(wl, 0); 716 releaseUid = wl.uid; 717 releaseName = wl.tag; 718 releaseType = wl.monitorType; 719 720 if (releaseType >= 0) { 721 long origId = Binder.clearCallingIdentity(); 722 try { 723 mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType); 724 } catch (RemoteException e) { 725 // Ignore 726 } finally { 727 Binder.restoreCallingIdentity(origId); 728 } 729 } 730 } 731 732 private class PokeLock implements IBinder.DeathRecipient 733 { 734 PokeLock(int p, IBinder b, String t) { 735 super(); 736 this.pokey = p; 737 this.binder = b; 738 this.tag = t; 739 try { 740 b.linkToDeath(this, 0); 741 } catch (RemoteException e) { 742 binderDied(); 743 } 744 } 745 public void binderDied() { 746 setPokeLock(0, this.binder, this.tag); 747 } 748 int pokey; 749 IBinder binder; 750 String tag; 751 boolean awakeOnSet; 752 } 753 754 public void setPokeLock(int pokey, IBinder token, String tag) { 755 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 756 if (token == null) { 757 Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'"); 758 return; 759 } 760 761 if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) { 762 throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT" 763 + " and POKE_LOCK_MEDIUM_TIMEOUT"); 764 } 765 766 synchronized (mLocks) { 767 if (pokey != 0) { 768 PokeLock p = mPokeLocks.get(token); 769 int oldPokey = 0; 770 if (p != null) { 771 oldPokey = p.pokey; 772 p.pokey = pokey; 773 } else { 774 p = new PokeLock(pokey, token, tag); 775 mPokeLocks.put(token, p); 776 } 777 int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK; 778 int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK; 779 if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) { 780 p.awakeOnSet = true; 781 } 782 } else { 783 PokeLock rLock = mPokeLocks.remove(token); 784 if (rLock != null) { 785 token.unlinkToDeath(rLock, 0); 786 } 787 } 788 789 int oldPokey = mPokey; 790 int cumulative = 0; 791 boolean oldAwakeOnSet = mPokeAwakeOnSet; 792 boolean awakeOnSet = false; 793 for (PokeLock p: mPokeLocks.values()) { 794 cumulative |= p.pokey; 795 if (p.awakeOnSet) { 796 awakeOnSet = true; 797 } 798 } 799 mPokey = cumulative; 800 mPokeAwakeOnSet = awakeOnSet; 801 802 int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK; 803 int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK; 804 805 if (oldCumulativeTimeout != newCumulativeTimeout) { 806 setScreenOffTimeoutsLocked(); 807 // reset the countdown timer, but use the existing nextState so it doesn't 808 // change anything 809 setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState); 810 } 811 } 812 } 813 814 private static String lockType(int type) 815 { 816 switch (type) 817 { 818 case PowerManager.FULL_WAKE_LOCK: 819 return "FULL_WAKE_LOCK "; 820 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK: 821 return "SCREEN_BRIGHT_WAKE_LOCK "; 822 case PowerManager.SCREEN_DIM_WAKE_LOCK: 823 return "SCREEN_DIM_WAKE_LOCK "; 824 case PowerManager.PARTIAL_WAKE_LOCK: 825 return "PARTIAL_WAKE_LOCK "; 826 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK: 827 return "PROXIMITY_SCREEN_OFF_WAKE_LOCK"; 828 default: 829 return "??? "; 830 } 831 } 832 833 private static String dumpPowerState(int state) { 834 return (((state & KEYBOARD_BRIGHT_BIT) != 0) 835 ? "KEYBOARD_BRIGHT_BIT " : "") 836 + (((state & SCREEN_BRIGHT_BIT) != 0) 837 ? "SCREEN_BRIGHT_BIT " : "") 838 + (((state & SCREEN_ON_BIT) != 0) 839 ? "SCREEN_ON_BIT " : "") 840 + (((state & BATTERY_LOW_BIT) != 0) 841 ? "BATTERY_LOW_BIT " : ""); 842 } 843 844 @Override 845 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 846 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 847 != PackageManager.PERMISSION_GRANTED) { 848 pw.println("Permission Denial: can't dump PowerManager from from pid=" 849 + Binder.getCallingPid() 850 + ", uid=" + Binder.getCallingUid()); 851 return; 852 } 853 854 long now = SystemClock.uptimeMillis(); 855 856 pw.println("Power Manager State:"); 857 pw.println(" mIsPowered=" + mIsPowered 858 + " mPowerState=" + mPowerState 859 + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime) 860 + " ms"); 861 pw.println(" mPartialCount=" + mPartialCount); 862 pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState)); 863 pw.println(" mUserState=" + dumpPowerState(mUserState)); 864 pw.println(" mPowerState=" + dumpPowerState(mPowerState)); 865 pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState())); 866 pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now 867 + " " + ((mNextTimeout-now)/1000) + "s from now"); 868 pw.println(" mDimScreen=" + mDimScreen 869 + " mStayOnConditions=" + mStayOnConditions); 870 pw.println(" mOffBecauseOfUser=" + mOffBecauseOfUser 871 + " mUserState=" + mUserState); 872 pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1] 873 + ',' + mBroadcastQueue[2] + "}"); 874 pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1] 875 + ',' + mBroadcastWhy[2] + "}"); 876 pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet); 877 pw.println(" mKeyboardVisible=" + mKeyboardVisible 878 + " mUserActivityAllowed=" + mUserActivityAllowed); 879 pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay 880 + " mScreenOffDelay=" + mScreenOffDelay); 881 pw.println(" mPreventScreenOn=" + mPreventScreenOn 882 + " mScreenBrightnessOverride=" + mScreenBrightnessOverride); 883 pw.println(" mTotalDelaySetting=" + mTotalDelaySetting); 884 pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock); 885 pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock); 886 pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock); 887 pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock); 888 pw.println(" mProximitySensorActive=" + mProximitySensorActive); 889 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled); 890 pw.println(" mLightSensorValue=" + mLightSensorValue); 891 pw.println(" mLightSensorPendingValue=" + mLightSensorPendingValue); 892 pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness); 893 pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled); 894 mScreenBrightness.dump(pw, " mScreenBrightness: "); 895 mKeyboardBrightness.dump(pw, " mKeyboardBrightness: "); 896 mButtonBrightness.dump(pw, " mButtonBrightness: "); 897 898 int N = mLocks.size(); 899 pw.println(); 900 pw.println("mLocks.size=" + N + ":"); 901 for (int i=0; i<N; i++) { 902 WakeLock wl = mLocks.get(i); 903 String type = lockType(wl.flags & LOCK_MASK); 904 String acquireCausesWakeup = ""; 905 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) { 906 acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP "; 907 } 908 String activated = ""; 909 if (wl.activated) { 910 activated = " activated"; 911 } 912 pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup 913 + activated + " (minState=" + wl.minState + ")"); 914 } 915 916 pw.println(); 917 pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":"); 918 for (PokeLock p: mPokeLocks.values()) { 919 pw.println(" poke lock '" + p.tag + "':" 920 + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0 921 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "") 922 + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0 923 ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "") 924 + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0 925 ? " POKE_LOCK_SHORT_TIMEOUT" : "") 926 + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0 927 ? " POKE_LOCK_MEDIUM_TIMEOUT" : "")); 928 } 929 930 pw.println(); 931 } 932 933 private void setTimeoutLocked(long now, int nextState) 934 { 935 if (mDoneBooting) { 936 mHandler.removeCallbacks(mTimeoutTask); 937 mTimeoutTask.nextState = nextState; 938 long when = now; 939 switch (nextState) 940 { 941 case SCREEN_BRIGHT: 942 when += mKeylightDelay; 943 break; 944 case SCREEN_DIM: 945 if (mDimDelay >= 0) { 946 when += mDimDelay; 947 break; 948 } else { 949 Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim"); 950 } 951 case SCREEN_OFF: 952 synchronized (mLocks) { 953 when += mScreenOffDelay; 954 } 955 break; 956 } 957 if (mSpew) { 958 Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState 959 + " when=" + when); 960 } 961 mHandler.postAtTime(mTimeoutTask, when); 962 mNextTimeout = when; // for debugging 963 } 964 } 965 966 private void cancelTimerLocked() 967 { 968 mHandler.removeCallbacks(mTimeoutTask); 969 mTimeoutTask.nextState = -1; 970 } 971 972 private class TimeoutTask implements Runnable 973 { 974 int nextState; // access should be synchronized on mLocks 975 public void run() 976 { 977 synchronized (mLocks) { 978 if (mSpew) { 979 Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState); 980 } 981 982 if (nextState == -1) { 983 return; 984 } 985 986 mUserState = this.nextState; 987 setPowerState(this.nextState | mWakeLockState); 988 989 long now = SystemClock.uptimeMillis(); 990 991 switch (this.nextState) 992 { 993 case SCREEN_BRIGHT: 994 if (mDimDelay >= 0) { 995 setTimeoutLocked(now, SCREEN_DIM); 996 break; 997 } 998 case SCREEN_DIM: 999 setTimeoutLocked(now, SCREEN_OFF); 1000 break; 1001 } 1002 } 1003 } 1004 } 1005 1006 private void sendNotificationLocked(boolean on, int why) 1007 { 1008 if (!on) { 1009 mStillNeedSleepNotification = false; 1010 } 1011 1012 // Add to the queue. 1013 int index = 0; 1014 while (mBroadcastQueue[index] != -1) { 1015 index++; 1016 } 1017 mBroadcastQueue[index] = on ? 1 : 0; 1018 mBroadcastWhy[index] = why; 1019 1020 // If we added it position 2, then there is a pair that can be stripped. 1021 // If we added it position 1 and we're turning the screen off, we can strip 1022 // the pair and do nothing, because the screen is already off, and therefore 1023 // keyguard has already been enabled. 1024 // However, if we added it at position 1 and we're turning it on, then position 1025 // 0 was to turn it off, and we can't strip that, because keyguard needs to come 1026 // on, so have to run the queue then. 1027 if (index == 2) { 1028 // Also, while we're collapsing them, if it's going to be an "off," and one 1029 // is off because of user, then use that, regardless of whether it's the first 1030 // or second one. 1031 if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) { 1032 mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER; 1033 } 1034 mBroadcastQueue[0] = on ? 1 : 0; 1035 mBroadcastQueue[1] = -1; 1036 mBroadcastQueue[2] = -1; 1037 index = 0; 1038 } 1039 if (index == 1 && !on) { 1040 mBroadcastQueue[0] = -1; 1041 mBroadcastQueue[1] = -1; 1042 index = -1; 1043 // The wake lock was being held, but we're not actually going to do any 1044 // broadcasts, so release the wake lock. 1045 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount); 1046 mBroadcastWakeLock.release(); 1047 } 1048 1049 // Now send the message. 1050 if (index >= 0) { 1051 // Acquire the broadcast wake lock before changing the power 1052 // state. It will be release after the broadcast is sent. 1053 // We always increment the ref count for each notification in the queue 1054 // and always decrement when that notification is handled. 1055 mBroadcastWakeLock.acquire(); 1056 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount); 1057 mHandler.post(mNotificationTask); 1058 } 1059 } 1060 1061 private Runnable mNotificationTask = new Runnable() 1062 { 1063 public void run() 1064 { 1065 while (true) { 1066 int value; 1067 int why; 1068 WindowManagerPolicy policy; 1069 synchronized (mLocks) { 1070 value = mBroadcastQueue[0]; 1071 why = mBroadcastWhy[0]; 1072 for (int i=0; i<2; i++) { 1073 mBroadcastQueue[i] = mBroadcastQueue[i+1]; 1074 mBroadcastWhy[i] = mBroadcastWhy[i+1]; 1075 } 1076 policy = getPolicyLocked(); 1077 } 1078 if (value == 1) { 1079 mScreenOnStart = SystemClock.uptimeMillis(); 1080 1081 policy.screenTurnedOn(); 1082 try { 1083 ActivityManagerNative.getDefault().wakingUp(); 1084 } catch (RemoteException e) { 1085 // ignore it 1086 } 1087 1088 if (mSpew) { 1089 Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock); 1090 } 1091 if (mContext != null && ActivityManagerNative.isSystemReady()) { 1092 mContext.sendOrderedBroadcast(mScreenOnIntent, null, 1093 mScreenOnBroadcastDone, mHandler, 0, null, null); 1094 } else { 1095 synchronized (mLocks) { 1096 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2, 1097 mBroadcastWakeLock.mCount); 1098 mBroadcastWakeLock.release(); 1099 } 1100 } 1101 } 1102 else if (value == 0) { 1103 mScreenOffStart = SystemClock.uptimeMillis(); 1104 1105 policy.screenTurnedOff(why); 1106 try { 1107 ActivityManagerNative.getDefault().goingToSleep(); 1108 } catch (RemoteException e) { 1109 // ignore it. 1110 } 1111 1112 if (mContext != null && ActivityManagerNative.isSystemReady()) { 1113 mContext.sendOrderedBroadcast(mScreenOffIntent, null, 1114 mScreenOffBroadcastDone, mHandler, 0, null, null); 1115 } else { 1116 synchronized (mLocks) { 1117 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3, 1118 mBroadcastWakeLock.mCount); 1119 mBroadcastWakeLock.release(); 1120 } 1121 } 1122 } 1123 else { 1124 // If we're in this case, then this handler is running for a previous 1125 // paired transaction. mBroadcastWakeLock will already have been released. 1126 break; 1127 } 1128 } 1129 } 1130 }; 1131 1132 long mScreenOnStart; 1133 private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() { 1134 public void onReceive(Context context, Intent intent) { 1135 synchronized (mLocks) { 1136 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1, 1137 SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount); 1138 mBroadcastWakeLock.release(); 1139 } 1140 } 1141 }; 1142 1143 long mScreenOffStart; 1144 private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() { 1145 public void onReceive(Context context, Intent intent) { 1146 synchronized (mLocks) { 1147 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0, 1148 SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount); 1149 mBroadcastWakeLock.release(); 1150 } 1151 } 1152 }; 1153 1154 void logPointerUpEvent() { 1155 if (LOG_TOUCH_DOWNS) { 1156 mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown; 1157 mLastTouchDown = 0; 1158 } 1159 } 1160 1161 void logPointerDownEvent() { 1162 if (LOG_TOUCH_DOWNS) { 1163 // If we are not already timing a down/up sequence 1164 if (mLastTouchDown == 0) { 1165 mLastTouchDown = SystemClock.elapsedRealtime(); 1166 mTouchCycles++; 1167 } 1168 } 1169 } 1170 1171 /** 1172 * Prevents the screen from turning on even if it *should* turn on due 1173 * to a subsequent full wake lock being acquired. 1174 * <p> 1175 * This is a temporary hack that allows an activity to "cover up" any 1176 * display glitches that happen during the activity's startup 1177 * sequence. (Specifically, this API was added to work around a 1178 * cosmetic bug in the "incoming call" sequence, where the lock screen 1179 * would flicker briefly before the incoming call UI became visible.) 1180 * TODO: There ought to be a more elegant way of doing this, 1181 * probably by having the PowerManager and ActivityManager 1182 * work together to let apps specify that the screen on/off 1183 * state should be synchronized with the Activity lifecycle. 1184 * <p> 1185 * Note that calling preventScreenOn(true) will NOT turn the screen 1186 * off if it's currently on. (This API only affects *future* 1187 * acquisitions of full wake locks.) 1188 * But calling preventScreenOn(false) WILL turn the screen on if 1189 * it's currently off because of a prior preventScreenOn(true) call. 1190 * <p> 1191 * Any call to preventScreenOn(true) MUST be followed promptly by a call 1192 * to preventScreenOn(false). In fact, if the preventScreenOn(false) 1193 * call doesn't occur within 5 seconds, we'll turn the screen back on 1194 * ourselves (and log a warning about it); this prevents a buggy app 1195 * from disabling the screen forever.) 1196 * <p> 1197 * TODO: this feature should really be controlled by a new type of poke 1198 * lock (rather than an IPowerManager call). 1199 */ 1200 public void preventScreenOn(boolean prevent) { 1201 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 1202 1203 synchronized (mLocks) { 1204 if (prevent) { 1205 // First of all, grab a partial wake lock to 1206 // make sure the CPU stays on during the entire 1207 // preventScreenOn(true) -> preventScreenOn(false) sequence. 1208 mPreventScreenOnPartialLock.acquire(); 1209 1210 // Post a forceReenableScreen() call (for 5 seconds in the 1211 // future) to make sure the matching preventScreenOn(false) call 1212 // has happened by then. 1213 mHandler.removeCallbacks(mForceReenableScreenTask); 1214 mHandler.postDelayed(mForceReenableScreenTask, 5000); 1215 1216 // Finally, set the flag that prevents the screen from turning on. 1217 // (Below, in setPowerState(), we'll check mPreventScreenOn and 1218 // we *won't* call setScreenStateLocked(true) if it's set.) 1219 mPreventScreenOn = true; 1220 } else { 1221 // (Re)enable the screen. 1222 mPreventScreenOn = false; 1223 1224 // We're "undoing" a the prior preventScreenOn(true) call, so we 1225 // no longer need the 5-second safeguard. 1226 mHandler.removeCallbacks(mForceReenableScreenTask); 1227 1228 // Forcibly turn on the screen if it's supposed to be on. (This 1229 // handles the case where the screen is currently off because of 1230 // a prior preventScreenOn(true) call.) 1231 if ((mPowerState & SCREEN_ON_BIT) != 0) { 1232 if (mSpew) { 1233 Log.d(TAG, 1234 "preventScreenOn: turning on after a prior preventScreenOn(true)!"); 1235 } 1236 int err = setScreenStateLocked(true); 1237 if (err != 0) { 1238 Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err); 1239 } 1240 } 1241 1242 // Release the partial wake lock that we held during the 1243 // preventScreenOn(true) -> preventScreenOn(false) sequence. 1244 mPreventScreenOnPartialLock.release(); 1245 } 1246 } 1247 } 1248 1249 public void setScreenBrightnessOverride(int brightness) { 1250 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 1251 1252 synchronized (mLocks) { 1253 if (mScreenBrightnessOverride != brightness) { 1254 mScreenBrightnessOverride = brightness; 1255 updateLightsLocked(mPowerState, SCREEN_ON_BIT); 1256 } 1257 } 1258 } 1259 1260 /** 1261 * Sanity-check that gets called 5 seconds after any call to 1262 * preventScreenOn(true). This ensures that the original call 1263 * is followed promptly by a call to preventScreenOn(false). 1264 */ 1265 private void forceReenableScreen() { 1266 // We shouldn't get here at all if mPreventScreenOn is false, since 1267 // we should have already removed any existing 1268 // mForceReenableScreenTask messages... 1269 if (!mPreventScreenOn) { 1270 Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do"); 1271 return; 1272 } 1273 1274 // Uh oh. It's been 5 seconds since a call to 1275 // preventScreenOn(true) and we haven't re-enabled the screen yet. 1276 // This means the app that called preventScreenOn(true) is either 1277 // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)), 1278 // or buggy (i.e. it forgot to call preventScreenOn(false), or 1279 // crashed before doing so.) 1280 1281 // Log a warning, and forcibly turn the screen back on. 1282 Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! " 1283 + "Forcing the screen back on..."); 1284 preventScreenOn(false); 1285 } 1286 1287 private Runnable mForceReenableScreenTask = new Runnable() { 1288 public void run() { 1289 forceReenableScreen(); 1290 } 1291 }; 1292 1293 private int setScreenStateLocked(boolean on) { 1294 int err = Power.setScreenState(on); 1295 if (err == 0 && mUseSoftwareAutoBrightness) { 1296 enableLightSensor(on); 1297 if (!on) { 1298 // make sure button and key backlights are off too 1299 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0); 1300 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0); 1301 // clear current value so we will update based on the new conditions 1302 // when the sensor is reenabled. 1303 mLightSensorValue = -1; 1304 } 1305 } 1306 return err; 1307 } 1308 1309 private void setPowerState(int state) 1310 { 1311 setPowerState(state, false, false); 1312 } 1313 1314 private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser) 1315 { 1316 synchronized (mLocks) { 1317 int err; 1318 1319 if (mSpew) { 1320 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState) 1321 + " newState=0x" + Integer.toHexString(newState) 1322 + " noChangeLights=" + noChangeLights); 1323 } 1324 1325 if (noChangeLights) { 1326 newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK); 1327 } 1328 if (mProximitySensorActive) { 1329 // don't turn on the screen when the proximity sensor lock is held 1330 newState = (newState & ~SCREEN_BRIGHT); 1331 } 1332 1333 if (batteryIsLow()) { 1334 newState |= BATTERY_LOW_BIT; 1335 } else { 1336 newState &= ~BATTERY_LOW_BIT; 1337 } 1338 if (newState == mPowerState) { 1339 return; 1340 } 1341 1342 if (!mDoneBooting && !mUseSoftwareAutoBrightness) { 1343 newState |= ALL_BRIGHT; 1344 } 1345 1346 boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0; 1347 boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0; 1348 1349 if (mSpew) { 1350 Log.d(TAG, "setPowerState: mPowerState=" + mPowerState 1351 + " newState=" + newState + " noChangeLights=" + noChangeLights); 1352 Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0) 1353 + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0)); 1354 Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0) 1355 + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0)); 1356 Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0) 1357 + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0)); 1358 Log.d(TAG, " oldScreenOn=" + oldScreenOn 1359 + " newScreenOn=" + newScreenOn); 1360 Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0) 1361 + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0)); 1362 } 1363 1364 if (mPowerState != newState) { 1365 updateLightsLocked(newState, 0); 1366 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK); 1367 } 1368 1369 if (oldScreenOn != newScreenOn) { 1370 if (newScreenOn) { 1371 // When the user presses the power button, we need to always send out the 1372 // notification that it's going to sleep so the keyguard goes on. But 1373 // we can't do that until the screen fades out, so we don't show the keyguard 1374 // too early. 1375 if (mStillNeedSleepNotification) { 1376 sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER); 1377 } 1378 1379 // Turn on the screen UNLESS there was a prior 1380 // preventScreenOn(true) request. (Note that the lifetime 1381 // of a single preventScreenOn() request is limited to 5 1382 // seconds to prevent a buggy app from disabling the 1383 // screen forever; see forceReenableScreen().) 1384 boolean reallyTurnScreenOn = true; 1385 if (mSpew) { 1386 Log.d(TAG, "- turning screen on... mPreventScreenOn = " 1387 + mPreventScreenOn); 1388 } 1389 1390 if (mPreventScreenOn) { 1391 if (mSpew) { 1392 Log.d(TAG, "- PREVENTING screen from really turning on!"); 1393 } 1394 reallyTurnScreenOn = false; 1395 } 1396 if (reallyTurnScreenOn) { 1397 err = setScreenStateLocked(true); 1398 long identity = Binder.clearCallingIdentity(); 1399 try { 1400 mBatteryStats.noteScreenBrightness( 1401 getPreferredBrightness()); 1402 mBatteryStats.noteScreenOn(); 1403 } catch (RemoteException e) { 1404 Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e); 1405 } finally { 1406 Binder.restoreCallingIdentity(identity); 1407 } 1408 } else { 1409 setScreenStateLocked(false); 1410 // But continue as if we really did turn the screen on... 1411 err = 0; 1412 } 1413 1414 mScreenOnStartTime = SystemClock.elapsedRealtime(); 1415 mLastTouchDown = 0; 1416 mTotalTouchDownTime = 0; 1417 mTouchCycles = 0; 1418 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0, 1419 mTotalTouchDownTime, mTouchCycles); 1420 if (err == 0) { 1421 mPowerState |= SCREEN_ON_BIT; 1422 sendNotificationLocked(true, -1); 1423 } 1424 } else { 1425 mScreenOffTime = SystemClock.elapsedRealtime(); 1426 long identity = Binder.clearCallingIdentity(); 1427 try { 1428 mBatteryStats.noteScreenOff(); 1429 } catch (RemoteException e) { 1430 Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e); 1431 } finally { 1432 Binder.restoreCallingIdentity(identity); 1433 } 1434 mPowerState &= ~SCREEN_ON_BIT; 1435 if (!mScreenBrightness.animating) { 1436 err = screenOffFinishedAnimatingLocked(becauseOfUser); 1437 } else { 1438 mOffBecauseOfUser = becauseOfUser; 1439 err = 0; 1440 mLastTouchDown = 0; 1441 } 1442 } 1443 } 1444 } 1445 } 1446 1447 private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) { 1448 // I don't think we need to check the current state here because all of these 1449 // Power.setScreenState and sendNotificationLocked can both handle being 1450 // called multiple times in the same state. -joeo 1451 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0, 1452 mTotalTouchDownTime, mTouchCycles); 1453 mLastTouchDown = 0; 1454 int err = setScreenStateLocked(false); 1455 if (mScreenOnStartTime != 0) { 1456 mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime; 1457 mScreenOnStartTime = 0; 1458 } 1459 if (err == 0) { 1460 int why = becauseOfUser 1461 ? WindowManagerPolicy.OFF_BECAUSE_OF_USER 1462 : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT; 1463 sendNotificationLocked(false, why); 1464 } 1465 return err; 1466 } 1467 1468 private boolean batteryIsLow() { 1469 return (!mIsPowered && 1470 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD); 1471 } 1472 1473 private void updateLightsLocked(int newState, int forceState) { 1474 final int oldState = mPowerState; 1475 final int realDifference = (newState ^ oldState); 1476 final int difference = realDifference | forceState; 1477 if (difference == 0) { 1478 return; 1479 } 1480 1481 int offMask = 0; 1482 int dimMask = 0; 1483 int onMask = 0; 1484 1485 int preferredBrightness = getPreferredBrightness(); 1486 boolean startAnimation = false; 1487 1488 if ((difference & KEYBOARD_BRIGHT_BIT) != 0) { 1489 if (ANIMATE_KEYBOARD_LIGHTS) { 1490 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { 1491 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, 1492 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, 1493 preferredBrightness); 1494 } else { 1495 mKeyboardBrightness.setTargetLocked(preferredBrightness, 1496 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS, 1497 Power.BRIGHTNESS_OFF); 1498 } 1499 startAnimation = true; 1500 } else { 1501 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) { 1502 offMask |= KEYBOARD_BRIGHT_BIT; 1503 } else { 1504 onMask |= KEYBOARD_BRIGHT_BIT; 1505 } 1506 } 1507 } 1508 1509 if ((difference & BUTTON_BRIGHT_BIT) != 0) { 1510 if (ANIMATE_BUTTON_LIGHTS) { 1511 if ((newState & BUTTON_BRIGHT_BIT) == 0) { 1512 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF, 1513 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, 1514 preferredBrightness); 1515 } else { 1516 mButtonBrightness.setTargetLocked(preferredBrightness, 1517 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, 1518 Power.BRIGHTNESS_OFF); 1519 } 1520 startAnimation = true; 1521 } else { 1522 if ((newState & BUTTON_BRIGHT_BIT) == 0) { 1523 offMask |= BUTTON_BRIGHT_BIT; 1524 } else { 1525 onMask |= BUTTON_BRIGHT_BIT; 1526 } 1527 } 1528 } 1529 1530 if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { 1531 if (ANIMATE_SCREEN_LIGHTS) { 1532 int nominalCurrentValue = -1; 1533 // If there was an actual difference in the light state, then 1534 // figure out the "ideal" current value based on the previous 1535 // state. Otherwise, this is a change due to the brightness 1536 // override, so we want to animate from whatever the current 1537 // value is. 1538 if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) { 1539 switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) { 1540 case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT: 1541 nominalCurrentValue = preferredBrightness; 1542 break; 1543 case SCREEN_ON_BIT: 1544 nominalCurrentValue = Power.BRIGHTNESS_DIM; 1545 break; 1546 case 0: 1547 nominalCurrentValue = Power.BRIGHTNESS_OFF; 1548 break; 1549 case SCREEN_BRIGHT_BIT: 1550 default: 1551 // not possible 1552 nominalCurrentValue = (int)mScreenBrightness.curValue; 1553 break; 1554 } 1555 } 1556 int brightness = preferredBrightness; 1557 int steps = ANIM_STEPS; 1558 if ((newState & SCREEN_BRIGHT_BIT) == 0) { 1559 // dim or turn off backlight, depending on if the screen is on 1560 // the scale is because the brightness ramp isn't linear and this biases 1561 // it so the later parts take longer. 1562 final float scale = 1.5f; 1563 float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness); 1564 if (ratio > 1.0f) ratio = 1.0f; 1565 if ((newState & SCREEN_ON_BIT) == 0) { 1566 if ((oldState & SCREEN_BRIGHT_BIT) != 0) { 1567 // was bright 1568 steps = ANIM_STEPS; 1569 } else { 1570 // was dim 1571 steps = (int)(ANIM_STEPS*ratio*scale); 1572 } 1573 brightness = Power.BRIGHTNESS_OFF; 1574 } else { 1575 if ((oldState & SCREEN_ON_BIT) != 0) { 1576 // was bright 1577 steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale); 1578 } else { 1579 // was dim 1580 steps = (int)(ANIM_STEPS*ratio); 1581 } 1582 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) { 1583 // If the "stay on while plugged in" option is 1584 // turned on, then the screen will often not 1585 // automatically turn off while plugged in. To 1586 // still have a sense of when it is inactive, we 1587 // will then count going dim as turning off. 1588 mScreenOffTime = SystemClock.elapsedRealtime(); 1589 } 1590 brightness = Power.BRIGHTNESS_DIM; 1591 } 1592 } 1593 long identity = Binder.clearCallingIdentity(); 1594 try { 1595 mBatteryStats.noteScreenBrightness(brightness); 1596 } catch (RemoteException e) { 1597 // Nothing interesting to do. 1598 } finally { 1599 Binder.restoreCallingIdentity(identity); 1600 } 1601 if (mScreenBrightness.setTargetLocked(brightness, 1602 steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) { 1603 startAnimation = true; 1604 } 1605 } else { 1606 if ((newState & SCREEN_BRIGHT_BIT) == 0) { 1607 // dim or turn off backlight, depending on if the screen is on 1608 if ((newState & SCREEN_ON_BIT) == 0) { 1609 offMask |= SCREEN_BRIGHT_BIT; 1610 } else { 1611 dimMask |= SCREEN_BRIGHT_BIT; 1612 } 1613 } else { 1614 onMask |= SCREEN_BRIGHT_BIT; 1615 } 1616 } 1617 } 1618 1619 if (startAnimation) { 1620 if (mSpew) { 1621 Log.i(TAG, "Scheduling light animator!"); 1622 } 1623 mHandler.removeCallbacks(mLightAnimator); 1624 mHandler.post(mLightAnimator); 1625 } 1626 1627 if (offMask != 0) { 1628 //Log.i(TAG, "Setting brightess off: " + offMask); 1629 setLightBrightness(offMask, Power.BRIGHTNESS_OFF); 1630 } 1631 if (dimMask != 0) { 1632 int brightness = Power.BRIGHTNESS_DIM; 1633 if ((newState & BATTERY_LOW_BIT) != 0 && 1634 brightness > Power.BRIGHTNESS_LOW_BATTERY) { 1635 brightness = Power.BRIGHTNESS_LOW_BATTERY; 1636 } 1637 //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask); 1638 setLightBrightness(dimMask, brightness); 1639 } 1640 if (onMask != 0) { 1641 int brightness = getPreferredBrightness(); 1642 if ((newState & BATTERY_LOW_BIT) != 0 && 1643 brightness > Power.BRIGHTNESS_LOW_BATTERY) { 1644 brightness = Power.BRIGHTNESS_LOW_BATTERY; 1645 } 1646 //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask); 1647 setLightBrightness(onMask, brightness); 1648 } 1649 } 1650 1651 private void setLightBrightness(int mask, int value) { 1652 if ((mask & SCREEN_BRIGHT_BIT) != 0) { 1653 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value); 1654 } 1655 if ((mask & BUTTON_BRIGHT_BIT) != 0) { 1656 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value); 1657 } 1658 if ((mask & KEYBOARD_BRIGHT_BIT) != 0) { 1659 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value); 1660 } 1661 } 1662 1663 class BrightnessState { 1664 final int mask; 1665 1666 boolean initialized; 1667 int targetValue; 1668 float curValue; 1669 float delta; 1670 boolean animating; 1671 1672 BrightnessState(int m) { 1673 mask = m; 1674 } 1675 1676 public void dump(PrintWriter pw, String prefix) { 1677 pw.println(prefix + "animating=" + animating 1678 + " targetValue=" + targetValue 1679 + " curValue=" + curValue 1680 + " delta=" + delta); 1681 } 1682 1683 boolean setTargetLocked(int target, int stepsToTarget, int initialValue, 1684 int nominalCurrentValue) { 1685 if (!initialized) { 1686 initialized = true; 1687 curValue = (float)initialValue; 1688 } else if (targetValue == target) { 1689 return false; 1690 } 1691 targetValue = target; 1692 delta = (targetValue - 1693 (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue)) 1694 / stepsToTarget; 1695 if (mSpew) { 1696 String noticeMe = nominalCurrentValue == curValue ? "" : " ******************"; 1697 Log.i(TAG, "Setting target " + mask + ": cur=" + curValue 1698 + " target=" + targetValue + " delta=" + delta 1699 + " nominalCurrentValue=" + nominalCurrentValue 1700 + noticeMe); 1701 } 1702 animating = true; 1703 return true; 1704 } 1705 1706 boolean stepLocked() { 1707 if (!animating) return false; 1708 if (false && mSpew) { 1709 Log.i(TAG, "Step target " + mask + ": cur=" + curValue 1710 + " target=" + targetValue + " delta=" + delta); 1711 } 1712 curValue += delta; 1713 int curIntValue = (int)curValue; 1714 boolean more = true; 1715 if (delta == 0) { 1716 curValue = curIntValue = targetValue; 1717 more = false; 1718 } else if (delta > 0) { 1719 if (curIntValue >= targetValue) { 1720 curValue = curIntValue = targetValue; 1721 more = false; 1722 } 1723 } else { 1724 if (curIntValue <= targetValue) { 1725 curValue = curIntValue = targetValue; 1726 more = false; 1727 } 1728 } 1729 //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask); 1730 setLightBrightness(mask, curIntValue); 1731 animating = more; 1732 if (!more) { 1733 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) { 1734 screenOffFinishedAnimatingLocked(mOffBecauseOfUser); 1735 } 1736 } 1737 return more; 1738 } 1739 } 1740 1741 private class LightAnimator implements Runnable { 1742 public void run() { 1743 synchronized (mLocks) { 1744 long now = SystemClock.uptimeMillis(); 1745 boolean more = mScreenBrightness.stepLocked(); 1746 if (mKeyboardBrightness.stepLocked()) { 1747 more = true; 1748 } 1749 if (mButtonBrightness.stepLocked()) { 1750 more = true; 1751 } 1752 if (more) { 1753 mHandler.postAtTime(mLightAnimator, now+(1000/60)); 1754 } 1755 } 1756 } 1757 } 1758 1759 private int getPreferredBrightness() { 1760 try { 1761 if (mScreenBrightnessOverride >= 0) { 1762 return mScreenBrightnessOverride; 1763 } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness 1764 && mAutoBrightessEnabled) { 1765 return mLightSensorBrightness; 1766 } 1767 final int brightness = Settings.System.getInt(mContext.getContentResolver(), 1768 SCREEN_BRIGHTNESS); 1769 // Don't let applications turn the screen all the way off 1770 return Math.max(brightness, Power.BRIGHTNESS_DIM); 1771 } catch (SettingNotFoundException snfe) { 1772 return Power.BRIGHTNESS_ON; 1773 } 1774 } 1775 1776 boolean screenIsOn() { 1777 synchronized (mLocks) { 1778 return (mPowerState & SCREEN_ON_BIT) != 0; 1779 } 1780 } 1781 1782 boolean screenIsBright() { 1783 synchronized (mLocks) { 1784 return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT; 1785 } 1786 } 1787 1788 private void forceUserActivityLocked() { 1789 // cancel animation so userActivity will succeed 1790 mScreenBrightness.animating = false; 1791 boolean savedActivityAllowed = mUserActivityAllowed; 1792 mUserActivityAllowed = true; 1793 userActivity(SystemClock.uptimeMillis(), false); 1794 mUserActivityAllowed = savedActivityAllowed; 1795 } 1796 1797 public void userActivityWithForce(long time, boolean noChangeLights, boolean force) { 1798 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 1799 userActivity(time, noChangeLights, OTHER_EVENT, force); 1800 } 1801 1802 public void userActivity(long time, boolean noChangeLights) { 1803 userActivity(time, noChangeLights, OTHER_EVENT, false); 1804 } 1805 1806 public void userActivity(long time, boolean noChangeLights, int eventType) { 1807 userActivity(time, noChangeLights, eventType, false); 1808 } 1809 1810 public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) { 1811 //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 1812 1813 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0) 1814 && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) { 1815 if (false) { 1816 Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey)); 1817 } 1818 return; 1819 } 1820 1821 if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0) 1822 && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT 1823 || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) { 1824 if (false) { 1825 Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey)); 1826 } 1827 return; 1828 } 1829 1830 if (false) { 1831 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) { 1832 Log.d(TAG, "userActivity !!!");//, new RuntimeException()); 1833 } else { 1834 Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey)); 1835 } 1836 } 1837 1838 synchronized (mLocks) { 1839 if (mSpew) { 1840 Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time 1841 + " mUserActivityAllowed=" + mUserActivityAllowed 1842 + " mUserState=0x" + Integer.toHexString(mUserState) 1843 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState) 1844 + " mProximitySensorActive=" + mProximitySensorActive 1845 + " force=" + force); 1846 } 1847 // ignore user activity if we are in the process of turning off the screen 1848 if (mScreenBrightness.animating && mScreenBrightness.targetValue == 0) { 1849 Log.d(TAG, "ignoring user activity while turning off screen"); 1850 return; 1851 } 1852 if (mLastEventTime <= time || force) { 1853 mLastEventTime = time; 1854 if ((mUserActivityAllowed && !mProximitySensorActive) || force) { 1855 // Only turn on button backlights if a button was pressed 1856 // and auto brightness is disabled 1857 if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) { 1858 mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT); 1859 } else { 1860 // don't clear button/keyboard backlights when the screen is touched. 1861 mUserState |= SCREEN_BRIGHT; 1862 } 1863 1864 int uid = Binder.getCallingUid(); 1865 long ident = Binder.clearCallingIdentity(); 1866 try { 1867 mBatteryStats.noteUserActivity(uid, eventType); 1868 } catch (RemoteException e) { 1869 // Ignore 1870 } finally { 1871 Binder.restoreCallingIdentity(ident); 1872 } 1873 1874 mWakeLockState = mLocks.reactivateScreenLocksLocked(); 1875 setPowerState(mUserState | mWakeLockState, noChangeLights, true); 1876 setTimeoutLocked(time, SCREEN_BRIGHT); 1877 } 1878 } 1879 } 1880 } 1881 1882 private int getAutoBrightnessValue(int sensorValue, int[] values) { 1883 try { 1884 int i; 1885 for (i = 0; i < mAutoBrightnessLevels.length; i++) { 1886 if (sensorValue < mAutoBrightnessLevels[i]) { 1887 break; 1888 } 1889 } 1890 return values[i]; 1891 } catch (Exception e) { 1892 // guard against null pointer or index out of bounds errors 1893 Log.e(TAG, "getAutoBrightnessValue", e); 1894 return 255; 1895 } 1896 } 1897 1898 private Runnable mAutoBrightnessTask = new Runnable() { 1899 public void run() { 1900 synchronized (mLocks) { 1901 int value = (int)mLightSensorPendingValue; 1902 if (value >= 0) { 1903 mLightSensorPendingValue = -1; 1904 lightSensorChangedLocked(value); 1905 } 1906 } 1907 } 1908 }; 1909 1910 private void lightSensorChangedLocked(int value) { 1911 if (mDebugLightSensor) { 1912 Log.d(TAG, "lightSensorChangedLocked " + value); 1913 } 1914 1915 if (mLightSensorValue != value) { 1916 mLightSensorValue = value; 1917 if ((mPowerState & BATTERY_LOW_BIT) == 0) { 1918 int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues); 1919 int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues); 1920 int keyboardValue; 1921 if (mKeyboardVisible) { 1922 keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues); 1923 } else { 1924 keyboardValue = 0; 1925 } 1926 mLightSensorBrightness = lcdValue; 1927 1928 if (mDebugLightSensor) { 1929 Log.d(TAG, "lcdValue " + lcdValue); 1930 Log.d(TAG, "buttonValue " + buttonValue); 1931 Log.d(TAG, "keyboardValue " + keyboardValue); 1932 } 1933 1934 boolean startAnimation = false; 1935 if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) { 1936 if (ANIMATE_SCREEN_LIGHTS) { 1937 if (mScreenBrightness.setTargetLocked(lcdValue, 1938 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS, 1939 (int)mScreenBrightness.curValue)) { 1940 startAnimation = true; 1941 } 1942 } else { 1943 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, 1944 lcdValue); 1945 } 1946 } 1947 if (ANIMATE_BUTTON_LIGHTS) { 1948 if (mButtonBrightness.setTargetLocked(buttonValue, 1949 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, 1950 (int)mButtonBrightness.curValue)) { 1951 startAnimation = true; 1952 } 1953 } else { 1954 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 1955 buttonValue); 1956 } 1957 if (ANIMATE_KEYBOARD_LIGHTS) { 1958 if (mKeyboardBrightness.setTargetLocked(keyboardValue, 1959 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS, 1960 (int)mKeyboardBrightness.curValue)) { 1961 startAnimation = true; 1962 } 1963 } else { 1964 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 1965 keyboardValue); 1966 } 1967 if (startAnimation) { 1968 if (mDebugLightSensor) { 1969 Log.i(TAG, "lightSensorChangedLocked scheduling light animator"); 1970 } 1971 mHandler.removeCallbacks(mLightAnimator); 1972 mHandler.post(mLightAnimator); 1973 } 1974 } 1975 } 1976 } 1977 1978 /** 1979 * The user requested that we go to sleep (probably with the power button). 1980 * This overrides all wake locks that are held. 1981 */ 1982 public void goToSleep(long time) 1983 { 1984 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 1985 synchronized (mLocks) { 1986 goToSleepLocked(time); 1987 } 1988 } 1989 1990 /** 1991 * Returns the time the screen has been on since boot, in millis. 1992 * @return screen on time 1993 */ 1994 public long getScreenOnTime() { 1995 synchronized (mLocks) { 1996 if (mScreenOnStartTime == 0) { 1997 return mScreenOnTime; 1998 } else { 1999 return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime; 2000 } 2001 } 2002 } 2003 2004 private void goToSleepLocked(long time) { 2005 2006 if (mLastEventTime <= time) { 2007 mLastEventTime = time; 2008 // cancel all of the wake locks 2009 mWakeLockState = SCREEN_OFF; 2010 int N = mLocks.size(); 2011 int numCleared = 0; 2012 for (int i=0; i<N; i++) { 2013 WakeLock wl = mLocks.get(i); 2014 if (isScreenLock(wl.flags)) { 2015 mLocks.get(i).activated = false; 2016 numCleared++; 2017 } 2018 } 2019 EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared); 2020 mStillNeedSleepNotification = true; 2021 mUserState = SCREEN_OFF; 2022 setPowerState(SCREEN_OFF, false, true); 2023 cancelTimerLocked(); 2024 } 2025 } 2026 2027 public long timeSinceScreenOn() { 2028 synchronized (mLocks) { 2029 if ((mPowerState & SCREEN_ON_BIT) != 0) { 2030 return 0; 2031 } 2032 return SystemClock.elapsedRealtime() - mScreenOffTime; 2033 } 2034 } 2035 2036 public void setKeyboardVisibility(boolean visible) { 2037 synchronized (mLocks) { 2038 if (mSpew) { 2039 Log.d(TAG, "setKeyboardVisibility: " + visible); 2040 } 2041 if (mKeyboardVisible != visible) { 2042 mKeyboardVisible = visible; 2043 // don't signal user activity if the screen is off; other code 2044 // will take care of turning on due to a true change to the lid 2045 // switch and synchronized with the lock screen. 2046 if ((mPowerState & SCREEN_ON_BIT) != 0) { 2047 if (mUseSoftwareAutoBrightness) { 2048 // force recompute of backlight values 2049 if (mLightSensorValue >= 0) { 2050 int value = (int)mLightSensorValue; 2051 mLightSensorValue = -1; 2052 lightSensorChangedLocked(value); 2053 } 2054 } 2055 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true); 2056 } 2057 } 2058 } 2059 } 2060 2061 /** 2062 * When the keyguard is up, it manages the power state, and userActivity doesn't do anything. 2063 */ 2064 public void enableUserActivity(boolean enabled) { 2065 synchronized (mLocks) { 2066 mUserActivityAllowed = enabled; 2067 } 2068 } 2069 2070 private void setScreenBrightnessMode(int mode) { 2071 boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC); 2072 if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) { 2073 mAutoBrightessEnabled = enabled; 2074 if (screenIsOn()) { 2075 // force recompute of backlight values 2076 if (mLightSensorValue >= 0) { 2077 int value = (int)mLightSensorValue; 2078 mLightSensorValue = -1; 2079 lightSensorChangedLocked(value); 2080 } 2081 } 2082 } 2083 } 2084 2085 /** Sets the screen off timeouts: 2086 * mKeylightDelay 2087 * mDimDelay 2088 * mScreenOffDelay 2089 * */ 2090 private void setScreenOffTimeoutsLocked() { 2091 if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) { 2092 mKeylightDelay = mShortKeylightDelay; // Configurable via Gservices 2093 mDimDelay = -1; 2094 mScreenOffDelay = 0; 2095 } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) { 2096 mKeylightDelay = MEDIUM_KEYLIGHT_DELAY; 2097 mDimDelay = -1; 2098 mScreenOffDelay = 0; 2099 } else { 2100 int totalDelay = mTotalDelaySetting; 2101 mKeylightDelay = LONG_KEYLIGHT_DELAY; 2102 if (totalDelay < 0) { 2103 mScreenOffDelay = Integer.MAX_VALUE; 2104 } else if (mKeylightDelay < totalDelay) { 2105 // subtract the time that the keylight delay. This will give us the 2106 // remainder of the time that we need to sleep to get the accurate 2107 // screen off timeout. 2108 mScreenOffDelay = totalDelay - mKeylightDelay; 2109 } else { 2110 mScreenOffDelay = 0; 2111 } 2112 if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) { 2113 mDimDelay = mScreenOffDelay - LONG_DIM_TIME; 2114 mScreenOffDelay = LONG_DIM_TIME; 2115 } else { 2116 mDimDelay = -1; 2117 } 2118 } 2119 if (mSpew) { 2120 Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay 2121 + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay 2122 + " mDimScreen=" + mDimScreen); 2123 } 2124 } 2125 2126 /** 2127 * Refreshes cached Gservices settings. Called once on startup, and 2128 * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see 2129 * GservicesChangedReceiver). 2130 */ 2131 private void updateGservicesValues() { 2132 mShortKeylightDelay = Settings.Gservices.getInt( 2133 mContext.getContentResolver(), 2134 Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS, 2135 SHORT_KEYLIGHT_DELAY_DEFAULT); 2136 // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay); 2137 } 2138 2139 /** 2140 * Receiver for the Gservices.CHANGED_ACTION broadcast intent, 2141 * which tells us we need to refresh our cached Gservices settings. 2142 */ 2143 private class GservicesChangedReceiver extends BroadcastReceiver { 2144 @Override 2145 public void onReceive(Context context, Intent intent) { 2146 // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent); 2147 updateGservicesValues(); 2148 } 2149 } 2150 2151 private class LockList extends ArrayList<WakeLock> 2152 { 2153 void addLock(WakeLock wl) 2154 { 2155 int index = getIndex(wl.binder); 2156 if (index < 0) { 2157 this.add(wl); 2158 } 2159 } 2160 2161 WakeLock removeLock(IBinder binder) 2162 { 2163 int index = getIndex(binder); 2164 if (index >= 0) { 2165 return this.remove(index); 2166 } else { 2167 return null; 2168 } 2169 } 2170 2171 int getIndex(IBinder binder) 2172 { 2173 int N = this.size(); 2174 for (int i=0; i<N; i++) { 2175 if (this.get(i).binder == binder) { 2176 return i; 2177 } 2178 } 2179 return -1; 2180 } 2181 2182 int gatherState() 2183 { 2184 int result = 0; 2185 int N = this.size(); 2186 for (int i=0; i<N; i++) { 2187 WakeLock wl = this.get(i); 2188 if (wl.activated) { 2189 if (isScreenLock(wl.flags)) { 2190 result |= wl.minState; 2191 } 2192 } 2193 } 2194 return result; 2195 } 2196 2197 int reactivateScreenLocksLocked() 2198 { 2199 int result = 0; 2200 int N = this.size(); 2201 for (int i=0; i<N; i++) { 2202 WakeLock wl = this.get(i); 2203 if (isScreenLock(wl.flags)) { 2204 wl.activated = true; 2205 result |= wl.minState; 2206 } 2207 } 2208 return result; 2209 } 2210 } 2211 2212 void setPolicy(WindowManagerPolicy p) { 2213 synchronized (mLocks) { 2214 mPolicy = p; 2215 mLocks.notifyAll(); 2216 } 2217 } 2218 2219 WindowManagerPolicy getPolicyLocked() { 2220 while (mPolicy == null || !mDoneBooting) { 2221 try { 2222 mLocks.wait(); 2223 } catch (InterruptedException e) { 2224 // Ignore 2225 } 2226 } 2227 return mPolicy; 2228 } 2229 2230 void systemReady() { 2231 mSensorManager = new SensorManager(mHandlerThread.getLooper()); 2232 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 2233 // don't bother with the light sensor if auto brightness is handled in hardware 2234 if (mUseSoftwareAutoBrightness) { 2235 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); 2236 enableLightSensor(true); 2237 } 2238 2239 synchronized (mLocks) { 2240 Log.d(TAG, "system ready!"); 2241 mDoneBooting = true; 2242 long identity = Binder.clearCallingIdentity(); 2243 try { 2244 mBatteryStats.noteScreenBrightness(getPreferredBrightness()); 2245 mBatteryStats.noteScreenOn(); 2246 } catch (RemoteException e) { 2247 // Nothing interesting to do. 2248 } finally { 2249 Binder.restoreCallingIdentity(identity); 2250 } 2251 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true); 2252 updateWakeLockLocked(); 2253 mLocks.notifyAll(); 2254 } 2255 } 2256 2257 public void monitor() { 2258 synchronized (mLocks) { } 2259 } 2260 2261 public int getSupportedWakeLockFlags() { 2262 int result = PowerManager.PARTIAL_WAKE_LOCK 2263 | PowerManager.FULL_WAKE_LOCK 2264 | PowerManager.SCREEN_DIM_WAKE_LOCK; 2265 2266 if (mProximitySensor != null) { 2267 result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK; 2268 } 2269 2270 return result; 2271 } 2272 2273 public void setBacklightBrightness(int brightness) { 2274 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); 2275 // Don't let applications turn the screen all the way off 2276 brightness = Math.max(brightness, Power.BRIGHTNESS_DIM); 2277 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness); 2278 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 2279 (mKeyboardVisible ? brightness : 0)); 2280 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness); 2281 long identity = Binder.clearCallingIdentity(); 2282 try { 2283 mBatteryStats.noteScreenBrightness(brightness); 2284 } catch (RemoteException e) { 2285 Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e); 2286 } finally { 2287 Binder.restoreCallingIdentity(identity); 2288 } 2289 2290 // update our animation state 2291 if (ANIMATE_SCREEN_LIGHTS) { 2292 mScreenBrightness.curValue = brightness; 2293 mScreenBrightness.animating = false; 2294 mScreenBrightness.targetValue = -1; 2295 } 2296 if (ANIMATE_KEYBOARD_LIGHTS) { 2297 mKeyboardBrightness.curValue = brightness; 2298 mKeyboardBrightness.animating = false; 2299 mKeyboardBrightness.targetValue = -1; 2300 } 2301 if (ANIMATE_BUTTON_LIGHTS) { 2302 mButtonBrightness.curValue = brightness; 2303 mButtonBrightness.animating = false; 2304 mButtonBrightness.targetValue = -1; 2305 } 2306 } 2307 2308 private void enableProximityLockLocked() { 2309 if (mSpew) { 2310 Log.d(TAG, "enableProximityLockLocked"); 2311 } 2312 // clear calling identity so sensor manager battery stats are accurate 2313 long identity = Binder.clearCallingIdentity(); 2314 try { 2315 mSensorManager.registerListener(mProximityListener, mProximitySensor, 2316 SensorManager.SENSOR_DELAY_NORMAL); 2317 } finally { 2318 Binder.restoreCallingIdentity(identity); 2319 } 2320 } 2321 2322 private void disableProximityLockLocked() { 2323 if (mSpew) { 2324 Log.d(TAG, "disableProximityLockLocked"); 2325 } 2326 // clear calling identity so sensor manager battery stats are accurate 2327 long identity = Binder.clearCallingIdentity(); 2328 try { 2329 mSensorManager.unregisterListener(mProximityListener); 2330 } finally { 2331 Binder.restoreCallingIdentity(identity); 2332 } 2333 synchronized (mLocks) { 2334 if (mProximitySensorActive) { 2335 mProximitySensorActive = false; 2336 forceUserActivityLocked(); 2337 } 2338 } 2339 } 2340 2341 private void enableLightSensor(boolean enable) { 2342 if (mDebugLightSensor) { 2343 Log.d(TAG, "enableLightSensor " + enable); 2344 } 2345 if (mSensorManager != null && mLightSensorEnabled != enable) { 2346 mLightSensorEnabled = enable; 2347 // clear calling identity so sensor manager battery stats are accurate 2348 long identity = Binder.clearCallingIdentity(); 2349 try { 2350 if (enable) { 2351 mSensorManager.registerListener(mLightListener, mLightSensor, 2352 SensorManager.SENSOR_DELAY_NORMAL); 2353 } else { 2354 mSensorManager.unregisterListener(mLightListener); 2355 mHandler.removeCallbacks(mAutoBrightnessTask); 2356 } 2357 } finally { 2358 Binder.restoreCallingIdentity(identity); 2359 } 2360 } 2361 } 2362 2363 SensorEventListener mProximityListener = new SensorEventListener() { 2364 public void onSensorChanged(SensorEvent event) { 2365 long milliseconds = event.timestamp / 1000000; 2366 synchronized (mLocks) { 2367 float distance = event.values[0]; 2368 // compare against getMaximumRange to support sensors that only return 0 or 1 2369 if (distance >= 0.0 && distance < PROXIMITY_THRESHOLD && 2370 distance < mProximitySensor.getMaximumRange()) { 2371 if (mSpew) { 2372 Log.d(TAG, "onSensorChanged: proximity active, distance: " + distance); 2373 } 2374 goToSleepLocked(milliseconds); 2375 mProximitySensorActive = true; 2376 } else { 2377 // proximity sensor negative events trigger as user activity. 2378 // temporarily set mUserActivityAllowed to true so this will work 2379 // even when the keyguard is on. 2380 if (mSpew) { 2381 Log.d(TAG, "onSensorChanged: proximity inactive, distance: " + distance); 2382 } 2383 mProximitySensorActive = false; 2384 forceUserActivityLocked(); 2385 } 2386 } 2387 } 2388 2389 public void onAccuracyChanged(Sensor sensor, int accuracy) { 2390 // ignore 2391 } 2392 }; 2393 2394 SensorEventListener mLightListener = new SensorEventListener() { 2395 public void onSensorChanged(SensorEvent event) { 2396 synchronized (mLocks) { 2397 int value = (int)event.values[0]; 2398 if (mDebugLightSensor) { 2399 Log.d(TAG, "onSensorChanged: light value: " + value); 2400 } 2401 mHandler.removeCallbacks(mAutoBrightnessTask); 2402 if (mLightSensorValue != value) { 2403 if (mLightSensorValue == -1) { 2404 // process the value immediately 2405 lightSensorChangedLocked(value); 2406 } else { 2407 // delay processing to debounce the sensor 2408 mLightSensorPendingValue = value; 2409 mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY); 2410 } 2411 } else { 2412 mLightSensorPendingValue = -1; 2413 } 2414 } 2415 } 2416 2417 public void onAccuracyChanged(Sensor sensor, int accuracy) { 2418 // ignore 2419 } 2420 }; 2421} 2422