blob: 966ecb0bf5e34c61c54a73b22ade873b7e564b23 [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;
48import android.os.SystemClock;
49import android.provider.Settings.SettingNotFoundException;
50import android.provider.Settings;
51import android.util.EventLog;
52import android.util.Log;
53import android.view.WindowManagerPolicy;
54import static android.provider.Settings.System.DIM_SCREEN;
55import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
Dan Murphy951764b2009-08-27 14:59:03 -050056import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
Mike Lockwooddc3494e2009-10-14 21:17:09 -070057import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
59import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
60
61import java.io.FileDescriptor;
62import java.io.PrintWriter;
63import java.util.ArrayList;
64import java.util.HashMap;
65import java.util.Observable;
66import java.util.Observer;
67
Mike Lockwoodbc706a02009-07-27 13:50:57 -070068class PowerManagerService extends IPowerManager.Stub
Mike Lockwood8738e0c2009-10-04 08:44:47 -040069 implements LocalPowerManager, Watchdog.Monitor {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070
71 private static final String TAG = "PowerManagerService";
72 static final String PARTIAL_NAME = "PowerManagerService";
73
74 private static final boolean LOG_PARTIAL_WL = false;
75
76 // Indicates whether touch-down cycles should be logged as part of the
77 // LOG_POWER_SCREEN_STATE log events
78 private static final boolean LOG_TOUCH_DOWNS = true;
79
80 private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
81 | PowerManager.SCREEN_DIM_WAKE_LOCK
82 | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
Mike Lockwoodbc706a02009-07-27 13:50:57 -070083 | PowerManager.FULL_WAKE_LOCK
84 | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080085
86 // time since last state: time since last event:
87 // The short keylight delay comes from Gservices; this is the default.
88 private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
89 private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
90 private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
91 private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
92
Mike Lockwoodd7786b42009-10-15 17:09:16 -070093 // How long to wait to debounce light sensor changes.
Mike Lockwood9b8136922009-11-06 15:53:59 -050094 private static final int LIGHT_SENSOR_DELAY = 2000;
Mike Lockwoodd7786b42009-10-15 17:09:16 -070095
Mike Lockwood20f87d72009-11-05 16:08:51 -050096 // For debouncing the proximity sensor.
97 private static final int PROXIMITY_SENSOR_DELAY = 1000;
98
Mike Lockwoodd20ea362009-09-15 00:13:38 -040099 // trigger proximity if distance is less than 5 cm
100 private static final float PROXIMITY_THRESHOLD = 5.0f;
101
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 // Cached Gservices settings; see updateGservicesValues()
103 private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
104
105 // flags for setPowerState
106 private static final int SCREEN_ON_BIT = 0x00000001;
107 private static final int SCREEN_BRIGHT_BIT = 0x00000002;
108 private static final int BUTTON_BRIGHT_BIT = 0x00000004;
109 private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
110 private static final int BATTERY_LOW_BIT = 0x00000010;
111
112 // values for setPowerState
113
114 // SCREEN_OFF == everything off
115 private static final int SCREEN_OFF = 0x00000000;
116
117 // SCREEN_DIM == screen on, screen backlight dim
118 private static final int SCREEN_DIM = SCREEN_ON_BIT;
119
120 // SCREEN_BRIGHT == screen on, screen backlight bright
121 private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
122
123 // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
124 private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
125
126 // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
127 private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
128
129 // used for noChangeLights in setPowerState()
130 private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
131
132 static final boolean ANIMATE_SCREEN_LIGHTS = true;
133 static final boolean ANIMATE_BUTTON_LIGHTS = false;
134 static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
135
136 static final int ANIM_STEPS = 60/4;
Mike Lockwooddd9668e2009-10-27 15:47:02 -0400137 // Slower animation for autobrightness changes
138 static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800139
140 // These magic numbers are the initial state of the LEDs at boot. Ideally
141 // we should read them from the driver, but our current hardware returns 0
142 // for the initial value. Oops!
143 static final int INITIAL_SCREEN_BRIGHTNESS = 255;
144 static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
145 static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
146
147 static final int LOG_POWER_SLEEP_REQUESTED = 2724;
148 static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725;
149 static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726;
150 static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727;
151 static final int LOG_POWER_SCREEN_STATE = 2728;
152 static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729;
153
154 private final int MY_UID;
155
156 private boolean mDoneBooting = false;
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500157 private boolean mBootCompleted = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 private int mStayOnConditions = 0;
Joe Onorato128e7292009-03-24 18:41:31 -0700159 private int[] mBroadcastQueue = new int[] { -1, -1, -1 };
160 private int[] mBroadcastWhy = new int[3];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800161 private int mPartialCount = 0;
162 private int mPowerState;
Mike Lockwood435eb642009-12-03 08:40:18 -0500163 // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
164 // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
165 private int mScreenOffReason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 private int mUserState;
167 private boolean mKeyboardVisible = false;
168 private boolean mUserActivityAllowed = true;
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500169 private int mProximityWakeLockCount = 0;
170 private boolean mProximitySensorEnabled = false;
Mike Lockwood36fc3022009-08-25 16:49:06 -0700171 private boolean mProximitySensorActive = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -0500172 private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
173 private long mLastProximityEventTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 private int mTotalDelaySetting;
175 private int mKeylightDelay;
176 private int mDimDelay;
177 private int mScreenOffDelay;
178 private int mWakeLockState;
179 private long mLastEventTime = 0;
180 private long mScreenOffTime;
181 private volatile WindowManagerPolicy mPolicy;
182 private final LockList mLocks = new LockList();
183 private Intent mScreenOffIntent;
184 private Intent mScreenOnIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -0700185 private HardwareService mHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 private Context mContext;
187 private UnsynchronizedWakeLock mBroadcastWakeLock;
188 private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
189 private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
190 private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500191 private UnsynchronizedWakeLock mProximityPartialLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 private HandlerThread mHandlerThread;
193 private Handler mHandler;
194 private TimeoutTask mTimeoutTask = new TimeoutTask();
195 private LightAnimator mLightAnimator = new LightAnimator();
196 private final BrightnessState mScreenBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700197 = new BrightnessState(SCREEN_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 private final BrightnessState mKeyboardBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700199 = new BrightnessState(KEYBOARD_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 private final BrightnessState mButtonBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700201 = new BrightnessState(BUTTON_BRIGHT_BIT);
Joe Onorato128e7292009-03-24 18:41:31 -0700202 private boolean mStillNeedSleepNotification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 private boolean mIsPowered = false;
204 private IActivityManager mActivityService;
205 private IBatteryStats mBatteryStats;
206 private BatteryService mBatteryService;
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700207 private SensorManager mSensorManager;
208 private Sensor mProximitySensor;
Mike Lockwood8738e0c2009-10-04 08:44:47 -0400209 private Sensor mLightSensor;
210 private boolean mLightSensorEnabled;
211 private float mLightSensorValue = -1;
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700212 private float mLightSensorPendingValue = -1;
213 private int mLightSensorBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 private boolean mDimScreen = true;
215 private long mNextTimeout;
216 private volatile int mPokey = 0;
217 private volatile boolean mPokeAwakeOnSet = false;
218 private volatile boolean mInitComplete = false;
219 private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500220 // mScreenOnTime and mScreenOnStartTime are used for computing total time screen
221 // has been on since boot
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 private long mScreenOnTime;
223 private long mScreenOnStartTime;
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500224 // mLastScreenOnTime is the time the screen was last turned on
225 private long mLastScreenOnTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 private boolean mPreventScreenOn;
227 private int mScreenBrightnessOverride = -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;
418
419 // Add ourself to the Watchdog monitors.
420 Watchdog.getInstance().addMonitor(this);
421 mScreenOnStartTime = SystemClock.elapsedRealtime();
422 }
423
424 private ContentQueryMap mSettings;
425
The Android Open Source Project10592532009-03-18 17:39:46 -0700426 void init(Context context, HardwareService hardware, IActivityManager activity,
427 BatteryService battery) {
428 mHardware = hardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 mContext = context;
430 mActivityService = activity;
431 mBatteryStats = BatteryStatsService.getService();
432 mBatteryService = battery;
433
434 mHandlerThread = new HandlerThread("PowerManagerService") {
435 @Override
436 protected void onLooperPrepared() {
437 super.onLooperPrepared();
438 initInThread();
439 }
440 };
441 mHandlerThread.start();
442
443 synchronized (mHandlerThread) {
444 while (!mInitComplete) {
445 try {
446 mHandlerThread.wait();
447 } catch (InterruptedException e) {
448 // Ignore
449 }
450 }
451 }
452 }
453
454 void initInThread() {
455 mHandler = new Handler();
456
457 mBroadcastWakeLock = new UnsynchronizedWakeLock(
Joe Onorato128e7292009-03-24 18:41:31 -0700458 PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
460 PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
461 mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
462 PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
463 mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
464 PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500465 mProximityPartialLock = new UnsynchronizedWakeLock(
466 PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467
468 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
469 mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
470 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
471 mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
472
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700473 Resources resources = mContext.getResources();
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400474
475 // read settings for auto-brightness
476 mUseSoftwareAutoBrightness = resources.getBoolean(
477 com.android.internal.R.bool.config_automatic_brightness_available);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400478 if (mUseSoftwareAutoBrightness) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700479 mAutoBrightnessLevels = resources.getIntArray(
480 com.android.internal.R.array.config_autoBrightnessLevels);
481 mLcdBacklightValues = resources.getIntArray(
482 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
483 mButtonBacklightValues = resources.getIntArray(
484 com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
485 mKeyboardBacklightValues = resources.getIntArray(
486 com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500487 mLightSensorWarmupTime = resources.getInteger(
488 com.android.internal.R.integer.config_lightSensorWarmupTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700489 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700490
491 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
493 "(" + Settings.System.NAME + "=?) or ("
494 + Settings.System.NAME + "=?) or ("
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700495 + Settings.System.NAME + "=?) or ("
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800496 + Settings.System.NAME + "=?)",
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700497 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
498 SCREEN_BRIGHTNESS_MODE},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 null);
500 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
501 SettingsObserver settingsObserver = new SettingsObserver();
502 mSettings.addObserver(settingsObserver);
503
504 // pretend that the settings changed so we will get their initial state
505 settingsObserver.update(mSettings, null);
506
507 // register for the battery changed notifications
508 IntentFilter filter = new IntentFilter();
509 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
510 mContext.registerReceiver(new BatteryReceiver(), filter);
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500511 filter = new IntentFilter();
512 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
513 mContext.registerReceiver(new BootCompletedReceiver(), filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514
515 // Listen for Gservices changes
516 IntentFilter gservicesChangedFilter =
517 new IntentFilter(Settings.Gservices.CHANGED_ACTION);
518 mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter);
519 // And explicitly do the initial update of our cached settings
520 updateGservicesValues();
521
Mike Lockwood4984e732009-11-01 08:16:33 -0500522 if (mUseSoftwareAutoBrightness) {
Mike Lockwood6c97fca2009-10-20 08:10:00 -0400523 // turn the screen on
524 setPowerState(SCREEN_BRIGHT);
525 } else {
526 // turn everything on
527 setPowerState(ALL_BRIGHT);
528 }
Dan Murphy951764b2009-08-27 14:59:03 -0500529
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 synchronized (mHandlerThread) {
531 mInitComplete = true;
532 mHandlerThread.notifyAll();
533 }
534 }
535
536 private class WakeLock implements IBinder.DeathRecipient
537 {
538 WakeLock(int f, IBinder b, String t, int u) {
539 super();
540 flags = f;
541 binder = b;
542 tag = t;
543 uid = u == MY_UID ? Process.SYSTEM_UID : u;
544 if (u != MY_UID || (
545 !"KEEP_SCREEN_ON_FLAG".equals(tag)
546 && !"KeyInputQueue".equals(tag))) {
547 monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
548 ? BatteryStats.WAKE_TYPE_PARTIAL
549 : BatteryStats.WAKE_TYPE_FULL;
550 } else {
551 monitorType = -1;
552 }
553 try {
554 b.linkToDeath(this, 0);
555 } catch (RemoteException e) {
556 binderDied();
557 }
558 }
559 public void binderDied() {
560 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500561 releaseWakeLockLocked(this.binder, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800562 }
563 }
564 final int flags;
565 final IBinder binder;
566 final String tag;
567 final int uid;
568 final int monitorType;
569 boolean activated = true;
570 int minState;
571 }
572
573 private void updateWakeLockLocked() {
574 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
575 // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
576 mStayOnWhilePluggedInScreenDimLock.acquire();
577 mStayOnWhilePluggedInPartialLock.acquire();
578 } else {
579 mStayOnWhilePluggedInScreenDimLock.release();
580 mStayOnWhilePluggedInPartialLock.release();
581 }
582 }
583
584 private boolean isScreenLock(int flags)
585 {
586 int n = flags & LOCK_MASK;
587 return n == PowerManager.FULL_WAKE_LOCK
588 || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
589 || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
590 }
591
592 public void acquireWakeLock(int flags, IBinder lock, String tag) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800593 int uid = Binder.getCallingUid();
Michael Chane96440f2009-05-06 10:27:36 -0700594 if (uid != Process.myUid()) {
595 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
596 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 long ident = Binder.clearCallingIdentity();
598 try {
599 synchronized (mLocks) {
600 acquireWakeLockLocked(flags, lock, uid, tag);
601 }
602 } finally {
603 Binder.restoreCallingIdentity(ident);
604 }
605 }
606
607 public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
608 int acquireUid = -1;
609 String acquireName = null;
610 int acquireType = -1;
611
612 if (mSpew) {
613 Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
614 }
615
616 int index = mLocks.getIndex(lock);
617 WakeLock wl;
618 boolean newlock;
619 if (index < 0) {
620 wl = new WakeLock(flags, lock, tag, uid);
621 switch (wl.flags & LOCK_MASK)
622 {
623 case PowerManager.FULL_WAKE_LOCK:
Mike Lockwood4984e732009-11-01 08:16:33 -0500624 if (mUseSoftwareAutoBrightness) {
Mike Lockwood3333fa42009-10-26 14:50:42 -0400625 wl.minState = SCREEN_BRIGHT;
626 } else {
627 wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
628 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 break;
630 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
631 wl.minState = SCREEN_BRIGHT;
632 break;
633 case PowerManager.SCREEN_DIM_WAKE_LOCK:
634 wl.minState = SCREEN_DIM;
635 break;
636 case PowerManager.PARTIAL_WAKE_LOCK:
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700637 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 break;
639 default:
640 // just log and bail. we're in the server, so don't
641 // throw an exception.
642 Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
643 + " flags=" + flags);
644 return;
645 }
646 mLocks.addLock(wl);
647 newlock = true;
648 } else {
649 wl = mLocks.get(index);
650 newlock = false;
651 }
652 if (isScreenLock(flags)) {
653 // if this causes a wakeup, we reactivate all of the locks and
654 // set it to whatever they want. otherwise, we modulate that
655 // by the current state so we never turn it more on than
656 // it already is.
657 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
Michael Chane96440f2009-05-06 10:27:36 -0700658 int oldWakeLockState = mWakeLockState;
659 mWakeLockState = mLocks.reactivateScreenLocksLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800660 if (mSpew) {
661 Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
Michael Chane96440f2009-05-06 10:27:36 -0700662 + " mWakeLockState=0x"
663 + Integer.toHexString(mWakeLockState)
664 + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 } else {
667 if (mSpew) {
668 Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
669 + " mLocks.gatherState()=0x"
670 + Integer.toHexString(mLocks.gatherState())
671 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
672 }
673 mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
674 }
675 setPowerState(mWakeLockState | mUserState);
676 }
677 else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
678 if (newlock) {
679 mPartialCount++;
680 if (mPartialCount == 1) {
681 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag);
682 }
683 }
684 Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700685 } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500686 mProximityWakeLockCount++;
687 if (mProximityWakeLockCount == 1) {
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700688 enableProximityLockLocked();
689 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690 }
691 if (newlock) {
692 acquireUid = wl.uid;
693 acquireName = wl.tag;
694 acquireType = wl.monitorType;
695 }
696
697 if (acquireType >= 0) {
698 try {
699 mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
700 } catch (RemoteException e) {
701 // Ignore
702 }
703 }
704 }
705
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500706 public void releaseWakeLock(IBinder lock, int flags) {
Michael Chane96440f2009-05-06 10:27:36 -0700707 int uid = Binder.getCallingUid();
708 if (uid != Process.myUid()) {
709 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711
712 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500713 releaseWakeLockLocked(lock, flags, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800714 }
715 }
716
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500717 private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 int releaseUid;
719 String releaseName;
720 int releaseType;
721
722 WakeLock wl = mLocks.removeLock(lock);
723 if (wl == null) {
724 return;
725 }
726
727 if (mSpew) {
728 Log.d(TAG, "releaseWakeLock flags=0x"
729 + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
730 }
731
732 if (isScreenLock(wl.flags)) {
733 mWakeLockState = mLocks.gatherState();
734 // goes in the middle to reduce flicker
735 if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
736 userActivity(SystemClock.uptimeMillis(), false);
737 }
738 setPowerState(mWakeLockState | mUserState);
739 }
740 else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
741 mPartialCount--;
742 if (mPartialCount == 0) {
743 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
744 Power.releaseWakeLock(PARTIAL_NAME);
745 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700746 } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500747 mProximityWakeLockCount--;
748 if (mProximityWakeLockCount == 0) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500749 if (mProximitySensorActive &&
750 ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500751 // wait for proximity sensor to go negative before disabling sensor
752 if (mDebugProximitySensor) {
753 Log.d(TAG, "waiting for proximity sensor to go negative");
754 }
755 } else {
756 disableProximityLockLocked();
757 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700758 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800759 }
760 // Unlink the lock from the binder.
761 wl.binder.unlinkToDeath(wl, 0);
762 releaseUid = wl.uid;
763 releaseName = wl.tag;
764 releaseType = wl.monitorType;
765
766 if (releaseType >= 0) {
767 long origId = Binder.clearCallingIdentity();
768 try {
769 mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
770 } catch (RemoteException e) {
771 // Ignore
772 } finally {
773 Binder.restoreCallingIdentity(origId);
774 }
775 }
776 }
777
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800778 private class PokeLock implements IBinder.DeathRecipient
779 {
780 PokeLock(int p, IBinder b, String t) {
781 super();
782 this.pokey = p;
783 this.binder = b;
784 this.tag = t;
785 try {
786 b.linkToDeath(this, 0);
787 } catch (RemoteException e) {
788 binderDied();
789 }
790 }
791 public void binderDied() {
792 setPokeLock(0, this.binder, this.tag);
793 }
794 int pokey;
795 IBinder binder;
796 String tag;
797 boolean awakeOnSet;
798 }
799
800 public void setPokeLock(int pokey, IBinder token, String tag) {
801 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
802 if (token == null) {
803 Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
804 return;
805 }
806
807 if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
808 throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
809 + " and POKE_LOCK_MEDIUM_TIMEOUT");
810 }
811
812 synchronized (mLocks) {
813 if (pokey != 0) {
814 PokeLock p = mPokeLocks.get(token);
815 int oldPokey = 0;
816 if (p != null) {
817 oldPokey = p.pokey;
818 p.pokey = pokey;
819 } else {
820 p = new PokeLock(pokey, token, tag);
821 mPokeLocks.put(token, p);
822 }
823 int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
824 int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
825 if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
826 p.awakeOnSet = true;
827 }
828 } else {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700829 PokeLock rLock = mPokeLocks.remove(token);
830 if (rLock != null) {
831 token.unlinkToDeath(rLock, 0);
832 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
834
835 int oldPokey = mPokey;
836 int cumulative = 0;
837 boolean oldAwakeOnSet = mPokeAwakeOnSet;
838 boolean awakeOnSet = false;
839 for (PokeLock p: mPokeLocks.values()) {
840 cumulative |= p.pokey;
841 if (p.awakeOnSet) {
842 awakeOnSet = true;
843 }
844 }
845 mPokey = cumulative;
846 mPokeAwakeOnSet = awakeOnSet;
847
848 int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
849 int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
850
851 if (oldCumulativeTimeout != newCumulativeTimeout) {
852 setScreenOffTimeoutsLocked();
853 // reset the countdown timer, but use the existing nextState so it doesn't
854 // change anything
855 setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
856 }
857 }
858 }
859
860 private static String lockType(int type)
861 {
862 switch (type)
863 {
864 case PowerManager.FULL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700865 return "FULL_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700867 return "SCREEN_BRIGHT_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800868 case PowerManager.SCREEN_DIM_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700869 return "SCREEN_DIM_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800870 case PowerManager.PARTIAL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700871 return "PARTIAL_WAKE_LOCK ";
872 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
873 return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 default:
David Brown251faa62009-08-02 22:04:36 -0700875 return "??? ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 }
877 }
878
879 private static String dumpPowerState(int state) {
880 return (((state & KEYBOARD_BRIGHT_BIT) != 0)
881 ? "KEYBOARD_BRIGHT_BIT " : "")
882 + (((state & SCREEN_BRIGHT_BIT) != 0)
883 ? "SCREEN_BRIGHT_BIT " : "")
884 + (((state & SCREEN_ON_BIT) != 0)
885 ? "SCREEN_ON_BIT " : "")
886 + (((state & BATTERY_LOW_BIT) != 0)
887 ? "BATTERY_LOW_BIT " : "");
888 }
889
890 @Override
891 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
892 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
893 != PackageManager.PERMISSION_GRANTED) {
894 pw.println("Permission Denial: can't dump PowerManager from from pid="
895 + Binder.getCallingPid()
896 + ", uid=" + Binder.getCallingUid());
897 return;
898 }
899
900 long now = SystemClock.uptimeMillis();
901
902 pw.println("Power Manager State:");
903 pw.println(" mIsPowered=" + mIsPowered
904 + " mPowerState=" + mPowerState
905 + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
906 + " ms");
907 pw.println(" mPartialCount=" + mPartialCount);
908 pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
909 pw.println(" mUserState=" + dumpPowerState(mUserState));
910 pw.println(" mPowerState=" + dumpPowerState(mPowerState));
911 pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
912 pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
913 + " " + ((mNextTimeout-now)/1000) + "s from now");
914 pw.println(" mDimScreen=" + mDimScreen
915 + " mStayOnConditions=" + mStayOnConditions);
Mike Lockwood435eb642009-12-03 08:40:18 -0500916 pw.println(" mScreenOffReason=" + mScreenOffReason
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800917 + " mUserState=" + mUserState);
Joe Onorato128e7292009-03-24 18:41:31 -0700918 pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
919 + ',' + mBroadcastQueue[2] + "}");
920 pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
921 + ',' + mBroadcastWhy[2] + "}");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
923 pw.println(" mKeyboardVisible=" + mKeyboardVisible
924 + " mUserActivityAllowed=" + mUserActivityAllowed);
925 pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
926 + " mScreenOffDelay=" + mScreenOffDelay);
927 pw.println(" mPreventScreenOn=" + mPreventScreenOn
928 + " mScreenBrightnessOverride=" + mScreenBrightnessOverride);
929 pw.println(" mTotalDelaySetting=" + mTotalDelaySetting);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500930 pw.println(" mLastScreenOnTime=" + mLastScreenOnTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800931 pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
932 pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
933 pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
934 pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500935 pw.println(" mProximityPartialLock=" + mProximityPartialLock);
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500936 pw.println(" mProximityWakeLockCount=" + mProximityWakeLockCount);
937 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700938 pw.println(" mProximitySensorActive=" + mProximitySensorActive);
Mike Lockwood20f87d72009-11-05 16:08:51 -0500939 pw.println(" mProximityPendingValue=" + mProximityPendingValue);
940 pw.println(" mLastProximityEventTime=" + mLastProximityEventTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700941 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
942 pw.println(" mLightSensorValue=" + mLightSensorValue);
943 pw.println(" mLightSensorPendingValue=" + mLightSensorPendingValue);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400944 pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700945 pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800946 mScreenBrightness.dump(pw, " mScreenBrightness: ");
947 mKeyboardBrightness.dump(pw, " mKeyboardBrightness: ");
948 mButtonBrightness.dump(pw, " mButtonBrightness: ");
949
950 int N = mLocks.size();
951 pw.println();
952 pw.println("mLocks.size=" + N + ":");
953 for (int i=0; i<N; i++) {
954 WakeLock wl = mLocks.get(i);
955 String type = lockType(wl.flags & LOCK_MASK);
956 String acquireCausesWakeup = "";
957 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
958 acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
959 }
960 String activated = "";
961 if (wl.activated) {
962 activated = " activated";
963 }
964 pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
965 + activated + " (minState=" + wl.minState + ")");
966 }
967
968 pw.println();
969 pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
970 for (PokeLock p: mPokeLocks.values()) {
971 pw.println(" poke lock '" + p.tag + "':"
972 + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
973 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
Joe Onoratoe68ffcb2009-03-24 19:11:13 -0700974 + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0
975 ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
977 ? " POKE_LOCK_SHORT_TIMEOUT" : "")
978 + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
979 ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
980 }
981
982 pw.println();
983 }
984
985 private void setTimeoutLocked(long now, int nextState)
986 {
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500987 if (mBootCompleted) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 mHandler.removeCallbacks(mTimeoutTask);
989 mTimeoutTask.nextState = nextState;
990 long when = now;
991 switch (nextState)
992 {
993 case SCREEN_BRIGHT:
994 when += mKeylightDelay;
995 break;
996 case SCREEN_DIM:
997 if (mDimDelay >= 0) {
998 when += mDimDelay;
999 break;
1000 } else {
1001 Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
1002 }
1003 case SCREEN_OFF:
1004 synchronized (mLocks) {
1005 when += mScreenOffDelay;
1006 }
1007 break;
1008 }
1009 if (mSpew) {
1010 Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
1011 + " when=" + when);
1012 }
1013 mHandler.postAtTime(mTimeoutTask, when);
1014 mNextTimeout = when; // for debugging
1015 }
1016 }
1017
1018 private void cancelTimerLocked()
1019 {
1020 mHandler.removeCallbacks(mTimeoutTask);
1021 mTimeoutTask.nextState = -1;
1022 }
1023
1024 private class TimeoutTask implements Runnable
1025 {
1026 int nextState; // access should be synchronized on mLocks
1027 public void run()
1028 {
1029 synchronized (mLocks) {
1030 if (mSpew) {
1031 Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
1032 }
1033
1034 if (nextState == -1) {
1035 return;
1036 }
1037
1038 mUserState = this.nextState;
1039 setPowerState(this.nextState | mWakeLockState);
1040
1041 long now = SystemClock.uptimeMillis();
1042
1043 switch (this.nextState)
1044 {
1045 case SCREEN_BRIGHT:
1046 if (mDimDelay >= 0) {
1047 setTimeoutLocked(now, SCREEN_DIM);
1048 break;
1049 }
1050 case SCREEN_DIM:
1051 setTimeoutLocked(now, SCREEN_OFF);
1052 break;
1053 }
1054 }
1055 }
1056 }
1057
1058 private void sendNotificationLocked(boolean on, int why)
1059 {
Joe Onorato64c62ba2009-03-24 20:13:57 -07001060 if (!on) {
1061 mStillNeedSleepNotification = false;
1062 }
1063
Joe Onorato128e7292009-03-24 18:41:31 -07001064 // Add to the queue.
1065 int index = 0;
1066 while (mBroadcastQueue[index] != -1) {
1067 index++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001068 }
Joe Onorato128e7292009-03-24 18:41:31 -07001069 mBroadcastQueue[index] = on ? 1 : 0;
1070 mBroadcastWhy[index] = why;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071
Joe Onorato128e7292009-03-24 18:41:31 -07001072 // If we added it position 2, then there is a pair that can be stripped.
1073 // If we added it position 1 and we're turning the screen off, we can strip
1074 // the pair and do nothing, because the screen is already off, and therefore
1075 // keyguard has already been enabled.
1076 // However, if we added it at position 1 and we're turning it on, then position
1077 // 0 was to turn it off, and we can't strip that, because keyguard needs to come
1078 // on, so have to run the queue then.
1079 if (index == 2) {
1080 // Also, while we're collapsing them, if it's going to be an "off," and one
1081 // is off because of user, then use that, regardless of whether it's the first
1082 // or second one.
1083 if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
1084 mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
1085 }
1086 mBroadcastQueue[0] = on ? 1 : 0;
1087 mBroadcastQueue[1] = -1;
1088 mBroadcastQueue[2] = -1;
1089 index = 0;
1090 }
1091 if (index == 1 && !on) {
1092 mBroadcastQueue[0] = -1;
1093 mBroadcastQueue[1] = -1;
1094 index = -1;
1095 // The wake lock was being held, but we're not actually going to do any
1096 // broadcasts, so release the wake lock.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1098 mBroadcastWakeLock.release();
Joe Onorato128e7292009-03-24 18:41:31 -07001099 }
1100
1101 // Now send the message.
1102 if (index >= 0) {
1103 // Acquire the broadcast wake lock before changing the power
1104 // state. It will be release after the broadcast is sent.
1105 // We always increment the ref count for each notification in the queue
1106 // and always decrement when that notification is handled.
1107 mBroadcastWakeLock.acquire();
1108 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
1109 mHandler.post(mNotificationTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 }
1111 }
1112
1113 private Runnable mNotificationTask = new Runnable()
1114 {
1115 public void run()
1116 {
Joe Onorato128e7292009-03-24 18:41:31 -07001117 while (true) {
1118 int value;
1119 int why;
1120 WindowManagerPolicy policy;
1121 synchronized (mLocks) {
1122 value = mBroadcastQueue[0];
1123 why = mBroadcastWhy[0];
1124 for (int i=0; i<2; i++) {
1125 mBroadcastQueue[i] = mBroadcastQueue[i+1];
1126 mBroadcastWhy[i] = mBroadcastWhy[i+1];
1127 }
1128 policy = getPolicyLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 }
Joe Onorato128e7292009-03-24 18:41:31 -07001130 if (value == 1) {
1131 mScreenOnStart = SystemClock.uptimeMillis();
1132
1133 policy.screenTurnedOn();
1134 try {
1135 ActivityManagerNative.getDefault().wakingUp();
1136 } catch (RemoteException e) {
1137 // ignore it
1138 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001139
Joe Onorato128e7292009-03-24 18:41:31 -07001140 if (mSpew) {
1141 Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
1142 }
1143 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1144 mContext.sendOrderedBroadcast(mScreenOnIntent, null,
1145 mScreenOnBroadcastDone, mHandler, 0, null, null);
1146 } else {
1147 synchronized (mLocks) {
1148 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2,
1149 mBroadcastWakeLock.mCount);
1150 mBroadcastWakeLock.release();
1151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 }
1153 }
Joe Onorato128e7292009-03-24 18:41:31 -07001154 else if (value == 0) {
1155 mScreenOffStart = SystemClock.uptimeMillis();
1156
1157 policy.screenTurnedOff(why);
1158 try {
1159 ActivityManagerNative.getDefault().goingToSleep();
1160 } catch (RemoteException e) {
1161 // ignore it.
1162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163
Joe Onorato128e7292009-03-24 18:41:31 -07001164 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1165 mContext.sendOrderedBroadcast(mScreenOffIntent, null,
1166 mScreenOffBroadcastDone, mHandler, 0, null, null);
1167 } else {
1168 synchronized (mLocks) {
1169 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3,
1170 mBroadcastWakeLock.mCount);
1171 mBroadcastWakeLock.release();
1172 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 }
1174 }
Joe Onorato128e7292009-03-24 18:41:31 -07001175 else {
1176 // If we're in this case, then this handler is running for a previous
1177 // paired transaction. mBroadcastWakeLock will already have been released.
1178 break;
1179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 }
1181 }
1182 };
1183
1184 long mScreenOnStart;
1185 private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
1186 public void onReceive(Context context, Intent intent) {
1187 synchronized (mLocks) {
1188 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1,
1189 SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
1190 mBroadcastWakeLock.release();
1191 }
1192 }
1193 };
1194
1195 long mScreenOffStart;
1196 private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
1197 public void onReceive(Context context, Intent intent) {
1198 synchronized (mLocks) {
1199 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0,
1200 SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
1201 mBroadcastWakeLock.release();
1202 }
1203 }
1204 };
1205
1206 void logPointerUpEvent() {
1207 if (LOG_TOUCH_DOWNS) {
1208 mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1209 mLastTouchDown = 0;
1210 }
1211 }
1212
1213 void logPointerDownEvent() {
1214 if (LOG_TOUCH_DOWNS) {
1215 // If we are not already timing a down/up sequence
1216 if (mLastTouchDown == 0) {
1217 mLastTouchDown = SystemClock.elapsedRealtime();
1218 mTouchCycles++;
1219 }
1220 }
1221 }
1222
1223 /**
1224 * Prevents the screen from turning on even if it *should* turn on due
1225 * to a subsequent full wake lock being acquired.
1226 * <p>
1227 * This is a temporary hack that allows an activity to "cover up" any
1228 * display glitches that happen during the activity's startup
1229 * sequence. (Specifically, this API was added to work around a
1230 * cosmetic bug in the "incoming call" sequence, where the lock screen
1231 * would flicker briefly before the incoming call UI became visible.)
1232 * TODO: There ought to be a more elegant way of doing this,
1233 * probably by having the PowerManager and ActivityManager
1234 * work together to let apps specify that the screen on/off
1235 * state should be synchronized with the Activity lifecycle.
1236 * <p>
1237 * Note that calling preventScreenOn(true) will NOT turn the screen
1238 * off if it's currently on. (This API only affects *future*
1239 * acquisitions of full wake locks.)
1240 * But calling preventScreenOn(false) WILL turn the screen on if
1241 * it's currently off because of a prior preventScreenOn(true) call.
1242 * <p>
1243 * Any call to preventScreenOn(true) MUST be followed promptly by a call
1244 * to preventScreenOn(false). In fact, if the preventScreenOn(false)
1245 * call doesn't occur within 5 seconds, we'll turn the screen back on
1246 * ourselves (and log a warning about it); this prevents a buggy app
1247 * from disabling the screen forever.)
1248 * <p>
1249 * TODO: this feature should really be controlled by a new type of poke
1250 * lock (rather than an IPowerManager call).
1251 */
1252 public void preventScreenOn(boolean prevent) {
1253 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1254
1255 synchronized (mLocks) {
1256 if (prevent) {
1257 // First of all, grab a partial wake lock to
1258 // make sure the CPU stays on during the entire
1259 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1260 mPreventScreenOnPartialLock.acquire();
1261
1262 // Post a forceReenableScreen() call (for 5 seconds in the
1263 // future) to make sure the matching preventScreenOn(false) call
1264 // has happened by then.
1265 mHandler.removeCallbacks(mForceReenableScreenTask);
1266 mHandler.postDelayed(mForceReenableScreenTask, 5000);
1267
1268 // Finally, set the flag that prevents the screen from turning on.
1269 // (Below, in setPowerState(), we'll check mPreventScreenOn and
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001270 // we *won't* call setScreenStateLocked(true) if it's set.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001271 mPreventScreenOn = true;
1272 } else {
1273 // (Re)enable the screen.
1274 mPreventScreenOn = false;
1275
1276 // We're "undoing" a the prior preventScreenOn(true) call, so we
1277 // no longer need the 5-second safeguard.
1278 mHandler.removeCallbacks(mForceReenableScreenTask);
1279
1280 // Forcibly turn on the screen if it's supposed to be on. (This
1281 // handles the case where the screen is currently off because of
1282 // a prior preventScreenOn(true) call.)
Mike Lockwoode090281422009-11-14 21:02:56 -05001283 if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 if (mSpew) {
1285 Log.d(TAG,
1286 "preventScreenOn: turning on after a prior preventScreenOn(true)!");
1287 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001288 int err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 if (err != 0) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001290 Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001291 }
1292 }
1293
1294 // Release the partial wake lock that we held during the
1295 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1296 mPreventScreenOnPartialLock.release();
1297 }
1298 }
1299 }
1300
1301 public void setScreenBrightnessOverride(int brightness) {
1302 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1303
1304 synchronized (mLocks) {
1305 if (mScreenBrightnessOverride != brightness) {
1306 mScreenBrightnessOverride = brightness;
1307 updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1308 }
1309 }
1310 }
1311
1312 /**
1313 * Sanity-check that gets called 5 seconds after any call to
1314 * preventScreenOn(true). This ensures that the original call
1315 * is followed promptly by a call to preventScreenOn(false).
1316 */
1317 private void forceReenableScreen() {
1318 // We shouldn't get here at all if mPreventScreenOn is false, since
1319 // we should have already removed any existing
1320 // mForceReenableScreenTask messages...
1321 if (!mPreventScreenOn) {
1322 Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
1323 return;
1324 }
1325
1326 // Uh oh. It's been 5 seconds since a call to
1327 // preventScreenOn(true) and we haven't re-enabled the screen yet.
1328 // This means the app that called preventScreenOn(true) is either
1329 // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
1330 // or buggy (i.e. it forgot to call preventScreenOn(false), or
1331 // crashed before doing so.)
1332
1333 // Log a warning, and forcibly turn the screen back on.
1334 Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
1335 + "Forcing the screen back on...");
1336 preventScreenOn(false);
1337 }
1338
1339 private Runnable mForceReenableScreenTask = new Runnable() {
1340 public void run() {
1341 forceReenableScreen();
1342 }
1343 };
1344
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001345 private int setScreenStateLocked(boolean on) {
1346 int err = Power.setScreenState(on);
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001347 if (err == 0) {
1348 mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
1349 if (mUseSoftwareAutoBrightness) {
1350 enableLightSensor(on);
1351 if (!on) {
1352 // make sure button and key backlights are off too
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001353 int brightnessMode = (mUseSoftwareAutoBrightness
1354 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1355 : HardwareService.BRIGHTNESS_MODE_USER);
1356 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0,
1357 brightnessMode);
1358 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0,
1359 brightnessMode);
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001360 // clear current value so we will update based on the new conditions
1361 // when the sensor is reenabled.
1362 mLightSensorValue = -1;
1363 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001364 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001365 }
1366 return err;
1367 }
1368
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 private void setPowerState(int state)
1370 {
Mike Lockwood435eb642009-12-03 08:40:18 -05001371 setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001372 }
1373
Mike Lockwood435eb642009-12-03 08:40:18 -05001374 private void setPowerState(int newState, boolean noChangeLights, int reason)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001375 {
1376 synchronized (mLocks) {
1377 int err;
1378
1379 if (mSpew) {
1380 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1381 + " newState=0x" + Integer.toHexString(newState)
Mike Lockwood435eb642009-12-03 08:40:18 -05001382 + " noChangeLights=" + noChangeLights
1383 + " reason=" + reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385
1386 if (noChangeLights) {
1387 newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1388 }
Mike Lockwood36fc3022009-08-25 16:49:06 -07001389 if (mProximitySensorActive) {
1390 // don't turn on the screen when the proximity sensor lock is held
1391 newState = (newState & ~SCREEN_BRIGHT);
1392 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001393
1394 if (batteryIsLow()) {
1395 newState |= BATTERY_LOW_BIT;
1396 } else {
1397 newState &= ~BATTERY_LOW_BIT;
1398 }
1399 if (newState == mPowerState) {
1400 return;
1401 }
Mike Lockwood3333fa42009-10-26 14:50:42 -04001402
Mike Lockwood2d7bb812009-11-15 18:12:22 -05001403 if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001404 newState |= ALL_BRIGHT;
1405 }
1406
1407 boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1408 boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1409
Mike Lockwood51b844962009-11-16 21:51:18 -05001410 if (mSpew) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001411 Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
1412 + " newState=" + newState + " noChangeLights=" + noChangeLights);
1413 Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1414 + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1415 Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1416 + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1417 Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1418 + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1419 Log.d(TAG, " oldScreenOn=" + oldScreenOn
1420 + " newScreenOn=" + newScreenOn);
1421 Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1422 + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1423 }
1424
1425 if (mPowerState != newState) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001426 updateLightsLocked(newState, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001427 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1428 }
1429
1430 if (oldScreenOn != newScreenOn) {
1431 if (newScreenOn) {
Joe Onorato128e7292009-03-24 18:41:31 -07001432 // When the user presses the power button, we need to always send out the
1433 // notification that it's going to sleep so the keyguard goes on. But
1434 // we can't do that until the screen fades out, so we don't show the keyguard
1435 // too early.
1436 if (mStillNeedSleepNotification) {
1437 sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1438 }
1439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001440 // Turn on the screen UNLESS there was a prior
1441 // preventScreenOn(true) request. (Note that the lifetime
1442 // of a single preventScreenOn() request is limited to 5
1443 // seconds to prevent a buggy app from disabling the
1444 // screen forever; see forceReenableScreen().)
1445 boolean reallyTurnScreenOn = true;
1446 if (mSpew) {
1447 Log.d(TAG, "- turning screen on... mPreventScreenOn = "
1448 + mPreventScreenOn);
1449 }
1450
1451 if (mPreventScreenOn) {
1452 if (mSpew) {
1453 Log.d(TAG, "- PREVENTING screen from really turning on!");
1454 }
1455 reallyTurnScreenOn = false;
1456 }
1457 if (reallyTurnScreenOn) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001458 err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001459 long identity = Binder.clearCallingIdentity();
1460 try {
Dianne Hackborn617f8772009-03-31 15:04:46 -07001461 mBatteryStats.noteScreenBrightness(
1462 getPreferredBrightness());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 mBatteryStats.noteScreenOn();
1464 } catch (RemoteException e) {
1465 Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
1466 } finally {
1467 Binder.restoreCallingIdentity(identity);
1468 }
1469 } else {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001470 setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001471 // But continue as if we really did turn the screen on...
1472 err = 0;
1473 }
1474
1475 mScreenOnStartTime = SystemClock.elapsedRealtime();
1476 mLastTouchDown = 0;
1477 mTotalTouchDownTime = 0;
1478 mTouchCycles = 0;
Mike Lockwood435eb642009-12-03 08:40:18 -05001479 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, reason,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 mTotalTouchDownTime, mTouchCycles);
1481 if (err == 0) {
1482 mPowerState |= SCREEN_ON_BIT;
1483 sendNotificationLocked(true, -1);
1484 }
1485 } else {
Mike Lockwood497087e32009-11-08 18:33:03 -05001486 // cancel light sensor task
1487 mHandler.removeCallbacks(mAutoBrightnessTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 mScreenOffTime = SystemClock.elapsedRealtime();
1489 long identity = Binder.clearCallingIdentity();
1490 try {
1491 mBatteryStats.noteScreenOff();
1492 } catch (RemoteException e) {
1493 Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
1494 } finally {
1495 Binder.restoreCallingIdentity(identity);
1496 }
1497 mPowerState &= ~SCREEN_ON_BIT;
Mike Lockwood435eb642009-12-03 08:40:18 -05001498 mScreenOffReason = reason;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001499 if (!mScreenBrightness.animating) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001500 err = screenOffFinishedAnimatingLocked(reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001501 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 err = 0;
1503 mLastTouchDown = 0;
1504 }
1505 }
1506 }
1507 }
1508 }
1509
Mike Lockwood435eb642009-12-03 08:40:18 -05001510 private int screenOffFinishedAnimatingLocked(int reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 // I don't think we need to check the current state here because all of these
1512 // Power.setScreenState and sendNotificationLocked can both handle being
1513 // called multiple times in the same state. -joeo
Mike Lockwood435eb642009-12-03 08:40:18 -05001514 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 mLastTouchDown = 0;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001516 int err = setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 if (mScreenOnStartTime != 0) {
1518 mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
1519 mScreenOnStartTime = 0;
1520 }
1521 if (err == 0) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001522 mScreenOffReason = reason;
1523 sendNotificationLocked(false, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001524 }
1525 return err;
1526 }
1527
1528 private boolean batteryIsLow() {
1529 return (!mIsPowered &&
1530 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1531 }
1532
The Android Open Source Project10592532009-03-18 17:39:46 -07001533 private void updateLightsLocked(int newState, int forceState) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001534 final int oldState = mPowerState;
1535 final int realDifference = (newState ^ oldState);
1536 final int difference = realDifference | forceState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 if (difference == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001538 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 }
1540
1541 int offMask = 0;
1542 int dimMask = 0;
1543 int onMask = 0;
1544
1545 int preferredBrightness = getPreferredBrightness();
1546 boolean startAnimation = false;
1547
1548 if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1549 if (ANIMATE_KEYBOARD_LIGHTS) {
1550 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1551 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001552 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1553 preferredBrightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001554 } else {
1555 mKeyboardBrightness.setTargetLocked(preferredBrightness,
Joe Onorato128e7292009-03-24 18:41:31 -07001556 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1557 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 }
1559 startAnimation = true;
1560 } else {
1561 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001562 offMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001564 onMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001565 }
1566 }
1567 }
1568
1569 if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1570 if (ANIMATE_BUTTON_LIGHTS) {
1571 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1572 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001573 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1574 preferredBrightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 } else {
1576 mButtonBrightness.setTargetLocked(preferredBrightness,
Joe Onorato128e7292009-03-24 18:41:31 -07001577 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1578 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 }
1580 startAnimation = true;
1581 } else {
1582 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001583 offMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001585 onMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001586 }
1587 }
1588 }
1589
1590 if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1591 if (ANIMATE_SCREEN_LIGHTS) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001592 int nominalCurrentValue = -1;
1593 // If there was an actual difference in the light state, then
1594 // figure out the "ideal" current value based on the previous
1595 // state. Otherwise, this is a change due to the brightness
1596 // override, so we want to animate from whatever the current
1597 // value is.
1598 if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1599 switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
1600 case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
1601 nominalCurrentValue = preferredBrightness;
1602 break;
1603 case SCREEN_ON_BIT:
1604 nominalCurrentValue = Power.BRIGHTNESS_DIM;
1605 break;
1606 case 0:
1607 nominalCurrentValue = Power.BRIGHTNESS_OFF;
1608 break;
1609 case SCREEN_BRIGHT_BIT:
1610 default:
1611 // not possible
1612 nominalCurrentValue = (int)mScreenBrightness.curValue;
1613 break;
1614 }
Joe Onorato128e7292009-03-24 18:41:31 -07001615 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001616 int brightness = preferredBrightness;
1617 int steps = ANIM_STEPS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1619 // dim or turn off backlight, depending on if the screen is on
1620 // the scale is because the brightness ramp isn't linear and this biases
1621 // it so the later parts take longer.
1622 final float scale = 1.5f;
1623 float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
1624 if (ratio > 1.0f) ratio = 1.0f;
1625 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
1627 // was bright
1628 steps = ANIM_STEPS;
1629 } else {
1630 // was dim
1631 steps = (int)(ANIM_STEPS*ratio*scale);
1632 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001633 brightness = Power.BRIGHTNESS_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 if ((oldState & SCREEN_ON_BIT) != 0) {
1636 // was bright
1637 steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
1638 } else {
1639 // was dim
1640 steps = (int)(ANIM_STEPS*ratio);
1641 }
1642 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
1643 // If the "stay on while plugged in" option is
1644 // turned on, then the screen will often not
1645 // automatically turn off while plugged in. To
1646 // still have a sense of when it is inactive, we
1647 // will then count going dim as turning off.
1648 mScreenOffTime = SystemClock.elapsedRealtime();
1649 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001650 brightness = Power.BRIGHTNESS_DIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001653 long identity = Binder.clearCallingIdentity();
1654 try {
1655 mBatteryStats.noteScreenBrightness(brightness);
1656 } catch (RemoteException e) {
1657 // Nothing interesting to do.
1658 } finally {
1659 Binder.restoreCallingIdentity(identity);
1660 }
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001661 if (mScreenBrightness.setTargetLocked(brightness,
1662 steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
1663 startAnimation = true;
1664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 } else {
1666 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1667 // dim or turn off backlight, depending on if the screen is on
1668 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001669 offMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001671 dimMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001672 }
1673 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001674 onMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 }
1676 }
1677 }
1678
1679 if (startAnimation) {
1680 if (mSpew) {
1681 Log.i(TAG, "Scheduling light animator!");
1682 }
1683 mHandler.removeCallbacks(mLightAnimator);
1684 mHandler.post(mLightAnimator);
1685 }
1686
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 if (offMask != 0) {
1688 //Log.i(TAG, "Setting brightess off: " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001689 setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 }
1691 if (dimMask != 0) {
1692 int brightness = Power.BRIGHTNESS_DIM;
1693 if ((newState & BATTERY_LOW_BIT) != 0 &&
1694 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1695 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1696 }
1697 //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001698 setLightBrightness(dimMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001699 }
1700 if (onMask != 0) {
1701 int brightness = getPreferredBrightness();
1702 if ((newState & BATTERY_LOW_BIT) != 0 &&
1703 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1704 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1705 }
1706 //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001707 setLightBrightness(onMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001710
The Android Open Source Project10592532009-03-18 17:39:46 -07001711 private void setLightBrightness(int mask, int value) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001712 int brightnessMode = (mAutoBrightessEnabled
1713 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1714 : HardwareService.BRIGHTNESS_MODE_USER);
The Android Open Source Project10592532009-03-18 17:39:46 -07001715 if ((mask & SCREEN_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001716 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value,
1717 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001718 }
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001719 brightnessMode = (mUseSoftwareAutoBrightness
1720 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1721 : HardwareService.BRIGHTNESS_MODE_USER);
The Android Open Source Project10592532009-03-18 17:39:46 -07001722 if ((mask & BUTTON_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001723 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value,
1724 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001725 }
1726 if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001727 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value,
1728 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001730 }
1731
1732 class BrightnessState {
1733 final int mask;
1734
1735 boolean initialized;
1736 int targetValue;
1737 float curValue;
1738 float delta;
1739 boolean animating;
1740
1741 BrightnessState(int m) {
1742 mask = m;
1743 }
1744
1745 public void dump(PrintWriter pw, String prefix) {
1746 pw.println(prefix + "animating=" + animating
1747 + " targetValue=" + targetValue
1748 + " curValue=" + curValue
1749 + " delta=" + delta);
1750 }
1751
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001752 boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
Joe Onorato128e7292009-03-24 18:41:31 -07001753 int nominalCurrentValue) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001754 if (!initialized) {
1755 initialized = true;
1756 curValue = (float)initialValue;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001757 } else if (targetValue == target) {
1758 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001759 }
1760 targetValue = target;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001761 delta = (targetValue -
1762 (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
1763 / stepsToTarget;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001764 if (mSpew) {
Joe Onorato128e7292009-03-24 18:41:31 -07001765 String noticeMe = nominalCurrentValue == curValue ? "" : " ******************";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001766 Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
Joe Onorato128e7292009-03-24 18:41:31 -07001767 + " target=" + targetValue + " delta=" + delta
1768 + " nominalCurrentValue=" + nominalCurrentValue
1769 + noticeMe);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
1771 animating = true;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001772 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 }
1774
1775 boolean stepLocked() {
1776 if (!animating) return false;
1777 if (false && mSpew) {
1778 Log.i(TAG, "Step target " + mask + ": cur=" + curValue
1779 + " target=" + targetValue + " delta=" + delta);
1780 }
1781 curValue += delta;
1782 int curIntValue = (int)curValue;
1783 boolean more = true;
1784 if (delta == 0) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001785 curValue = curIntValue = targetValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001786 more = false;
1787 } else if (delta > 0) {
1788 if (curIntValue >= targetValue) {
1789 curValue = curIntValue = targetValue;
1790 more = false;
1791 }
1792 } else {
1793 if (curIntValue <= targetValue) {
1794 curValue = curIntValue = targetValue;
1795 more = false;
1796 }
1797 }
1798 //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001799 setLightBrightness(mask, curIntValue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 animating = more;
1801 if (!more) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001802 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
Mike Lockwood435eb642009-12-03 08:40:18 -05001803 screenOffFinishedAnimatingLocked(mScreenOffReason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 }
1805 }
1806 return more;
1807 }
1808 }
1809
1810 private class LightAnimator implements Runnable {
1811 public void run() {
1812 synchronized (mLocks) {
1813 long now = SystemClock.uptimeMillis();
1814 boolean more = mScreenBrightness.stepLocked();
1815 if (mKeyboardBrightness.stepLocked()) {
1816 more = true;
1817 }
1818 if (mButtonBrightness.stepLocked()) {
1819 more = true;
1820 }
1821 if (more) {
1822 mHandler.postAtTime(mLightAnimator, now+(1000/60));
1823 }
1824 }
1825 }
1826 }
1827
1828 private int getPreferredBrightness() {
1829 try {
1830 if (mScreenBrightnessOverride >= 0) {
1831 return mScreenBrightnessOverride;
Mike Lockwood27c6dd72009-11-04 08:57:07 -05001832 } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness
1833 && mAutoBrightessEnabled) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001834 return mLightSensorBrightness;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001835 }
1836 final int brightness = Settings.System.getInt(mContext.getContentResolver(),
1837 SCREEN_BRIGHTNESS);
1838 // Don't let applications turn the screen all the way off
1839 return Math.max(brightness, Power.BRIGHTNESS_DIM);
1840 } catch (SettingNotFoundException snfe) {
1841 return Power.BRIGHTNESS_ON;
1842 }
1843 }
1844
Charles Mendis322591c2009-10-29 11:06:59 -07001845 public boolean isScreenOn() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001846 synchronized (mLocks) {
1847 return (mPowerState & SCREEN_ON_BIT) != 0;
1848 }
1849 }
1850
Charles Mendis322591c2009-10-29 11:06:59 -07001851 boolean isScreenBright() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001852 synchronized (mLocks) {
1853 return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
1854 }
1855 }
1856
Mike Lockwood497087e32009-11-08 18:33:03 -05001857 private boolean isScreenTurningOffLocked() {
1858 return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
1859 }
1860
Mike Lockwood200b30b2009-09-20 00:23:59 -04001861 private void forceUserActivityLocked() {
Mike Lockwoode090281422009-11-14 21:02:56 -05001862 if (isScreenTurningOffLocked()) {
1863 // cancel animation so userActivity will succeed
1864 mScreenBrightness.animating = false;
1865 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04001866 boolean savedActivityAllowed = mUserActivityAllowed;
1867 mUserActivityAllowed = true;
1868 userActivity(SystemClock.uptimeMillis(), false);
1869 mUserActivityAllowed = savedActivityAllowed;
1870 }
1871
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001872 public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
1873 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1874 userActivity(time, noChangeLights, OTHER_EVENT, force);
1875 }
1876
1877 public void userActivity(long time, boolean noChangeLights) {
1878 userActivity(time, noChangeLights, OTHER_EVENT, false);
1879 }
1880
1881 public void userActivity(long time, boolean noChangeLights, int eventType) {
1882 userActivity(time, noChangeLights, eventType, false);
1883 }
1884
1885 public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
1886 //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1887
1888 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001889 && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001890 if (false) {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001891 Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001892 }
1893 return;
1894 }
1895
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001896 if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
1897 && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
1898 || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
1899 if (false) {
1900 Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
1901 }
1902 return;
1903 }
1904
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001905 if (false) {
1906 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
1907 Log.d(TAG, "userActivity !!!");//, new RuntimeException());
1908 } else {
1909 Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
1910 }
1911 }
1912
1913 synchronized (mLocks) {
1914 if (mSpew) {
1915 Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
1916 + " mUserActivityAllowed=" + mUserActivityAllowed
1917 + " mUserState=0x" + Integer.toHexString(mUserState)
Mike Lockwood36fc3022009-08-25 16:49:06 -07001918 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
1919 + " mProximitySensorActive=" + mProximitySensorActive
1920 + " force=" + force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001921 }
Mike Lockwood05067122009-10-27 23:07:25 -04001922 // ignore user activity if we are in the process of turning off the screen
Mike Lockwood497087e32009-11-08 18:33:03 -05001923 if (isScreenTurningOffLocked()) {
Mike Lockwood05067122009-10-27 23:07:25 -04001924 Log.d(TAG, "ignoring user activity while turning off screen");
1925 return;
1926 }
Mike Lockwood0e39ea82009-11-18 15:37:10 -05001927 // Disable proximity sensor if if user presses power key while we are in the
1928 // "waiting for proximity sensor to go negative" state.
1929 if (mProximitySensorActive && mProximityWakeLockCount == 0) {
1930 mProximitySensorActive = false;
1931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001932 if (mLastEventTime <= time || force) {
1933 mLastEventTime = time;
Mike Lockwood36fc3022009-08-25 16:49:06 -07001934 if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001935 // Only turn on button backlights if a button was pressed
1936 // and auto brightness is disabled
Mike Lockwood4984e732009-11-01 08:16:33 -05001937 if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001938 mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
1939 } else {
1940 // don't clear button/keyboard backlights when the screen is touched.
1941 mUserState |= SCREEN_BRIGHT;
1942 }
1943
Dianne Hackborn617f8772009-03-31 15:04:46 -07001944 int uid = Binder.getCallingUid();
1945 long ident = Binder.clearCallingIdentity();
1946 try {
1947 mBatteryStats.noteUserActivity(uid, eventType);
1948 } catch (RemoteException e) {
1949 // Ignore
1950 } finally {
1951 Binder.restoreCallingIdentity(ident);
1952 }
1953
Michael Chane96440f2009-05-06 10:27:36 -07001954 mWakeLockState = mLocks.reactivateScreenLocksLocked();
Mike Lockwood435eb642009-12-03 08:40:18 -05001955 setPowerState(mUserState | mWakeLockState, noChangeLights,
1956 WindowManagerPolicy.OFF_BECAUSE_OF_USER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001957 setTimeoutLocked(time, SCREEN_BRIGHT);
1958 }
1959 }
1960 }
1961 }
1962
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001963 private int getAutoBrightnessValue(int sensorValue, int[] values) {
1964 try {
1965 int i;
1966 for (i = 0; i < mAutoBrightnessLevels.length; i++) {
1967 if (sensorValue < mAutoBrightnessLevels[i]) {
1968 break;
1969 }
1970 }
1971 return values[i];
1972 } catch (Exception e) {
1973 // guard against null pointer or index out of bounds errors
1974 Log.e(TAG, "getAutoBrightnessValue", e);
1975 return 255;
1976 }
1977 }
1978
Mike Lockwood20f87d72009-11-05 16:08:51 -05001979 private Runnable mProximityTask = new Runnable() {
1980 public void run() {
1981 synchronized (mLocks) {
1982 if (mProximityPendingValue != -1) {
1983 proximityChangedLocked(mProximityPendingValue == 1);
1984 mProximityPendingValue = -1;
1985 }
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05001986 if (mProximityPartialLock.isHeld()) {
1987 mProximityPartialLock.release();
1988 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05001989 }
1990 }
1991 };
1992
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001993 private Runnable mAutoBrightnessTask = new Runnable() {
1994 public void run() {
Mike Lockwoodfa68ab42009-10-20 11:08:49 -04001995 synchronized (mLocks) {
1996 int value = (int)mLightSensorPendingValue;
1997 if (value >= 0) {
1998 mLightSensorPendingValue = -1;
1999 lightSensorChangedLocked(value);
2000 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002001 }
2002 }
2003 };
2004
2005 private void lightSensorChangedLocked(int value) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002006 if (mDebugLightSensor) {
2007 Log.d(TAG, "lightSensorChangedLocked " + value);
2008 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002009
2010 if (mLightSensorValue != value) {
2011 mLightSensorValue = value;
2012 if ((mPowerState & BATTERY_LOW_BIT) == 0) {
2013 int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
2014 int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
Mike Lockwooddf024922009-10-29 21:29:15 -04002015 int keyboardValue;
2016 if (mKeyboardVisible) {
2017 keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
2018 } else {
2019 keyboardValue = 0;
2020 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002021 mLightSensorBrightness = lcdValue;
2022
2023 if (mDebugLightSensor) {
2024 Log.d(TAG, "lcdValue " + lcdValue);
2025 Log.d(TAG, "buttonValue " + buttonValue);
2026 Log.d(TAG, "keyboardValue " + keyboardValue);
2027 }
2028
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002029 boolean startAnimation = false;
Mike Lockwood4984e732009-11-01 08:16:33 -05002030 if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002031 if (ANIMATE_SCREEN_LIGHTS) {
2032 if (mScreenBrightness.setTargetLocked(lcdValue,
2033 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
2034 (int)mScreenBrightness.curValue)) {
2035 startAnimation = true;
2036 }
2037 } else {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002038 int brightnessMode = (mAutoBrightessEnabled
2039 ? HardwareService.BRIGHTNESS_MODE_SENSOR
2040 : HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002041 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002042 lcdValue, brightnessMode);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002043 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002044 }
2045 if (ANIMATE_BUTTON_LIGHTS) {
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002046 if (mButtonBrightness.setTargetLocked(buttonValue,
2047 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2048 (int)mButtonBrightness.curValue)) {
2049 startAnimation = true;
2050 }
2051 } else {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002052 int brightnessMode = (mUseSoftwareAutoBrightness
2053 ? HardwareService.BRIGHTNESS_MODE_SENSOR
2054 : HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002055 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002056 buttonValue, brightnessMode);
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002057 }
2058 if (ANIMATE_KEYBOARD_LIGHTS) {
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002059 if (mKeyboardBrightness.setTargetLocked(keyboardValue,
2060 AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2061 (int)mKeyboardBrightness.curValue)) {
2062 startAnimation = true;
2063 }
2064 } else {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002065 int brightnessMode = (mUseSoftwareAutoBrightness
2066 ? HardwareService.BRIGHTNESS_MODE_SENSOR
2067 : HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002068 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002069 keyboardValue, brightnessMode);
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002070 }
2071 if (startAnimation) {
2072 if (mDebugLightSensor) {
2073 Log.i(TAG, "lightSensorChangedLocked scheduling light animator");
2074 }
2075 mHandler.removeCallbacks(mLightAnimator);
2076 mHandler.post(mLightAnimator);
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002077 }
2078 }
2079 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002080 }
2081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 /**
2083 * The user requested that we go to sleep (probably with the power button).
2084 * This overrides all wake locks that are held.
2085 */
2086 public void goToSleep(long time)
2087 {
2088 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2089 synchronized (mLocks) {
Mike Lockwood435eb642009-12-03 08:40:18 -05002090 goToSleepLocked(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002091 }
2092 }
2093
2094 /**
2095 * Returns the time the screen has been on since boot, in millis.
2096 * @return screen on time
2097 */
2098 public long getScreenOnTime() {
2099 synchronized (mLocks) {
2100 if (mScreenOnStartTime == 0) {
2101 return mScreenOnTime;
2102 } else {
2103 return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime;
2104 }
2105 }
2106 }
2107
Mike Lockwood435eb642009-12-03 08:40:18 -05002108 private void goToSleepLocked(long time, int reason) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109
2110 if (mLastEventTime <= time) {
2111 mLastEventTime = time;
2112 // cancel all of the wake locks
2113 mWakeLockState = SCREEN_OFF;
2114 int N = mLocks.size();
2115 int numCleared = 0;
2116 for (int i=0; i<N; i++) {
2117 WakeLock wl = mLocks.get(i);
2118 if (isScreenLock(wl.flags)) {
2119 mLocks.get(i).activated = false;
2120 numCleared++;
2121 }
2122 }
2123 EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
Joe Onorato128e7292009-03-24 18:41:31 -07002124 mStillNeedSleepNotification = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002125 mUserState = SCREEN_OFF;
Mike Lockwood435eb642009-12-03 08:40:18 -05002126 setPowerState(SCREEN_OFF, false, reason);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002127 cancelTimerLocked();
2128 }
2129 }
2130
2131 public long timeSinceScreenOn() {
2132 synchronized (mLocks) {
2133 if ((mPowerState & SCREEN_ON_BIT) != 0) {
2134 return 0;
2135 }
2136 return SystemClock.elapsedRealtime() - mScreenOffTime;
2137 }
2138 }
2139
2140 public void setKeyboardVisibility(boolean visible) {
Mike Lockwooda625b382009-09-12 17:36:03 -07002141 synchronized (mLocks) {
2142 if (mSpew) {
2143 Log.d(TAG, "setKeyboardVisibility: " + visible);
2144 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002145 if (mKeyboardVisible != visible) {
2146 mKeyboardVisible = visible;
2147 // don't signal user activity if the screen is off; other code
2148 // will take care of turning on due to a true change to the lid
2149 // switch and synchronized with the lock screen.
2150 if ((mPowerState & SCREEN_ON_BIT) != 0) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002151 if (mUseSoftwareAutoBrightness) {
Mike Lockwooddf024922009-10-29 21:29:15 -04002152 // force recompute of backlight values
2153 if (mLightSensorValue >= 0) {
2154 int value = (int)mLightSensorValue;
2155 mLightSensorValue = -1;
2156 lightSensorChangedLocked(value);
2157 }
2158 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002159 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2160 }
Mike Lockwooda625b382009-09-12 17:36:03 -07002161 }
2162 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002163 }
2164
2165 /**
2166 * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
Mike Lockwood50c548d2009-11-09 16:02:06 -05002167 * When disabling user activity we also reset user power state so the keyguard can reset its
2168 * short screen timeout when keyguard is unhidden.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002169 */
2170 public void enableUserActivity(boolean enabled) {
Mike Lockwood50c548d2009-11-09 16:02:06 -05002171 if (mSpew) {
2172 Log.d(TAG, "enableUserActivity " + enabled);
2173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002174 synchronized (mLocks) {
2175 mUserActivityAllowed = enabled;
Mike Lockwood50c548d2009-11-09 16:02:06 -05002176 if (!enabled) {
2177 // cancel timeout and clear mUserState so the keyguard can set a short timeout
2178 setTimeoutLocked(SystemClock.uptimeMillis(), 0);
2179 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 }
2181 }
2182
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002183 private void setScreenBrightnessMode(int mode) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002184 boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
Mike Lockwoodf90ffcc2009-11-03 11:41:27 -05002185 if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002186 mAutoBrightessEnabled = enabled;
Charles Mendis322591c2009-10-29 11:06:59 -07002187 if (isScreenOn()) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002188 // force recompute of backlight values
2189 if (mLightSensorValue >= 0) {
2190 int value = (int)mLightSensorValue;
2191 mLightSensorValue = -1;
2192 lightSensorChangedLocked(value);
2193 }
Mike Lockwood2d155d22009-10-27 09:32:30 -04002194 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002195 }
2196 }
2197
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 /** Sets the screen off timeouts:
2199 * mKeylightDelay
2200 * mDimDelay
2201 * mScreenOffDelay
2202 * */
2203 private void setScreenOffTimeoutsLocked() {
2204 if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
2205 mKeylightDelay = mShortKeylightDelay; // Configurable via Gservices
2206 mDimDelay = -1;
2207 mScreenOffDelay = 0;
2208 } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
2209 mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
2210 mDimDelay = -1;
2211 mScreenOffDelay = 0;
2212 } else {
2213 int totalDelay = mTotalDelaySetting;
2214 mKeylightDelay = LONG_KEYLIGHT_DELAY;
2215 if (totalDelay < 0) {
2216 mScreenOffDelay = Integer.MAX_VALUE;
2217 } else if (mKeylightDelay < totalDelay) {
2218 // subtract the time that the keylight delay. This will give us the
2219 // remainder of the time that we need to sleep to get the accurate
2220 // screen off timeout.
2221 mScreenOffDelay = totalDelay - mKeylightDelay;
2222 } else {
2223 mScreenOffDelay = 0;
2224 }
2225 if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
2226 mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
2227 mScreenOffDelay = LONG_DIM_TIME;
2228 } else {
2229 mDimDelay = -1;
2230 }
2231 }
2232 if (mSpew) {
2233 Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
2234 + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
2235 + " mDimScreen=" + mDimScreen);
2236 }
2237 }
2238
2239 /**
2240 * Refreshes cached Gservices settings. Called once on startup, and
2241 * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see
2242 * GservicesChangedReceiver).
2243 */
2244 private void updateGservicesValues() {
2245 mShortKeylightDelay = Settings.Gservices.getInt(
2246 mContext.getContentResolver(),
2247 Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS,
2248 SHORT_KEYLIGHT_DELAY_DEFAULT);
2249 // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay);
2250 }
2251
2252 /**
2253 * Receiver for the Gservices.CHANGED_ACTION broadcast intent,
2254 * which tells us we need to refresh our cached Gservices settings.
2255 */
2256 private class GservicesChangedReceiver extends BroadcastReceiver {
2257 @Override
2258 public void onReceive(Context context, Intent intent) {
2259 // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent);
2260 updateGservicesValues();
2261 }
2262 }
2263
2264 private class LockList extends ArrayList<WakeLock>
2265 {
2266 void addLock(WakeLock wl)
2267 {
2268 int index = getIndex(wl.binder);
2269 if (index < 0) {
2270 this.add(wl);
2271 }
2272 }
2273
2274 WakeLock removeLock(IBinder binder)
2275 {
2276 int index = getIndex(binder);
2277 if (index >= 0) {
2278 return this.remove(index);
2279 } else {
2280 return null;
2281 }
2282 }
2283
2284 int getIndex(IBinder binder)
2285 {
2286 int N = this.size();
2287 for (int i=0; i<N; i++) {
2288 if (this.get(i).binder == binder) {
2289 return i;
2290 }
2291 }
2292 return -1;
2293 }
2294
2295 int gatherState()
2296 {
2297 int result = 0;
2298 int N = this.size();
2299 for (int i=0; i<N; i++) {
2300 WakeLock wl = this.get(i);
2301 if (wl.activated) {
2302 if (isScreenLock(wl.flags)) {
2303 result |= wl.minState;
2304 }
2305 }
2306 }
2307 return result;
2308 }
Michael Chane96440f2009-05-06 10:27:36 -07002309
2310 int reactivateScreenLocksLocked()
2311 {
2312 int result = 0;
2313 int N = this.size();
2314 for (int i=0; i<N; i++) {
2315 WakeLock wl = this.get(i);
2316 if (isScreenLock(wl.flags)) {
2317 wl.activated = true;
2318 result |= wl.minState;
2319 }
2320 }
2321 return result;
2322 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002323 }
2324
2325 void setPolicy(WindowManagerPolicy p) {
2326 synchronized (mLocks) {
2327 mPolicy = p;
2328 mLocks.notifyAll();
2329 }
2330 }
2331
2332 WindowManagerPolicy getPolicyLocked() {
2333 while (mPolicy == null || !mDoneBooting) {
2334 try {
2335 mLocks.wait();
2336 } catch (InterruptedException e) {
2337 // Ignore
2338 }
2339 }
2340 return mPolicy;
2341 }
2342
2343 void systemReady() {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002344 mSensorManager = new SensorManager(mHandlerThread.getLooper());
2345 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
2346 // don't bother with the light sensor if auto brightness is handled in hardware
Mike Lockwoodaa66ea82009-10-31 16:31:27 -04002347 if (mUseSoftwareAutoBrightness) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002348 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
Mike Lockwood4984e732009-11-01 08:16:33 -05002349 enableLightSensor(true);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002350 }
2351
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002352 synchronized (mLocks) {
2353 Log.d(TAG, "system ready!");
2354 mDoneBooting = true;
Dianne Hackborn617f8772009-03-31 15:04:46 -07002355 long identity = Binder.clearCallingIdentity();
2356 try {
2357 mBatteryStats.noteScreenBrightness(getPreferredBrightness());
2358 mBatteryStats.noteScreenOn();
2359 } catch (RemoteException e) {
2360 // Nothing interesting to do.
2361 } finally {
2362 Binder.restoreCallingIdentity(identity);
2363 }
Mike Lockwood2d7bb812009-11-15 18:12:22 -05002364 }
2365 }
2366
2367 void bootCompleted() {
2368 Log.d(TAG, "bootCompleted");
2369 synchronized (mLocks) {
2370 mBootCompleted = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2372 updateWakeLockLocked();
2373 mLocks.notifyAll();
2374 }
2375 }
2376
2377 public void monitor() {
2378 synchronized (mLocks) { }
2379 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002380
2381 public int getSupportedWakeLockFlags() {
2382 int result = PowerManager.PARTIAL_WAKE_LOCK
2383 | PowerManager.FULL_WAKE_LOCK
2384 | PowerManager.SCREEN_DIM_WAKE_LOCK;
2385
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002386 if (mProximitySensor != null) {
2387 result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
2388 }
2389
2390 return result;
2391 }
2392
Mike Lockwood237a2992009-09-15 14:42:16 -04002393 public void setBacklightBrightness(int brightness) {
2394 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2395 // Don't let applications turn the screen all the way off
2396 brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002397 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness,
2398 HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwooddf024922009-10-29 21:29:15 -04002399 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002400 (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);
2401 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness,
2402 HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwood237a2992009-09-15 14:42:16 -04002403 long identity = Binder.clearCallingIdentity();
2404 try {
2405 mBatteryStats.noteScreenBrightness(brightness);
2406 } catch (RemoteException e) {
2407 Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2408 } finally {
2409 Binder.restoreCallingIdentity(identity);
2410 }
2411
2412 // update our animation state
2413 if (ANIMATE_SCREEN_LIGHTS) {
2414 mScreenBrightness.curValue = brightness;
2415 mScreenBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002416 mScreenBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002417 }
2418 if (ANIMATE_KEYBOARD_LIGHTS) {
2419 mKeyboardBrightness.curValue = brightness;
2420 mKeyboardBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002421 mKeyboardBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002422 }
2423 if (ANIMATE_BUTTON_LIGHTS) {
2424 mButtonBrightness.curValue = brightness;
2425 mButtonBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002426 mButtonBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002427 }
2428 }
2429
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002430 private void enableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002431 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002432 Log.d(TAG, "enableProximityLockLocked");
2433 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002434 if (!mProximitySensorEnabled) {
2435 // clear calling identity so sensor manager battery stats are accurate
2436 long identity = Binder.clearCallingIdentity();
2437 try {
2438 mSensorManager.registerListener(mProximityListener, mProximitySensor,
2439 SensorManager.SENSOR_DELAY_NORMAL);
2440 mProximitySensorEnabled = true;
2441 } finally {
2442 Binder.restoreCallingIdentity(identity);
2443 }
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002444 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002445 }
2446
2447 private void disableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002448 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002449 Log.d(TAG, "disableProximityLockLocked");
2450 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002451 if (mProximitySensorEnabled) {
2452 // clear calling identity so sensor manager battery stats are accurate
2453 long identity = Binder.clearCallingIdentity();
2454 try {
2455 mSensorManager.unregisterListener(mProximityListener);
2456 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002457 if (mProximityPartialLock.isHeld()) {
2458 mProximityPartialLock.release();
2459 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002460 mProximitySensorEnabled = false;
2461 } finally {
2462 Binder.restoreCallingIdentity(identity);
2463 }
2464 if (mProximitySensorActive) {
2465 mProximitySensorActive = false;
2466 forceUserActivityLocked();
2467 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04002468 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002469 }
2470
Mike Lockwood20f87d72009-11-05 16:08:51 -05002471 private void proximityChangedLocked(boolean active) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002472 if (mDebugProximitySensor) {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002473 Log.d(TAG, "proximityChangedLocked, active: " + active);
2474 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002475 if (!mProximitySensorEnabled) {
2476 Log.d(TAG, "Ignoring proximity change after sensor is disabled");
Mike Lockwood0d72f7e2009-11-05 20:53:00 -05002477 return;
2478 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002479 if (active) {
Mike Lockwood435eb642009-12-03 08:40:18 -05002480 goToSleepLocked(SystemClock.uptimeMillis(),
2481 WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
Mike Lockwood20f87d72009-11-05 16:08:51 -05002482 mProximitySensorActive = true;
2483 } else {
2484 // proximity sensor negative events trigger as user activity.
2485 // temporarily set mUserActivityAllowed to true so this will work
2486 // even when the keyguard is on.
2487 mProximitySensorActive = false;
2488 forceUserActivityLocked();
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002489
2490 if (mProximityWakeLockCount == 0) {
2491 // disable sensor if we have no listeners left after proximity negative
2492 disableProximityLockLocked();
2493 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002494 }
2495 }
2496
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002497 private void enableLightSensor(boolean enable) {
2498 if (mDebugLightSensor) {
2499 Log.d(TAG, "enableLightSensor " + enable);
2500 }
2501 if (mSensorManager != null && mLightSensorEnabled != enable) {
2502 mLightSensorEnabled = enable;
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002503 // clear calling identity so sensor manager battery stats are accurate
2504 long identity = Binder.clearCallingIdentity();
2505 try {
2506 if (enable) {
2507 mSensorManager.registerListener(mLightListener, mLightSensor,
2508 SensorManager.SENSOR_DELAY_NORMAL);
2509 } else {
2510 mSensorManager.unregisterListener(mLightListener);
2511 mHandler.removeCallbacks(mAutoBrightnessTask);
2512 }
2513 } finally {
2514 Binder.restoreCallingIdentity(identity);
Mike Lockwood06952d92009-08-13 16:05:38 -04002515 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002516 }
2517 }
2518
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002519 SensorEventListener mProximityListener = new SensorEventListener() {
2520 public void onSensorChanged(SensorEvent event) {
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002521 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002522 synchronized (mLocks) {
2523 float distance = event.values[0];
Mike Lockwood20f87d72009-11-05 16:08:51 -05002524 long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
2525 mLastProximityEventTime = milliseconds;
2526 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002527 boolean proximityTaskQueued = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -05002528
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002529 // compare against getMaximumRange to support sensors that only return 0 or 1
Mike Lockwood20f87d72009-11-05 16:08:51 -05002530 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
2531 distance < mProximitySensor.getMaximumRange());
2532
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002533 if (mDebugProximitySensor) {
2534 Log.d(TAG, "mProximityListener.onSensorChanged active: " + active);
2535 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002536 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
2537 // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
2538 mProximityPendingValue = (active ? 1 : 0);
2539 mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002540 proximityTaskQueued = true;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002541 } else {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002542 // process the value immediately
2543 mProximityPendingValue = -1;
2544 proximityChangedLocked(active);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002545 }
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002546
2547 // update mProximityPartialLock state
2548 boolean held = mProximityPartialLock.isHeld();
2549 if (!held && proximityTaskQueued) {
2550 // hold wakelock until mProximityTask runs
2551 mProximityPartialLock.acquire();
2552 } else if (held && !proximityTaskQueued) {
2553 mProximityPartialLock.release();
2554 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002555 }
2556 }
2557
2558 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2559 // ignore
2560 }
2561 };
2562
2563 SensorEventListener mLightListener = new SensorEventListener() {
2564 public void onSensorChanged(SensorEvent event) {
2565 synchronized (mLocks) {
Mike Lockwood497087e32009-11-08 18:33:03 -05002566 // ignore light sensor while screen is turning off
2567 if (isScreenTurningOffLocked()) {
2568 return;
2569 }
2570
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002571 int value = (int)event.values[0];
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002572 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002573 if (mDebugLightSensor) {
2574 Log.d(TAG, "onSensorChanged: light value: " + value);
2575 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002576 mHandler.removeCallbacks(mAutoBrightnessTask);
2577 if (mLightSensorValue != value) {
Mike Lockwood20ee6f22009-11-07 20:33:47 -05002578 if (mLightSensorValue == -1 ||
2579 milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
2580 // process the value immediately if screen has just turned on
Mike Lockwood6c97fca2009-10-20 08:10:00 -04002581 lightSensorChangedLocked(value);
2582 } else {
2583 // delay processing to debounce the sensor
2584 mLightSensorPendingValue = value;
2585 mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
2586 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002587 } else {
2588 mLightSensorPendingValue = -1;
2589 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002590 }
2591 }
2592
2593 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2594 // ignore
2595 }
2596 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002597}