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