blob: 0e22f863d4b9cff4da7e9c349edb2c8a2ff9f940 [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;
Doug Zongker50a21f42009-11-19 12:49:53 -080062import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import java.io.PrintWriter;
64import java.util.ArrayList;
65import java.util.HashMap;
66import java.util.Observable;
67import java.util.Observer;
68
Mike Lockwoodbc706a02009-07-27 13:50:57 -070069class PowerManagerService extends IPowerManager.Stub
Mike Lockwood8738e0c2009-10-04 08:44:47 -040070 implements LocalPowerManager, Watchdog.Monitor {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
72 private static final String TAG = "PowerManagerService";
73 static final String PARTIAL_NAME = "PowerManagerService";
74
75 private static final boolean LOG_PARTIAL_WL = false;
76
77 // Indicates whether touch-down cycles should be logged as part of the
78 // LOG_POWER_SCREEN_STATE log events
79 private static final boolean LOG_TOUCH_DOWNS = true;
80
81 private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
82 | PowerManager.SCREEN_DIM_WAKE_LOCK
83 | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
Mike Lockwoodbc706a02009-07-27 13:50:57 -070084 | PowerManager.FULL_WAKE_LOCK
85 | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086
87 // time since last state: time since last event:
88 // The short keylight delay comes from Gservices; this is the default.
89 private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
90 private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
91 private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
92 private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
93
Mike Lockwoodd7786b42009-10-15 17:09:16 -070094 // How long to wait to debounce light sensor changes.
Mike Lockwood9b8136922009-11-06 15:53:59 -050095 private static final int LIGHT_SENSOR_DELAY = 2000;
Mike Lockwoodd7786b42009-10-15 17:09:16 -070096
Mike Lockwood20f87d72009-11-05 16:08:51 -050097 // For debouncing the proximity sensor.
98 private static final int PROXIMITY_SENSOR_DELAY = 1000;
99
Mike Lockwoodd20ea362009-09-15 00:13:38 -0400100 // trigger proximity if distance is less than 5 cm
101 private static final float PROXIMITY_THRESHOLD = 5.0f;
102
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 // Cached Gservices settings; see updateGservicesValues()
104 private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
105
106 // flags for setPowerState
107 private static final int SCREEN_ON_BIT = 0x00000001;
108 private static final int SCREEN_BRIGHT_BIT = 0x00000002;
109 private static final int BUTTON_BRIGHT_BIT = 0x00000004;
110 private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
111 private static final int BATTERY_LOW_BIT = 0x00000010;
112
113 // values for setPowerState
114
115 // SCREEN_OFF == everything off
116 private static final int SCREEN_OFF = 0x00000000;
117
118 // SCREEN_DIM == screen on, screen backlight dim
119 private static final int SCREEN_DIM = SCREEN_ON_BIT;
120
121 // SCREEN_BRIGHT == screen on, screen backlight bright
122 private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
123
124 // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
125 private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
126
127 // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
128 private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
129
130 // used for noChangeLights in setPowerState()
131 private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
132
133 static final boolean ANIMATE_SCREEN_LIGHTS = true;
134 static final boolean ANIMATE_BUTTON_LIGHTS = false;
135 static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
136
137 static final int ANIM_STEPS = 60/4;
Mike Lockwooddd9668e2009-10-27 15:47:02 -0400138 // Slower animation for autobrightness changes
139 static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140
141 // These magic numbers are the initial state of the LEDs at boot. Ideally
142 // we should read them from the driver, but our current hardware returns 0
143 // for the initial value. Oops!
144 static final int INITIAL_SCREEN_BRIGHTNESS = 255;
145 static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
146 static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
147
148 static final int LOG_POWER_SLEEP_REQUESTED = 2724;
149 static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725;
150 static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726;
151 static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727;
152 static final int LOG_POWER_SCREEN_STATE = 2728;
153 static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729;
154
155 private final int MY_UID;
156
157 private boolean mDoneBooting = false;
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500158 private boolean mBootCompleted = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 private int mStayOnConditions = 0;
Joe Onorato128e7292009-03-24 18:41:31 -0700160 private int[] mBroadcastQueue = new int[] { -1, -1, -1 };
161 private int[] mBroadcastWhy = new int[3];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 private int mPartialCount = 0;
163 private int mPowerState;
164 private boolean mOffBecauseOfUser;
165 private int mUserState;
166 private boolean mKeyboardVisible = false;
167 private boolean mUserActivityAllowed = true;
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500168 private int mProximityWakeLockCount = 0;
169 private boolean mProximitySensorEnabled = false;
Mike Lockwood36fc3022009-08-25 16:49:06 -0700170 private boolean mProximitySensorActive = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -0500171 private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
172 private long mLastProximityEventTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 private int mTotalDelaySetting;
174 private int mKeylightDelay;
175 private int mDimDelay;
176 private int mScreenOffDelay;
177 private int mWakeLockState;
178 private long mLastEventTime = 0;
179 private long mScreenOffTime;
180 private volatile WindowManagerPolicy mPolicy;
181 private final LockList mLocks = new LockList();
182 private Intent mScreenOffIntent;
183 private Intent mScreenOnIntent;
The Android Open Source Project10592532009-03-18 17:39:46 -0700184 private HardwareService mHardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800185 private Context mContext;
186 private UnsynchronizedWakeLock mBroadcastWakeLock;
187 private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
188 private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
189 private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500190 private UnsynchronizedWakeLock mProximityPartialLock;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800191 private HandlerThread mHandlerThread;
192 private Handler mHandler;
193 private TimeoutTask mTimeoutTask = new TimeoutTask();
194 private LightAnimator mLightAnimator = new LightAnimator();
195 private final BrightnessState mScreenBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700196 = new BrightnessState(SCREEN_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 private final BrightnessState mKeyboardBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700198 = new BrightnessState(KEYBOARD_BRIGHT_BIT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 private final BrightnessState mButtonBrightness
The Android Open Source Project10592532009-03-18 17:39:46 -0700200 = new BrightnessState(BUTTON_BRIGHT_BIT);
Joe Onorato128e7292009-03-24 18:41:31 -0700201 private boolean mStillNeedSleepNotification;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 private boolean mIsPowered = false;
203 private IActivityManager mActivityService;
204 private IBatteryStats mBatteryStats;
205 private BatteryService mBatteryService;
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700206 private SensorManager mSensorManager;
207 private Sensor mProximitySensor;
Mike Lockwood8738e0c2009-10-04 08:44:47 -0400208 private Sensor mLightSensor;
209 private boolean mLightSensorEnabled;
210 private float mLightSensorValue = -1;
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700211 private float mLightSensorPendingValue = -1;
212 private int mLightSensorBrightness = -1;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 private boolean mDimScreen = true;
214 private long mNextTimeout;
215 private volatile int mPokey = 0;
216 private volatile boolean mPokeAwakeOnSet = false;
217 private volatile boolean mInitComplete = false;
218 private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500219 // mScreenOnTime and mScreenOnStartTime are used for computing total time screen
220 // has been on since boot
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 private long mScreenOnTime;
222 private long mScreenOnStartTime;
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500223 // mLastScreenOnTime is the time the screen was last turned on
224 private long mLastScreenOnTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 private boolean mPreventScreenOn;
226 private int mScreenBrightnessOverride = -1;
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400227 private boolean mUseSoftwareAutoBrightness;
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700228 private boolean mAutoBrightessEnabled;
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700229 private int[] mAutoBrightnessLevels;
230 private int[] mLcdBacklightValues;
231 private int[] mButtonBacklightValues;
232 private int[] mKeyboardBacklightValues;
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500233 private int mLightSensorWarmupTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800234
235 // Used when logging number and duration of touch-down cycles
236 private long mTotalTouchDownTime;
237 private long mLastTouchDown;
238 private int mTouchCycles;
239
240 // could be either static or controllable at runtime
241 private static final boolean mSpew = false;
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500242 private static final boolean mDebugProximitySensor = (true || mSpew);
Mike Lockwooddd9668e2009-10-27 15:47:02 -0400243 private static final boolean mDebugLightSensor = (false || mSpew);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244
245 /*
246 static PrintStream mLog;
247 static {
248 try {
249 mLog = new PrintStream("/data/power.log");
250 }
251 catch (FileNotFoundException e) {
252 android.util.Log.e(TAG, "Life is hard", e);
253 }
254 }
255 static class Log {
256 static void d(String tag, String s) {
257 mLog.println(s);
258 android.util.Log.d(tag, s);
259 }
260 static void i(String tag, String s) {
261 mLog.println(s);
262 android.util.Log.i(tag, s);
263 }
264 static void w(String tag, String s) {
265 mLog.println(s);
266 android.util.Log.w(tag, s);
267 }
268 static void e(String tag, String s) {
269 mLog.println(s);
270 android.util.Log.e(tag, s);
271 }
272 }
273 */
274
275 /**
276 * This class works around a deadlock between the lock in PowerManager.WakeLock
277 * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its
278 * mToken object so it can be accessed from any thread, but it calls into here
279 * with its lock held. This class is essentially a reimplementation of
280 * PowerManager.WakeLock, but without that extra synchronized block, because we'll
281 * only call it with our own locks held.
282 */
283 private class UnsynchronizedWakeLock {
284 int mFlags;
285 String mTag;
286 IBinder mToken;
287 int mCount = 0;
288 boolean mRefCounted;
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500289 boolean mHeld;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290
291 UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
292 mFlags = flags;
293 mTag = tag;
294 mToken = new Binder();
295 mRefCounted = refCounted;
296 }
297
298 public void acquire() {
299 if (!mRefCounted || mCount++ == 0) {
300 long ident = Binder.clearCallingIdentity();
301 try {
302 PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
303 MY_UID, mTag);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500304 mHeld = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 } finally {
306 Binder.restoreCallingIdentity(ident);
307 }
308 }
309 }
310
311 public void release() {
312 if (!mRefCounted || --mCount == 0) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500313 PowerManagerService.this.releaseWakeLockLocked(mToken, 0, false);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500314 mHeld = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 }
316 if (mCount < 0) {
317 throw new RuntimeException("WakeLock under-locked " + mTag);
318 }
319 }
320
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500321 public boolean isHeld()
322 {
323 return mHeld;
324 }
325
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 public String toString() {
327 return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500328 + " mCount=" + mCount + " mHeld=" + mHeld + ")";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 }
330 }
331
332 private final class BatteryReceiver extends BroadcastReceiver {
333 @Override
334 public void onReceive(Context context, Intent intent) {
335 synchronized (mLocks) {
336 boolean wasPowered = mIsPowered;
337 mIsPowered = mBatteryService.isPowered();
338
339 if (mIsPowered != wasPowered) {
340 // update mStayOnWhilePluggedIn wake lock
341 updateWakeLockLocked();
342
343 // treat plugging and unplugging the devices as a user activity.
344 // users find it disconcerting when they unplug the device
345 // and it shuts off right away.
346 // temporarily set mUserActivityAllowed to true so this will work
347 // even when the keyguard is on.
348 synchronized (mLocks) {
Mike Lockwood200b30b2009-09-20 00:23:59 -0400349 forceUserActivityLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351 }
352 }
353 }
354 }
355
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500356 private final class BootCompletedReceiver extends BroadcastReceiver {
357 @Override
358 public void onReceive(Context context, Intent intent) {
359 bootCompleted();
360 }
361 }
362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 /**
364 * Set the setting that determines whether the device stays on when plugged in.
365 * The argument is a bit string, with each bit specifying a power source that,
366 * when the device is connected to that source, causes the device to stay on.
367 * See {@link android.os.BatteryManager} for the list of power sources that
368 * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
369 * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
370 * @param val an {@code int} containing the bits that specify which power sources
371 * should cause the device to stay on.
372 */
373 public void setStayOnSetting(int val) {
374 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
375 Settings.System.putInt(mContext.getContentResolver(),
376 Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
377 }
378
379 private class SettingsObserver implements Observer {
380 private int getInt(String name) {
381 return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
382 }
383
384 public void update(Observable o, Object arg) {
385 synchronized (mLocks) {
386 // STAY_ON_WHILE_PLUGGED_IN
387 mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN);
388 updateWakeLockLocked();
389
390 // SCREEN_OFF_TIMEOUT
391 mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);
392
393 // DIM_SCREEN
394 //mDimScreen = getInt(DIM_SCREEN) != 0;
395
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700396 // SCREEN_BRIGHTNESS_MODE
397 setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE));
398
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 // recalculate everything
400 setScreenOffTimeoutsLocked();
401 }
402 }
403 }
404
405 PowerManagerService()
406 {
407 // Hack to get our uid... should have a func for this.
408 long token = Binder.clearCallingIdentity();
409 MY_UID = Binder.getCallingUid();
410 Binder.restoreCallingIdentity(token);
411
412 // XXX remove this when the kernel doesn't timeout wake locks
413 Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
414
415 // assume nothing is on yet
416 mUserState = mPowerState = 0;
417
418 // Add ourself to the Watchdog monitors.
419 Watchdog.getInstance().addMonitor(this);
420 mScreenOnStartTime = SystemClock.elapsedRealtime();
421 }
422
423 private ContentQueryMap mSettings;
424
The Android Open Source Project10592532009-03-18 17:39:46 -0700425 void init(Context context, HardwareService hardware, IActivityManager activity,
426 BatteryService battery) {
427 mHardware = hardware;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 mContext = context;
429 mActivityService = activity;
430 mBatteryStats = BatteryStatsService.getService();
431 mBatteryService = battery;
432
433 mHandlerThread = new HandlerThread("PowerManagerService") {
434 @Override
435 protected void onLooperPrepared() {
436 super.onLooperPrepared();
437 initInThread();
438 }
439 };
440 mHandlerThread.start();
441
442 synchronized (mHandlerThread) {
443 while (!mInitComplete) {
444 try {
445 mHandlerThread.wait();
446 } catch (InterruptedException e) {
447 // Ignore
448 }
449 }
450 }
451 }
452
453 void initInThread() {
454 mHandler = new Handler();
455
456 mBroadcastWakeLock = new UnsynchronizedWakeLock(
Joe Onorato128e7292009-03-24 18:41:31 -0700457 PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
459 PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
460 mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
461 PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
462 mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
463 PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500464 mProximityPartialLock = new UnsynchronizedWakeLock(
465 PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466
467 mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
468 mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
469 mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
470 mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
471
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700472 Resources resources = mContext.getResources();
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400473
474 // read settings for auto-brightness
475 mUseSoftwareAutoBrightness = resources.getBoolean(
476 com.android.internal.R.bool.config_automatic_brightness_available);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400477 if (mUseSoftwareAutoBrightness) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700478 mAutoBrightnessLevels = resources.getIntArray(
479 com.android.internal.R.array.config_autoBrightnessLevels);
480 mLcdBacklightValues = resources.getIntArray(
481 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
482 mButtonBacklightValues = resources.getIntArray(
483 com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
484 mKeyboardBacklightValues = resources.getIntArray(
485 com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500486 mLightSensorWarmupTime = resources.getInteger(
487 com.android.internal.R.integer.config_lightSensorWarmupTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700488 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700489
490 ContentResolver resolver = mContext.getContentResolver();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800491 Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
492 "(" + Settings.System.NAME + "=?) or ("
493 + Settings.System.NAME + "=?) or ("
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700494 + Settings.System.NAME + "=?) or ("
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495 + Settings.System.NAME + "=?)",
Mike Lockwooddc3494e2009-10-14 21:17:09 -0700496 new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
497 SCREEN_BRIGHTNESS_MODE},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 null);
499 mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
500 SettingsObserver settingsObserver = new SettingsObserver();
501 mSettings.addObserver(settingsObserver);
502
503 // pretend that the settings changed so we will get their initial state
504 settingsObserver.update(mSettings, null);
505
506 // register for the battery changed notifications
507 IntentFilter filter = new IntentFilter();
508 filter.addAction(Intent.ACTION_BATTERY_CHANGED);
509 mContext.registerReceiver(new BatteryReceiver(), filter);
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500510 filter = new IntentFilter();
511 filter.addAction(Intent.ACTION_BOOT_COMPLETED);
512 mContext.registerReceiver(new BootCompletedReceiver(), filter);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800513
514 // Listen for Gservices changes
515 IntentFilter gservicesChangedFilter =
516 new IntentFilter(Settings.Gservices.CHANGED_ACTION);
517 mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter);
518 // And explicitly do the initial update of our cached settings
519 updateGservicesValues();
520
Mike Lockwood4984e732009-11-01 08:16:33 -0500521 if (mUseSoftwareAutoBrightness) {
Mike Lockwood6c97fca2009-10-20 08:10:00 -0400522 // turn the screen on
523 setPowerState(SCREEN_BRIGHT);
524 } else {
525 // turn everything on
526 setPowerState(ALL_BRIGHT);
527 }
Dan Murphy951764b2009-08-27 14:59:03 -0500528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 synchronized (mHandlerThread) {
530 mInitComplete = true;
531 mHandlerThread.notifyAll();
532 }
533 }
534
535 private class WakeLock implements IBinder.DeathRecipient
536 {
537 WakeLock(int f, IBinder b, String t, int u) {
538 super();
539 flags = f;
540 binder = b;
541 tag = t;
542 uid = u == MY_UID ? Process.SYSTEM_UID : u;
543 if (u != MY_UID || (
544 !"KEEP_SCREEN_ON_FLAG".equals(tag)
545 && !"KeyInputQueue".equals(tag))) {
546 monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
547 ? BatteryStats.WAKE_TYPE_PARTIAL
548 : BatteryStats.WAKE_TYPE_FULL;
549 } else {
550 monitorType = -1;
551 }
552 try {
553 b.linkToDeath(this, 0);
554 } catch (RemoteException e) {
555 binderDied();
556 }
557 }
558 public void binderDied() {
559 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500560 releaseWakeLockLocked(this.binder, 0, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561 }
562 }
563 final int flags;
564 final IBinder binder;
565 final String tag;
566 final int uid;
567 final int monitorType;
568 boolean activated = true;
569 int minState;
570 }
571
572 private void updateWakeLockLocked() {
573 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
574 // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
575 mStayOnWhilePluggedInScreenDimLock.acquire();
576 mStayOnWhilePluggedInPartialLock.acquire();
577 } else {
578 mStayOnWhilePluggedInScreenDimLock.release();
579 mStayOnWhilePluggedInPartialLock.release();
580 }
581 }
582
583 private boolean isScreenLock(int flags)
584 {
585 int n = flags & LOCK_MASK;
586 return n == PowerManager.FULL_WAKE_LOCK
587 || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
588 || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
589 }
590
591 public void acquireWakeLock(int flags, IBinder lock, String tag) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800592 int uid = Binder.getCallingUid();
Michael Chane96440f2009-05-06 10:27:36 -0700593 if (uid != Process.myUid()) {
594 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
595 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800596 long ident = Binder.clearCallingIdentity();
597 try {
598 synchronized (mLocks) {
599 acquireWakeLockLocked(flags, lock, uid, tag);
600 }
601 } finally {
602 Binder.restoreCallingIdentity(ident);
603 }
604 }
605
606 public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
607 int acquireUid = -1;
608 String acquireName = null;
609 int acquireType = -1;
610
611 if (mSpew) {
612 Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
613 }
614
615 int index = mLocks.getIndex(lock);
616 WakeLock wl;
617 boolean newlock;
618 if (index < 0) {
619 wl = new WakeLock(flags, lock, tag, uid);
620 switch (wl.flags & LOCK_MASK)
621 {
622 case PowerManager.FULL_WAKE_LOCK:
Mike Lockwood4984e732009-11-01 08:16:33 -0500623 if (mUseSoftwareAutoBrightness) {
Mike Lockwood3333fa42009-10-26 14:50:42 -0400624 wl.minState = SCREEN_BRIGHT;
625 } else {
626 wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
627 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800628 break;
629 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
630 wl.minState = SCREEN_BRIGHT;
631 break;
632 case PowerManager.SCREEN_DIM_WAKE_LOCK:
633 wl.minState = SCREEN_DIM;
634 break;
635 case PowerManager.PARTIAL_WAKE_LOCK:
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700636 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 break;
638 default:
639 // just log and bail. we're in the server, so don't
640 // throw an exception.
641 Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
642 + " flags=" + flags);
643 return;
644 }
645 mLocks.addLock(wl);
646 newlock = true;
647 } else {
648 wl = mLocks.get(index);
649 newlock = false;
650 }
651 if (isScreenLock(flags)) {
652 // if this causes a wakeup, we reactivate all of the locks and
653 // set it to whatever they want. otherwise, we modulate that
654 // by the current state so we never turn it more on than
655 // it already is.
656 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
Michael Chane96440f2009-05-06 10:27:36 -0700657 int oldWakeLockState = mWakeLockState;
658 mWakeLockState = mLocks.reactivateScreenLocksLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 if (mSpew) {
660 Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
Michael Chane96440f2009-05-06 10:27:36 -0700661 + " mWakeLockState=0x"
662 + Integer.toHexString(mWakeLockState)
663 + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800664 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800665 } else {
666 if (mSpew) {
667 Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
668 + " mLocks.gatherState()=0x"
669 + Integer.toHexString(mLocks.gatherState())
670 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
671 }
672 mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
673 }
674 setPowerState(mWakeLockState | mUserState);
675 }
676 else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
677 if (newlock) {
678 mPartialCount++;
679 if (mPartialCount == 1) {
680 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag);
681 }
682 }
683 Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700684 } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500685 mProximityWakeLockCount++;
686 if (mProximityWakeLockCount == 1) {
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700687 enableProximityLockLocked();
688 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 }
690 if (newlock) {
691 acquireUid = wl.uid;
692 acquireName = wl.tag;
693 acquireType = wl.monitorType;
694 }
695
696 if (acquireType >= 0) {
697 try {
698 mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
699 } catch (RemoteException e) {
700 // Ignore
701 }
702 }
703 }
704
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500705 public void releaseWakeLock(IBinder lock, int flags) {
Michael Chane96440f2009-05-06 10:27:36 -0700706 int uid = Binder.getCallingUid();
707 if (uid != Process.myUid()) {
708 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
709 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710
711 synchronized (mLocks) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500712 releaseWakeLockLocked(lock, flags, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 }
714 }
715
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500716 private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800717 int releaseUid;
718 String releaseName;
719 int releaseType;
720
721 WakeLock wl = mLocks.removeLock(lock);
722 if (wl == null) {
723 return;
724 }
725
726 if (mSpew) {
727 Log.d(TAG, "releaseWakeLock flags=0x"
728 + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
729 }
730
731 if (isScreenLock(wl.flags)) {
732 mWakeLockState = mLocks.gatherState();
733 // goes in the middle to reduce flicker
734 if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
735 userActivity(SystemClock.uptimeMillis(), false);
736 }
737 setPowerState(mWakeLockState | mUserState);
738 }
739 else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
740 mPartialCount--;
741 if (mPartialCount == 0) {
742 if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
743 Power.releaseWakeLock(PARTIAL_NAME);
744 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700745 } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500746 mProximityWakeLockCount--;
747 if (mProximityWakeLockCount == 0) {
Mike Lockwood0e39ea82009-11-18 15:37:10 -0500748 if (mProximitySensorActive &&
749 ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500750 // wait for proximity sensor to go negative before disabling sensor
751 if (mDebugProximitySensor) {
752 Log.d(TAG, "waiting for proximity sensor to go negative");
753 }
754 } else {
755 disableProximityLockLocked();
756 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -0700757 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758 }
759 // Unlink the lock from the binder.
760 wl.binder.unlinkToDeath(wl, 0);
761 releaseUid = wl.uid;
762 releaseName = wl.tag;
763 releaseType = wl.monitorType;
764
765 if (releaseType >= 0) {
766 long origId = Binder.clearCallingIdentity();
767 try {
768 mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
769 } catch (RemoteException e) {
770 // Ignore
771 } finally {
772 Binder.restoreCallingIdentity(origId);
773 }
774 }
775 }
776
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777 private class PokeLock implements IBinder.DeathRecipient
778 {
779 PokeLock(int p, IBinder b, String t) {
780 super();
781 this.pokey = p;
782 this.binder = b;
783 this.tag = t;
784 try {
785 b.linkToDeath(this, 0);
786 } catch (RemoteException e) {
787 binderDied();
788 }
789 }
790 public void binderDied() {
791 setPokeLock(0, this.binder, this.tag);
792 }
793 int pokey;
794 IBinder binder;
795 String tag;
796 boolean awakeOnSet;
797 }
798
799 public void setPokeLock(int pokey, IBinder token, String tag) {
800 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
801 if (token == null) {
802 Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
803 return;
804 }
805
806 if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
807 throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
808 + " and POKE_LOCK_MEDIUM_TIMEOUT");
809 }
810
811 synchronized (mLocks) {
812 if (pokey != 0) {
813 PokeLock p = mPokeLocks.get(token);
814 int oldPokey = 0;
815 if (p != null) {
816 oldPokey = p.pokey;
817 p.pokey = pokey;
818 } else {
819 p = new PokeLock(pokey, token, tag);
820 mPokeLocks.put(token, p);
821 }
822 int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
823 int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
824 if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
825 p.awakeOnSet = true;
826 }
827 } else {
Suchi Amalapurapufff2fda2009-06-30 21:36:16 -0700828 PokeLock rLock = mPokeLocks.remove(token);
829 if (rLock != null) {
830 token.unlinkToDeath(rLock, 0);
831 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 }
833
834 int oldPokey = mPokey;
835 int cumulative = 0;
836 boolean oldAwakeOnSet = mPokeAwakeOnSet;
837 boolean awakeOnSet = false;
838 for (PokeLock p: mPokeLocks.values()) {
839 cumulative |= p.pokey;
840 if (p.awakeOnSet) {
841 awakeOnSet = true;
842 }
843 }
844 mPokey = cumulative;
845 mPokeAwakeOnSet = awakeOnSet;
846
847 int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
848 int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
849
850 if (oldCumulativeTimeout != newCumulativeTimeout) {
851 setScreenOffTimeoutsLocked();
852 // reset the countdown timer, but use the existing nextState so it doesn't
853 // change anything
854 setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
855 }
856 }
857 }
858
859 private static String lockType(int type)
860 {
861 switch (type)
862 {
863 case PowerManager.FULL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700864 return "FULL_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700866 return "SCREEN_BRIGHT_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 case PowerManager.SCREEN_DIM_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700868 return "SCREEN_DIM_WAKE_LOCK ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800869 case PowerManager.PARTIAL_WAKE_LOCK:
David Brown251faa62009-08-02 22:04:36 -0700870 return "PARTIAL_WAKE_LOCK ";
871 case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
872 return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 default:
David Brown251faa62009-08-02 22:04:36 -0700874 return "??? ";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800875 }
876 }
877
878 private static String dumpPowerState(int state) {
879 return (((state & KEYBOARD_BRIGHT_BIT) != 0)
880 ? "KEYBOARD_BRIGHT_BIT " : "")
881 + (((state & SCREEN_BRIGHT_BIT) != 0)
882 ? "SCREEN_BRIGHT_BIT " : "")
883 + (((state & SCREEN_ON_BIT) != 0)
884 ? "SCREEN_ON_BIT " : "")
885 + (((state & BATTERY_LOW_BIT) != 0)
886 ? "BATTERY_LOW_BIT " : "");
887 }
888
889 @Override
890 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
891 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
892 != PackageManager.PERMISSION_GRANTED) {
893 pw.println("Permission Denial: can't dump PowerManager from from pid="
894 + Binder.getCallingPid()
895 + ", uid=" + Binder.getCallingUid());
896 return;
897 }
898
899 long now = SystemClock.uptimeMillis();
900
901 pw.println("Power Manager State:");
902 pw.println(" mIsPowered=" + mIsPowered
903 + " mPowerState=" + mPowerState
904 + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
905 + " ms");
906 pw.println(" mPartialCount=" + mPartialCount);
907 pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
908 pw.println(" mUserState=" + dumpPowerState(mUserState));
909 pw.println(" mPowerState=" + dumpPowerState(mPowerState));
910 pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
911 pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
912 + " " + ((mNextTimeout-now)/1000) + "s from now");
913 pw.println(" mDimScreen=" + mDimScreen
914 + " mStayOnConditions=" + mStayOnConditions);
915 pw.println(" mOffBecauseOfUser=" + mOffBecauseOfUser
916 + " mUserState=" + mUserState);
Joe Onorato128e7292009-03-24 18:41:31 -0700917 pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
918 + ',' + mBroadcastQueue[2] + "}");
919 pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
920 + ',' + mBroadcastWhy[2] + "}");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800921 pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
922 pw.println(" mKeyboardVisible=" + mKeyboardVisible
923 + " mUserActivityAllowed=" + mUserActivityAllowed);
924 pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
925 + " mScreenOffDelay=" + mScreenOffDelay);
926 pw.println(" mPreventScreenOn=" + mPreventScreenOn
927 + " mScreenBrightnessOverride=" + mScreenBrightnessOverride);
928 pw.println(" mTotalDelaySetting=" + mTotalDelaySetting);
Mike Lockwood20ee6f22009-11-07 20:33:47 -0500929 pw.println(" mLastScreenOnTime=" + mLastScreenOnTime);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
931 pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
932 pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
933 pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -0500934 pw.println(" mProximityPartialLock=" + mProximityPartialLock);
Mike Lockwoodee2b0942009-11-09 14:09:02 -0500935 pw.println(" mProximityWakeLockCount=" + mProximityWakeLockCount);
936 pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700937 pw.println(" mProximitySensorActive=" + mProximitySensorActive);
Mike Lockwood20f87d72009-11-05 16:08:51 -0500938 pw.println(" mProximityPendingValue=" + mProximityPendingValue);
939 pw.println(" mLastProximityEventTime=" + mLastProximityEventTime);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700940 pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
941 pw.println(" mLightSensorValue=" + mLightSensorValue);
942 pw.println(" mLightSensorPendingValue=" + mLightSensorPendingValue);
Mike Lockwoodaa66ea82009-10-31 16:31:27 -0400943 pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
Mike Lockwoodd7786b42009-10-15 17:09:16 -0700944 pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 mScreenBrightness.dump(pw, " mScreenBrightness: ");
946 mKeyboardBrightness.dump(pw, " mKeyboardBrightness: ");
947 mButtonBrightness.dump(pw, " mButtonBrightness: ");
948
949 int N = mLocks.size();
950 pw.println();
951 pw.println("mLocks.size=" + N + ":");
952 for (int i=0; i<N; i++) {
953 WakeLock wl = mLocks.get(i);
954 String type = lockType(wl.flags & LOCK_MASK);
955 String acquireCausesWakeup = "";
956 if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
957 acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
958 }
959 String activated = "";
960 if (wl.activated) {
961 activated = " activated";
962 }
963 pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
964 + activated + " (minState=" + wl.minState + ")");
965 }
966
967 pw.println();
968 pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
969 for (PokeLock p: mPokeLocks.values()) {
970 pw.println(" poke lock '" + p.tag + "':"
971 + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
972 ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
Joe Onoratoe68ffcb2009-03-24 19:11:13 -0700973 + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0
974 ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800975 + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
976 ? " POKE_LOCK_SHORT_TIMEOUT" : "")
977 + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
978 ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
979 }
980
981 pw.println();
982 }
983
984 private void setTimeoutLocked(long now, int nextState)
985 {
Mike Lockwood2d7bb812009-11-15 18:12:22 -0500986 if (mBootCompleted) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800987 mHandler.removeCallbacks(mTimeoutTask);
988 mTimeoutTask.nextState = nextState;
989 long when = now;
990 switch (nextState)
991 {
992 case SCREEN_BRIGHT:
993 when += mKeylightDelay;
994 break;
995 case SCREEN_DIM:
996 if (mDimDelay >= 0) {
997 when += mDimDelay;
998 break;
999 } else {
1000 Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
1001 }
1002 case SCREEN_OFF:
1003 synchronized (mLocks) {
1004 when += mScreenOffDelay;
1005 }
1006 break;
1007 }
1008 if (mSpew) {
1009 Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
1010 + " when=" + when);
1011 }
1012 mHandler.postAtTime(mTimeoutTask, when);
1013 mNextTimeout = when; // for debugging
1014 }
1015 }
1016
1017 private void cancelTimerLocked()
1018 {
1019 mHandler.removeCallbacks(mTimeoutTask);
1020 mTimeoutTask.nextState = -1;
1021 }
1022
1023 private class TimeoutTask implements Runnable
1024 {
1025 int nextState; // access should be synchronized on mLocks
1026 public void run()
1027 {
1028 synchronized (mLocks) {
1029 if (mSpew) {
1030 Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
1031 }
1032
1033 if (nextState == -1) {
1034 return;
1035 }
1036
1037 mUserState = this.nextState;
1038 setPowerState(this.nextState | mWakeLockState);
1039
1040 long now = SystemClock.uptimeMillis();
1041
1042 switch (this.nextState)
1043 {
1044 case SCREEN_BRIGHT:
1045 if (mDimDelay >= 0) {
1046 setTimeoutLocked(now, SCREEN_DIM);
1047 break;
1048 }
1049 case SCREEN_DIM:
1050 setTimeoutLocked(now, SCREEN_OFF);
1051 break;
1052 }
1053 }
1054 }
1055 }
1056
1057 private void sendNotificationLocked(boolean on, int why)
1058 {
Joe Onorato64c62ba2009-03-24 20:13:57 -07001059 if (!on) {
1060 mStillNeedSleepNotification = false;
1061 }
1062
Joe Onorato128e7292009-03-24 18:41:31 -07001063 // Add to the queue.
1064 int index = 0;
1065 while (mBroadcastQueue[index] != -1) {
1066 index++;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 }
Joe Onorato128e7292009-03-24 18:41:31 -07001068 mBroadcastQueue[index] = on ? 1 : 0;
1069 mBroadcastWhy[index] = why;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070
Joe Onorato128e7292009-03-24 18:41:31 -07001071 // If we added it position 2, then there is a pair that can be stripped.
1072 // If we added it position 1 and we're turning the screen off, we can strip
1073 // the pair and do nothing, because the screen is already off, and therefore
1074 // keyguard has already been enabled.
1075 // However, if we added it at position 1 and we're turning it on, then position
1076 // 0 was to turn it off, and we can't strip that, because keyguard needs to come
1077 // on, so have to run the queue then.
1078 if (index == 2) {
1079 // Also, while we're collapsing them, if it's going to be an "off," and one
1080 // is off because of user, then use that, regardless of whether it's the first
1081 // or second one.
1082 if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
1083 mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
1084 }
1085 mBroadcastQueue[0] = on ? 1 : 0;
1086 mBroadcastQueue[1] = -1;
1087 mBroadcastQueue[2] = -1;
1088 index = 0;
1089 }
1090 if (index == 1 && !on) {
1091 mBroadcastQueue[0] = -1;
1092 mBroadcastQueue[1] = -1;
1093 index = -1;
1094 // The wake lock was being held, but we're not actually going to do any
1095 // broadcasts, so release the wake lock.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001096 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1097 mBroadcastWakeLock.release();
Joe Onorato128e7292009-03-24 18:41:31 -07001098 }
1099
1100 // Now send the message.
1101 if (index >= 0) {
1102 // Acquire the broadcast wake lock before changing the power
1103 // state. It will be release after the broadcast is sent.
1104 // We always increment the ref count for each notification in the queue
1105 // and always decrement when that notification is handled.
1106 mBroadcastWakeLock.acquire();
1107 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
1108 mHandler.post(mNotificationTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 }
1110 }
1111
1112 private Runnable mNotificationTask = new Runnable()
1113 {
1114 public void run()
1115 {
Joe Onorato128e7292009-03-24 18:41:31 -07001116 while (true) {
1117 int value;
1118 int why;
1119 WindowManagerPolicy policy;
1120 synchronized (mLocks) {
1121 value = mBroadcastQueue[0];
1122 why = mBroadcastWhy[0];
1123 for (int i=0; i<2; i++) {
1124 mBroadcastQueue[i] = mBroadcastQueue[i+1];
1125 mBroadcastWhy[i] = mBroadcastWhy[i+1];
1126 }
1127 policy = getPolicyLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 }
Joe Onorato128e7292009-03-24 18:41:31 -07001129 if (value == 1) {
1130 mScreenOnStart = SystemClock.uptimeMillis();
1131
1132 policy.screenTurnedOn();
1133 try {
1134 ActivityManagerNative.getDefault().wakingUp();
1135 } catch (RemoteException e) {
1136 // ignore it
1137 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138
Joe Onorato128e7292009-03-24 18:41:31 -07001139 if (mSpew) {
1140 Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
1141 }
1142 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1143 mContext.sendOrderedBroadcast(mScreenOnIntent, null,
1144 mScreenOnBroadcastDone, mHandler, 0, null, null);
1145 } else {
1146 synchronized (mLocks) {
1147 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2,
1148 mBroadcastWakeLock.mCount);
1149 mBroadcastWakeLock.release();
1150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 }
1152 }
Joe Onorato128e7292009-03-24 18:41:31 -07001153 else if (value == 0) {
1154 mScreenOffStart = SystemClock.uptimeMillis();
1155
1156 policy.screenTurnedOff(why);
1157 try {
1158 ActivityManagerNative.getDefault().goingToSleep();
1159 } catch (RemoteException e) {
1160 // ignore it.
1161 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001162
Joe Onorato128e7292009-03-24 18:41:31 -07001163 if (mContext != null && ActivityManagerNative.isSystemReady()) {
1164 mContext.sendOrderedBroadcast(mScreenOffIntent, null,
1165 mScreenOffBroadcastDone, mHandler, 0, null, null);
1166 } else {
1167 synchronized (mLocks) {
1168 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3,
1169 mBroadcastWakeLock.mCount);
1170 mBroadcastWakeLock.release();
1171 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 }
1173 }
Joe Onorato128e7292009-03-24 18:41:31 -07001174 else {
1175 // If we're in this case, then this handler is running for a previous
1176 // paired transaction. mBroadcastWakeLock will already have been released.
1177 break;
1178 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 }
1180 }
1181 };
1182
1183 long mScreenOnStart;
1184 private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
1185 public void onReceive(Context context, Intent intent) {
1186 synchronized (mLocks) {
1187 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1,
1188 SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
1189 mBroadcastWakeLock.release();
1190 }
1191 }
1192 };
1193
1194 long mScreenOffStart;
1195 private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
1196 public void onReceive(Context context, Intent intent) {
1197 synchronized (mLocks) {
1198 EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0,
1199 SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
1200 mBroadcastWakeLock.release();
1201 }
1202 }
1203 };
1204
1205 void logPointerUpEvent() {
1206 if (LOG_TOUCH_DOWNS) {
1207 mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1208 mLastTouchDown = 0;
1209 }
1210 }
1211
1212 void logPointerDownEvent() {
1213 if (LOG_TOUCH_DOWNS) {
1214 // If we are not already timing a down/up sequence
1215 if (mLastTouchDown == 0) {
1216 mLastTouchDown = SystemClock.elapsedRealtime();
1217 mTouchCycles++;
1218 }
1219 }
1220 }
1221
1222 /**
1223 * Prevents the screen from turning on even if it *should* turn on due
1224 * to a subsequent full wake lock being acquired.
1225 * <p>
1226 * This is a temporary hack that allows an activity to "cover up" any
1227 * display glitches that happen during the activity's startup
1228 * sequence. (Specifically, this API was added to work around a
1229 * cosmetic bug in the "incoming call" sequence, where the lock screen
1230 * would flicker briefly before the incoming call UI became visible.)
1231 * TODO: There ought to be a more elegant way of doing this,
1232 * probably by having the PowerManager and ActivityManager
1233 * work together to let apps specify that the screen on/off
1234 * state should be synchronized with the Activity lifecycle.
1235 * <p>
1236 * Note that calling preventScreenOn(true) will NOT turn the screen
1237 * off if it's currently on. (This API only affects *future*
1238 * acquisitions of full wake locks.)
1239 * But calling preventScreenOn(false) WILL turn the screen on if
1240 * it's currently off because of a prior preventScreenOn(true) call.
1241 * <p>
1242 * Any call to preventScreenOn(true) MUST be followed promptly by a call
1243 * to preventScreenOn(false). In fact, if the preventScreenOn(false)
1244 * call doesn't occur within 5 seconds, we'll turn the screen back on
1245 * ourselves (and log a warning about it); this prevents a buggy app
1246 * from disabling the screen forever.)
1247 * <p>
1248 * TODO: this feature should really be controlled by a new type of poke
1249 * lock (rather than an IPowerManager call).
1250 */
1251 public void preventScreenOn(boolean prevent) {
1252 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1253
1254 synchronized (mLocks) {
1255 if (prevent) {
1256 // First of all, grab a partial wake lock to
1257 // make sure the CPU stays on during the entire
1258 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1259 mPreventScreenOnPartialLock.acquire();
1260
1261 // Post a forceReenableScreen() call (for 5 seconds in the
1262 // future) to make sure the matching preventScreenOn(false) call
1263 // has happened by then.
1264 mHandler.removeCallbacks(mForceReenableScreenTask);
1265 mHandler.postDelayed(mForceReenableScreenTask, 5000);
1266
1267 // Finally, set the flag that prevents the screen from turning on.
1268 // (Below, in setPowerState(), we'll check mPreventScreenOn and
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001269 // we *won't* call setScreenStateLocked(true) if it's set.)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 mPreventScreenOn = true;
1271 } else {
1272 // (Re)enable the screen.
1273 mPreventScreenOn = false;
1274
1275 // We're "undoing" a the prior preventScreenOn(true) call, so we
1276 // no longer need the 5-second safeguard.
1277 mHandler.removeCallbacks(mForceReenableScreenTask);
1278
1279 // Forcibly turn on the screen if it's supposed to be on. (This
1280 // handles the case where the screen is currently off because of
1281 // a prior preventScreenOn(true) call.)
Mike Lockwoode090281422009-11-14 21:02:56 -05001282 if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001283 if (mSpew) {
1284 Log.d(TAG,
1285 "preventScreenOn: turning on after a prior preventScreenOn(true)!");
1286 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001287 int err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001288 if (err != 0) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001289 Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290 }
1291 }
1292
1293 // Release the partial wake lock that we held during the
1294 // preventScreenOn(true) -> preventScreenOn(false) sequence.
1295 mPreventScreenOnPartialLock.release();
1296 }
1297 }
1298 }
1299
1300 public void setScreenBrightnessOverride(int brightness) {
1301 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1302
1303 synchronized (mLocks) {
1304 if (mScreenBrightnessOverride != brightness) {
1305 mScreenBrightnessOverride = brightness;
1306 updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1307 }
1308 }
1309 }
1310
1311 /**
1312 * Sanity-check that gets called 5 seconds after any call to
1313 * preventScreenOn(true). This ensures that the original call
1314 * is followed promptly by a call to preventScreenOn(false).
1315 */
1316 private void forceReenableScreen() {
1317 // We shouldn't get here at all if mPreventScreenOn is false, since
1318 // we should have already removed any existing
1319 // mForceReenableScreenTask messages...
1320 if (!mPreventScreenOn) {
1321 Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
1322 return;
1323 }
1324
1325 // Uh oh. It's been 5 seconds since a call to
1326 // preventScreenOn(true) and we haven't re-enabled the screen yet.
1327 // This means the app that called preventScreenOn(true) is either
1328 // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
1329 // or buggy (i.e. it forgot to call preventScreenOn(false), or
1330 // crashed before doing so.)
1331
1332 // Log a warning, and forcibly turn the screen back on.
1333 Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
1334 + "Forcing the screen back on...");
1335 preventScreenOn(false);
1336 }
1337
1338 private Runnable mForceReenableScreenTask = new Runnable() {
1339 public void run() {
1340 forceReenableScreen();
1341 }
1342 };
1343
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001344 private int setScreenStateLocked(boolean on) {
1345 int err = Power.setScreenState(on);
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001346 if (err == 0) {
1347 mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
1348 if (mUseSoftwareAutoBrightness) {
1349 enableLightSensor(on);
1350 if (!on) {
1351 // make sure button and key backlights are off too
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001352 int brightnessMode = (mUseSoftwareAutoBrightness
1353 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1354 : HardwareService.BRIGHTNESS_MODE_USER);
1355 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0,
1356 brightnessMode);
1357 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0,
1358 brightnessMode);
Mike Lockwood20ee6f22009-11-07 20:33:47 -05001359 // clear current value so we will update based on the new conditions
1360 // when the sensor is reenabled.
1361 mLightSensorValue = -1;
1362 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001363 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001364 }
1365 return err;
1366 }
1367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 private void setPowerState(int state)
1369 {
1370 setPowerState(state, false, false);
1371 }
1372
1373 private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
1374 {
1375 synchronized (mLocks) {
1376 int err;
1377
1378 if (mSpew) {
1379 Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1380 + " newState=0x" + Integer.toHexString(newState)
1381 + " noChangeLights=" + noChangeLights);
1382 }
1383
1384 if (noChangeLights) {
1385 newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1386 }
Mike Lockwood36fc3022009-08-25 16:49:06 -07001387 if (mProximitySensorActive) {
1388 // don't turn on the screen when the proximity sensor lock is held
1389 newState = (newState & ~SCREEN_BRIGHT);
1390 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001391
1392 if (batteryIsLow()) {
1393 newState |= BATTERY_LOW_BIT;
1394 } else {
1395 newState &= ~BATTERY_LOW_BIT;
1396 }
1397 if (newState == mPowerState) {
1398 return;
1399 }
Mike Lockwood3333fa42009-10-26 14:50:42 -04001400
Mike Lockwood2d7bb812009-11-15 18:12:22 -05001401 if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 newState |= ALL_BRIGHT;
1403 }
1404
1405 boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1406 boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1407
Mike Lockwood51b84492009-11-16 21:51:18 -05001408 if (mSpew) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001409 Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
1410 + " newState=" + newState + " noChangeLights=" + noChangeLights);
1411 Log.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1412 + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1413 Log.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1414 + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1415 Log.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1416 + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1417 Log.d(TAG, " oldScreenOn=" + oldScreenOn
1418 + " newScreenOn=" + newScreenOn);
1419 Log.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1420 + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1421 }
1422
1423 if (mPowerState != newState) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001424 updateLightsLocked(newState, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001425 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1426 }
1427
1428 if (oldScreenOn != newScreenOn) {
1429 if (newScreenOn) {
Joe Onorato128e7292009-03-24 18:41:31 -07001430 // When the user presses the power button, we need to always send out the
1431 // notification that it's going to sleep so the keyguard goes on. But
1432 // we can't do that until the screen fades out, so we don't show the keyguard
1433 // too early.
1434 if (mStillNeedSleepNotification) {
1435 sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1436 }
1437
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001438 // Turn on the screen UNLESS there was a prior
1439 // preventScreenOn(true) request. (Note that the lifetime
1440 // of a single preventScreenOn() request is limited to 5
1441 // seconds to prevent a buggy app from disabling the
1442 // screen forever; see forceReenableScreen().)
1443 boolean reallyTurnScreenOn = true;
1444 if (mSpew) {
1445 Log.d(TAG, "- turning screen on... mPreventScreenOn = "
1446 + mPreventScreenOn);
1447 }
1448
1449 if (mPreventScreenOn) {
1450 if (mSpew) {
1451 Log.d(TAG, "- PREVENTING screen from really turning on!");
1452 }
1453 reallyTurnScreenOn = false;
1454 }
1455 if (reallyTurnScreenOn) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001456 err = setScreenStateLocked(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 long identity = Binder.clearCallingIdentity();
1458 try {
Dianne Hackborn617f8772009-03-31 15:04:46 -07001459 mBatteryStats.noteScreenBrightness(
1460 getPreferredBrightness());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 mBatteryStats.noteScreenOn();
1462 } catch (RemoteException e) {
1463 Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
1464 } finally {
1465 Binder.restoreCallingIdentity(identity);
1466 }
1467 } else {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001468 setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 // But continue as if we really did turn the screen on...
1470 err = 0;
1471 }
1472
1473 mScreenOnStartTime = SystemClock.elapsedRealtime();
1474 mLastTouchDown = 0;
1475 mTotalTouchDownTime = 0;
1476 mTouchCycles = 0;
1477 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
1478 mTotalTouchDownTime, mTouchCycles);
1479 if (err == 0) {
1480 mPowerState |= SCREEN_ON_BIT;
1481 sendNotificationLocked(true, -1);
1482 }
1483 } else {
Mike Lockwood497087e32009-11-08 18:33:03 -05001484 // cancel light sensor task
1485 mHandler.removeCallbacks(mAutoBrightnessTask);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001486 mScreenOffTime = SystemClock.elapsedRealtime();
1487 long identity = Binder.clearCallingIdentity();
1488 try {
1489 mBatteryStats.noteScreenOff();
1490 } catch (RemoteException e) {
1491 Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
1492 } finally {
1493 Binder.restoreCallingIdentity(identity);
1494 }
1495 mPowerState &= ~SCREEN_ON_BIT;
1496 if (!mScreenBrightness.animating) {
Joe Onorato128e7292009-03-24 18:41:31 -07001497 err = screenOffFinishedAnimatingLocked(becauseOfUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001498 } else {
1499 mOffBecauseOfUser = becauseOfUser;
1500 err = 0;
1501 mLastTouchDown = 0;
1502 }
1503 }
1504 }
1505 }
1506 }
1507
Joe Onorato128e7292009-03-24 18:41:31 -07001508 private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 // I don't think we need to check the current state here because all of these
1510 // Power.setScreenState and sendNotificationLocked can both handle being
1511 // called multiple times in the same state. -joeo
1512 EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
1513 mTotalTouchDownTime, mTouchCycles);
1514 mLastTouchDown = 0;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04001515 int err = setScreenStateLocked(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 if (mScreenOnStartTime != 0) {
1517 mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
1518 mScreenOnStartTime = 0;
1519 }
1520 if (err == 0) {
1521 int why = becauseOfUser
1522 ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
1523 : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
1524 sendNotificationLocked(false, why);
1525 }
1526 return err;
1527 }
1528
1529 private boolean batteryIsLow() {
1530 return (!mIsPowered &&
1531 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1532 }
1533
The Android Open Source Project10592532009-03-18 17:39:46 -07001534 private void updateLightsLocked(int newState, int forceState) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001535 final int oldState = mPowerState;
1536 final int realDifference = (newState ^ oldState);
1537 final int difference = realDifference | forceState;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 if (difference == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001539 return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 }
1541
1542 int offMask = 0;
1543 int dimMask = 0;
1544 int onMask = 0;
1545
1546 int preferredBrightness = getPreferredBrightness();
1547 boolean startAnimation = false;
1548
1549 if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1550 if (ANIMATE_KEYBOARD_LIGHTS) {
1551 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1552 mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001553 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1554 preferredBrightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001555 } else {
1556 mKeyboardBrightness.setTargetLocked(preferredBrightness,
Joe Onorato128e7292009-03-24 18:41:31 -07001557 ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1558 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001559 }
1560 startAnimation = true;
1561 } else {
1562 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001563 offMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001564 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001565 onMask |= KEYBOARD_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001566 }
1567 }
1568 }
1569
1570 if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1571 if (ANIMATE_BUTTON_LIGHTS) {
1572 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1573 mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
Joe Onorato128e7292009-03-24 18:41:31 -07001574 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1575 preferredBrightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 } else {
1577 mButtonBrightness.setTargetLocked(preferredBrightness,
Joe Onorato128e7292009-03-24 18:41:31 -07001578 ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1579 Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 }
1581 startAnimation = true;
1582 } else {
1583 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001584 offMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001585 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001586 onMask |= BUTTON_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001587 }
1588 }
1589 }
1590
1591 if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1592 if (ANIMATE_SCREEN_LIGHTS) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001593 int nominalCurrentValue = -1;
1594 // If there was an actual difference in the light state, then
1595 // figure out the "ideal" current value based on the previous
1596 // state. Otherwise, this is a change due to the brightness
1597 // override, so we want to animate from whatever the current
1598 // value is.
1599 if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1600 switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
1601 case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
1602 nominalCurrentValue = preferredBrightness;
1603 break;
1604 case SCREEN_ON_BIT:
1605 nominalCurrentValue = Power.BRIGHTNESS_DIM;
1606 break;
1607 case 0:
1608 nominalCurrentValue = Power.BRIGHTNESS_OFF;
1609 break;
1610 case SCREEN_BRIGHT_BIT:
1611 default:
1612 // not possible
1613 nominalCurrentValue = (int)mScreenBrightness.curValue;
1614 break;
1615 }
Joe Onorato128e7292009-03-24 18:41:31 -07001616 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001617 int brightness = preferredBrightness;
1618 int steps = ANIM_STEPS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1620 // dim or turn off backlight, depending on if the screen is on
1621 // the scale is because the brightness ramp isn't linear and this biases
1622 // it so the later parts take longer.
1623 final float scale = 1.5f;
1624 float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
1625 if (ratio > 1.0f) ratio = 1.0f;
1626 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001627 if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
1628 // was bright
1629 steps = ANIM_STEPS;
1630 } else {
1631 // was dim
1632 steps = (int)(ANIM_STEPS*ratio*scale);
1633 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001634 brightness = Power.BRIGHTNESS_OFF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635 } else {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 if ((oldState & SCREEN_ON_BIT) != 0) {
1637 // was bright
1638 steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
1639 } else {
1640 // was dim
1641 steps = (int)(ANIM_STEPS*ratio);
1642 }
1643 if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
1644 // If the "stay on while plugged in" option is
1645 // turned on, then the screen will often not
1646 // automatically turn off while plugged in. To
1647 // still have a sense of when it is inactive, we
1648 // will then count going dim as turning off.
1649 mScreenOffTime = SystemClock.elapsedRealtime();
1650 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001651 brightness = Power.BRIGHTNESS_DIM;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 }
Dianne Hackborn617f8772009-03-31 15:04:46 -07001654 long identity = Binder.clearCallingIdentity();
1655 try {
1656 mBatteryStats.noteScreenBrightness(brightness);
1657 } catch (RemoteException e) {
1658 // Nothing interesting to do.
1659 } finally {
1660 Binder.restoreCallingIdentity(identity);
1661 }
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001662 if (mScreenBrightness.setTargetLocked(brightness,
1663 steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
1664 startAnimation = true;
1665 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001666 } else {
1667 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1668 // dim or turn off backlight, depending on if the screen is on
1669 if ((newState & SCREEN_ON_BIT) == 0) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001670 offMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001672 dimMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001673 }
1674 } else {
The Android Open Source Project10592532009-03-18 17:39:46 -07001675 onMask |= SCREEN_BRIGHT_BIT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001676 }
1677 }
1678 }
1679
1680 if (startAnimation) {
1681 if (mSpew) {
1682 Log.i(TAG, "Scheduling light animator!");
1683 }
1684 mHandler.removeCallbacks(mLightAnimator);
1685 mHandler.post(mLightAnimator);
1686 }
1687
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 if (offMask != 0) {
1689 //Log.i(TAG, "Setting brightess off: " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001690 setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001691 }
1692 if (dimMask != 0) {
1693 int brightness = Power.BRIGHTNESS_DIM;
1694 if ((newState & BATTERY_LOW_BIT) != 0 &&
1695 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1696 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1697 }
1698 //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001699 setLightBrightness(dimMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001700 }
1701 if (onMask != 0) {
1702 int brightness = getPreferredBrightness();
1703 if ((newState & BATTERY_LOW_BIT) != 0 &&
1704 brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1705 brightness = Power.BRIGHTNESS_LOW_BATTERY;
1706 }
1707 //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001708 setLightBrightness(onMask, brightness);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 }
The Android Open Source Project10592532009-03-18 17:39:46 -07001710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711
The Android Open Source Project10592532009-03-18 17:39:46 -07001712 private void setLightBrightness(int mask, int value) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001713 int brightnessMode = (mAutoBrightessEnabled
1714 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1715 : HardwareService.BRIGHTNESS_MODE_USER);
The Android Open Source Project10592532009-03-18 17:39:46 -07001716 if ((mask & SCREEN_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001717 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value,
1718 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001719 }
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001720 brightnessMode = (mUseSoftwareAutoBrightness
1721 ? HardwareService.BRIGHTNESS_MODE_SENSOR
1722 : HardwareService.BRIGHTNESS_MODE_USER);
The Android Open Source Project10592532009-03-18 17:39:46 -07001723 if ((mask & BUTTON_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001724 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value,
1725 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001726 }
1727 if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05001728 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value,
1729 brightnessMode);
The Android Open Source Project10592532009-03-18 17:39:46 -07001730 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 }
1732
1733 class BrightnessState {
1734 final int mask;
1735
1736 boolean initialized;
1737 int targetValue;
1738 float curValue;
1739 float delta;
1740 boolean animating;
1741
1742 BrightnessState(int m) {
1743 mask = m;
1744 }
1745
1746 public void dump(PrintWriter pw, String prefix) {
1747 pw.println(prefix + "animating=" + animating
1748 + " targetValue=" + targetValue
1749 + " curValue=" + curValue
1750 + " delta=" + delta);
1751 }
1752
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001753 boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
Joe Onorato128e7292009-03-24 18:41:31 -07001754 int nominalCurrentValue) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001755 if (!initialized) {
1756 initialized = true;
1757 curValue = (float)initialValue;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001758 } else if (targetValue == target) {
1759 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 }
1761 targetValue = target;
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001762 delta = (targetValue -
1763 (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
1764 / stepsToTarget;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001765 if (mSpew) {
Joe Onorato128e7292009-03-24 18:41:31 -07001766 String noticeMe = nominalCurrentValue == curValue ? "" : " ******************";
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001767 Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
Joe Onorato128e7292009-03-24 18:41:31 -07001768 + " target=" + targetValue + " delta=" + delta
1769 + " nominalCurrentValue=" + nominalCurrentValue
1770 + noticeMe);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001771 }
1772 animating = true;
Dianne Hackbornaa80b602009-10-09 17:38:26 -07001773 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001774 }
1775
1776 boolean stepLocked() {
1777 if (!animating) return false;
1778 if (false && mSpew) {
1779 Log.i(TAG, "Step target " + mask + ": cur=" + curValue
1780 + " target=" + targetValue + " delta=" + delta);
1781 }
1782 curValue += delta;
1783 int curIntValue = (int)curValue;
1784 boolean more = true;
1785 if (delta == 0) {
Dianne Hackborn9ed4a4b2009-03-25 17:10:37 -07001786 curValue = curIntValue = targetValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 more = false;
1788 } else if (delta > 0) {
1789 if (curIntValue >= targetValue) {
1790 curValue = curIntValue = targetValue;
1791 more = false;
1792 }
1793 } else {
1794 if (curIntValue <= targetValue) {
1795 curValue = curIntValue = targetValue;
1796 more = false;
1797 }
1798 }
1799 //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
The Android Open Source Project10592532009-03-18 17:39:46 -07001800 setLightBrightness(mask, curIntValue);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 animating = more;
1802 if (!more) {
The Android Open Source Project10592532009-03-18 17:39:46 -07001803 if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
Joe Onorato128e7292009-03-24 18:41:31 -07001804 screenOffFinishedAnimatingLocked(mOffBecauseOfUser);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 }
1806 }
1807 return more;
1808 }
1809 }
1810
1811 private class LightAnimator implements Runnable {
1812 public void run() {
1813 synchronized (mLocks) {
1814 long now = SystemClock.uptimeMillis();
1815 boolean more = mScreenBrightness.stepLocked();
1816 if (mKeyboardBrightness.stepLocked()) {
1817 more = true;
1818 }
1819 if (mButtonBrightness.stepLocked()) {
1820 more = true;
1821 }
1822 if (more) {
1823 mHandler.postAtTime(mLightAnimator, now+(1000/60));
1824 }
1825 }
1826 }
1827 }
1828
1829 private int getPreferredBrightness() {
1830 try {
1831 if (mScreenBrightnessOverride >= 0) {
1832 return mScreenBrightnessOverride;
Mike Lockwood27c6dd72009-11-04 08:57:07 -05001833 } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness
1834 && mAutoBrightessEnabled) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001835 return mLightSensorBrightness;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001836 }
1837 final int brightness = Settings.System.getInt(mContext.getContentResolver(),
1838 SCREEN_BRIGHTNESS);
1839 // Don't let applications turn the screen all the way off
1840 return Math.max(brightness, Power.BRIGHTNESS_DIM);
1841 } catch (SettingNotFoundException snfe) {
1842 return Power.BRIGHTNESS_ON;
1843 }
1844 }
1845
Charles Mendis322591c2009-10-29 11:06:59 -07001846 public boolean isScreenOn() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001847 synchronized (mLocks) {
1848 return (mPowerState & SCREEN_ON_BIT) != 0;
1849 }
1850 }
1851
Charles Mendis322591c2009-10-29 11:06:59 -07001852 boolean isScreenBright() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001853 synchronized (mLocks) {
1854 return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
1855 }
1856 }
1857
Mike Lockwood497087e32009-11-08 18:33:03 -05001858 private boolean isScreenTurningOffLocked() {
1859 return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
1860 }
1861
Mike Lockwood200b30b2009-09-20 00:23:59 -04001862 private void forceUserActivityLocked() {
Mike Lockwoode090281422009-11-14 21:02:56 -05001863 if (isScreenTurningOffLocked()) {
1864 // cancel animation so userActivity will succeed
1865 mScreenBrightness.animating = false;
1866 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04001867 boolean savedActivityAllowed = mUserActivityAllowed;
1868 mUserActivityAllowed = true;
1869 userActivity(SystemClock.uptimeMillis(), false);
1870 mUserActivityAllowed = savedActivityAllowed;
1871 }
1872
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001873 public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
1874 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1875 userActivity(time, noChangeLights, OTHER_EVENT, force);
1876 }
1877
1878 public void userActivity(long time, boolean noChangeLights) {
1879 userActivity(time, noChangeLights, OTHER_EVENT, false);
1880 }
1881
1882 public void userActivity(long time, boolean noChangeLights, int eventType) {
1883 userActivity(time, noChangeLights, eventType, false);
1884 }
1885
1886 public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
1887 //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1888
1889 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001890 && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001891 if (false) {
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001892 Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001893 }
1894 return;
1895 }
1896
Joe Onoratoe68ffcb2009-03-24 19:11:13 -07001897 if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
1898 && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
1899 || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
1900 if (false) {
1901 Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
1902 }
1903 return;
1904 }
1905
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 if (false) {
1907 if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
1908 Log.d(TAG, "userActivity !!!");//, new RuntimeException());
1909 } else {
1910 Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
1911 }
1912 }
1913
1914 synchronized (mLocks) {
1915 if (mSpew) {
1916 Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
1917 + " mUserActivityAllowed=" + mUserActivityAllowed
1918 + " mUserState=0x" + Integer.toHexString(mUserState)
Mike Lockwood36fc3022009-08-25 16:49:06 -07001919 + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
1920 + " mProximitySensorActive=" + mProximitySensorActive
1921 + " force=" + force);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001922 }
Mike Lockwood05067122009-10-27 23:07:25 -04001923 // ignore user activity if we are in the process of turning off the screen
Mike Lockwood497087e32009-11-08 18:33:03 -05001924 if (isScreenTurningOffLocked()) {
Mike Lockwood05067122009-10-27 23:07:25 -04001925 Log.d(TAG, "ignoring user activity while turning off screen");
1926 return;
1927 }
Mike Lockwood0e39ea82009-11-18 15:37:10 -05001928 // Disable proximity sensor if if user presses power key while we are in the
1929 // "waiting for proximity sensor to go negative" state.
1930 if (mProximitySensorActive && mProximityWakeLockCount == 0) {
1931 mProximitySensorActive = false;
1932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 if (mLastEventTime <= time || force) {
1934 mLastEventTime = time;
Mike Lockwood36fc3022009-08-25 16:49:06 -07001935 if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
Mike Lockwoodd7786b42009-10-15 17:09:16 -07001936 // Only turn on button backlights if a button was pressed
1937 // and auto brightness is disabled
Mike Lockwood4984e732009-11-01 08:16:33 -05001938 if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001939 mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
1940 } else {
1941 // don't clear button/keyboard backlights when the screen is touched.
1942 mUserState |= SCREEN_BRIGHT;
1943 }
1944
Dianne Hackborn617f8772009-03-31 15:04:46 -07001945 int uid = Binder.getCallingUid();
1946 long ident = Binder.clearCallingIdentity();
1947 try {
1948 mBatteryStats.noteUserActivity(uid, eventType);
1949 } catch (RemoteException e) {
1950 // Ignore
1951 } finally {
1952 Binder.restoreCallingIdentity(ident);
1953 }
1954
Michael Chane96440f2009-05-06 10:27:36 -07001955 mWakeLockState = mLocks.reactivateScreenLocksLocked();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001956 setPowerState(mUserState | mWakeLockState, noChangeLights, true);
1957 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) {
2090 goToSleepLocked(time);
2091 }
2092 }
2093
2094 /**
Doug Zongker50a21f42009-11-19 12:49:53 -08002095 * Reboot the device immediately, passing 'reason' (may be null)
2096 * to the underlying __reboot system call. Should not return.
2097 */
2098 public void reboot(String reason)
2099 {
2100 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2101 try {
2102 Power.reboot(reason);
2103 } catch (IOException e) {
2104 Log.e(TAG, "reboot failed", e);
2105 }
2106 }
2107
2108 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002109 * Returns the time the screen has been on since boot, in millis.
2110 * @return screen on time
2111 */
2112 public long getScreenOnTime() {
2113 synchronized (mLocks) {
2114 if (mScreenOnStartTime == 0) {
2115 return mScreenOnTime;
2116 } else {
2117 return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime;
2118 }
2119 }
2120 }
2121
2122 private void goToSleepLocked(long time) {
2123
2124 if (mLastEventTime <= time) {
2125 mLastEventTime = time;
2126 // cancel all of the wake locks
2127 mWakeLockState = SCREEN_OFF;
2128 int N = mLocks.size();
2129 int numCleared = 0;
2130 for (int i=0; i<N; i++) {
2131 WakeLock wl = mLocks.get(i);
2132 if (isScreenLock(wl.flags)) {
2133 mLocks.get(i).activated = false;
2134 numCleared++;
2135 }
2136 }
2137 EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
Joe Onorato128e7292009-03-24 18:41:31 -07002138 mStillNeedSleepNotification = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002139 mUserState = SCREEN_OFF;
2140 setPowerState(SCREEN_OFF, false, true);
2141 cancelTimerLocked();
2142 }
2143 }
2144
2145 public long timeSinceScreenOn() {
2146 synchronized (mLocks) {
2147 if ((mPowerState & SCREEN_ON_BIT) != 0) {
2148 return 0;
2149 }
2150 return SystemClock.elapsedRealtime() - mScreenOffTime;
2151 }
2152 }
2153
2154 public void setKeyboardVisibility(boolean visible) {
Mike Lockwooda625b382009-09-12 17:36:03 -07002155 synchronized (mLocks) {
2156 if (mSpew) {
2157 Log.d(TAG, "setKeyboardVisibility: " + visible);
2158 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002159 if (mKeyboardVisible != visible) {
2160 mKeyboardVisible = visible;
2161 // don't signal user activity if the screen is off; other code
2162 // will take care of turning on due to a true change to the lid
2163 // switch and synchronized with the lock screen.
2164 if ((mPowerState & SCREEN_ON_BIT) != 0) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002165 if (mUseSoftwareAutoBrightness) {
Mike Lockwooddf024922009-10-29 21:29:15 -04002166 // force recompute of backlight values
2167 if (mLightSensorValue >= 0) {
2168 int value = (int)mLightSensorValue;
2169 mLightSensorValue = -1;
2170 lightSensorChangedLocked(value);
2171 }
2172 }
Mike Lockwood3c9435a2009-10-22 15:45:37 -04002173 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2174 }
Mike Lockwooda625b382009-09-12 17:36:03 -07002175 }
2176 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002177 }
2178
2179 /**
2180 * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
Mike Lockwood50c548d2009-11-09 16:02:06 -05002181 * When disabling user activity we also reset user power state so the keyguard can reset its
2182 * short screen timeout when keyguard is unhidden.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002183 */
2184 public void enableUserActivity(boolean enabled) {
Mike Lockwood50c548d2009-11-09 16:02:06 -05002185 if (mSpew) {
2186 Log.d(TAG, "enableUserActivity " + enabled);
2187 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002188 synchronized (mLocks) {
2189 mUserActivityAllowed = enabled;
Mike Lockwood50c548d2009-11-09 16:02:06 -05002190 if (!enabled) {
2191 // cancel timeout and clear mUserState so the keyguard can set a short timeout
2192 setTimeoutLocked(SystemClock.uptimeMillis(), 0);
2193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002194 }
2195 }
2196
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002197 private void setScreenBrightnessMode(int mode) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002198 boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
Mike Lockwoodf90ffcc2009-11-03 11:41:27 -05002199 if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
Mike Lockwood2d155d22009-10-27 09:32:30 -04002200 mAutoBrightessEnabled = enabled;
Charles Mendis322591c2009-10-29 11:06:59 -07002201 if (isScreenOn()) {
Mike Lockwood4984e732009-11-01 08:16:33 -05002202 // force recompute of backlight values
2203 if (mLightSensorValue >= 0) {
2204 int value = (int)mLightSensorValue;
2205 mLightSensorValue = -1;
2206 lightSensorChangedLocked(value);
2207 }
Mike Lockwood2d155d22009-10-27 09:32:30 -04002208 }
Mike Lockwooddc3494e2009-10-14 21:17:09 -07002209 }
2210 }
2211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002212 /** Sets the screen off timeouts:
2213 * mKeylightDelay
2214 * mDimDelay
2215 * mScreenOffDelay
2216 * */
2217 private void setScreenOffTimeoutsLocked() {
2218 if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
2219 mKeylightDelay = mShortKeylightDelay; // Configurable via Gservices
2220 mDimDelay = -1;
2221 mScreenOffDelay = 0;
2222 } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
2223 mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
2224 mDimDelay = -1;
2225 mScreenOffDelay = 0;
2226 } else {
2227 int totalDelay = mTotalDelaySetting;
2228 mKeylightDelay = LONG_KEYLIGHT_DELAY;
2229 if (totalDelay < 0) {
2230 mScreenOffDelay = Integer.MAX_VALUE;
2231 } else if (mKeylightDelay < totalDelay) {
2232 // subtract the time that the keylight delay. This will give us the
2233 // remainder of the time that we need to sleep to get the accurate
2234 // screen off timeout.
2235 mScreenOffDelay = totalDelay - mKeylightDelay;
2236 } else {
2237 mScreenOffDelay = 0;
2238 }
2239 if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
2240 mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
2241 mScreenOffDelay = LONG_DIM_TIME;
2242 } else {
2243 mDimDelay = -1;
2244 }
2245 }
2246 if (mSpew) {
2247 Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
2248 + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
2249 + " mDimScreen=" + mDimScreen);
2250 }
2251 }
2252
2253 /**
2254 * Refreshes cached Gservices settings. Called once on startup, and
2255 * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see
2256 * GservicesChangedReceiver).
2257 */
2258 private void updateGservicesValues() {
2259 mShortKeylightDelay = Settings.Gservices.getInt(
2260 mContext.getContentResolver(),
2261 Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS,
2262 SHORT_KEYLIGHT_DELAY_DEFAULT);
2263 // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay);
2264 }
2265
2266 /**
2267 * Receiver for the Gservices.CHANGED_ACTION broadcast intent,
2268 * which tells us we need to refresh our cached Gservices settings.
2269 */
2270 private class GservicesChangedReceiver extends BroadcastReceiver {
2271 @Override
2272 public void onReceive(Context context, Intent intent) {
2273 // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent);
2274 updateGservicesValues();
2275 }
2276 }
2277
2278 private class LockList extends ArrayList<WakeLock>
2279 {
2280 void addLock(WakeLock wl)
2281 {
2282 int index = getIndex(wl.binder);
2283 if (index < 0) {
2284 this.add(wl);
2285 }
2286 }
2287
2288 WakeLock removeLock(IBinder binder)
2289 {
2290 int index = getIndex(binder);
2291 if (index >= 0) {
2292 return this.remove(index);
2293 } else {
2294 return null;
2295 }
2296 }
2297
2298 int getIndex(IBinder binder)
2299 {
2300 int N = this.size();
2301 for (int i=0; i<N; i++) {
2302 if (this.get(i).binder == binder) {
2303 return i;
2304 }
2305 }
2306 return -1;
2307 }
2308
2309 int gatherState()
2310 {
2311 int result = 0;
2312 int N = this.size();
2313 for (int i=0; i<N; i++) {
2314 WakeLock wl = this.get(i);
2315 if (wl.activated) {
2316 if (isScreenLock(wl.flags)) {
2317 result |= wl.minState;
2318 }
2319 }
2320 }
2321 return result;
2322 }
Michael Chane96440f2009-05-06 10:27:36 -07002323
2324 int reactivateScreenLocksLocked()
2325 {
2326 int result = 0;
2327 int N = this.size();
2328 for (int i=0; i<N; i++) {
2329 WakeLock wl = this.get(i);
2330 if (isScreenLock(wl.flags)) {
2331 wl.activated = true;
2332 result |= wl.minState;
2333 }
2334 }
2335 return result;
2336 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002337 }
2338
2339 void setPolicy(WindowManagerPolicy p) {
2340 synchronized (mLocks) {
2341 mPolicy = p;
2342 mLocks.notifyAll();
2343 }
2344 }
2345
2346 WindowManagerPolicy getPolicyLocked() {
2347 while (mPolicy == null || !mDoneBooting) {
2348 try {
2349 mLocks.wait();
2350 } catch (InterruptedException e) {
2351 // Ignore
2352 }
2353 }
2354 return mPolicy;
2355 }
2356
2357 void systemReady() {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002358 mSensorManager = new SensorManager(mHandlerThread.getLooper());
2359 mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
2360 // don't bother with the light sensor if auto brightness is handled in hardware
Mike Lockwoodaa66ea82009-10-31 16:31:27 -04002361 if (mUseSoftwareAutoBrightness) {
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002362 mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
Mike Lockwood4984e732009-11-01 08:16:33 -05002363 enableLightSensor(true);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002364 }
2365
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002366 synchronized (mLocks) {
2367 Log.d(TAG, "system ready!");
2368 mDoneBooting = true;
Dianne Hackborn617f8772009-03-31 15:04:46 -07002369 long identity = Binder.clearCallingIdentity();
2370 try {
2371 mBatteryStats.noteScreenBrightness(getPreferredBrightness());
2372 mBatteryStats.noteScreenOn();
2373 } catch (RemoteException e) {
2374 // Nothing interesting to do.
2375 } finally {
2376 Binder.restoreCallingIdentity(identity);
2377 }
Mike Lockwood2d7bb812009-11-15 18:12:22 -05002378 }
2379 }
2380
2381 void bootCompleted() {
2382 Log.d(TAG, "bootCompleted");
2383 synchronized (mLocks) {
2384 mBootCompleted = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002385 userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2386 updateWakeLockLocked();
2387 mLocks.notifyAll();
2388 }
2389 }
2390
2391 public void monitor() {
2392 synchronized (mLocks) { }
2393 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002394
2395 public int getSupportedWakeLockFlags() {
2396 int result = PowerManager.PARTIAL_WAKE_LOCK
2397 | PowerManager.FULL_WAKE_LOCK
2398 | PowerManager.SCREEN_DIM_WAKE_LOCK;
2399
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002400 if (mProximitySensor != null) {
2401 result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
2402 }
2403
2404 return result;
2405 }
2406
Mike Lockwood237a2992009-09-15 14:42:16 -04002407 public void setBacklightBrightness(int brightness) {
2408 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2409 // Don't let applications turn the screen all the way off
2410 brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002411 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness,
2412 HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwooddf024922009-10-29 21:29:15 -04002413 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
Mike Lockwoodcc9a63d2009-11-10 07:50:28 -05002414 (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);
2415 mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness,
2416 HardwareService.BRIGHTNESS_MODE_USER);
Mike Lockwood237a2992009-09-15 14:42:16 -04002417 long identity = Binder.clearCallingIdentity();
2418 try {
2419 mBatteryStats.noteScreenBrightness(brightness);
2420 } catch (RemoteException e) {
2421 Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2422 } finally {
2423 Binder.restoreCallingIdentity(identity);
2424 }
2425
2426 // update our animation state
2427 if (ANIMATE_SCREEN_LIGHTS) {
2428 mScreenBrightness.curValue = brightness;
2429 mScreenBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002430 mScreenBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002431 }
2432 if (ANIMATE_KEYBOARD_LIGHTS) {
2433 mKeyboardBrightness.curValue = brightness;
2434 mKeyboardBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002435 mKeyboardBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002436 }
2437 if (ANIMATE_BUTTON_LIGHTS) {
2438 mButtonBrightness.curValue = brightness;
2439 mButtonBrightness.animating = false;
Mike Lockwooddd9668e2009-10-27 15:47:02 -04002440 mButtonBrightness.targetValue = -1;
Mike Lockwood237a2992009-09-15 14:42:16 -04002441 }
2442 }
2443
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002444 private void enableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002445 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002446 Log.d(TAG, "enableProximityLockLocked");
2447 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002448 if (!mProximitySensorEnabled) {
2449 // clear calling identity so sensor manager battery stats are accurate
2450 long identity = Binder.clearCallingIdentity();
2451 try {
2452 mSensorManager.registerListener(mProximityListener, mProximitySensor,
2453 SensorManager.SENSOR_DELAY_NORMAL);
2454 mProximitySensorEnabled = true;
2455 } finally {
2456 Binder.restoreCallingIdentity(identity);
2457 }
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002458 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002459 }
2460
2461 private void disableProximityLockLocked() {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002462 if (mDebugProximitySensor) {
Mike Lockwood36fc3022009-08-25 16:49:06 -07002463 Log.d(TAG, "disableProximityLockLocked");
2464 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002465 if (mProximitySensorEnabled) {
2466 // clear calling identity so sensor manager battery stats are accurate
2467 long identity = Binder.clearCallingIdentity();
2468 try {
2469 mSensorManager.unregisterListener(mProximityListener);
2470 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002471 if (mProximityPartialLock.isHeld()) {
2472 mProximityPartialLock.release();
2473 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002474 mProximitySensorEnabled = false;
2475 } finally {
2476 Binder.restoreCallingIdentity(identity);
2477 }
2478 if (mProximitySensorActive) {
2479 mProximitySensorActive = false;
2480 forceUserActivityLocked();
2481 }
Mike Lockwood200b30b2009-09-20 00:23:59 -04002482 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002483 }
2484
Mike Lockwood20f87d72009-11-05 16:08:51 -05002485 private void proximityChangedLocked(boolean active) {
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002486 if (mDebugProximitySensor) {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002487 Log.d(TAG, "proximityChangedLocked, active: " + active);
2488 }
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002489 if (!mProximitySensorEnabled) {
2490 Log.d(TAG, "Ignoring proximity change after sensor is disabled");
Mike Lockwood0d72f7e2009-11-05 20:53:00 -05002491 return;
2492 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002493 if (active) {
2494 goToSleepLocked(SystemClock.uptimeMillis());
2495 mProximitySensorActive = true;
2496 } else {
2497 // proximity sensor negative events trigger as user activity.
2498 // temporarily set mUserActivityAllowed to true so this will work
2499 // even when the keyguard is on.
2500 mProximitySensorActive = false;
2501 forceUserActivityLocked();
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002502
2503 if (mProximityWakeLockCount == 0) {
2504 // disable sensor if we have no listeners left after proximity negative
2505 disableProximityLockLocked();
2506 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002507 }
2508 }
2509
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002510 private void enableLightSensor(boolean enable) {
2511 if (mDebugLightSensor) {
2512 Log.d(TAG, "enableLightSensor " + enable);
2513 }
2514 if (mSensorManager != null && mLightSensorEnabled != enable) {
2515 mLightSensorEnabled = enable;
Mike Lockwood809ad0f2009-10-26 22:10:33 -04002516 // clear calling identity so sensor manager battery stats are accurate
2517 long identity = Binder.clearCallingIdentity();
2518 try {
2519 if (enable) {
2520 mSensorManager.registerListener(mLightListener, mLightSensor,
2521 SensorManager.SENSOR_DELAY_NORMAL);
2522 } else {
2523 mSensorManager.unregisterListener(mLightListener);
2524 mHandler.removeCallbacks(mAutoBrightnessTask);
2525 }
2526 } finally {
2527 Binder.restoreCallingIdentity(identity);
Mike Lockwood06952d92009-08-13 16:05:38 -04002528 }
Mike Lockwoodbc706a02009-07-27 13:50:57 -07002529 }
2530 }
2531
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002532 SensorEventListener mProximityListener = new SensorEventListener() {
2533 public void onSensorChanged(SensorEvent event) {
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002534 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002535 synchronized (mLocks) {
2536 float distance = event.values[0];
Mike Lockwood20f87d72009-11-05 16:08:51 -05002537 long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
2538 mLastProximityEventTime = milliseconds;
2539 mHandler.removeCallbacks(mProximityTask);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002540 boolean proximityTaskQueued = false;
Mike Lockwood20f87d72009-11-05 16:08:51 -05002541
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002542 // compare against getMaximumRange to support sensors that only return 0 or 1
Mike Lockwood20f87d72009-11-05 16:08:51 -05002543 boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
2544 distance < mProximitySensor.getMaximumRange());
2545
Mike Lockwoodee2b0942009-11-09 14:09:02 -05002546 if (mDebugProximitySensor) {
2547 Log.d(TAG, "mProximityListener.onSensorChanged active: " + active);
2548 }
Mike Lockwood20f87d72009-11-05 16:08:51 -05002549 if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
2550 // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
2551 mProximityPendingValue = (active ? 1 : 0);
2552 mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002553 proximityTaskQueued = true;
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002554 } else {
Mike Lockwood20f87d72009-11-05 16:08:51 -05002555 // process the value immediately
2556 mProximityPendingValue = -1;
2557 proximityChangedLocked(active);
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002558 }
Mike Lockwood0e5bb7f2009-11-14 06:36:31 -05002559
2560 // update mProximityPartialLock state
2561 boolean held = mProximityPartialLock.isHeld();
2562 if (!held && proximityTaskQueued) {
2563 // hold wakelock until mProximityTask runs
2564 mProximityPartialLock.acquire();
2565 } else if (held && !proximityTaskQueued) {
2566 mProximityPartialLock.release();
2567 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002568 }
2569 }
2570
2571 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2572 // ignore
2573 }
2574 };
2575
2576 SensorEventListener mLightListener = new SensorEventListener() {
2577 public void onSensorChanged(SensorEvent event) {
2578 synchronized (mLocks) {
Mike Lockwood497087e32009-11-08 18:33:03 -05002579 // ignore light sensor while screen is turning off
2580 if (isScreenTurningOffLocked()) {
2581 return;
2582 }
2583
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002584 int value = (int)event.values[0];
Mike Lockwoodba8eb1e2009-11-08 19:31:18 -05002585 long milliseconds = SystemClock.elapsedRealtime();
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002586 if (mDebugLightSensor) {
2587 Log.d(TAG, "onSensorChanged: light value: " + value);
2588 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002589 mHandler.removeCallbacks(mAutoBrightnessTask);
2590 if (mLightSensorValue != value) {
Mike Lockwood20ee6f22009-11-07 20:33:47 -05002591 if (mLightSensorValue == -1 ||
2592 milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
2593 // process the value immediately if screen has just turned on
Mike Lockwood6c97fca2009-10-20 08:10:00 -04002594 lightSensorChangedLocked(value);
2595 } else {
2596 // delay processing to debounce the sensor
2597 mLightSensorPendingValue = value;
2598 mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
2599 }
Mike Lockwoodd7786b42009-10-15 17:09:16 -07002600 } else {
2601 mLightSensorPendingValue = -1;
2602 }
Mike Lockwood8738e0c2009-10-04 08:44:47 -04002603 }
2604 }
2605
2606 public void onAccuracyChanged(Sensor sensor, int accuracy) {
2607 // ignore
2608 }
2609 };
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002610}