blob: 89261a8268d31b84dd054e49f0f2eed4dc33f819 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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;
Mike Lockwoodd7786b42009-10-15 17:09:16 -070031import android.content.res.Resources;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.database.Cursor;
Mike Lockwoodbc706a02009-07-27 13:50:57 -070033import android.hardware.Sensor;
34import android.hardware.SensorEvent;
35import android.hardware.SensorEventListener;
36import android.hardware.SensorManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import 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;
San Mehat14e69af2010-01-06 14:58:18 -080048import android.os.ServiceManager;
49import android.os.Environment;
50import android.os.IMountService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051import android.os.SystemClock;
52import android.provider.Settings.SettingNotFoundException;
53import android.provider.Settings;
54import android.util.EventLog;
55import android.util.Log;
56import android.view.WindowManagerPolicy;
57import static android.provider.Settings.System.DIM_SCREEN;
58import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
Dan Murphy951764b2009-08-27 14:59:03 -050059import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
Mike Lockwooddc3494e2009-10-14 21:17:09 -070060import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
62import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
63
64import java.io.FileDescriptor;
Doug Zongker50a21f42009-11-19 12:49:53 -080065import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066import java.io.PrintWriter;
67import java.util.ArrayList;
68import java.util.HashMap;
69import java.util.Observable;
70import java.util.Observer;
71
Mike Lockwoodbc706a02009-07-27 13:50:57 -070072class PowerManagerService extends IPowerManager.Stub
Mike Lockwood8738e0c2009-10-04 08:44:47 -040073 implements LocalPowerManager, Watchdog.Monitor {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074
75 private static final String TAG = "PowerManagerService";
76 static final String PARTIAL_NAME = "PowerManagerService";
77
78 private static final boolean LOG_PARTIAL_WL = false;
79
80 // Indicates whether touch-down cycles should be logged as part of the
81 // LOG_POWER_SCREEN_STATE log events
82 private static final boolean LOG_TOUCH_DOWNS = true;
83
84 private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
85 | PowerManager.SCREEN_DIM_WAKE_LOCK
86 | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
Mike Lockwoodbc706a02009-07-27 13:50:57 -070087 | PowerManager.FULL_WAKE_LOCK
88 | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089
90 // time since last state: time since last event:
91 // The short keylight delay comes from Gservices; this is the default.
92 private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
93 private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
94 private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
95 private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
96
Mike Lockwoodd7786b42009-10-15 17:09:16 -070097 // How long to wait to debounce light sensor changes.
Mike Lockwood9b8136922009-11-06 15:53:59 -050098 private static final int LIGHT_SENSOR_DELAY = 2000;
Mike Lockwoodd7786b42009-10-15 17:09:16 -070099
Mike Lockwood20f87d72009-11-05 16:08:51 -0500100 // For debouncing the proximity sensor.
101 private static final int PROXIMITY_SENSOR_DELAY = 1000;
102
Mike Lockwoodd20ea362009-09-15 00:13:38 -0400103 // trigger proximity if distance is less than 5 cm
104 private static final float PROXIMITY_THRESHOLD = 5.0f;
105
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 // Cached Gservices settings; see updateGservicesValues()
107 private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
108
109 // flags for setPowerState
110 private static final int SCREEN_ON_BIT = 0x00000001;
111 private static final int SCREEN_BRIGHT_BIT = 0x00000002;
112 private static final int BUTTON_BRIGHT_BIT = 0x00000004;
113 private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
114 private static final int BATTERY_LOW_BIT = 0x00000010;
115
116 // values for setPowerState
117
118 // SCREEN_OFF == everything off
119 private static final int SCREEN_OFF = 0x00000000;
120
121 // SCREEN_DIM == screen on, screen backlight dim
122 private static final int SCREEN_DIM = SCREEN_ON_BIT;
123
124 // SCREEN_BRIGHT == screen on, screen backlight bright
125 private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
126
127 // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
128 private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
129
130 // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
131 private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
132
133 // used for noChangeLights in setPowerState()
134 private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
135
136 static final boolean ANIMATE_SCREEN_LIGHTS = true;
137 static final boolean ANIMATE_BUTTON_LIGHTS = false;
138 static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800139
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 static final int ANIM_STEPS = 60/4;
Mike Lockwooddd9668e2009-10-27 15:47:02 -0400141 // Slower animation for autobrightness changes
142 static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143
144 // These magic numbers are the initial state of the LEDs at boot. Ideally
145 // we should read them from the driver, but our current hardware returns 0
146 // for the initial value. Oops!
147 static final int INITIAL_SCREEN_BRIGHTNESS = 255;
148 static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
149 static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800151 private final int MY_UID;
152
153 private boolean mDoneBooting = false;
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500154 private boolean mBootCompleted = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 private int mStayOnConditions = 0;
Joe Onorato128e7292009-03-24 18:41:31 -0700156 private int[] mBroadcastQueue = new int[] { -1, -1, -1 };
157 private int[] mBroadcastWhy = new int[3];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private int mPartialCount = 0;
159 private int mPowerState;
Mike Lockwood435eb642009-12-03 08:40:18 -0500160 // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
161 // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
162 private int mScreenOffReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800163 private int mUserState;
164 private boolean mKeyboardVisible = false;
165 private boolean mUserActivityAllowed = true;
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500166 private int mProximityWakeLockCount = 0;
167 private boolean mProximitySensorEnabled = false;
Mike Lockwood36fc3022009-08-25 16:49:06 -0700168 private boolean mProximitySensorActive = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -0500169 private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
170 private long mLastProximityEventTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800171 private int mTotalDelaySetting;
172 private int mKeylightDelay;
173 private int mDimDelay;
174 private int mScreenOffDelay;
175 private int mWakeLockState;
176 private long mLastEventTime = 0;
177 private long mScreenOffTime;
178 private volatile WindowManagerPolicy mPolicy;
179 private final LockList mLocks = new LockList();
180 private Intent mScreenOffIntent;
181 private Intent mScreenOnIntent;
Mike Lockwood3a322132009-11-24 00:30:52 -0500182 private LightsService mLightsService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 private Context mContext;
Mike Lockwood3cb67a32009-11-27 14:25:58 -0500184 private LightsService.Light mLcdLight;
185 private LightsService.Light mButtonLight;
186 private LightsService.Light mKeyboardLight;
187 private LightsService.Light mAttentionLight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800188 private UnsynchronizedWakeLock mBroadcastWakeLock;
189 private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
190 private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
191 private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500192 private UnsynchronizedWakeLock mProximityPartialLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800193 private HandlerThread mHandlerThread;
194 private Handler mHandler;
195 private TimeoutTask mTimeoutTask = new TimeoutTask();
196 private LightAnimator mLightAnimator = new LightAnimator();
197 private final BrightnessState mScreenBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700198 = new BrightnessState(SCREEN_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 private final BrightnessState mKeyboardBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700200 = new BrightnessState(KEYBOARD_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 private final BrightnessState mButtonBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700202 = new BrightnessState(BUTTON_BRIGHT_BIT);
Joe Onorato128e7292009-03-24 18:41:31 -0700203 private boolean mStillNeedSleepNotification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 private boolean mIsPowered = false;
205 private IActivityManager mActivityService;
206 private IBatteryStats mBatteryStats;
207 private BatteryService mBatteryService;
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700208 private SensorManager mSensorManager;
209 private Sensor mProximitySensor;
Mike Lockwood8738e0c2009-10-04 08:44:47 -0400210 private Sensor mLightSensor;
211 private boolean mLightSensorEnabled;
212 private float mLightSensorValue = -1;
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700213 private float mLightSensorPendingValue = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -0500214 private int mLightSensorScreenBrightness = -1;
215 private int mLightSensorButtonBrightness = -1;
216 private int mLightSensorKeyboardBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 private boolean mDimScreen = true;
218 private long mNextTimeout;
219 private volatile int mPokey = 0;
220 private volatile boolean mPokeAwakeOnSet = false;
221 private volatile boolean mInitComplete = false;
222 private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500223 // mLastScreenOnTime is the time the screen was last turned on
224 private long mLastScreenOnTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 private boolean mPreventScreenOn;
226 private int mScreenBrightnessOverride = -1;
Mike Lockwoodfb73f792009-11-20 11:31:18 -0500227 private int mButtonBrightnessOverride = -1;
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400228 private boolean mUseSoftwareAutoBrightness;
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700229 private boolean mAutoBrightessEnabled;
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700230 private int[] mAutoBrightnessLevels;
231 private int[] mLcdBacklightValues;
232 private int[] mButtonBacklightValues;
233 private int[] mKeyboardBacklightValues;
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500234 private int mLightSensorWarmupTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235
236 // Used when logging number and duration of touch-down cycles
237 private long mTotalTouchDownTime;
238 private long mLastTouchDown;
239 private int mTouchCycles;
240
241 // could be either static or controllable at runtime
242 private static final boolean mSpew = false;
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500243 private static final boolean mDebugProximitySensor = (true || mSpew);
Mike Lockwooddd9668e2009-10-27 15:47:02 -0400244 private static final boolean mDebugLightSensor = (false || mSpew);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245
246 /*
247 static PrintStream mLog;
248 static {
249 try {
250 mLog = new PrintStream("/data/power.log");
251 }
252 catch (FileNotFoundException e) {
253 android.util.Log.e(TAG, "Life is hard", e);
254 }
255 }
256 static class Log {
257 static void d(String tag, String s) {
258 mLog.println(s);
259 android.util.Log.d(tag, s);
260 }
261 static void i(String tag, String s) {
262 mLog.println(s);
263 android.util.Log.i(tag, s);
264 }
265 static void w(String tag, String s) {
266 mLog.println(s);
267 android.util.Log.w(tag, s);
268 }
269 static void e(String tag, String s) {
270 mLog.println(s);
271 android.util.Log.e(tag, s);
272 }
273 }
274 */
275
276 /**
277 * This class works around a deadlock between the lock in PowerManager.WakeLock
278 * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its
279 * mToken object so it can be accessed from any thread, but it calls into here
280 * with its lock held. This class is essentially a reimplementation of
281 * PowerManager.WakeLock, but without that extra synchronized block, because we'll
282 * only call it with our own locks held.
283 */
284 private class UnsynchronizedWakeLock {
285 int mFlags;
286 String mTag;
287 IBinder mToken;
288 int mCount = 0;
289 boolean mRefCounted;
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500290 boolean mHeld;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800291
292 UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
293 mFlags = flags;
294 mTag = tag;
295 mToken = new Binder();
296 mRefCounted = refCounted;
297 }
298
299 public void acquire() {
300 if (!mRefCounted || mCount++ == 0) {
301 long ident = Binder.clearCallingIdentity();
302 try {
303 PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
304 MY_UID, mTag);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500305 mHeld = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 } finally {
307 Binder.restoreCallingIdentity(ident);
308 }
309 }
310 }
311
312 public void release() {
313 if (!mRefCounted || --mCount == 0) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500314 PowerManagerService.this.releaseWakeLockLocked(mToken, 0, false);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500315 mHeld = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
317 if (mCount < 0) {
318 throw new RuntimeException("WakeLock under-locked " + mTag);
319 }
320 }
321
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500322 public boolean isHeld()
323 {
324 return mHeld;
325 }
326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 public String toString() {
328 return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500329 + " mCount=" + mCount + " mHeld=" + mHeld + ")";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 }
331 }
332
333 private final class BatteryReceiver extends BroadcastReceiver {
334 @Override
335 public void onReceive(Context context, Intent intent) {
336 synchronized (mLocks) {
337 boolean wasPowered = mIsPowered;
338 mIsPowered = mBatteryService.isPowered();
339
340 if (mIsPowered != wasPowered) {
341 // update mStayOnWhilePluggedIn wake lock
342 updateWakeLockLocked();
343
344 // treat plugging and unplugging the devices as a user activity.
345 // users find it disconcerting when they unplug the device
346 // and it shuts off right away.
347 // temporarily set mUserActivityAllowed to true so this will work
348 // even when the keyguard is on.
349 synchronized (mLocks) {
Mike Lockwood200b30b2009-09-20 00:23:59 -0400350 forceUserActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800351 }
352 }
353 }
354 }
355 }
356
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500357 private final class BootCompletedReceiver extends BroadcastReceiver {
358 @Override
359 public void onReceive(Context context, Intent intent) {
360 bootCompleted();
361 }
362 }
363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 /**
365 * Set the setting that determines whether the device stays on when plugged in.
366 * The argument is a bit string, with each bit specifying a power source that,
367 * when the device is connected to that source, causes the device to stay on.
368 * See {@link android.os.BatteryManager} for the list of power sources that
369 * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
370 * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
371 * @param val an {@code int} containing the bits that specify which power sources
372 * should cause the device to stay on.
373 */
374 public void setStayOnSetting(int val) {
375 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
376 Settings.System.putInt(mContext.getContentResolver(),
377 Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
378 }
379
380 private class SettingsObserver implements Observer {
381 private int getInt(String name) {
382 return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
383 }
384
385 public void update(Observable o, Object arg) {
386 synchronized (mLocks) {
387 // STAY_ON_WHILE_PLUGGED_IN
388 mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN);
389 updateWakeLockLocked();
390
391 // SCREEN_OFF_TIMEOUT
392 mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);
393
394 // DIM_SCREEN
395 //mDimScreen = getInt(DIM_SCREEN) != 0;
396
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700397 // SCREEN_BRIGHTNESS_MODE
398 setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE));
399
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 // recalculate everything
401 setScreenOffTimeoutsLocked();
402 }
403 }
404 }
405
406 PowerManagerService()
407 {
408 // Hack to get our uid... should have a func for this.
409 long token = Binder.clearCallingIdentity();
410 MY_UID = Binder.getCallingUid();
411 Binder.restoreCallingIdentity(token);
412
413 // XXX remove this when the kernel doesn't timeout wake locks
414 Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
415
416 // assume nothing is on yet
417 mUserState = mPowerState = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 // Add ourself to the Watchdog monitors.
420 Watchdog.getInstance().addMonitor(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
423 private ContentQueryMap mSettings;
424
Mike Lockwood3a322132009-11-24 00:30:52 -0500425 void init(Context context, LightsService lights, IActivityManager activity,
The Android Open Source Project10592532009-03-18 17:39:46 -0700426 BatteryService battery) {
Mike Lockwood3a322132009-11-24 00:30:52 -0500427 mLightsService = lights;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 mContext = context;
429 mActivityService = activity;
430 mBatteryStats = BatteryStatsService.getService();
431 mBatteryService = battery;
432
Mike Lockwood3cb67a32009-11-27 14:25:58 -0500433 mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
434 mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
435 mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
436 mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800438 mHandlerThread = new HandlerThread("PowerManagerService") {
439 @Override
440 protected void onLooperPrepared() {
441 super.onLooperPrepared();
442 initInThread();
443 }
444 };
445 mHandlerThread.start();
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800447 synchronized (mHandlerThread) {
448 while (!mInitComplete) {
449 try {
450 mHandlerThread.wait();
451 } catch (InterruptedException e) {
452 // Ignore
453 }
454 }
455 }
456 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800457
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 void initInThread() {
459 mHandler = new Handler();
460
461 mBroadcastWakeLock = new UnsynchronizedWakeLock(
Joe Onorato128e7292009-03-24 18:41:31 -0700462 PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
464 PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
465 mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
466 PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
467 mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
468 PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500469 mProximityPartialLock = new UnsynchronizedWakeLock(
470 PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471
472 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
473 mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
474 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
475 mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
476
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700477 Resources resources = mContext.getResources();
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400478
479 // read settings for auto-brightness
480 mUseSoftwareAutoBrightness = resources.getBoolean(
481 com.android.internal.R.bool.config_automatic_brightness_available);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400482 if (mUseSoftwareAutoBrightness) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700483 mAutoBrightnessLevels = resources.getIntArray(
484 com.android.internal.R.array.config_autoBrightnessLevels);
485 mLcdBacklightValues = resources.getIntArray(
486 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
487 mButtonBacklightValues = resources.getIntArray(
488 com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
489 mKeyboardBacklightValues = resources.getIntArray(
490 com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500491 mLightSensorWarmupTime = resources.getInteger(
492 com.android.internal.R.integer.config_lightSensorWarmupTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700493 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700494
495 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
497 "(" + Settings.System.NAME + "=?) or ("
498 + Settings.System.NAME + "=?) or ("
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700499 + Settings.System.NAME + "=?) or ("
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 + Settings.System.NAME + "=?)",
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700501 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
502 SCREEN_BRIGHTNESS_MODE},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 null);
504 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
505 SettingsObserver settingsObserver = new SettingsObserver();
506 mSettings.addObserver(settingsObserver);
507
508 // pretend that the settings changed so we will get their initial state
509 settingsObserver.update(mSettings, null);
510
511 // register for the battery changed notifications
512 IntentFilter filter = new IntentFilter();
513 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
514 mContext.registerReceiver(new BatteryReceiver(), filter);
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500515 filter = new IntentFilter();
516 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
517 mContext.registerReceiver(new BootCompletedReceiver(), filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518
519 // Listen for Gservices changes
520 IntentFilter gservicesChangedFilter =
521 new IntentFilter(Settings.Gservices.CHANGED_ACTION);
522 mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter);
523 // And explicitly do the initial update of our cached settings
524 updateGservicesValues();
525
Mike Lockwood4984e732009-11-01 08:16:33 -0500526 if (mUseSoftwareAutoBrightness) {
Mike Lockwood6c97fca2009-10-20 08:10:00 -0400527 // turn the screen on
528 setPowerState(SCREEN_BRIGHT);
529 } else {
530 // turn everything on
531 setPowerState(ALL_BRIGHT);
532 }
Dan Murphy951764b2009-08-27 14:59:03 -0500533
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 synchronized (mHandlerThread) {
535 mInitComplete = true;
536 mHandlerThread.notifyAll();
537 }
538 }
539
540 private class WakeLock implements IBinder.DeathRecipient
541 {
542 WakeLock(int f, IBinder b, String t, int u) {
543 super();
544 flags = f;
545 binder = b;
546 tag = t;
547 uid = u == MY_UID ? Process.SYSTEM_UID : u;
548 if (u != MY_UID || (
549 !"KEEP_SCREEN_ON_FLAG".equals(tag)
550 && !"KeyInputQueue".equals(tag))) {
551 monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
552 ? BatteryStats.WAKE_TYPE_PARTIAL
553 : BatteryStats.WAKE_TYPE_FULL;
554 } else {
555 monitorType = -1;
556 }
557 try {
558 b.linkToDeath(this, 0);
559 } catch (RemoteException e) {
560 binderDied();
561 }
562 }
563 public void binderDied() {
564 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500565 releaseWakeLockLocked(this.binder, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800566 }
567 }
568 final int flags;
569 final IBinder binder;
570 final String tag;
571 final int uid;
572 final int monitorType;
573 boolean activated = true;
574 int minState;
575 }
576
577 private void updateWakeLockLocked() {
578 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
579 // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
580 mStayOnWhilePluggedInScreenDimLock.acquire();
581 mStayOnWhilePluggedInPartialLock.acquire();
582 } else {
583 mStayOnWhilePluggedInScreenDimLock.release();
584 mStayOnWhilePluggedInPartialLock.release();
585 }
586 }
587
588 private boolean isScreenLock(int flags)
589 {
590 int n = flags & LOCK_MASK;
591 return n == PowerManager.FULL_WAKE_LOCK
592 || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
593 || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
594 }
595
596 public void acquireWakeLock(int flags, IBinder lock, String tag) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 int uid = Binder.getCallingUid();
Michael Chane96440f2009-05-06 10:27:36 -0700598 if (uid != Process.myUid()) {
599 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 long ident = Binder.clearCallingIdentity();
602 try {
603 synchronized (mLocks) {
604 acquireWakeLockLocked(flags, lock, uid, tag);
605 }
606 } finally {
607 Binder.restoreCallingIdentity(ident);
608 }
609 }
610
611 public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
612 int acquireUid = -1;
613 String acquireName = null;
614 int acquireType = -1;
615
616 if (mSpew) {
617 Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
618 }
619
620 int index = mLocks.getIndex(lock);
621 WakeLock wl;
622 boolean newlock;
623 if (index < 0) {
624 wl = new WakeLock(flags, lock, tag, uid);
625 switch (wl.flags & LOCK_MASK)
626 {
627 case PowerManager.FULL_WAKE_LOCK:
Mike Lockwood4984e732009-11-01 08:16:33 -0500628 if (mUseSoftwareAutoBrightness) {
Mike Lockwood3333fa42009-10-26 14:50:42 -0400629 wl.minState = SCREEN_BRIGHT;
630 } else {
631 wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
632 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 break;
634 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
635 wl.minState = SCREEN_BRIGHT;
636 break;
637 case PowerManager.SCREEN_DIM_WAKE_LOCK:
638 wl.minState = SCREEN_DIM;
639 break;
640 case PowerManager.PARTIAL_WAKE_LOCK:
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700641 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 break;
643 default:
644 // just log and bail. we're in the server, so don't
645 // throw an exception.
646 Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
647 + " flags=" + flags);
648 return;
649 }
650 mLocks.addLock(wl);
651 newlock = true;
652 } else {
653 wl = mLocks.get(index);
654 newlock = false;
655 }
656 if (isScreenLock(flags)) {
657 // if this causes a wakeup, we reactivate all of the locks and
658 // set it to whatever they want. otherwise, we modulate that
659 // by the current state so we never turn it more on than
660 // it already is.
661 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
Michael Chane96440f2009-05-06 10:27:36 -0700662 int oldWakeLockState = mWakeLockState;
663 mWakeLockState = mLocks.reactivateScreenLocksLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 if (mSpew) {
665 Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
Michael Chane96440f2009-05-06 10:27:36 -0700666 + " mWakeLockState=0x"
667 + Integer.toHexString(mWakeLockState)
668 + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670 } else {
671 if (mSpew) {
672 Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
673 + " mLocks.gatherState()=0x"
674 + Integer.toHexString(mLocks.gatherState())
675 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
676 }
677 mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
678 }
679 setPowerState(mWakeLockState | mUserState);
680 }
681 else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
682 if (newlock) {
683 mPartialCount++;
684 if (mPartialCount == 1) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800685 if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800686 }
687 }
688 Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700689 } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500690 mProximityWakeLockCount++;
691 if (mProximityWakeLockCount == 1) {
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700692 enableProximityLockLocked();
693 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694 }
695 if (newlock) {
696 acquireUid = wl.uid;
697 acquireName = wl.tag;
698 acquireType = wl.monitorType;
699 }
700
701 if (acquireType >= 0) {
702 try {
703 mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
704 } catch (RemoteException e) {
705 // Ignore
706 }
707 }
708 }
709
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500710 public void releaseWakeLock(IBinder lock, int flags) {
Michael Chane96440f2009-05-06 10:27:36 -0700711 int uid = Binder.getCallingUid();
712 if (uid != Process.myUid()) {
713 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
714 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715
716 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500717 releaseWakeLockLocked(lock, flags, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 }
719 }
720
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500721 private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800722 int releaseUid;
723 String releaseName;
724 int releaseType;
725
726 WakeLock wl = mLocks.removeLock(lock);
727 if (wl == null) {
728 return;
729 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800730
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731 if (mSpew) {
732 Log.d(TAG, "releaseWakeLock flags=0x"
733 + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
734 }
735
736 if (isScreenLock(wl.flags)) {
737 mWakeLockState = mLocks.gatherState();
738 // goes in the middle to reduce flicker
739 if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
740 userActivity(SystemClock.uptimeMillis(), false);
741 }
742 setPowerState(mWakeLockState | mUserState);
743 }
744 else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
745 mPartialCount--;
746 if (mPartialCount == 0) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800747 if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800748 Power.releaseWakeLock(PARTIAL_NAME);
749 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700750 } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500751 mProximityWakeLockCount--;
752 if (mProximityWakeLockCount == 0) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500753 if (mProximitySensorActive &&
754 ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500755 // wait for proximity sensor to go negative before disabling sensor
756 if (mDebugProximitySensor) {
757 Log.d(TAG, "waiting for proximity sensor to go negative");
758 }
759 } else {
760 disableProximityLockLocked();
761 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700762 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 }
764 // Unlink the lock from the binder.
765 wl.binder.unlinkToDeath(wl, 0);
766 releaseUid = wl.uid;
767 releaseName = wl.tag;
768 releaseType = wl.monitorType;
769
770 if (releaseType >= 0) {
771 long origId = Binder.clearCallingIdentity();
772 try {
773 mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
774 } catch (RemoteException e) {
775 // Ignore
776 } finally {
777 Binder.restoreCallingIdentity(origId);
778 }
779 }
780 }
781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 private class PokeLock implements IBinder.DeathRecipient
783 {
784 PokeLock(int p, IBinder b, String t) {
785 super();
786 this.pokey = p;
787 this.binder = b;
788 this.tag = t;
789 try {
790 b.linkToDeath(this, 0);
791 } catch (RemoteException e) {
792 binderDied();
793 }
794 }
795 public void binderDied() {
796 setPokeLock(0, this.binder, this.tag);
797 }
798 int pokey;
799 IBinder binder;
800 String tag;
801 boolean awakeOnSet;
802 }
803
804 public void setPokeLock(int pokey, IBinder token, String tag) {
805 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
806 if (token == null) {
807 Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
808 return;
809 }
810
811 if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
812 throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
813 + " and POKE_LOCK_MEDIUM_TIMEOUT");
814 }
815
816 synchronized (mLocks) {
817 if (pokey != 0) {
818 PokeLock p = mPokeLocks.get(token);
819 int oldPokey = 0;
820 if (p != null) {
821 oldPokey = p.pokey;
822 p.pokey = pokey;
823 } else {
824 p = new PokeLock(pokey, token, tag);
825 mPokeLocks.put(token, p);
826 }
827 int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
828 int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
829 if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
830 p.awakeOnSet = true;
831 }
832 } else {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700833 PokeLock rLock = mPokeLocks.remove(token);
834 if (rLock != null) {
835 token.unlinkToDeath(rLock, 0);
836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 }
838
839 int oldPokey = mPokey;
840 int cumulative = 0;
841 boolean oldAwakeOnSet = mPokeAwakeOnSet;
842 boolean awakeOnSet = false;
843 for (PokeLock p: mPokeLocks.values()) {
844 cumulative |= p.pokey;
845 if (p.awakeOnSet) {
846 awakeOnSet = true;
847 }
848 }
849 mPokey = cumulative;
850 mPokeAwakeOnSet = awakeOnSet;
851
852 int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
853 int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 if (oldCumulativeTimeout != newCumulativeTimeout) {
856 setScreenOffTimeoutsLocked();
857 // reset the countdown timer, but use the existing nextState so it doesn't
858 // change anything
859 setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
860 }
861 }
862 }
863
864 private static String lockType(int type)
865 {
866 switch (type)
867 {
868 case PowerManager.FULL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700869 return "FULL_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700871 return "SCREEN_BRIGHT_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800872 case PowerManager.SCREEN_DIM_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700873 return "SCREEN_DIM_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 case PowerManager.PARTIAL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700875 return "PARTIAL_WAKE_LOCK ";
876 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
877 return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 default:
David Brown251faa62009-08-02 22:04:36 -0700879 return "??? ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800880 }
881 }
882
883 private static String dumpPowerState(int state) {
884 return (((state & KEYBOARD_BRIGHT_BIT) != 0)
885 ? "KEYBOARD_BRIGHT_BIT " : "")
886 + (((state & SCREEN_BRIGHT_BIT) != 0)
887 ? "SCREEN_BRIGHT_BIT " : "")
888 + (((state & SCREEN_ON_BIT) != 0)
889 ? "SCREEN_ON_BIT " : "")
890 + (((state & BATTERY_LOW_BIT) != 0)
891 ? "BATTERY_LOW_BIT " : "");
892 }
893
894 @Override
895 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
896 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
897 != PackageManager.PERMISSION_GRANTED) {
898 pw.println("Permission Denial: can't dump PowerManager from from pid="
899 + Binder.getCallingPid()
900 + ", uid=" + Binder.getCallingUid());
901 return;
902 }
903
904 long now = SystemClock.uptimeMillis();
905
906 pw.println("Power Manager State:");
907 pw.println(" mIsPowered=" + mIsPowered
908 + " mPowerState=" + mPowerState
909 + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
910 + " ms");
911 pw.println(" mPartialCount=" + mPartialCount);
912 pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
913 pw.println(" mUserState=" + dumpPowerState(mUserState));
914 pw.println(" mPowerState=" + dumpPowerState(mPowerState));
915 pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
916 pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
917 + " " + ((mNextTimeout-now)/1000) + "s from now");
918 pw.println(" mDimScreen=" + mDimScreen
919 + " mStayOnConditions=" + mStayOnConditions);
Mike Lockwood435eb642009-12-03 08:40:18 -0500920 pw.println(" mScreenOffReason=" + mScreenOffReason
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 + " mUserState=" + mUserState);
Joe Onorato128e7292009-03-24 18:41:31 -0700922 pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
923 + ',' + mBroadcastQueue[2] + "}");
924 pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
925 + ',' + mBroadcastWhy[2] + "}");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800926 pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
927 pw.println(" mKeyboardVisible=" + mKeyboardVisible
928 + " mUserActivityAllowed=" + mUserActivityAllowed);
929 pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
930 + " mScreenOffDelay=" + mScreenOffDelay);
931 pw.println(" mPreventScreenOn=" + mPreventScreenOn
Mike Lockwoodfb73f792009-11-20 11:31:18 -0500932 + " mScreenBrightnessOverride=" + mScreenBrightnessOverride
933 + " mButtonBrightnessOverride=" + mButtonBrightnessOverride);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 pw.println(" mTotalDelaySetting=" + mTotalDelaySetting);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500935 pw.println(" mLastScreenOnTime=" + mLastScreenOnTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800936 pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
937 pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
938 pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
939 pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500940 pw.println(" mProximityPartialLock=" + mProximityPartialLock);
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500941 pw.println(" mProximityWakeLockCount=" + mProximityWakeLockCount);
942 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700943 pw.println(" mProximitySensorActive=" + mProximitySensorActive);
Mike Lockwood20f87d72009-11-05 16:08:51 -0500944 pw.println(" mProximityPendingValue=" + mProximityPendingValue);
945 pw.println(" mLastProximityEventTime=" + mLastProximityEventTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700946 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
Mike Lockwoodfb73f792009-11-20 11:31:18 -0500947 pw.println(" mLightSensorValue=" + mLightSensorValue
948 + " mLightSensorPendingValue=" + mLightSensorPendingValue);
949 pw.println(" mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
950 + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
951 + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400952 pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700953 pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 mScreenBrightness.dump(pw, " mScreenBrightness: ");
955 mKeyboardBrightness.dump(pw, " mKeyboardBrightness: ");
956 mButtonBrightness.dump(pw, " mButtonBrightness: ");
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800957
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800958 int N = mLocks.size();
959 pw.println();
960 pw.println("mLocks.size=" + N + ":");
961 for (int i=0; i<N; i++) {
962 WakeLock wl = mLocks.get(i);
963 String type = lockType(wl.flags & LOCK_MASK);
964 String acquireCausesWakeup = "";
965 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
966 acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
967 }
968 String activated = "";
969 if (wl.activated) {
970 activated = " activated";
971 }
972 pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
973 + activated + " (minState=" + wl.minState + ")");
974 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -0800975
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 pw.println();
977 pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
978 for (PokeLock p: mPokeLocks.values()) {
979 pw.println(" poke lock '" + p.tag + "':"
980 + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
981 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
Joe Onoratoe68ffcb2009-03-24 19:11:13 -0700982 + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0
983 ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800984 + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
985 ? " POKE_LOCK_SHORT_TIMEOUT" : "")
986 + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
987 ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
988 }
989
990 pw.println();
991 }
992
993 private void setTimeoutLocked(long now, int nextState)
994 {
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500995 if (mBootCompleted) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800996 mHandler.removeCallbacks(mTimeoutTask);
997 mTimeoutTask.nextState = nextState;
998 long when = now;
999 switch (nextState)
1000 {
1001 case SCREEN_BRIGHT:
1002 when += mKeylightDelay;
1003 break;
1004 case SCREEN_DIM:
1005 if (mDimDelay >= 0) {
1006 when += mDimDelay;
1007 break;
1008 } else {
1009 Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
1010 }
1011 case SCREEN_OFF:
1012 synchronized (mLocks) {
1013 when += mScreenOffDelay;
1014 }
1015 break;
1016 }
1017 if (mSpew) {
1018 Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
1019 + " when=" + when);
1020 }
1021 mHandler.postAtTime(mTimeoutTask, when);
1022 mNextTimeout = when; // for debugging
1023 }
1024 }
1025
1026 private void cancelTimerLocked()
1027 {
1028 mHandler.removeCallbacks(mTimeoutTask);
1029 mTimeoutTask.nextState = -1;
1030 }
1031
1032 private class TimeoutTask implements Runnable
1033 {
1034 int nextState; // access should be synchronized on mLocks
1035 public void run()
1036 {
1037 synchronized (mLocks) {
1038 if (mSpew) {
1039 Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
1040 }
1041
1042 if (nextState == -1) {
1043 return;
1044 }
1045
1046 mUserState = this.nextState;
1047 setPowerState(this.nextState | mWakeLockState);
1048
1049 long now = SystemClock.uptimeMillis();
1050
1051 switch (this.nextState)
1052 {
1053 case SCREEN_BRIGHT:
1054 if (mDimDelay >= 0) {
1055 setTimeoutLocked(now, SCREEN_DIM);
1056 break;
1057 }
1058 case SCREEN_DIM:
1059 setTimeoutLocked(now, SCREEN_OFF);
1060 break;
1061 }
1062 }
1063 }
1064 }
1065
1066 private void sendNotificationLocked(boolean on, int why)
1067 {
Joe Onorato64c62ba2009-03-24 20:13:57 -07001068 if (!on) {
1069 mStillNeedSleepNotification = false;
1070 }
1071
Joe Onorato128e7292009-03-24 18:41:31 -07001072 // Add to the queue.
1073 int index = 0;
1074 while (mBroadcastQueue[index] != -1) {
1075 index++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 }
Joe Onorato128e7292009-03-24 18:41:31 -07001077 mBroadcastQueue[index] = on ? 1 : 0;
1078 mBroadcastWhy[index] = why;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079
Joe Onorato128e7292009-03-24 18:41:31 -07001080 // If we added it position 2, then there is a pair that can be stripped.
1081 // If we added it position 1 and we're turning the screen off, we can strip
1082 // the pair and do nothing, because the screen is already off, and therefore
1083 // keyguard has already been enabled.
1084 // However, if we added it at position 1 and we're turning it on, then position
1085 // 0 was to turn it off, and we can't strip that, because keyguard needs to come
1086 // on, so have to run the queue then.
1087 if (index == 2) {
1088 // Also, while we're collapsing them, if it's going to be an "off," and one
1089 // is off because of user, then use that, regardless of whether it's the first
1090 // or second one.
1091 if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
1092 mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
1093 }
1094 mBroadcastQueue[0] = on ? 1 : 0;
1095 mBroadcastQueue[1] = -1;
1096 mBroadcastQueue[2] = -1;
1097 index = 0;
1098 }
1099 if (index == 1 && !on) {
1100 mBroadcastQueue[0] = -1;
1101 mBroadcastQueue[1] = -1;
1102 index = -1;
1103 // The wake lock was being held, but we're not actually going to do any
1104 // broadcasts, so release the wake lock.
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001105 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001106 mBroadcastWakeLock.release();
Joe Onorato128e7292009-03-24 18:41:31 -07001107 }
1108
1109 // Now send the message.
1110 if (index >= 0) {
1111 // Acquire the broadcast wake lock before changing the power
1112 // state. It will be release after the broadcast is sent.
1113 // We always increment the ref count for each notification in the queue
1114 // and always decrement when that notification is handled.
1115 mBroadcastWakeLock.acquire();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001116 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
Joe Onorato128e7292009-03-24 18:41:31 -07001117 mHandler.post(mNotificationTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 }
1119 }
1120
1121 private Runnable mNotificationTask = new Runnable()
1122 {
1123 public void run()
1124 {
Joe Onorato128e7292009-03-24 18:41:31 -07001125 while (true) {
1126 int value;
1127 int why;
1128 WindowManagerPolicy policy;
1129 synchronized (mLocks) {
1130 value = mBroadcastQueue[0];
1131 why = mBroadcastWhy[0];
1132 for (int i=0; i<2; i++) {
1133 mBroadcastQueue[i] = mBroadcastQueue[i+1];
1134 mBroadcastWhy[i] = mBroadcastWhy[i+1];
1135 }
1136 policy = getPolicyLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 }
Joe Onorato128e7292009-03-24 18:41:31 -07001138 if (value == 1) {
1139 mScreenOnStart = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001140
Joe Onorato128e7292009-03-24 18:41:31 -07001141 policy.screenTurnedOn();
1142 try {
1143 ActivityManagerNative.getDefault().wakingUp();
1144 } catch (RemoteException e) {
1145 // ignore it
1146 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147
Joe Onorato128e7292009-03-24 18:41:31 -07001148 if (mSpew) {
1149 Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
1150 }
1151 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1152 mContext.sendOrderedBroadcast(mScreenOnIntent, null,
1153 mScreenOnBroadcastDone, mHandler, 0, null, null);
1154 } else {
1155 synchronized (mLocks) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001156 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2,
Joe Onorato128e7292009-03-24 18:41:31 -07001157 mBroadcastWakeLock.mCount);
1158 mBroadcastWakeLock.release();
1159 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 }
1161 }
Joe Onorato128e7292009-03-24 18:41:31 -07001162 else if (value == 0) {
1163 mScreenOffStart = SystemClock.uptimeMillis();
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001164
Joe Onorato128e7292009-03-24 18:41:31 -07001165 policy.screenTurnedOff(why);
1166 try {
1167 ActivityManagerNative.getDefault().goingToSleep();
1168 } catch (RemoteException e) {
1169 // ignore it.
1170 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171
Joe Onorato128e7292009-03-24 18:41:31 -07001172 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1173 mContext.sendOrderedBroadcast(mScreenOffIntent, null,
1174 mScreenOffBroadcastDone, mHandler, 0, null, null);
1175 } else {
1176 synchronized (mLocks) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001177 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
Joe Onorato128e7292009-03-24 18:41:31 -07001178 mBroadcastWakeLock.mCount);
1179 mBroadcastWakeLock.release();
1180 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 }
1182 }
Joe Onorato128e7292009-03-24 18:41:31 -07001183 else {
1184 // If we're in this case, then this handler is running for a previous
1185 // paired transaction. mBroadcastWakeLock will already have been released.
1186 break;
1187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001188 }
1189 }
1190 };
1191
1192 long mScreenOnStart;
1193 private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
1194 public void onReceive(Context context, Intent intent) {
1195 synchronized (mLocks) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001196 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
1198 mBroadcastWakeLock.release();
1199 }
1200 }
1201 };
1202
1203 long mScreenOffStart;
1204 private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
1205 public void onReceive(Context context, Intent intent) {
1206 synchronized (mLocks) {
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001207 EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208 SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
1209 mBroadcastWakeLock.release();
1210 }
1211 }
1212 };
1213
1214 void logPointerUpEvent() {
1215 if (LOG_TOUCH_DOWNS) {
1216 mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1217 mLastTouchDown = 0;
1218 }
1219 }
1220
1221 void logPointerDownEvent() {
1222 if (LOG_TOUCH_DOWNS) {
1223 // If we are not already timing a down/up sequence
1224 if (mLastTouchDown == 0) {
1225 mLastTouchDown = SystemClock.elapsedRealtime();
1226 mTouchCycles++;
1227 }
1228 }
1229 }
1230
1231 /**
1232 * Prevents the screen from turning on even if it *should* turn on due
1233 * to a subsequent full wake lock being acquired.
1234 * <p>
1235 * This is a temporary hack that allows an activity to "cover up" any
1236 * display glitches that happen during the activity's startup
1237 * sequence. (Specifically, this API was added to work around a
1238 * cosmetic bug in the "incoming call" sequence, where the lock screen
1239 * would flicker briefly before the incoming call UI became visible.)
1240 * TODO: There ought to be a more elegant way of doing this,
1241 * probably by having the PowerManager and ActivityManager
1242 * work together to let apps specify that the screen on/off
1243 * state should be synchronized with the Activity lifecycle.
1244 * <p>
1245 * Note that calling preventScreenOn(true) will NOT turn the screen
1246 * off if it's currently on. (This API only affects *future*
1247 * acquisitions of full wake locks.)
1248 * But calling preventScreenOn(false) WILL turn the screen on if
1249 * it's currently off because of a prior preventScreenOn(true) call.
1250 * <p>
1251 * Any call to preventScreenOn(true) MUST be followed promptly by a call
1252 * to preventScreenOn(false). In fact, if the preventScreenOn(false)
1253 * call doesn't occur within 5 seconds, we'll turn the screen back on
1254 * ourselves (and log a warning about it); this prevents a buggy app
1255 * from disabling the screen forever.)
1256 * <p>
1257 * TODO: this feature should really be controlled by a new type of poke
1258 * lock (rather than an IPowerManager call).
1259 */
1260 public void preventScreenOn(boolean prevent) {
1261 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1262
1263 synchronized (mLocks) {
1264 if (prevent) {
1265 // First of all, grab a partial wake lock to
1266 // make sure the CPU stays on during the entire
1267 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1268 mPreventScreenOnPartialLock.acquire();
1269
1270 // Post a forceReenableScreen() call (for 5 seconds in the
1271 // future) to make sure the matching preventScreenOn(false) call
1272 // has happened by then.
1273 mHandler.removeCallbacks(mForceReenableScreenTask);
1274 mHandler.postDelayed(mForceReenableScreenTask, 5000);
1275
1276 // Finally, set the flag that prevents the screen from turning on.
1277 // (Below, in setPowerState(), we'll check mPreventScreenOn and
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001278 // we *won't* call setScreenStateLocked(true) if it's set.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 mPreventScreenOn = true;
1280 } else {
1281 // (Re)enable the screen.
1282 mPreventScreenOn = false;
1283
1284 // We're "undoing" a the prior preventScreenOn(true) call, so we
1285 // no longer need the 5-second safeguard.
1286 mHandler.removeCallbacks(mForceReenableScreenTask);
1287
1288 // Forcibly turn on the screen if it's supposed to be on. (This
1289 // handles the case where the screen is currently off because of
1290 // a prior preventScreenOn(true) call.)
Mike Lockwoode090281422009-11-14 21:02:56 -05001291 if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 if (mSpew) {
1293 Log.d(TAG,
1294 "preventScreenOn: turning on after a prior preventScreenOn(true)!");
1295 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001296 int err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001297 if (err != 0) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001298 Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001299 }
1300 }
1301
1302 // Release the partial wake lock that we held during the
1303 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1304 mPreventScreenOnPartialLock.release();
1305 }
1306 }
1307 }
1308
1309 public void setScreenBrightnessOverride(int brightness) {
1310 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1311
1312 synchronized (mLocks) {
1313 if (mScreenBrightnessOverride != brightness) {
1314 mScreenBrightnessOverride = brightness;
1315 updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1316 }
1317 }
1318 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001319
1320 public void setButtonBrightnessOverride(int brightness) {
1321 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1322
1323 synchronized (mLocks) {
1324 if (mButtonBrightnessOverride != brightness) {
1325 mButtonBrightnessOverride = brightness;
1326 updateLightsLocked(mPowerState, BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT);
1327 }
1328 }
1329 }
1330
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 /**
1332 * Sanity-check that gets called 5 seconds after any call to
1333 * preventScreenOn(true). This ensures that the original call
1334 * is followed promptly by a call to preventScreenOn(false).
1335 */
1336 private void forceReenableScreen() {
1337 // We shouldn't get here at all if mPreventScreenOn is false, since
1338 // we should have already removed any existing
1339 // mForceReenableScreenTask messages...
1340 if (!mPreventScreenOn) {
1341 Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
1342 return;
1343 }
1344
1345 // Uh oh. It's been 5 seconds since a call to
1346 // preventScreenOn(true) and we haven't re-enabled the screen yet.
1347 // This means the app that called preventScreenOn(true) is either
1348 // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
1349 // or buggy (i.e. it forgot to call preventScreenOn(false), or
1350 // crashed before doing so.)
1351
1352 // Log a warning, and forcibly turn the screen back on.
1353 Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
1354 + "Forcing the screen back on...");
1355 preventScreenOn(false);
1356 }
1357
1358 private Runnable mForceReenableScreenTask = new Runnable() {
1359 public void run() {
1360 forceReenableScreen();
1361 }
1362 };
1363
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001364 private int setScreenStateLocked(boolean on) {
1365 int err = Power.setScreenState(on);
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001366 if (err == 0) {
1367 mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
1368 if (mUseSoftwareAutoBrightness) {
1369 enableLightSensor(on);
1370 if (!on) {
1371 // make sure button and key backlights are off too
Mike Lockwood3cb67a32009-11-27 14:25:58 -05001372 mButtonLight.turnOff();
1373 mKeyboardLight.turnOff();
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001374 // clear current value so we will update based on the new conditions
1375 // when the sensor is reenabled.
1376 mLightSensorValue = -1;
1377 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001378 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001379 }
1380 return err;
1381 }
1382
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001383 private void setPowerState(int state)
1384 {
Mike Lockwood435eb642009-12-03 08:40:18 -05001385 setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001386 }
1387
Mike Lockwood435eb642009-12-03 08:40:18 -05001388 private void setPowerState(int newState, boolean noChangeLights, int reason)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001389 {
1390 synchronized (mLocks) {
1391 int err;
1392
1393 if (mSpew) {
1394 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1395 + " newState=0x" + Integer.toHexString(newState)
Mike Lockwood435eb642009-12-03 08:40:18 -05001396 + " noChangeLights=" + noChangeLights
1397 + " reason=" + reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001398 }
1399
1400 if (noChangeLights) {
1401 newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1402 }
Mike Lockwood36fc3022009-08-25 16:49:06 -07001403 if (mProximitySensorActive) {
1404 // don't turn on the screen when the proximity sensor lock is held
1405 newState = (newState & ~SCREEN_BRIGHT);
1406 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001407
1408 if (batteryIsLow()) {
1409 newState |= BATTERY_LOW_BIT;
1410 } else {
1411 newState &= ~BATTERY_LOW_BIT;
1412 }
1413 if (newState == mPowerState) {
1414 return;
1415 }
Mike Lockwood3333fa42009-10-26 14:50:42 -04001416
Mike Lockwood2d7bb812009-11-15 18:12:22 -05001417 if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001418 newState |= ALL_BRIGHT;
1419 }
1420
1421 boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1422 boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1423
Mike Lockwood51b84492009-11-16 21:51:18 -05001424 if (mSpew) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
1426 + " newState=" + newState + " noChangeLights=" + noChangeLights);
1427 Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1428 + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1429 Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1430 + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1431 Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1432 + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1433 Log.d(TAG, " oldScreenOn=" + oldScreenOn
1434 + " newScreenOn=" + newScreenOn);
1435 Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1436 + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1437 }
1438
1439 if (mPowerState != newState) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001440 updateLightsLocked(newState, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001441 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1442 }
1443
1444 if (oldScreenOn != newScreenOn) {
1445 if (newScreenOn) {
Joe Onorato128e7292009-03-24 18:41:31 -07001446 // When the user presses the power button, we need to always send out the
1447 // notification that it's going to sleep so the keyguard goes on. But
1448 // we can't do that until the screen fades out, so we don't show the keyguard
1449 // too early.
1450 if (mStillNeedSleepNotification) {
1451 sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1452 }
1453
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 // Turn on the screen UNLESS there was a prior
1455 // preventScreenOn(true) request. (Note that the lifetime
1456 // of a single preventScreenOn() request is limited to 5
1457 // seconds to prevent a buggy app from disabling the
1458 // screen forever; see forceReenableScreen().)
1459 boolean reallyTurnScreenOn = true;
1460 if (mSpew) {
1461 Log.d(TAG, "- turning screen on... mPreventScreenOn = "
1462 + mPreventScreenOn);
1463 }
1464
1465 if (mPreventScreenOn) {
1466 if (mSpew) {
1467 Log.d(TAG, "- PREVENTING screen from really turning on!");
1468 }
1469 reallyTurnScreenOn = false;
1470 }
1471 if (reallyTurnScreenOn) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001472 err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 long identity = Binder.clearCallingIdentity();
1474 try {
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001475 mBatteryStats.noteScreenBrightness(getPreferredBrightness());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 mBatteryStats.noteScreenOn();
1477 } catch (RemoteException e) {
1478 Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
1479 } finally {
1480 Binder.restoreCallingIdentity(identity);
1481 }
1482 } else {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001483 setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 // But continue as if we really did turn the screen on...
1485 err = 0;
1486 }
1487
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 mLastTouchDown = 0;
1489 mTotalTouchDownTime = 0;
1490 mTouchCycles = 0;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001491 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001492 mTotalTouchDownTime, mTouchCycles);
1493 if (err == 0) {
1494 mPowerState |= SCREEN_ON_BIT;
1495 sendNotificationLocked(true, -1);
1496 }
1497 } else {
Mike Lockwood497087e32009-11-08 18:33:03 -05001498 // cancel light sensor task
1499 mHandler.removeCallbacks(mAutoBrightnessTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001500 mScreenOffTime = SystemClock.elapsedRealtime();
1501 long identity = Binder.clearCallingIdentity();
1502 try {
1503 mBatteryStats.noteScreenOff();
1504 } catch (RemoteException e) {
1505 Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
1506 } finally {
1507 Binder.restoreCallingIdentity(identity);
1508 }
1509 mPowerState &= ~SCREEN_ON_BIT;
Mike Lockwood435eb642009-12-03 08:40:18 -05001510 mScreenOffReason = reason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 if (!mScreenBrightness.animating) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001512 err = screenOffFinishedAnimatingLocked(reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001514 err = 0;
1515 mLastTouchDown = 0;
1516 }
1517 }
1518 }
1519 }
1520 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001521
Mike Lockwood435eb642009-12-03 08:40:18 -05001522 private int screenOffFinishedAnimatingLocked(int reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523 // I don't think we need to check the current state here because all of these
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001524 // Power.setScreenState and sendNotificationLocked can both handle being
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001525 // called multiple times in the same state. -joeo
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001526 EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001527 mLastTouchDown = 0;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001528 int err = setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529 if (err == 0) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001530 mScreenOffReason = reason;
1531 sendNotificationLocked(false, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532 }
1533 return err;
1534 }
1535
1536 private boolean batteryIsLow() {
1537 return (!mIsPowered &&
1538 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1539 }
1540
The Android Open Source Project10592532009-03-18 17:39:46 -07001541 private void updateLightsLocked(int newState, int forceState) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001542 final int oldState = mPowerState;
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001543 newState = applyButtonState(newState);
1544 newState = applyKeyboardState(newState);
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001545 final int realDifference = (newState ^ oldState);
1546 final int difference = realDifference | forceState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001547 if (difference == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001548 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001549 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001550
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001551 int offMask = 0;
1552 int dimMask = 0;
1553 int onMask = 0;
1554
1555 int preferredBrightness = getPreferredBrightness();
1556 boolean startAnimation = false;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001557
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1559 if (ANIMATE_KEYBOARD_LIGHTS) {
1560 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1561 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001562 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001563 Power.BRIGHTNESS_ON);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 } else {
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001565 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
Joe Onorato128e7292009-03-24 18:41:31 -07001566 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1567 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001568 }
1569 startAnimation = true;
1570 } else {
1571 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001572 offMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001574 onMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 }
1576 }
1577 }
1578
1579 if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1580 if (ANIMATE_BUTTON_LIGHTS) {
1581 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1582 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001583 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001584 Power.BRIGHTNESS_ON);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 } else {
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001586 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
Joe Onorato128e7292009-03-24 18:41:31 -07001587 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1588 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 }
1590 startAnimation = true;
1591 } else {
1592 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001593 offMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001595 onMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 }
1597 }
1598 }
1599
1600 if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1601 if (ANIMATE_SCREEN_LIGHTS) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001602 int nominalCurrentValue = -1;
1603 // If there was an actual difference in the light state, then
1604 // figure out the "ideal" current value based on the previous
1605 // state. Otherwise, this is a change due to the brightness
1606 // override, so we want to animate from whatever the current
1607 // value is.
1608 if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1609 switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
1610 case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
1611 nominalCurrentValue = preferredBrightness;
1612 break;
1613 case SCREEN_ON_BIT:
1614 nominalCurrentValue = Power.BRIGHTNESS_DIM;
1615 break;
1616 case 0:
1617 nominalCurrentValue = Power.BRIGHTNESS_OFF;
1618 break;
1619 case SCREEN_BRIGHT_BIT:
1620 default:
1621 // not possible
1622 nominalCurrentValue = (int)mScreenBrightness.curValue;
1623 break;
1624 }
Joe Onorato128e7292009-03-24 18:41:31 -07001625 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001626 int brightness = preferredBrightness;
1627 int steps = ANIM_STEPS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001628 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1629 // dim or turn off backlight, depending on if the screen is on
1630 // the scale is because the brightness ramp isn't linear and this biases
1631 // it so the later parts take longer.
1632 final float scale = 1.5f;
1633 float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
1634 if (ratio > 1.0f) ratio = 1.0f;
1635 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
1637 // was bright
1638 steps = ANIM_STEPS;
1639 } else {
1640 // was dim
1641 steps = (int)(ANIM_STEPS*ratio*scale);
1642 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001643 brightness = Power.BRIGHTNESS_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001644 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 if ((oldState & SCREEN_ON_BIT) != 0) {
1646 // was bright
1647 steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
1648 } else {
1649 // was dim
1650 steps = (int)(ANIM_STEPS*ratio);
1651 }
1652 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
1653 // If the "stay on while plugged in" option is
1654 // turned on, then the screen will often not
1655 // automatically turn off while plugged in. To
1656 // still have a sense of when it is inactive, we
1657 // will then count going dim as turning off.
1658 mScreenOffTime = SystemClock.elapsedRealtime();
1659 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001660 brightness = Power.BRIGHTNESS_DIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001663 long identity = Binder.clearCallingIdentity();
1664 try {
1665 mBatteryStats.noteScreenBrightness(brightness);
1666 } catch (RemoteException e) {
1667 // Nothing interesting to do.
1668 } finally {
1669 Binder.restoreCallingIdentity(identity);
1670 }
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001671 if (mScreenBrightness.setTargetLocked(brightness,
1672 steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
1673 startAnimation = true;
1674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 } else {
1676 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1677 // dim or turn off backlight, depending on if the screen is on
1678 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001679 offMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001681 dimMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 }
1683 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001684 onMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001685 }
1686 }
1687 }
1688
1689 if (startAnimation) {
1690 if (mSpew) {
1691 Log.i(TAG, "Scheduling light animator!");
1692 }
1693 mHandler.removeCallbacks(mLightAnimator);
1694 mHandler.post(mLightAnimator);
1695 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001696
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001697 if (offMask != 0) {
1698 //Log.i(TAG, "Setting brightess off: " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001699 setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 }
1701 if (dimMask != 0) {
1702 int brightness = Power.BRIGHTNESS_DIM;
1703 if ((newState & BATTERY_LOW_BIT) != 0 &&
1704 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1705 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1706 }
1707 //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001708 setLightBrightness(dimMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
1710 if (onMask != 0) {
1711 int brightness = getPreferredBrightness();
1712 if ((newState & BATTERY_LOW_BIT) != 0 &&
1713 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1714 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1715 }
1716 //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001717 setLightBrightness(onMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001718 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001719 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001720
The Android Open Source Project10592532009-03-18 17:39:46 -07001721 private void setLightBrightness(int mask, int value) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001722 int brightnessMode = (mAutoBrightessEnabled
Mike Lockwood3a322132009-11-24 00:30:52 -05001723 ? LightsService.BRIGHTNESS_MODE_SENSOR
1724 : LightsService.BRIGHTNESS_MODE_USER);
The Android Open Source Project10592532009-03-18 17:39:46 -07001725 if ((mask & SCREEN_BRIGHT_BIT) != 0) {
Mike Lockwood3cb67a32009-11-27 14:25:58 -05001726 mLcdLight.setBrightness(value, brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001727 }
1728 if ((mask & BUTTON_BRIGHT_BIT) != 0) {
Mike Lockwood3cb67a32009-11-27 14:25:58 -05001729 mButtonLight.setBrightness(value);
The Android Open Source Project10592532009-03-18 17:39:46 -07001730 }
1731 if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
Mike Lockwood3cb67a32009-11-27 14:25:58 -05001732 mKeyboardLight.setBrightness(value);
The Android Open Source Project10592532009-03-18 17:39:46 -07001733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001734 }
1735
1736 class BrightnessState {
1737 final int mask;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001738
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001739 boolean initialized;
1740 int targetValue;
1741 float curValue;
1742 float delta;
1743 boolean animating;
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001745 BrightnessState(int m) {
1746 mask = m;
1747 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001748
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001749 public void dump(PrintWriter pw, String prefix) {
1750 pw.println(prefix + "animating=" + animating
1751 + " targetValue=" + targetValue
1752 + " curValue=" + curValue
1753 + " delta=" + delta);
1754 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001755
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001756 boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
Joe Onorato128e7292009-03-24 18:41:31 -07001757 int nominalCurrentValue) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001758 if (!initialized) {
1759 initialized = true;
1760 curValue = (float)initialValue;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001761 } else if (targetValue == target) {
1762 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 }
1764 targetValue = target;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001765 delta = (targetValue -
1766 (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
1767 / stepsToTarget;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001768 if (mSpew) {
Joe Onorato128e7292009-03-24 18:41:31 -07001769 String noticeMe = nominalCurrentValue == curValue ? "" : " ******************";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
Joe Onorato128e7292009-03-24 18:41:31 -07001771 + " target=" + targetValue + " delta=" + delta
1772 + " nominalCurrentValue=" + nominalCurrentValue
1773 + noticeMe);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775 animating = true;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001776 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001777 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001778
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001779 boolean stepLocked() {
1780 if (!animating) return false;
1781 if (false && mSpew) {
1782 Log.i(TAG, "Step target " + mask + ": cur=" + curValue
1783 + " target=" + targetValue + " delta=" + delta);
1784 }
1785 curValue += delta;
1786 int curIntValue = (int)curValue;
1787 boolean more = true;
1788 if (delta == 0) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001789 curValue = curIntValue = targetValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001790 more = false;
1791 } else if (delta > 0) {
1792 if (curIntValue >= targetValue) {
1793 curValue = curIntValue = targetValue;
1794 more = false;
1795 }
1796 } else {
1797 if (curIntValue <= targetValue) {
1798 curValue = curIntValue = targetValue;
1799 more = false;
1800 }
1801 }
1802 //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001803 setLightBrightness(mask, curIntValue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 animating = more;
1805 if (!more) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001806 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001807 screenOffFinishedAnimatingLocked(mScreenOffReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 }
1809 }
1810 return more;
1811 }
1812 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001813
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001814 private class LightAnimator implements Runnable {
1815 public void run() {
1816 synchronized (mLocks) {
1817 long now = SystemClock.uptimeMillis();
1818 boolean more = mScreenBrightness.stepLocked();
1819 if (mKeyboardBrightness.stepLocked()) {
1820 more = true;
1821 }
1822 if (mButtonBrightness.stepLocked()) {
1823 more = true;
1824 }
1825 if (more) {
1826 mHandler.postAtTime(mLightAnimator, now+(1000/60));
1827 }
1828 }
1829 }
1830 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001831
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001832 private int getPreferredBrightness() {
1833 try {
1834 if (mScreenBrightnessOverride >= 0) {
1835 return mScreenBrightnessOverride;
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001836 } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
Mike Lockwood27c6dd72009-11-04 08:57:07 -05001837 && mAutoBrightessEnabled) {
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001838 return mLightSensorScreenBrightness;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001839 }
1840 final int brightness = Settings.System.getInt(mContext.getContentResolver(),
1841 SCREEN_BRIGHTNESS);
1842 // Don't let applications turn the screen all the way off
1843 return Math.max(brightness, Power.BRIGHTNESS_DIM);
1844 } catch (SettingNotFoundException snfe) {
1845 return Power.BRIGHTNESS_ON;
1846 }
1847 }
1848
Mike Lockwoodfb73f792009-11-20 11:31:18 -05001849 private int applyButtonState(int state) {
1850 int brightness = -1;
1851 if (mButtonBrightnessOverride >= 0) {
1852 brightness = mButtonBrightnessOverride;
1853 } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
1854 brightness = mLightSensorButtonBrightness;
1855 }
1856 if (brightness > 0) {
1857 return state | BUTTON_BRIGHT_BIT;
1858 } else if (brightness == 0) {
1859 return state & ~BUTTON_BRIGHT_BIT;
1860 } else {
1861 return state;
1862 }
1863 }
1864
1865 private int applyKeyboardState(int state) {
1866 int brightness = -1;
1867 if (!mKeyboardVisible) {
1868 brightness = 0;
1869 } else if (mButtonBrightnessOverride >= 0) {
1870 brightness = mButtonBrightnessOverride;
1871 } else if (mLightSensorKeyboardBrightness >= 0 && mUseSoftwareAutoBrightness) {
1872 brightness = mLightSensorKeyboardBrightness;
1873 }
1874 if (brightness > 0) {
1875 return state | KEYBOARD_BRIGHT_BIT;
1876 } else if (brightness == 0) {
1877 return state & ~KEYBOARD_BRIGHT_BIT;
1878 } else {
1879 return state;
1880 }
1881 }
1882
Charles Mendis322591c2009-10-29 11:06:59 -07001883 public boolean isScreenOn() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001884 synchronized (mLocks) {
1885 return (mPowerState & SCREEN_ON_BIT) != 0;
1886 }
1887 }
1888
Charles Mendis322591c2009-10-29 11:06:59 -07001889 boolean isScreenBright() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 synchronized (mLocks) {
1891 return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
1892 }
1893 }
1894
Mike Lockwood497087e32009-11-08 18:33:03 -05001895 private boolean isScreenTurningOffLocked() {
1896 return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
1897 }
1898
Mike Lockwood200b30b2009-09-20 00:23:59 -04001899 private void forceUserActivityLocked() {
Mike Lockwoode090281422009-11-14 21:02:56 -05001900 if (isScreenTurningOffLocked()) {
1901 // cancel animation so userActivity will succeed
1902 mScreenBrightness.animating = false;
1903 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04001904 boolean savedActivityAllowed = mUserActivityAllowed;
1905 mUserActivityAllowed = true;
1906 userActivity(SystemClock.uptimeMillis(), false);
1907 mUserActivityAllowed = savedActivityAllowed;
1908 }
1909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001910 public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
1911 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1912 userActivity(time, noChangeLights, OTHER_EVENT, force);
1913 }
1914
1915 public void userActivity(long time, boolean noChangeLights) {
1916 userActivity(time, noChangeLights, OTHER_EVENT, false);
1917 }
1918
1919 public void userActivity(long time, boolean noChangeLights, int eventType) {
1920 userActivity(time, noChangeLights, eventType, false);
1921 }
1922
1923 public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
1924 //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1925
1926 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001927 && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001928 if (false) {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001929 Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001930 }
1931 return;
1932 }
1933
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001934 if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
1935 && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
1936 || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
1937 if (false) {
1938 Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
1939 }
1940 return;
1941 }
1942
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001943 if (false) {
1944 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
1945 Log.d(TAG, "userActivity !!!");//, new RuntimeException());
1946 } else {
1947 Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
1948 }
1949 }
1950
1951 synchronized (mLocks) {
1952 if (mSpew) {
1953 Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
1954 + " mUserActivityAllowed=" + mUserActivityAllowed
1955 + " mUserState=0x" + Integer.toHexString(mUserState)
Mike Lockwood36fc3022009-08-25 16:49:06 -07001956 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
1957 + " mProximitySensorActive=" + mProximitySensorActive
1958 + " force=" + force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001959 }
Mike Lockwood05067122009-10-27 23:07:25 -04001960 // ignore user activity if we are in the process of turning off the screen
Mike Lockwood497087e32009-11-08 18:33:03 -05001961 if (isScreenTurningOffLocked()) {
Mike Lockwood05067122009-10-27 23:07:25 -04001962 Log.d(TAG, "ignoring user activity while turning off screen");
1963 return;
1964 }
Mike Lockwood0e39ea82009-11-18 15:37:10 -05001965 // Disable proximity sensor if if user presses power key while we are in the
1966 // "waiting for proximity sensor to go negative" state.
1967 if (mProximitySensorActive && mProximityWakeLockCount == 0) {
1968 mProximitySensorActive = false;
1969 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 if (mLastEventTime <= time || force) {
1971 mLastEventTime = time;
Mike Lockwood36fc3022009-08-25 16:49:06 -07001972 if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001973 // Only turn on button backlights if a button was pressed
1974 // and auto brightness is disabled
Mike Lockwood4984e732009-11-01 08:16:33 -05001975 if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001976 mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
1977 } else {
1978 // don't clear button/keyboard backlights when the screen is touched.
1979 mUserState |= SCREEN_BRIGHT;
1980 }
1981
Dianne Hackborn617f8772009-03-31 15:04:46 -07001982 int uid = Binder.getCallingUid();
1983 long ident = Binder.clearCallingIdentity();
1984 try {
1985 mBatteryStats.noteUserActivity(uid, eventType);
1986 } catch (RemoteException e) {
1987 // Ignore
1988 } finally {
1989 Binder.restoreCallingIdentity(ident);
1990 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08001991
Michael Chane96440f2009-05-06 10:27:36 -07001992 mWakeLockState = mLocks.reactivateScreenLocksLocked();
Mike Lockwood435eb642009-12-03 08:40:18 -05001993 setPowerState(mUserState | mWakeLockState, noChangeLights,
1994 WindowManagerPolicy.OFF_BECAUSE_OF_USER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001995 setTimeoutLocked(time, SCREEN_BRIGHT);
1996 }
1997 }
1998 }
1999 }
2000
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002001 private int getAutoBrightnessValue(int sensorValue, int[] values) {
2002 try {
2003 int i;
2004 for (i = 0; i < mAutoBrightnessLevels.length; i++) {
2005 if (sensorValue < mAutoBrightnessLevels[i]) {
2006 break;
2007 }
2008 }
2009 return values[i];
2010 } catch (Exception e) {
2011 // guard against null pointer or index out of bounds errors
2012 Log.e(TAG, "getAutoBrightnessValue", e);
2013 return 255;
2014 }
2015 }
2016
Mike Lockwood20f87d72009-11-05 16:08:51 -05002017 private Runnable mProximityTask = new Runnable() {
2018 public void run() {
2019 synchronized (mLocks) {
2020 if (mProximityPendingValue != -1) {
2021 proximityChangedLocked(mProximityPendingValue == 1);
2022 mProximityPendingValue = -1;
2023 }
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002024 if (mProximityPartialLock.isHeld()) {
2025 mProximityPartialLock.release();
2026 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002027 }
2028 }
2029 };
2030
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002031 private Runnable mAutoBrightnessTask = new Runnable() {
2032 public void run() {
Mike Lockwoodfa68ab42009-10-20 11:08:49 -04002033 synchronized (mLocks) {
2034 int value = (int)mLightSensorPendingValue;
2035 if (value >= 0) {
2036 mLightSensorPendingValue = -1;
2037 lightSensorChangedLocked(value);
2038 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002039 }
2040 }
2041 };
2042
2043 private void lightSensorChangedLocked(int value) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002044 if (mDebugLightSensor) {
2045 Log.d(TAG, "lightSensorChangedLocked " + value);
2046 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002047
2048 if (mLightSensorValue != value) {
2049 mLightSensorValue = value;
2050 if ((mPowerState & BATTERY_LOW_BIT) == 0) {
2051 int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
2052 int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
Mike Lockwooddf024922009-10-29 21:29:15 -04002053 int keyboardValue;
2054 if (mKeyboardVisible) {
2055 keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
2056 } else {
2057 keyboardValue = 0;
2058 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -05002059 mLightSensorScreenBrightness = lcdValue;
2060 mLightSensorButtonBrightness = buttonValue;
2061 mLightSensorKeyboardBrightness = keyboardValue;
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002062
2063 if (mDebugLightSensor) {
2064 Log.d(TAG, "lcdValue " + lcdValue);
2065 Log.d(TAG, "buttonValue " + buttonValue);
2066 Log.d(TAG, "keyboardValue " + keyboardValue);
2067 }
2068
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002069 boolean startAnimation = false;
Mike Lockwood4984e732009-11-01 08:16:33 -05002070 if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002071 if (ANIMATE_SCREEN_LIGHTS) {
2072 if (mScreenBrightness.setTargetLocked(lcdValue,
2073 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
2074 (int)mScreenBrightness.curValue)) {
2075 startAnimation = true;
2076 }
2077 } else {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002078 int brightnessMode = (mAutoBrightessEnabled
Mike Lockwood3a322132009-11-24 00:30:52 -05002079 ? LightsService.BRIGHTNESS_MODE_SENSOR
2080 : LightsService.BRIGHTNESS_MODE_USER);
Mike Lockwood3cb67a32009-11-27 14:25:58 -05002081 mLcdLight.setBrightness(lcdValue, brightnessMode);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002082 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002083 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -05002084 if (mButtonBrightnessOverride < 0) {
2085 if (ANIMATE_BUTTON_LIGHTS) {
2086 if (mButtonBrightness.setTargetLocked(buttonValue,
2087 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2088 (int)mButtonBrightness.curValue)) {
2089 startAnimation = true;
2090 }
2091 } else {
Mike Lockwood3cb67a32009-11-27 14:25:58 -05002092 mButtonLight.setBrightness(buttonValue);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002093 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002094 }
Mike Lockwoodfb73f792009-11-20 11:31:18 -05002095 if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
2096 if (ANIMATE_KEYBOARD_LIGHTS) {
2097 if (mKeyboardBrightness.setTargetLocked(keyboardValue,
2098 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2099 (int)mKeyboardBrightness.curValue)) {
2100 startAnimation = true;
2101 }
2102 } else {
Mike Lockwood3cb67a32009-11-27 14:25:58 -05002103 mKeyboardLight.setBrightness(keyboardValue);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002104 }
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002105 }
2106 if (startAnimation) {
2107 if (mDebugLightSensor) {
2108 Log.i(TAG, "lightSensorChangedLocked scheduling light animator");
2109 }
2110 mHandler.removeCallbacks(mLightAnimator);
2111 mHandler.post(mLightAnimator);
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002112 }
2113 }
2114 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002115 }
2116
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002117 /**
2118 * The user requested that we go to sleep (probably with the power button).
2119 * This overrides all wake locks that are held.
2120 */
2121 public void goToSleep(long time)
2122 {
2123 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2124 synchronized (mLocks) {
Mike Lockwood435eb642009-12-03 08:40:18 -05002125 goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002126 }
2127 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002128
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002129 /**
Doug Zongker50a21f42009-11-19 12:49:53 -08002130 * Reboot the device immediately, passing 'reason' (may be null)
2131 * to the underlying __reboot system call. Should not return.
2132 */
2133 public void reboot(String reason)
2134 {
2135 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
San Mehat14e69af2010-01-06 14:58:18 -08002136
San Mehat1e512792010-01-07 10:40:29 -08002137 /*
2138 * Manually shutdown the MountService to ensure media is
2139 * put into a safe state.
2140 */
2141 IMountService mSvc = IMountService.Stub.asInterface(
2142 ServiceManager.getService("mount"));
2143
2144 if (mSvc != null) {
2145 try {
2146 mSvc.shutdown();
2147 } catch (Exception e) {
2148 Log.e(TAG, "MountService shutdown failed", e);
2149 }
2150 } else {
2151 Log.w(TAG, "MountService unavailable for shutdown");
2152 }
San Mehat14e69af2010-01-06 14:58:18 -08002153
Doug Zongker50a21f42009-11-19 12:49:53 -08002154 try {
2155 Power.reboot(reason);
2156 } catch (IOException e) {
2157 Log.e(TAG, "reboot failed", e);
2158 }
2159 }
2160
Dan Egnor60d87622009-12-16 16:32:58 -08002161 /**
2162 * Crash the runtime (causing a complete restart of the Android framework).
2163 * Requires REBOOT permission. Mostly for testing. Should not return.
2164 */
2165 public void crash(final String message)
2166 {
2167 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2168 Thread t = new Thread("PowerManagerService.crash()") {
2169 public void run() { throw new RuntimeException(message); }
2170 };
2171 try {
2172 t.start();
2173 t.join();
2174 } catch (InterruptedException e) {
2175 Log.wtf(TAG, e);
2176 }
2177 }
2178
Mike Lockwood435eb642009-12-03 08:40:18 -05002179 private void goToSleepLocked(long time, int reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180
2181 if (mLastEventTime <= time) {
2182 mLastEventTime = time;
2183 // cancel all of the wake locks
2184 mWakeLockState = SCREEN_OFF;
2185 int N = mLocks.size();
2186 int numCleared = 0;
2187 for (int i=0; i<N; i++) {
2188 WakeLock wl = mLocks.get(i);
2189 if (isScreenLock(wl.flags)) {
2190 mLocks.get(i).activated = false;
2191 numCleared++;
2192 }
2193 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002194 EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
Joe Onorato128e7292009-03-24 18:41:31 -07002195 mStillNeedSleepNotification = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002196 mUserState = SCREEN_OFF;
Mike Lockwood435eb642009-12-03 08:40:18 -05002197 setPowerState(SCREEN_OFF, false, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 cancelTimerLocked();
2199 }
2200 }
2201
2202 public long timeSinceScreenOn() {
2203 synchronized (mLocks) {
2204 if ((mPowerState & SCREEN_ON_BIT) != 0) {
2205 return 0;
2206 }
2207 return SystemClock.elapsedRealtime() - mScreenOffTime;
2208 }
2209 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 public void setKeyboardVisibility(boolean visible) {
Mike Lockwooda625b382009-09-12 17:36:03 -07002212 synchronized (mLocks) {
2213 if (mSpew) {
2214 Log.d(TAG, "setKeyboardVisibility: " + visible);
2215 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002216 if (mKeyboardVisible != visible) {
2217 mKeyboardVisible = visible;
2218 // don't signal user activity if the screen is off; other code
2219 // will take care of turning on due to a true change to the lid
2220 // switch and synchronized with the lock screen.
2221 if ((mPowerState & SCREEN_ON_BIT) != 0) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002222 if (mUseSoftwareAutoBrightness) {
Mike Lockwooddf024922009-10-29 21:29:15 -04002223 // force recompute of backlight values
2224 if (mLightSensorValue >= 0) {
2225 int value = (int)mLightSensorValue;
2226 mLightSensorValue = -1;
2227 lightSensorChangedLocked(value);
2228 }
2229 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002230 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2231 }
Mike Lockwooda625b382009-09-12 17:36:03 -07002232 }
2233 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002234 }
2235
2236 /**
2237 * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
Mike Lockwood50c548d2009-11-09 16:02:06 -05002238 * When disabling user activity we also reset user power state so the keyguard can reset its
2239 * short screen timeout when keyguard is unhidden.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002240 */
2241 public void enableUserActivity(boolean enabled) {
Mike Lockwood50c548d2009-11-09 16:02:06 -05002242 if (mSpew) {
2243 Log.d(TAG, "enableUserActivity " + enabled);
2244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002245 synchronized (mLocks) {
2246 mUserActivityAllowed = enabled;
Mike Lockwood50c548d2009-11-09 16:02:06 -05002247 if (!enabled) {
2248 // cancel timeout and clear mUserState so the keyguard can set a short timeout
2249 setTimeoutLocked(SystemClock.uptimeMillis(), 0);
2250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002251 }
2252 }
2253
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002254 private void setScreenBrightnessMode(int mode) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002255 boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
Mike Lockwoodf90ffcc2009-11-03 11:41:27 -05002256 if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002257 mAutoBrightessEnabled = enabled;
Charles Mendis322591c2009-10-29 11:06:59 -07002258 if (isScreenOn()) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002259 // force recompute of backlight values
2260 if (mLightSensorValue >= 0) {
2261 int value = (int)mLightSensorValue;
2262 mLightSensorValue = -1;
2263 lightSensorChangedLocked(value);
2264 }
Mike Lockwood2d155d22009-10-27 09:32:30 -04002265 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002266 }
2267 }
2268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002269 /** Sets the screen off timeouts:
2270 * mKeylightDelay
2271 * mDimDelay
2272 * mScreenOffDelay
2273 * */
2274 private void setScreenOffTimeoutsLocked() {
2275 if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
2276 mKeylightDelay = mShortKeylightDelay; // Configurable via Gservices
2277 mDimDelay = -1;
2278 mScreenOffDelay = 0;
2279 } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
2280 mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
2281 mDimDelay = -1;
2282 mScreenOffDelay = 0;
2283 } else {
2284 int totalDelay = mTotalDelaySetting;
2285 mKeylightDelay = LONG_KEYLIGHT_DELAY;
2286 if (totalDelay < 0) {
2287 mScreenOffDelay = Integer.MAX_VALUE;
2288 } else if (mKeylightDelay < totalDelay) {
2289 // subtract the time that the keylight delay. This will give us the
2290 // remainder of the time that we need to sleep to get the accurate
2291 // screen off timeout.
2292 mScreenOffDelay = totalDelay - mKeylightDelay;
2293 } else {
2294 mScreenOffDelay = 0;
2295 }
2296 if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
2297 mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
2298 mScreenOffDelay = LONG_DIM_TIME;
2299 } else {
2300 mDimDelay = -1;
2301 }
2302 }
2303 if (mSpew) {
2304 Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
2305 + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
2306 + " mDimScreen=" + mDimScreen);
2307 }
2308 }
2309
2310 /**
2311 * Refreshes cached Gservices settings. Called once on startup, and
2312 * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see
2313 * GservicesChangedReceiver).
2314 */
2315 private void updateGservicesValues() {
2316 mShortKeylightDelay = Settings.Gservices.getInt(
2317 mContext.getContentResolver(),
2318 Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS,
2319 SHORT_KEYLIGHT_DELAY_DEFAULT);
2320 // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay);
2321 }
2322
2323 /**
2324 * Receiver for the Gservices.CHANGED_ACTION broadcast intent,
2325 * which tells us we need to refresh our cached Gservices settings.
2326 */
2327 private class GservicesChangedReceiver extends BroadcastReceiver {
2328 @Override
2329 public void onReceive(Context context, Intent intent) {
2330 // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent);
2331 updateGservicesValues();
2332 }
2333 }
2334
2335 private class LockList extends ArrayList<WakeLock>
2336 {
2337 void addLock(WakeLock wl)
2338 {
2339 int index = getIndex(wl.binder);
2340 if (index < 0) {
2341 this.add(wl);
2342 }
2343 }
2344
2345 WakeLock removeLock(IBinder binder)
2346 {
2347 int index = getIndex(binder);
2348 if (index >= 0) {
2349 return this.remove(index);
2350 } else {
2351 return null;
2352 }
2353 }
2354
2355 int getIndex(IBinder binder)
2356 {
2357 int N = this.size();
2358 for (int i=0; i<N; i++) {
2359 if (this.get(i).binder == binder) {
2360 return i;
2361 }
2362 }
2363 return -1;
2364 }
2365
2366 int gatherState()
2367 {
2368 int result = 0;
2369 int N = this.size();
2370 for (int i=0; i<N; i++) {
2371 WakeLock wl = this.get(i);
2372 if (wl.activated) {
2373 if (isScreenLock(wl.flags)) {
2374 result |= wl.minState;
2375 }
2376 }
2377 }
2378 return result;
2379 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002380
Michael Chane96440f2009-05-06 10:27:36 -07002381 int reactivateScreenLocksLocked()
2382 {
2383 int result = 0;
2384 int N = this.size();
2385 for (int i=0; i<N; i++) {
2386 WakeLock wl = this.get(i);
2387 if (isScreenLock(wl.flags)) {
2388 wl.activated = true;
2389 result |= wl.minState;
2390 }
2391 }
2392 return result;
2393 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002394 }
2395
2396 void setPolicy(WindowManagerPolicy p) {
2397 synchronized (mLocks) {
2398 mPolicy = p;
2399 mLocks.notifyAll();
2400 }
2401 }
2402
2403 WindowManagerPolicy getPolicyLocked() {
2404 while (mPolicy == null || !mDoneBooting) {
2405 try {
2406 mLocks.wait();
2407 } catch (InterruptedException e) {
2408 // Ignore
2409 }
2410 }
2411 return mPolicy;
2412 }
Doug Zongkerab5c49c2009-12-04 10:31:43 -08002413
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002414 void systemReady() {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002415 mSensorManager = new SensorManager(mHandlerThread.getLooper());
2416 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
2417 // don't bother with the light sensor if auto brightness is handled in hardware
Mike Lockwoodaa66ea82009-10-31 16:31:27 -04002418 if (mUseSoftwareAutoBrightness) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002419 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
Mike Lockwood4984e732009-11-01 08:16:33 -05002420 enableLightSensor(true);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002421 }
2422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002423 synchronized (mLocks) {
2424 Log.d(TAG, "system ready!");
2425 mDoneBooting = true;
Dianne Hackborn617f8772009-03-31 15:04:46 -07002426 long identity = Binder.clearCallingIdentity();
2427 try {
2428 mBatteryStats.noteScreenBrightness(getPreferredBrightness());
2429 mBatteryStats.noteScreenOn();
2430 } catch (RemoteException e) {
2431 // Nothing interesting to do.
2432 } finally {
2433 Binder.restoreCallingIdentity(identity);
2434 }
Mike Lockwood2d7bb812009-11-15 18:12:22 -05002435 }
2436 }
2437
2438 void bootCompleted() {
2439 Log.d(TAG, "bootCompleted");
2440 synchronized (mLocks) {
2441 mBootCompleted = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002442 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2443 updateWakeLockLocked();
2444 mLocks.notifyAll();
2445 }
2446 }
2447
2448 public void monitor() {
2449 synchronized (mLocks) { }
2450 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002451
2452 public int getSupportedWakeLockFlags() {
2453 int result = PowerManager.PARTIAL_WAKE_LOCK
2454 | PowerManager.FULL_WAKE_LOCK
2455 | PowerManager.SCREEN_DIM_WAKE_LOCK;
2456
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002457 if (mProximitySensor != null) {
2458 result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
2459 }
2460
2461 return result;
2462 }
2463
Mike Lockwood237a2992009-09-15 14:42:16 -04002464 public void setBacklightBrightness(int brightness) {
2465 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2466 // Don't let applications turn the screen all the way off
2467 brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
Mike Lockwood3cb67a32009-11-27 14:25:58 -05002468 mLcdLight.setBrightness(brightness);
2469 mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
2470 mButtonLight.setBrightness(brightness);
Mike Lockwood237a2992009-09-15 14:42:16 -04002471 long identity = Binder.clearCallingIdentity();
2472 try {
2473 mBatteryStats.noteScreenBrightness(brightness);
2474 } catch (RemoteException e) {
2475 Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2476 } finally {
2477 Binder.restoreCallingIdentity(identity);
2478 }
2479
2480 // update our animation state
2481 if (ANIMATE_SCREEN_LIGHTS) {
2482 mScreenBrightness.curValue = brightness;
2483 mScreenBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002484 mScreenBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002485 }
2486 if (ANIMATE_KEYBOARD_LIGHTS) {
2487 mKeyboardBrightness.curValue = brightness;
2488 mKeyboardBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002489 mKeyboardBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002490 }
2491 if (ANIMATE_BUTTON_LIGHTS) {
2492 mButtonBrightness.curValue = brightness;
2493 mButtonBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002494 mButtonBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002495 }
2496 }
2497
Mike Lockwoodb11832d2009-11-25 15:25:55 -05002498 public void setAttentionLight(boolean on, int color) {
2499 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
Mike Lockwood3cb67a32009-11-27 14:25:58 -05002500 mAttentionLight.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
Mike Lockwoodb11832d2009-11-25 15:25:55 -05002501 }
2502
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002503 private void enableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002504 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002505 Log.d(TAG, "enableProximityLockLocked");
2506 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002507 if (!mProximitySensorEnabled) {
2508 // clear calling identity so sensor manager battery stats are accurate
2509 long identity = Binder.clearCallingIdentity();
2510 try {
2511 mSensorManager.registerListener(mProximityListener, mProximitySensor,
2512 SensorManager.SENSOR_DELAY_NORMAL);
2513 mProximitySensorEnabled = true;
2514 } finally {
2515 Binder.restoreCallingIdentity(identity);
2516 }
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002517 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002518 }
2519
2520 private void disableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002521 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002522 Log.d(TAG, "disableProximityLockLocked");
2523 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002524 if (mProximitySensorEnabled) {
2525 // clear calling identity so sensor manager battery stats are accurate
2526 long identity = Binder.clearCallingIdentity();
2527 try {
2528 mSensorManager.unregisterListener(mProximityListener);
2529 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002530 if (mProximityPartialLock.isHeld()) {
2531 mProximityPartialLock.release();
2532 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002533 mProximitySensorEnabled = false;
2534 } finally {
2535 Binder.restoreCallingIdentity(identity);
2536 }
2537 if (mProximitySensorActive) {
2538 mProximitySensorActive = false;
2539 forceUserActivityLocked();
2540 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04002541 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002542 }
2543
Mike Lockwood20f87d72009-11-05 16:08:51 -05002544 private void proximityChangedLocked(boolean active) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002545 if (mDebugProximitySensor) {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002546 Log.d(TAG, "proximityChangedLocked, active: " + active);
2547 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002548 if (!mProximitySensorEnabled) {
2549 Log.d(TAG, "Ignoring proximity change after sensor is disabled");
Mike Lockwood0d72f7e2009-11-05 20:53:00 -05002550 return;
2551 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002552 if (active) {
Mike Lockwood435eb642009-12-03 08:40:18 -05002553 goToSleepLocked(SystemClock.uptimeMillis(),
2554 WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
Mike Lockwood20f87d72009-11-05 16:08:51 -05002555 mProximitySensorActive = true;
2556 } else {
2557 // proximity sensor negative events trigger as user activity.
2558 // temporarily set mUserActivityAllowed to true so this will work
2559 // even when the keyguard is on.
2560 mProximitySensorActive = false;
2561 forceUserActivityLocked();
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002562
2563 if (mProximityWakeLockCount == 0) {
2564 // disable sensor if we have no listeners left after proximity negative
2565 disableProximityLockLocked();
2566 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002567 }
2568 }
2569
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002570 private void enableLightSensor(boolean enable) {
2571 if (mDebugLightSensor) {
2572 Log.d(TAG, "enableLightSensor " + enable);
2573 }
2574 if (mSensorManager != null && mLightSensorEnabled != enable) {
2575 mLightSensorEnabled = enable;
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002576 // clear calling identity so sensor manager battery stats are accurate
2577 long identity = Binder.clearCallingIdentity();
2578 try {
2579 if (enable) {
2580 mSensorManager.registerListener(mLightListener, mLightSensor,
2581 SensorManager.SENSOR_DELAY_NORMAL);
2582 } else {
2583 mSensorManager.unregisterListener(mLightListener);
2584 mHandler.removeCallbacks(mAutoBrightnessTask);
2585 }
2586 } finally {
2587 Binder.restoreCallingIdentity(identity);
Mike Lockwood06952d92009-08-13 16:05:38 -04002588 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002589 }
2590 }
2591
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002592 SensorEventListener mProximityListener = new SensorEventListener() {
2593 public void onSensorChanged(SensorEvent event) {
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002594 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002595 synchronized (mLocks) {
2596 float distance = event.values[0];
Mike Lockwood20f87d72009-11-05 16:08:51 -05002597 long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
2598 mLastProximityEventTime = milliseconds;
2599 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002600 boolean proximityTaskQueued = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -05002601
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002602 // compare against getMaximumRange to support sensors that only return 0 or 1
Mike Lockwood20f87d72009-11-05 16:08:51 -05002603 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
2604 distance < mProximitySensor.getMaximumRange());
2605
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002606 if (mDebugProximitySensor) {
2607 Log.d(TAG, "mProximityListener.onSensorChanged active: " + active);
2608 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002609 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
2610 // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
2611 mProximityPendingValue = (active ? 1 : 0);
2612 mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002613 proximityTaskQueued = true;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002614 } else {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002615 // process the value immediately
2616 mProximityPendingValue = -1;
2617 proximityChangedLocked(active);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002618 }
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002619
2620 // update mProximityPartialLock state
2621 boolean held = mProximityPartialLock.isHeld();
2622 if (!held && proximityTaskQueued) {
2623 // hold wakelock until mProximityTask runs
2624 mProximityPartialLock.acquire();
2625 } else if (held && !proximityTaskQueued) {
2626 mProximityPartialLock.release();
2627 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002628 }
2629 }
2630
2631 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2632 // ignore
2633 }
2634 };
2635
2636 SensorEventListener mLightListener = new SensorEventListener() {
2637 public void onSensorChanged(SensorEvent event) {
2638 synchronized (mLocks) {
Mike Lockwood497087e32009-11-08 18:33:03 -05002639 // ignore light sensor while screen is turning off
2640 if (isScreenTurningOffLocked()) {
2641 return;
2642 }
2643
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002644 int value = (int)event.values[0];
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002645 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002646 if (mDebugLightSensor) {
2647 Log.d(TAG, "onSensorChanged: light value: " + value);
2648 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002649 mHandler.removeCallbacks(mAutoBrightnessTask);
2650 if (mLightSensorValue != value) {
Mike Lockwood20ee6f22009-11-07 20:33:47 -05002651 if (mLightSensorValue == -1 ||
2652 milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
2653 // process the value immediately if screen has just turned on
Mike Lockwood6c97fca2009-10-20 08:10:00 -04002654 lightSensorChangedLocked(value);
2655 } else {
2656 // delay processing to debounce the sensor
2657 mLightSensorPendingValue = value;
2658 mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
2659 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002660 } else {
2661 mLightSensorPendingValue = -1;
2662 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002663 }
2664 }
2665
2666 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2667 // ignore
2668 }
2669 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002670}