1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import com.android.internal.app.IBatteryStats;
20import com.android.internal.app.ShutdownThread;
21import com.android.server.am.BatteryStatsService;
22
23import android.app.ActivityManagerNative;
24import android.app.IActivityManager;
25import android.content.BroadcastReceiver;
26import android.content.ContentQueryMap;
27import android.content.ContentResolver;
28import android.content.ContentValues;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.content.pm.PackageManager;
33import android.content.res.Resources;
34import android.database.ContentObserver;
35import android.database.Cursor;
36import android.hardware.Sensor;
37import android.hardware.SensorEvent;
38import android.hardware.SensorEventListener;
39import android.hardware.SensorManager;
40import android.os.BatteryManager;
41import android.os.BatteryStats;
42import android.os.Binder;
43import android.os.Handler;
44import android.os.HandlerThread;
45import android.os.IBinder;
46import android.os.IPowerManager;
47import android.os.LocalPowerManager;
48import android.os.Power;
49import android.os.PowerManager;
50import android.os.Process;
51import android.os.RemoteException;
52import android.os.SystemClock;
53import android.os.WorkSource;
54import android.provider.Settings.SettingNotFoundException;
55import android.provider.Settings;
56import android.util.EventLog;
57import android.util.Log;
58import android.util.Slog;
59import android.view.WindowManagerPolicy;
60import static android.provider.Settings.System.DIM_SCREEN;
61import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
62import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
63import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
64import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
65import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
66import static android.provider.Settings.System.WINDOW_ANIMATION_SCALE;
67import static android.provider.Settings.System.TRANSITION_ANIMATION_SCALE;
68
69import java.io.FileDescriptor;
70import java.io.PrintWriter;
71import java.util.ArrayList;
72import java.util.HashMap;
73import java.util.Observable;
74import java.util.Observer;
75
76public class PowerManagerService extends IPowerManager.Stub
77        implements LocalPowerManager, Watchdog.Monitor {
78
79    private static final String TAG = "PowerManagerService";
80    static final String PARTIAL_NAME = "PowerManagerService";
81
82    static final boolean DEBUG_SCREEN_ON = false;
83
84    private static final boolean LOG_PARTIAL_WL = false;
85
86    // Indicates whether touch-down cycles should be logged as part of the
87    // LOG_POWER_SCREEN_STATE log events
88    private static final boolean LOG_TOUCH_DOWNS = true;
89
90    private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
91                                        | PowerManager.SCREEN_DIM_WAKE_LOCK
92                                        | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
93                                        | PowerManager.FULL_WAKE_LOCK
94                                        | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
95
96    //                       time since last state:               time since last event:
97    // The short keylight delay comes from secure settings; this is the default.
98    private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
99    private static final int MEDIUM_KEYLIGHT_DELAY = 15000;       // t+15 sec
100    private static final int LONG_KEYLIGHT_DELAY = 6000;        // t+6 sec
101    private static final int LONG_DIM_TIME = 7000;              // t+N-5 sec
102
103    // How long to wait to debounce light sensor changes in milliseconds
104    private static final int LIGHT_SENSOR_DELAY = 2000;
105
106    // light sensor events rate in microseconds
107    private static final int LIGHT_SENSOR_RATE = 1000000;
108
109    // For debouncing the proximity sensor in milliseconds
110    private static final int PROXIMITY_SENSOR_DELAY = 1000;
111
112    // trigger proximity if distance is less than 5 cm
113    private static final float PROXIMITY_THRESHOLD = 5.0f;
114
115    // Cached secure settings; see updateSettingsValues()
116    private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
117
118    // Default timeout for screen off, if not found in settings database = 15 seconds.
119    private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15000;
120
121    // flags for setPowerState
122    private static final int SCREEN_ON_BIT          = 0x00000001;
123    private static final int SCREEN_BRIGHT_BIT      = 0x00000002;
124    private static final int BUTTON_BRIGHT_BIT      = 0x00000004;
125    private static final int KEYBOARD_BRIGHT_BIT    = 0x00000008;
126    private static final int BATTERY_LOW_BIT        = 0x00000010;
127
128    // values for setPowerState
129
130    // SCREEN_OFF == everything off
131    private static final int SCREEN_OFF         = 0x00000000;
132
133    // SCREEN_DIM == screen on, screen backlight dim
134    private static final int SCREEN_DIM         = SCREEN_ON_BIT;
135
136    // SCREEN_BRIGHT == screen on, screen backlight bright
137    private static final int SCREEN_BRIGHT      = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
138
139    // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
140    private static final int SCREEN_BUTTON_BRIGHT  = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
141
142    // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
143    private static final int ALL_BRIGHT         = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
144
145    // used for noChangeLights in setPowerState()
146    private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
147
148    boolean mAnimateScreenLights = true;
149
150    static final int ANIM_STEPS = 60/4;
151    // Slower animation for autobrightness changes
152    static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;
153
154    // These magic numbers are the initial state of the LEDs at boot.  Ideally
155    // we should read them from the driver, but our current hardware returns 0
156    // for the initial value.  Oops!
157    static final int INITIAL_SCREEN_BRIGHTNESS = 255;
158    static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
159    static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
160
161    private final int MY_UID;
162    private final int MY_PID;
163
164    private boolean mDoneBooting = false;
165    private boolean mBootCompleted = false;
166    private int mStayOnConditions = 0;
167    private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
168    private final int[] mBroadcastWhy = new int[3];
169    private boolean mPreparingForScreenOn = false;
170    private boolean mSkippedScreenOn = false;
171    private boolean mInitialized = false;
172    private int mPartialCount = 0;
173    private int mPowerState;
174    // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
175    // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
176    private int mScreenOffReason;
177    private int mUserState;
178    private boolean mKeyboardVisible = false;
179    private boolean mUserActivityAllowed = true;
180    private int mProximityWakeLockCount = 0;
181    private boolean mProximitySensorEnabled = false;
182    private boolean mProximitySensorActive = false;
183    private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
184    private long mLastProximityEventTime;
185    private int mScreenOffTimeoutSetting;
186    private int mMaximumScreenOffTimeout = Integer.MAX_VALUE;
187    private int mKeylightDelay;
188    private int mDimDelay;
189    private int mScreenOffDelay;
190    private int mWakeLockState;
191    private long mLastEventTime = 0;
192    private long mScreenOffTime;
193    private volatile WindowManagerPolicy mPolicy;
194    private final LockList mLocks = new LockList();
195    private Intent mScreenOffIntent;
196    private Intent mScreenOnIntent;
197    private LightsService mLightsService;
198    private Context mContext;
199    private LightsService.Light mLcdLight;
200    private LightsService.Light mButtonLight;
201    private LightsService.Light mKeyboardLight;
202    private LightsService.Light mAttentionLight;
203    private UnsynchronizedWakeLock mBroadcastWakeLock;
204    private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
205    private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
206    private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
207    private UnsynchronizedWakeLock mProximityPartialLock;
208    private HandlerThread mHandlerThread;
209    private HandlerThread mScreenOffThread;
210    private Handler mScreenOffHandler;
211    private Handler mHandler;
212    private final TimeoutTask mTimeoutTask = new TimeoutTask();
213    private final BrightnessState mScreenBrightness
214            = new BrightnessState(SCREEN_BRIGHT_BIT);
215    private boolean mStillNeedSleepNotification;
216    private boolean mIsPowered = false;
217    private IActivityManager mActivityService;
218    private IBatteryStats mBatteryStats;
219    private BatteryService mBatteryService;
220    private SensorManager mSensorManager;
221    private Sensor mProximitySensor;
222    private Sensor mLightSensor;
223    private boolean mLightSensorEnabled;
224    private float mLightSensorValue = -1;
225    private boolean mProxIgnoredBecauseScreenTurnedOff = false;
226    private int mHighestLightSensorValue = -1;
227    private boolean mLightSensorPendingDecrease = false;
228    private boolean mLightSensorPendingIncrease = false;
229    private float mLightSensorPendingValue = -1;
230    private int mLightSensorScreenBrightness = -1;
231    private int mLightSensorButtonBrightness = -1;
232    private int mLightSensorKeyboardBrightness = -1;
233    private boolean mDimScreen = true;
234    private boolean mIsDocked = false;
235    private long mNextTimeout;
236    private volatile int mPokey = 0;
237    private volatile boolean mPokeAwakeOnSet = false;
238    private volatile boolean mInitComplete = false;
239    private final HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
240    // mLastScreenOnTime is the time the screen was last turned on
241    private long mLastScreenOnTime;
242    private boolean mPreventScreenOn;
243    private int mScreenBrightnessOverride = -1;
244    private int mButtonBrightnessOverride = -1;
245    private int mScreenBrightnessDim;
246    private boolean mUseSoftwareAutoBrightness;
247    private boolean mAutoBrightessEnabled;
248    private int[] mAutoBrightnessLevels;
249    private int[] mLcdBacklightValues;
250    private int[] mButtonBacklightValues;
251    private int[] mKeyboardBacklightValues;
252    private int mLightSensorWarmupTime;
253    boolean mUnplugTurnsOnScreen;
254    private int mWarningSpewThrottleCount;
255    private long mWarningSpewThrottleTime;
256    private int mAnimationSetting = ANIM_SETTING_OFF;
257
258    // Must match with the ISurfaceComposer constants in C++.
259    private static final int ANIM_SETTING_ON = 0x01;
260    private static final int ANIM_SETTING_OFF = 0x10;
261
262    // Used when logging number and duration of touch-down cycles
263    private long mTotalTouchDownTime;
264    private long mLastTouchDown;
265    private int mTouchCycles;
266
267    // could be either static or controllable at runtime
268    private static final boolean mSpew = false;
269    private static final boolean mDebugProximitySensor = (false || mSpew);
270    private static final boolean mDebugLightSensor = (false || mSpew);
271
272    private native void nativeInit();
273    private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
274    private native void nativeStartSurfaceFlingerAnimation(int mode);
275
276    /*
277    static PrintStream mLog;
278    static {
279        try {
280            mLog = new PrintStream("/data/power.log");
281        }
282        catch (FileNotFoundException e) {
283            android.util.Slog.e(TAG, "Life is hard", e);
284        }
285    }
286    static class Log {
287        static void d(String tag, String s) {
288            mLog.println(s);
289            android.util.Slog.d(tag, s);
290        }
291        static void i(String tag, String s) {
292            mLog.println(s);
293            android.util.Slog.i(tag, s);
294        }
295        static void w(String tag, String s) {
296            mLog.println(s);
297            android.util.Slog.w(tag, s);
298        }
299        static void e(String tag, String s) {
300            mLog.println(s);
301            android.util.Slog.e(tag, s);
302        }
303    }
304    */
305
306    /**
307     * This class works around a deadlock between the lock in PowerManager.WakeLock
308     * and our synchronizing on mLocks.  PowerManager.WakeLock synchronizes on its
309     * mToken object so it can be accessed from any thread, but it calls into here
310     * with its lock held.  This class is essentially a reimplementation of
311     * PowerManager.WakeLock, but without that extra synchronized block, because we'll
312     * only call it with our own locks held.
313     */
314    private class UnsynchronizedWakeLock {
315        int mFlags;
316        String mTag;
317        IBinder mToken;
318        int mCount = 0;
319        boolean mRefCounted;
320        boolean mHeld;
321
322        UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
323            mFlags = flags;
324            mTag = tag;
325            mToken = new Binder();
326            mRefCounted = refCounted;
327        }
328
329        public void acquire() {
330            if (!mRefCounted || mCount++ == 0) {
331                long ident = Binder.clearCallingIdentity();
332                try {
333                    PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
334                            MY_UID, MY_PID, mTag, null);
335                    mHeld = true;
336                } finally {
337                    Binder.restoreCallingIdentity(ident);
338                }
339            }
340        }
341
342        public void release() {
343            if (!mRefCounted || --mCount == 0) {
344                PowerManagerService.this.releaseWakeLockLocked(mToken, 0, false);
345                mHeld = false;
346            }
347            if (mCount < 0) {
348                throw new RuntimeException("WakeLock under-locked " + mTag);
349            }
350        }
351
352        public boolean isHeld()
353        {
354            return mHeld;
355        }
356
357        public String toString() {
358            return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
359                    + " mCount=" + mCount + " mHeld=" + mHeld + ")";
360        }
361    }
362
363    private final class BatteryReceiver extends BroadcastReceiver {
364        @Override
365        public void onReceive(Context context, Intent intent) {
366            synchronized (mLocks) {
367                boolean wasPowered = mIsPowered;
368                mIsPowered = mBatteryService.isPowered();
369
370                if (mIsPowered != wasPowered) {
371                    // update mStayOnWhilePluggedIn wake lock
372                    updateWakeLockLocked();
373
374                    // treat plugging and unplugging the devices as a user activity.
375                    // users find it disconcerting when they unplug the device
376                    // and it shuts off right away.
377                    // to avoid turning on the screen when unplugging, we only trigger
378                    // user activity when screen was already on.
379                    // temporarily set mUserActivityAllowed to true so this will work
380                    // even when the keyguard is on.
381                    // However, you can also set config_unplugTurnsOnScreen to have it
382                    // turn on.  Some devices want this because they don't have a
383                    // charging LED.
384                    synchronized (mLocks) {
385                        if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0 ||
386                                mUnplugTurnsOnScreen) {
387                            forceUserActivityLocked();
388                        }
389                    }
390                }
391            }
392        }
393    }
394
395    private final class BootCompletedReceiver extends BroadcastReceiver {
396        @Override
397        public void onReceive(Context context, Intent intent) {
398            bootCompleted();
399        }
400    }
401
402    private final class DockReceiver extends BroadcastReceiver {
403        @Override
404        public void onReceive(Context context, Intent intent) {
405            int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
406                    Intent.EXTRA_DOCK_STATE_UNDOCKED);
407            dockStateChanged(state);
408        }
409    }
410
411    /**
412     * Set the setting that determines whether the device stays on when plugged in.
413     * The argument is a bit string, with each bit specifying a power source that,
414     * when the device is connected to that source, causes the device to stay on.
415     * See {@link android.os.BatteryManager} for the list of power sources that
416     * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
417     * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
418     * @param val an {@code int} containing the bits that specify which power sources
419     * should cause the device to stay on.
420     */
421    public void setStayOnSetting(int val) {
422        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
423        Settings.System.putInt(mContext.getContentResolver(),
424                Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
425    }
426
427    public void setMaximumScreenOffTimeount(int timeMs) {
428        mContext.enforceCallingOrSelfPermission(
429                android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
430        synchronized (mLocks) {
431            mMaximumScreenOffTimeout = timeMs;
432            // recalculate everything
433            setScreenOffTimeoutsLocked();
434        }
435    }
436
437    private class SettingsObserver implements Observer {
438        private int getInt(String name, int defValue) {
439            ContentValues values = mSettings.getValues(name);
440            Integer iVal = values != null ? values.getAsInteger(Settings.System.VALUE) : null;
441            return iVal != null ? iVal : defValue;
442        }
443
444        private float getFloat(String name, float defValue) {
445            ContentValues values = mSettings.getValues(name);
446            Float fVal = values != null ? values.getAsFloat(Settings.System.VALUE) : null;
447            return fVal != null ? fVal : defValue;
448        }
449
450        public void update(Observable o, Object arg) {
451            synchronized (mLocks) {
452                // STAY_ON_WHILE_PLUGGED_IN, default to when plugged into AC
453                mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN,
454                        BatteryManager.BATTERY_PLUGGED_AC);
455                updateWakeLockLocked();
456
457                // SCREEN_OFF_TIMEOUT, default to 15 seconds
458                mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
459
460                // DIM_SCREEN
461                //mDimScreen = getInt(DIM_SCREEN) != 0;
462
463                // SCREEN_BRIGHTNESS_MODE, default to manual
464                setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE,
465                        Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL));
466
467                // recalculate everything
468                setScreenOffTimeoutsLocked();
469
470                final float windowScale = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
471                final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f);
472                mAnimationSetting = 0;
473                if (windowScale > 0.5f) {
474                    mAnimationSetting |= ANIM_SETTING_OFF;
475                }
476                if (transitionScale > 0.5f) {
477                    // Uncomment this if you want the screen-on animation.
478                    // mAnimationSetting |= ANIM_SETTING_ON;
479                }
480            }
481        }
482    }
483
484    PowerManagerService() {
485        // Hack to get our uid...  should have a func for this.
486        long token = Binder.clearCallingIdentity();
487        MY_UID = Process.myUid();
488        MY_PID = Process.myPid();
489        Binder.restoreCallingIdentity(token);
490
491        // XXX remove this when the kernel doesn't timeout wake locks
492        Power.setLastUserActivityTimeout(7*24*3600*1000); // one week
493
494        // assume nothing is on yet
495        mUserState = mPowerState = 0;
496
497        // Add ourself to the Watchdog monitors.
498        Watchdog.getInstance().addMonitor(this);
499    }
500
501    private ContentQueryMap mSettings;
502
503    void init(Context context, LightsService lights, IActivityManager activity,
504            BatteryService battery) {
505        mLightsService = lights;
506        mContext = context;
507        mActivityService = activity;
508        mBatteryStats = BatteryStatsService.getService();
509        mBatteryService = battery;
510
511        mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
512        mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
513        mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
514        mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
515
516        nativeInit();
517        synchronized (mLocks) {
518            updateNativePowerStateLocked();
519        }
520
521        mInitComplete = false;
522        mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") {
523            @Override
524            protected void onLooperPrepared() {
525                mScreenOffHandler = new Handler();
526                synchronized (mScreenOffThread) {
527                    mInitComplete = true;
528                    mScreenOffThread.notifyAll();
529                }
530            }
531        };
532        mScreenOffThread.start();
533
534        synchronized (mScreenOffThread) {
535            while (!mInitComplete) {
536                try {
537                    mScreenOffThread.wait();
538                } catch (InterruptedException e) {
539                    // Ignore
540                }
541            }
542        }
543
544        mInitComplete = false;
545        mHandlerThread = new HandlerThread("PowerManagerService") {
546            @Override
547            protected void onLooperPrepared() {
548                super.onLooperPrepared();
549                initInThread();
550            }
551        };
552        mHandlerThread.start();
553
554        synchronized (mHandlerThread) {
555            while (!mInitComplete) {
556                try {
557                    mHandlerThread.wait();
558                } catch (InterruptedException e) {
559                    // Ignore
560                }
561            }
562        }
563
564        nativeInit();
565        synchronized (mLocks) {
566            updateNativePowerStateLocked();
567            // We make sure to start out with the screen on due to user activity.
568            // (They did just boot their device, after all.)
569            forceUserActivityLocked();
570            mInitialized = true;
571        }
572    }
573
574    void initInThread() {
575        mHandler = new Handler();
576
577        mBroadcastWakeLock = new UnsynchronizedWakeLock(
578                                PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
579        mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
580                                PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
581        mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
582                                PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
583        mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
584                                PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
585        mProximityPartialLock = new UnsynchronizedWakeLock(
586                                PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
587
588        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
589        mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
590        mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
591        mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
592
593        Resources resources = mContext.getResources();
594
595        mAnimateScreenLights = resources.getBoolean(
596                com.android.internal.R.bool.config_animateScreenLights);
597
598        mUnplugTurnsOnScreen = resources.getBoolean(
599                com.android.internal.R.bool.config_unplugTurnsOnScreen);
600
601        mScreenBrightnessDim = resources.getInteger(
602                com.android.internal.R.integer.config_screenBrightnessDim);
603
604        // read settings for auto-brightness
605        mUseSoftwareAutoBrightness = resources.getBoolean(
606                com.android.internal.R.bool.config_automatic_brightness_available);
607        if (mUseSoftwareAutoBrightness) {
608            mAutoBrightnessLevels = resources.getIntArray(
609                    com.android.internal.R.array.config_autoBrightnessLevels);
610            mLcdBacklightValues = resources.getIntArray(
611                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
612            mButtonBacklightValues = resources.getIntArray(
613                    com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
614            mKeyboardBacklightValues = resources.getIntArray(
615                    com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
616            mLightSensorWarmupTime = resources.getInteger(
617                    com.android.internal.R.integer.config_lightSensorWarmupTime);
618        }
619
620       ContentResolver resolver = mContext.getContentResolver();
621        Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
622                "(" + Settings.System.NAME + "=?) or ("
623                        + Settings.System.NAME + "=?) or ("
624                        + Settings.System.NAME + "=?) or ("
625                        + Settings.System.NAME + "=?) or ("
626                        + Settings.System.NAME + "=?) or ("
627                        + Settings.System.NAME + "=?)",
628                new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
629                        SCREEN_BRIGHTNESS_MODE, WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE},
630                null);
631        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
632        SettingsObserver settingsObserver = new SettingsObserver();
633        mSettings.addObserver(settingsObserver);
634
635        // pretend that the settings changed so we will get their initial state
636        settingsObserver.update(mSettings, null);
637
638        // register for the battery changed notifications
639        IntentFilter filter = new IntentFilter();
640        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
641        mContext.registerReceiver(new BatteryReceiver(), filter);
642        filter = new IntentFilter();
643        filter.addAction(Intent.ACTION_BOOT_COMPLETED);
644        mContext.registerReceiver(new BootCompletedReceiver(), filter);
645        filter = new IntentFilter();
646        filter.addAction(Intent.ACTION_DOCK_EVENT);
647        mContext.registerReceiver(new DockReceiver(), filter);
648
649        // Listen for secure settings changes
650        mContext.getContentResolver().registerContentObserver(
651            Settings.Secure.CONTENT_URI, true,
652            new ContentObserver(new Handler()) {
653                public void onChange(boolean selfChange) {
654                    updateSettingsValues();
655                }
656            });
657        updateSettingsValues();
658
659        synchronized (mHandlerThread) {
660            mInitComplete = true;
661            mHandlerThread.notifyAll();
662        }
663    }
664
665    private class WakeLock implements IBinder.DeathRecipient
666    {
667        WakeLock(int f, IBinder b, String t, int u, int p) {
668            super();
669            flags = f;
670            binder = b;
671            tag = t;
672            uid = u == MY_UID ? Process.SYSTEM_UID : u;
673            pid = p;
674            if (u != MY_UID || (
675                    !"KEEP_SCREEN_ON_FLAG".equals(tag)
676                    && !"KeyInputQueue".equals(tag))) {
677                monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
678                        ? BatteryStats.WAKE_TYPE_PARTIAL
679                        : BatteryStats.WAKE_TYPE_FULL;
680            } else {
681                monitorType = -1;
682            }
683            try {
684                b.linkToDeath(this, 0);
685            } catch (RemoteException e) {
686                binderDied();
687            }
688        }
689        public void binderDied() {
690            synchronized (mLocks) {
691                releaseWakeLockLocked(this.binder, 0, true);
692            }
693        }
694        final int flags;
695        final IBinder binder;
696        final String tag;
697        final int uid;
698        final int pid;
699        final int monitorType;
700        WorkSource ws;
701        boolean activated = true;
702        int minState;
703    }
704
705    private void updateWakeLockLocked() {
706        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
707            // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
708            mStayOnWhilePluggedInScreenDimLock.acquire();
709            mStayOnWhilePluggedInPartialLock.acquire();
710        } else {
711            mStayOnWhilePluggedInScreenDimLock.release();
712            mStayOnWhilePluggedInPartialLock.release();
713        }
714    }
715
716    private boolean isScreenLock(int flags)
717    {
718        int n = flags & LOCK_MASK;
719        return n == PowerManager.FULL_WAKE_LOCK
720                || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
721                || n == PowerManager.SCREEN_DIM_WAKE_LOCK
722                || n == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
723    }
724
725    void enforceWakeSourcePermission(int uid, int pid) {
726        if (uid == Process.myUid()) {
727            return;
728        }
729        mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
730                pid, uid, null);
731    }
732
733    public void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws) {
734        int uid = Binder.getCallingUid();
735        int pid = Binder.getCallingPid();
736        if (uid != Process.myUid()) {
737            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
738        }
739        if (ws != null) {
740            enforceWakeSourcePermission(uid, pid);
741        }
742        long ident = Binder.clearCallingIdentity();
743        try {
744            synchronized (mLocks) {
745                acquireWakeLockLocked(flags, lock, uid, pid, tag, ws);
746            }
747        } finally {
748            Binder.restoreCallingIdentity(ident);
749        }
750    }
751
752    void noteStartWakeLocked(WakeLock wl, WorkSource ws) {
753        if (wl.monitorType >= 0) {
754            long origId = Binder.clearCallingIdentity();
755            try {
756                if (ws != null) {
757                    mBatteryStats.noteStartWakelockFromSource(ws, wl.pid, wl.tag,
758                            wl.monitorType);
759                } else {
760                    mBatteryStats.noteStartWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
761                }
762            } catch (RemoteException e) {
763                // Ignore
764            } finally {
765                Binder.restoreCallingIdentity(origId);
766            }
767        }
768    }
769
770    void noteStopWakeLocked(WakeLock wl, WorkSource ws) {
771        if (wl.monitorType >= 0) {
772            long origId = Binder.clearCallingIdentity();
773            try {
774                if (ws != null) {
775                    mBatteryStats.noteStopWakelockFromSource(ws, wl.pid, wl.tag,
776                            wl.monitorType);
777                } else {
778                    mBatteryStats.noteStopWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
779                }
780            } catch (RemoteException e) {
781                // Ignore
782            } finally {
783                Binder.restoreCallingIdentity(origId);
784            }
785        }
786    }
787
788    public void acquireWakeLockLocked(int flags, IBinder lock, int uid, int pid, String tag,
789            WorkSource ws) {
790        if (mSpew) {
791            Slog.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
792        }
793
794        if (ws != null && ws.size() == 0) {
795            ws = null;
796        }
797
798        int index = mLocks.getIndex(lock);
799        WakeLock wl;
800        boolean newlock;
801        boolean diffsource;
802        WorkSource oldsource;
803        if (index < 0) {
804            wl = new WakeLock(flags, lock, tag, uid, pid);
805            switch (wl.flags & LOCK_MASK)
806            {
807                case PowerManager.FULL_WAKE_LOCK:
808                    if (mUseSoftwareAutoBrightness) {
809                        wl.minState = SCREEN_BRIGHT;
810                    } else {
811                        wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
812                    }
813                    break;
814                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
815                    wl.minState = SCREEN_BRIGHT;
816                    break;
817                case PowerManager.SCREEN_DIM_WAKE_LOCK:
818                    wl.minState = SCREEN_DIM;
819                    break;
820                case PowerManager.PARTIAL_WAKE_LOCK:
821                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
822                    break;
823                default:
824                    // just log and bail.  we're in the server, so don't
825                    // throw an exception.
826                    Slog.e(TAG, "bad wakelock type for lock '" + tag + "' "
827                            + " flags=" + flags);
828                    return;
829            }
830            mLocks.addLock(wl);
831            if (ws != null) {
832                wl.ws = new WorkSource(ws);
833            }
834            newlock = true;
835            diffsource = false;
836            oldsource = null;
837        } else {
838            wl = mLocks.get(index);
839            newlock = false;
840            oldsource = wl.ws;
841            if (oldsource != null) {
842                if (ws == null) {
843                    wl.ws = null;
844                    diffsource = true;
845                } else {
846                    diffsource = oldsource.diff(ws);
847                }
848            } else if (ws != null) {
849                diffsource = true;
850            } else {
851                diffsource = false;
852            }
853            if (diffsource) {
854                wl.ws = new WorkSource(ws);
855            }
856        }
857        if (isScreenLock(flags)) {
858            // if this causes a wakeup, we reactivate all of the locks and
859            // set it to whatever they want.  otherwise, we modulate that
860            // by the current state so we never turn it more on than
861            // it already is.
862            if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
863                mProximityWakeLockCount++;
864                if (mProximityWakeLockCount == 1) {
865                    enableProximityLockLocked();
866                }
867            } else {
868                if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
869                    int oldWakeLockState = mWakeLockState;
870                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
871
872                    // Disable proximity sensor if if user presses power key while we are in the
873                    // "waiting for proximity sensor to go negative" state.
874                    if ((mWakeLockState & SCREEN_ON_BIT) != 0
875                            && mProximitySensorActive && mProximityWakeLockCount == 0) {
876                        mProximitySensorActive = false;
877                    }
878
879                    if (mSpew) {
880                        Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
881                                + " mWakeLockState=0x"
882                                + Integer.toHexString(mWakeLockState)
883                                + " previous wakeLockState=0x"
884                                + Integer.toHexString(oldWakeLockState));
885                    }
886                } else {
887                    if (mSpew) {
888                        Slog.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
889                                + " mLocks.gatherState()=0x"
890                                + Integer.toHexString(mLocks.gatherState())
891                                + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
892                    }
893                    mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
894                }
895                setPowerState(mWakeLockState | mUserState);
896            }
897        }
898        else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
899            if (newlock) {
900                mPartialCount++;
901                if (mPartialCount == 1) {
902                    if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
903                }
904            }
905            Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
906        }
907
908        if (diffsource) {
909            // If the lock sources have changed, need to first release the
910            // old ones.
911            noteStopWakeLocked(wl, oldsource);
912        }
913        if (newlock || diffsource) {
914            noteStartWakeLocked(wl, ws);
915        }
916    }
917
918    public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
919        int uid = Binder.getCallingUid();
920        int pid = Binder.getCallingPid();
921        if (ws != null && ws.size() == 0) {
922            ws = null;
923        }
924        if (ws != null) {
925            enforceWakeSourcePermission(uid, pid);
926        }
927        synchronized (mLocks) {
928            int index = mLocks.getIndex(lock);
929            if (index < 0) {
930                throw new IllegalArgumentException("Wake lock not active");
931            }
932            WakeLock wl = mLocks.get(index);
933            WorkSource oldsource = wl.ws;
934            wl.ws = ws != null ? new WorkSource(ws) : null;
935            noteStopWakeLocked(wl, oldsource);
936            noteStartWakeLocked(wl, ws);
937        }
938    }
939
940    public void releaseWakeLock(IBinder lock, int flags) {
941        int uid = Binder.getCallingUid();
942        if (uid != Process.myUid()) {
943            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
944        }
945
946        synchronized (mLocks) {
947            releaseWakeLockLocked(lock, flags, false);
948        }
949    }
950
951    private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
952        WakeLock wl = mLocks.removeLock(lock);
953        if (wl == null) {
954            return;
955        }
956
957        if (mSpew) {
958            Slog.d(TAG, "releaseWakeLock flags=0x"
959                    + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
960        }
961
962        if (isScreenLock(wl.flags)) {
963            if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
964                mProximityWakeLockCount--;
965                if (mProximityWakeLockCount == 0) {
966                    if (mProximitySensorActive &&
967                            ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
968                        // wait for proximity sensor to go negative before disabling sensor
969                        if (mDebugProximitySensor) {
970                            Slog.d(TAG, "waiting for proximity sensor to go negative");
971                        }
972                    } else {
973                        disableProximityLockLocked();
974                    }
975                }
976            } else {
977                mWakeLockState = mLocks.gatherState();
978                // goes in the middle to reduce flicker
979                if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
980                    userActivity(SystemClock.uptimeMillis(), -1, false, OTHER_EVENT, false);
981                }
982                setPowerState(mWakeLockState | mUserState);
983            }
984        }
985        else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
986            mPartialCount--;
987            if (mPartialCount == 0) {
988                if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
989                Power.releaseWakeLock(PARTIAL_NAME);
990            }
991        }
992        // Unlink the lock from the binder.
993        wl.binder.unlinkToDeath(wl, 0);
994
995        noteStopWakeLocked(wl, wl.ws);
996    }
997
998    private class PokeLock implements IBinder.DeathRecipient
999    {
1000        PokeLock(int p, IBinder b, String t) {
1001            super();
1002            this.pokey = p;
1003            this.binder = b;
1004            this.tag = t;
1005            try {
1006                b.linkToDeath(this, 0);
1007            } catch (RemoteException e) {
1008                binderDied();
1009            }
1010        }
1011        public void binderDied() {
1012            setPokeLock(0, this.binder, this.tag);
1013        }
1014        int pokey;
1015        IBinder binder;
1016        String tag;
1017        boolean awakeOnSet;
1018    }
1019
1020    public void setPokeLock(int pokey, IBinder token, String tag) {
1021        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1022        if (token == null) {
1023            Slog.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
1024            return;
1025        }
1026
1027        if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
1028            throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
1029                    + " and POKE_LOCK_MEDIUM_TIMEOUT");
1030        }
1031
1032        synchronized (mLocks) {
1033            if (pokey != 0) {
1034                PokeLock p = mPokeLocks.get(token);
1035                int oldPokey = 0;
1036                if (p != null) {
1037                    oldPokey = p.pokey;
1038                    p.pokey = pokey;
1039                } else {
1040                    p = new PokeLock(pokey, token, tag);
1041                    mPokeLocks.put(token, p);
1042                }
1043                int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
1044                int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
1045                if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
1046                    p.awakeOnSet = true;
1047                }
1048            } else {
1049                PokeLock rLock = mPokeLocks.remove(token);
1050                if (rLock != null) {
1051                    token.unlinkToDeath(rLock, 0);
1052                }
1053            }
1054
1055            int oldPokey = mPokey;
1056            int cumulative = 0;
1057            boolean oldAwakeOnSet = mPokeAwakeOnSet;
1058            boolean awakeOnSet = false;
1059            for (PokeLock p: mPokeLocks.values()) {
1060                cumulative |= p.pokey;
1061                if (p.awakeOnSet) {
1062                    awakeOnSet = true;
1063                }
1064            }
1065            mPokey = cumulative;
1066            mPokeAwakeOnSet = awakeOnSet;
1067
1068            int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
1069            int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
1070
1071            if (oldCumulativeTimeout != newCumulativeTimeout) {
1072                setScreenOffTimeoutsLocked();
1073                // reset the countdown timer, but use the existing nextState so it doesn't
1074                // change anything
1075                setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
1076            }
1077        }
1078    }
1079
1080    private static String lockType(int type)
1081    {
1082        switch (type)
1083        {
1084            case PowerManager.FULL_WAKE_LOCK:
1085                return "FULL_WAKE_LOCK                ";
1086            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
1087                return "SCREEN_BRIGHT_WAKE_LOCK       ";
1088            case PowerManager.SCREEN_DIM_WAKE_LOCK:
1089                return "SCREEN_DIM_WAKE_LOCK          ";
1090            case PowerManager.PARTIAL_WAKE_LOCK:
1091                return "PARTIAL_WAKE_LOCK             ";
1092            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
1093                return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
1094            default:
1095                return "???                           ";
1096        }
1097    }
1098
1099    private static String dumpPowerState(int state) {
1100        return (((state & KEYBOARD_BRIGHT_BIT) != 0)
1101                        ? "KEYBOARD_BRIGHT_BIT " : "")
1102                + (((state & SCREEN_BRIGHT_BIT) != 0)
1103                        ? "SCREEN_BRIGHT_BIT " : "")
1104                + (((state & SCREEN_ON_BIT) != 0)
1105                        ? "SCREEN_ON_BIT " : "")
1106                + (((state & BATTERY_LOW_BIT) != 0)
1107                        ? "BATTERY_LOW_BIT " : "");
1108    }
1109
1110    @Override
1111    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1112        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1113                != PackageManager.PERMISSION_GRANTED) {
1114            pw.println("Permission Denial: can't dump PowerManager from from pid="
1115                    + Binder.getCallingPid()
1116                    + ", uid=" + Binder.getCallingUid());
1117            return;
1118        }
1119
1120        long now = SystemClock.uptimeMillis();
1121
1122        synchronized (mLocks) {
1123            pw.println("Power Manager State:");
1124            pw.println("  mIsPowered=" + mIsPowered
1125                    + " mPowerState=" + mPowerState
1126                    + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
1127                    + " ms");
1128            pw.println("  mPartialCount=" + mPartialCount);
1129            pw.println("  mWakeLockState=" + dumpPowerState(mWakeLockState));
1130            pw.println("  mUserState=" + dumpPowerState(mUserState));
1131            pw.println("  mPowerState=" + dumpPowerState(mPowerState));
1132            pw.println("  mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
1133            pw.println("  mNextTimeout=" + mNextTimeout + " now=" + now
1134                    + " " + ((mNextTimeout-now)/1000) + "s from now");
1135            pw.println("  mDimScreen=" + mDimScreen
1136                    + " mStayOnConditions=" + mStayOnConditions
1137                    + " mPreparingForScreenOn=" + mPreparingForScreenOn
1138                    + " mSkippedScreenOn=" + mSkippedScreenOn);
1139            pw.println("  mScreenOffReason=" + mScreenOffReason
1140                    + " mUserState=" + mUserState);
1141            pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
1142                    + ',' + mBroadcastQueue[2] + "}");
1143            pw.println("  mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
1144                    + ',' + mBroadcastWhy[2] + "}");
1145            pw.println("  mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
1146            pw.println("  mKeyboardVisible=" + mKeyboardVisible
1147                    + " mUserActivityAllowed=" + mUserActivityAllowed);
1148            pw.println("  mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
1149                    + " mScreenOffDelay=" + mScreenOffDelay);
1150            pw.println("  mPreventScreenOn=" + mPreventScreenOn
1151                    + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride
1152                    + "  mButtonBrightnessOverride=" + mButtonBrightnessOverride);
1153            pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting
1154                    + " mMaximumScreenOffTimeout=" + mMaximumScreenOffTimeout);
1155            pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
1156            pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
1157            pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
1158            pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
1159            pw.println("  mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
1160            pw.println("  mProximityPartialLock=" + mProximityPartialLock);
1161            pw.println("  mProximityWakeLockCount=" + mProximityWakeLockCount);
1162            pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
1163            pw.println("  mProximitySensorActive=" + mProximitySensorActive);
1164            pw.println("  mProximityPendingValue=" + mProximityPendingValue);
1165            pw.println("  mLastProximityEventTime=" + mLastProximityEventTime);
1166            pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
1167            pw.println("  mLightSensorValue=" + mLightSensorValue
1168                    + " mLightSensorPendingValue=" + mLightSensorPendingValue);
1169            pw.println("  mLightSensorPendingDecrease=" + mLightSensorPendingDecrease
1170                    + " mLightSensorPendingIncrease=" + mLightSensorPendingIncrease);
1171            pw.println("  mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
1172                    + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
1173                    + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
1174            pw.println("  mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
1175            pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
1176            mScreenBrightness.dump(pw, "  mScreenBrightness: ");
1177
1178            int N = mLocks.size();
1179            pw.println();
1180            pw.println("mLocks.size=" + N + ":");
1181            for (int i=0; i<N; i++) {
1182                WakeLock wl = mLocks.get(i);
1183                String type = lockType(wl.flags & LOCK_MASK);
1184                String acquireCausesWakeup = "";
1185                if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
1186                    acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
1187                }
1188                String activated = "";
1189                if (wl.activated) {
1190                   activated = " activated";
1191                }
1192                pw.println("  " + type + " '" + wl.tag + "'" + acquireCausesWakeup
1193                        + activated + " (minState=" + wl.minState + ", uid=" + wl.uid
1194                        + ", pid=" + wl.pid + ")");
1195            }
1196
1197            pw.println();
1198            pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
1199            for (PokeLock p: mPokeLocks.values()) {
1200                pw.println("    poke lock '" + p.tag + "':"
1201                        + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0
1202                                ? " POKE_LOCK_IGNORE_TOUCH_EVENTS" : "")
1203                        + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
1204                                ? " POKE_LOCK_SHORT_TIMEOUT" : "")
1205                        + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
1206                                ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
1207            }
1208
1209            pw.println();
1210        }
1211    }
1212
1213    private void setTimeoutLocked(long now, int nextState) {
1214        setTimeoutLocked(now, -1, nextState);
1215    }
1216
1217    // If they gave a timeoutOverride it is the number of seconds
1218    // to screen-off.  Figure out where in the countdown cycle we
1219    // should jump to.
1220    private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
1221        long timeoutOverride = originalTimeoutOverride;
1222        if (mBootCompleted) {
1223            synchronized (mLocks) {
1224                long when = 0;
1225                if (timeoutOverride <= 0) {
1226                    switch (nextState)
1227                    {
1228                        case SCREEN_BRIGHT:
1229                            when = now + mKeylightDelay;
1230                            break;
1231                        case SCREEN_DIM:
1232                            if (mDimDelay >= 0) {
1233                                when = now + mDimDelay;
1234                                break;
1235                            } else {
1236                                Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
1237                            }
1238                       case SCREEN_OFF:
1239                            synchronized (mLocks) {
1240                                when = now + mScreenOffDelay;
1241                            }
1242                            break;
1243                        default:
1244                            when = now;
1245                            break;
1246                    }
1247                } else {
1248                    override: {
1249                        if (timeoutOverride <= mScreenOffDelay) {
1250                            when = now + timeoutOverride;
1251                            nextState = SCREEN_OFF;
1252                            break override;
1253                        }
1254                        timeoutOverride -= mScreenOffDelay;
1255
1256                        if (mDimDelay >= 0) {
1257                             if (timeoutOverride <= mDimDelay) {
1258                                when = now + timeoutOverride;
1259                                nextState = SCREEN_DIM;
1260                                break override;
1261                            }
1262                            timeoutOverride -= mDimDelay;
1263                        }
1264
1265                        when = now + timeoutOverride;
1266                        nextState = SCREEN_BRIGHT;
1267                    }
1268                }
1269                if (mSpew) {
1270                    Slog.d(TAG, "setTimeoutLocked now=" + now
1271                            + " timeoutOverride=" + timeoutOverride
1272                            + " nextState=" + nextState + " when=" + when);
1273                }
1274
1275                mHandler.removeCallbacks(mTimeoutTask);
1276                mTimeoutTask.nextState = nextState;
1277                mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
1278                        ? (originalTimeoutOverride - timeoutOverride)
1279                        : -1;
1280                mHandler.postAtTime(mTimeoutTask, when);
1281                mNextTimeout = when; // for debugging
1282            }
1283        }
1284    }
1285
1286    private void cancelTimerLocked()
1287    {
1288        mHandler.removeCallbacks(mTimeoutTask);
1289        mTimeoutTask.nextState = -1;
1290    }
1291
1292    private class TimeoutTask implements Runnable
1293    {
1294        int nextState; // access should be synchronized on mLocks
1295        long remainingTimeoutOverride;
1296        public void run()
1297        {
1298            synchronized (mLocks) {
1299                if (mSpew) {
1300                    Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
1301                }
1302
1303                if (nextState == -1) {
1304                    return;
1305                }
1306
1307                mUserState = this.nextState;
1308                setPowerState(this.nextState | mWakeLockState);
1309
1310                long now = SystemClock.uptimeMillis();
1311
1312                switch (this.nextState)
1313                {
1314                    case SCREEN_BRIGHT:
1315                        if (mDimDelay >= 0) {
1316                            setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
1317                            break;
1318                        }
1319                    case SCREEN_DIM:
1320                        setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
1321                        break;
1322                }
1323            }
1324        }
1325    }
1326
1327    private void sendNotificationLocked(boolean on, int why) {
1328        if (!mInitialized) {
1329            // No notifications sent until first initialization is done.
1330            // This is so that when we are moving from our initial state
1331            // which looks like the screen was off to it being on, we do not
1332            // go through the process of waiting for the higher-level user
1333            // space to be ready before turning up the display brightness.
1334            // (And also do not send needless broadcasts about the screen.)
1335            return;
1336        }
1337
1338        if (DEBUG_SCREEN_ON) {
1339            RuntimeException here = new RuntimeException("here");
1340            here.fillInStackTrace();
1341            Slog.i(TAG, "sendNotificationLocked: " + on, here);
1342        }
1343
1344        if (!on) {
1345            mStillNeedSleepNotification = false;
1346        }
1347
1348        // Add to the queue.
1349        int index = 0;
1350        while (mBroadcastQueue[index] != -1) {
1351            index++;
1352        }
1353        mBroadcastQueue[index] = on ? 1 : 0;
1354        mBroadcastWhy[index] = why;
1355
1356        // If we added it position 2, then there is a pair that can be stripped.
1357        // If we added it position 1 and we're turning the screen off, we can strip
1358        // the pair and do nothing, because the screen is already off, and therefore
1359        // keyguard has already been enabled.
1360        // However, if we added it at position 1 and we're turning it on, then position
1361        // 0 was to turn it off, and we can't strip that, because keyguard needs to come
1362        // on, so have to run the queue then.
1363        if (index == 2) {
1364            // While we're collapsing them, if it's going off, and the new reason
1365            // is more significant than the first, then use the new one.
1366            if (!on && mBroadcastWhy[0] > why) {
1367                mBroadcastWhy[0] = why;
1368            }
1369            mBroadcastQueue[0] = on ? 1 : 0;
1370            mBroadcastQueue[1] = -1;
1371            mBroadcastQueue[2] = -1;
1372            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1373            mBroadcastWakeLock.release();
1374            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1375            mBroadcastWakeLock.release();
1376            index = 0;
1377        }
1378        if (index == 1 && !on) {
1379            mBroadcastQueue[0] = -1;
1380            mBroadcastQueue[1] = -1;
1381            index = -1;
1382            // The wake lock was being held, but we're not actually going to do any
1383            // broadcasts, so release the wake lock.
1384            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1385            mBroadcastWakeLock.release();
1386        }
1387
1388        // The broadcast queue has changed; make sure the screen is on if it
1389        // is now possible for it to be.
1390        if (mSkippedScreenOn) {
1391            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1392        }
1393
1394        // Now send the message.
1395        if (index >= 0) {
1396            // Acquire the broadcast wake lock before changing the power
1397            // state. It will be release after the broadcast is sent.
1398            // We always increment the ref count for each notification in the queue
1399            // and always decrement when that notification is handled.
1400            mBroadcastWakeLock.acquire();
1401            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
1402            mHandler.post(mNotificationTask);
1403        }
1404    }
1405
1406    private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
1407            new WindowManagerPolicy.ScreenOnListener() {
1408                @Override public void onScreenOn() {
1409                    synchronized (mLocks) {
1410                        if (mPreparingForScreenOn) {
1411                            mPreparingForScreenOn = false;
1412                            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1413                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
1414                                    4, mBroadcastWakeLock.mCount);
1415                            mBroadcastWakeLock.release();
1416                        }
1417                    }
1418                }
1419    };
1420
1421    private Runnable mNotificationTask = new Runnable()
1422    {
1423        public void run()
1424        {
1425            while (true) {
1426                int value;
1427                int why;
1428                WindowManagerPolicy policy;
1429                synchronized (mLocks) {
1430                    value = mBroadcastQueue[0];
1431                    why = mBroadcastWhy[0];
1432                    for (int i=0; i<2; i++) {
1433                        mBroadcastQueue[i] = mBroadcastQueue[i+1];
1434                        mBroadcastWhy[i] = mBroadcastWhy[i+1];
1435                    }
1436                    policy = getPolicyLocked();
1437                    if (value == 1 && !mPreparingForScreenOn) {
1438                        mPreparingForScreenOn = true;
1439                        mBroadcastWakeLock.acquire();
1440                        EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND,
1441                                mBroadcastWakeLock.mCount);
1442                    }
1443                }
1444                if (value == 1) {
1445                    mScreenOnStart = SystemClock.uptimeMillis();
1446
1447                    policy.screenTurningOn(mScreenOnListener);
1448                    try {
1449                        ActivityManagerNative.getDefault().wakingUp();
1450                    } catch (RemoteException e) {
1451                        // ignore it
1452                    }
1453
1454                    if (mSpew) {
1455                        Slog.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
1456                    }
1457                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
1458                        mContext.sendOrderedBroadcast(mScreenOnIntent, null,
1459                                mScreenOnBroadcastDone, mHandler, 0, null, null);
1460                    } else {
1461                        synchronized (mLocks) {
1462                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2,
1463                                    mBroadcastWakeLock.mCount);
1464                            mBroadcastWakeLock.release();
1465                        }
1466                    }
1467                }
1468                else if (value == 0) {
1469                    mScreenOffStart = SystemClock.uptimeMillis();
1470
1471                    policy.screenTurnedOff(why);
1472                    try {
1473                        ActivityManagerNative.getDefault().goingToSleep();
1474                    } catch (RemoteException e) {
1475                        // ignore it.
1476                    }
1477
1478                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
1479                        mContext.sendOrderedBroadcast(mScreenOffIntent, null,
1480                                mScreenOffBroadcastDone, mHandler, 0, null, null);
1481                    } else {
1482                        synchronized (mLocks) {
1483                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
1484                                    mBroadcastWakeLock.mCount);
1485                            updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1486                            mBroadcastWakeLock.release();
1487                        }
1488                    }
1489                }
1490                else {
1491                    // If we're in this case, then this handler is running for a previous
1492                    // paired transaction.  mBroadcastWakeLock will already have been released.
1493                    break;
1494                }
1495            }
1496        }
1497    };
1498
1499    long mScreenOnStart;
1500    private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
1501        public void onReceive(Context context, Intent intent) {
1502            synchronized (mLocks) {
1503                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
1504                        SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
1505                mBroadcastWakeLock.release();
1506            }
1507        }
1508    };
1509
1510    long mScreenOffStart;
1511    private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
1512        public void onReceive(Context context, Intent intent) {
1513            synchronized (mLocks) {
1514                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
1515                        SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
1516                mBroadcastWakeLock.release();
1517            }
1518        }
1519    };
1520
1521    void logPointerUpEvent() {
1522        if (LOG_TOUCH_DOWNS) {
1523            mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1524            mLastTouchDown = 0;
1525        }
1526    }
1527
1528    void logPointerDownEvent() {
1529        if (LOG_TOUCH_DOWNS) {
1530            // If we are not already timing a down/up sequence
1531            if (mLastTouchDown == 0) {
1532                mLastTouchDown = SystemClock.elapsedRealtime();
1533                mTouchCycles++;
1534            }
1535        }
1536    }
1537
1538    /**
1539     * Prevents the screen from turning on even if it *should* turn on due
1540     * to a subsequent full wake lock being acquired.
1541     * <p>
1542     * This is a temporary hack that allows an activity to "cover up" any
1543     * display glitches that happen during the activity's startup
1544     * sequence.  (Specifically, this API was added to work around a
1545     * cosmetic bug in the "incoming call" sequence, where the lock screen
1546     * would flicker briefly before the incoming call UI became visible.)
1547     * TODO: There ought to be a more elegant way of doing this,
1548     * probably by having the PowerManager and ActivityManager
1549     * work together to let apps specify that the screen on/off
1550     * state should be synchronized with the Activity lifecycle.
1551     * <p>
1552     * Note that calling preventScreenOn(true) will NOT turn the screen
1553     * off if it's currently on.  (This API only affects *future*
1554     * acquisitions of full wake locks.)
1555     * But calling preventScreenOn(false) WILL turn the screen on if
1556     * it's currently off because of a prior preventScreenOn(true) call.
1557     * <p>
1558     * Any call to preventScreenOn(true) MUST be followed promptly by a call
1559     * to preventScreenOn(false).  In fact, if the preventScreenOn(false)
1560     * call doesn't occur within 5 seconds, we'll turn the screen back on
1561     * ourselves (and log a warning about it); this prevents a buggy app
1562     * from disabling the screen forever.)
1563     * <p>
1564     * TODO: this feature should really be controlled by a new type of poke
1565     * lock (rather than an IPowerManager call).
1566     */
1567    public void preventScreenOn(boolean prevent) {
1568        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1569
1570        synchronized (mLocks) {
1571            if (prevent) {
1572                // First of all, grab a partial wake lock to
1573                // make sure the CPU stays on during the entire
1574                // preventScreenOn(true) -> preventScreenOn(false) sequence.
1575                mPreventScreenOnPartialLock.acquire();
1576
1577                // Post a forceReenableScreen() call (for 5 seconds in the
1578                // future) to make sure the matching preventScreenOn(false) call
1579                // has happened by then.
1580                mHandler.removeCallbacks(mForceReenableScreenTask);
1581                mHandler.postDelayed(mForceReenableScreenTask, 5000);
1582
1583                // Finally, set the flag that prevents the screen from turning on.
1584                // (Below, in setPowerState(), we'll check mPreventScreenOn and
1585                // we *won't* call setScreenStateLocked(true) if it's set.)
1586                mPreventScreenOn = true;
1587            } else {
1588                // (Re)enable the screen.
1589                mPreventScreenOn = false;
1590
1591                // We're "undoing" a the prior preventScreenOn(true) call, so we
1592                // no longer need the 5-second safeguard.
1593                mHandler.removeCallbacks(mForceReenableScreenTask);
1594
1595                // Forcibly turn on the screen if it's supposed to be on.  (This
1596                // handles the case where the screen is currently off because of
1597                // a prior preventScreenOn(true) call.)
1598                if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
1599                    if (mSpew) {
1600                        Slog.d(TAG,
1601                              "preventScreenOn: turning on after a prior preventScreenOn(true)!");
1602                    }
1603                    int err = setScreenStateLocked(true);
1604                    if (err != 0) {
1605                        Slog.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
1606                    }
1607                }
1608
1609                // Release the partial wake lock that we held during the
1610                // preventScreenOn(true) -> preventScreenOn(false) sequence.
1611                mPreventScreenOnPartialLock.release();
1612            }
1613        }
1614    }
1615
1616    public void setScreenBrightnessOverride(int brightness) {
1617        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1618
1619        if (mSpew) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
1620        synchronized (mLocks) {
1621            if (mScreenBrightnessOverride != brightness) {
1622                mScreenBrightnessOverride = brightness;
1623                if (isScreenOn()) {
1624                    updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1625                }
1626            }
1627        }
1628    }
1629
1630    public void setButtonBrightnessOverride(int brightness) {
1631        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1632
1633        if (mSpew) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
1634         synchronized (mLocks) {
1635           if (mButtonBrightnessOverride != brightness) {
1636                mButtonBrightnessOverride = brightness;
1637                if (isScreenOn()) {
1638                    updateLightsLocked(mPowerState, BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT);
1639                }
1640            }
1641        }
1642    }
1643
1644    /**
1645     * Sanity-check that gets called 5 seconds after any call to
1646     * preventScreenOn(true).  This ensures that the original call
1647     * is followed promptly by a call to preventScreenOn(false).
1648     */
1649    private void forceReenableScreen() {
1650        // We shouldn't get here at all if mPreventScreenOn is false, since
1651        // we should have already removed any existing
1652        // mForceReenableScreenTask messages...
1653        if (!mPreventScreenOn) {
1654            Slog.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
1655            return;
1656        }
1657
1658        // Uh oh.  It's been 5 seconds since a call to
1659        // preventScreenOn(true) and we haven't re-enabled the screen yet.
1660        // This means the app that called preventScreenOn(true) is either
1661        // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
1662        // or buggy (i.e. it forgot to call preventScreenOn(false), or
1663        // crashed before doing so.)
1664
1665        // Log a warning, and forcibly turn the screen back on.
1666        Slog.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
1667              + "Forcing the screen back on...");
1668        preventScreenOn(false);
1669    }
1670
1671    private Runnable mForceReenableScreenTask = new Runnable() {
1672            public void run() {
1673                forceReenableScreen();
1674            }
1675        };
1676
1677    private int setScreenStateLocked(boolean on) {
1678        if (DEBUG_SCREEN_ON) {
1679            RuntimeException e = new RuntimeException("here");
1680            e.fillInStackTrace();
1681            Slog.i(TAG, "Set screen state: " + on, e);
1682        }
1683        if (on) {
1684            if ((mPowerState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
1685                // If we are turning the screen state on, but the screen
1686                // light is currently off, then make sure that we set the
1687                // light at this point to 0.  This is the case where we are
1688                // turning on the screen and waiting for the UI to be drawn
1689                // before showing it to the user.  We want the light off
1690                // until it is ready to be shown to the user, not it using
1691                // whatever the last value it had.
1692                if (DEBUG_SCREEN_ON) {
1693                    Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
1694                            + Integer.toHexString(mPowerState)
1695                            + " mSkippedScreenOn=" + mSkippedScreenOn);
1696                }
1697                mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF);
1698            }
1699        }
1700        int err = Power.setScreenState(on);
1701        if (err == 0) {
1702            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
1703            if (mUseSoftwareAutoBrightness) {
1704                enableLightSensorLocked(on);
1705                if (!on) {
1706                    // make sure button and key backlights are off too
1707                    mButtonLight.turnOff();
1708                    mKeyboardLight.turnOff();
1709                    // clear current value so we will update based on the new conditions
1710                    // when the sensor is reenabled.
1711                    mLightSensorValue = -1;
1712                    // reset our highest light sensor value when the screen turns off
1713                    mHighestLightSensorValue = -1;
1714                }
1715            }
1716        }
1717        return err;
1718    }
1719
1720    private void setPowerState(int state)
1721    {
1722        setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
1723    }
1724
1725    private void setPowerState(int newState, boolean noChangeLights, int reason)
1726    {
1727        synchronized (mLocks) {
1728            int err;
1729
1730            if (mSpew) {
1731                Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1732                        + " newState=0x" + Integer.toHexString(newState)
1733                        + " noChangeLights=" + noChangeLights
1734                        + " reason=" + reason);
1735            }
1736
1737            if (noChangeLights) {
1738                newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1739            }
1740            if (mProximitySensorActive) {
1741                // don't turn on the screen when the proximity sensor lock is held
1742                newState = (newState & ~SCREEN_BRIGHT);
1743            }
1744
1745            if (batteryIsLow()) {
1746                newState |= BATTERY_LOW_BIT;
1747            } else {
1748                newState &= ~BATTERY_LOW_BIT;
1749            }
1750            if (newState == mPowerState && mInitialized) {
1751                return;
1752            }
1753
1754            if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
1755                newState |= ALL_BRIGHT;
1756            }
1757
1758            boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1759            boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1760
1761            if (mSpew) {
1762                Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
1763                        + " newState=" + newState + " noChangeLights=" + noChangeLights);
1764                Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1765                         + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1766                Slog.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1767                         + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1768                Slog.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1769                         + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1770                Slog.d(TAG, "  oldScreenOn=" + oldScreenOn
1771                         + " newScreenOn=" + newScreenOn);
1772                Slog.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1773                         + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1774            }
1775
1776            final boolean stateChanged = mPowerState != newState;
1777
1778            if (oldScreenOn != newScreenOn) {
1779                if (newScreenOn) {
1780                    // When the user presses the power button, we need to always send out the
1781                    // notification that it's going to sleep so the keyguard goes on.  But
1782                    // we can't do that until the screen fades out, so we don't show the keyguard
1783                    // too early.
1784                    if (mStillNeedSleepNotification) {
1785                        sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1786                    }
1787
1788                    // Turn on the screen UNLESS there was a prior
1789                    // preventScreenOn(true) request.  (Note that the lifetime
1790                    // of a single preventScreenOn() request is limited to 5
1791                    // seconds to prevent a buggy app from disabling the
1792                    // screen forever; see forceReenableScreen().)
1793                    boolean reallyTurnScreenOn = true;
1794                    if (mSpew) {
1795                        Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "
1796                              + mPreventScreenOn);
1797                    }
1798
1799                    if (mPreventScreenOn) {
1800                        if (mSpew) {
1801                            Slog.d(TAG, "- PREVENTING screen from really turning on!");
1802                        }
1803                        reallyTurnScreenOn = false;
1804                    }
1805                    if (reallyTurnScreenOn) {
1806                        err = setScreenStateLocked(true);
1807                        long identity = Binder.clearCallingIdentity();
1808                        try {
1809                            mBatteryStats.noteScreenBrightness(getPreferredBrightness());
1810                            mBatteryStats.noteScreenOn();
1811                        } catch (RemoteException e) {
1812                            Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
1813                        } finally {
1814                            Binder.restoreCallingIdentity(identity);
1815                        }
1816                    } else {
1817                        setScreenStateLocked(false);
1818                        // But continue as if we really did turn the screen on...
1819                        err = 0;
1820                    }
1821
1822                    mLastTouchDown = 0;
1823                    mTotalTouchDownTime = 0;
1824                    mTouchCycles = 0;
1825                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
1826                            mTotalTouchDownTime, mTouchCycles);
1827                    if (err == 0) {
1828                        sendNotificationLocked(true, -1);
1829                        // Update the lights *after* taking care of turning the
1830                        // screen on, so we do this after our notifications are
1831                        // enqueued and thus will delay turning on the screen light
1832                        // until the windows are correctly displayed.
1833                        if (stateChanged) {
1834                            updateLightsLocked(newState, 0);
1835                        }
1836                        mPowerState |= SCREEN_ON_BIT;
1837                    }
1838
1839                } else {
1840                    // Update the lights *before* taking care of turning the
1841                    // screen off, so we can initiate any animations that are desired.
1842                    if (stateChanged) {
1843                        updateLightsLocked(newState, 0);
1844                    }
1845
1846                    // cancel light sensor task
1847                    mHandler.removeCallbacks(mAutoBrightnessTask);
1848                    mLightSensorPendingDecrease = false;
1849                    mLightSensorPendingIncrease = false;
1850                    mScreenOffTime = SystemClock.elapsedRealtime();
1851                    long identity = Binder.clearCallingIdentity();
1852                    try {
1853                        mBatteryStats.noteScreenOff();
1854                    } catch (RemoteException e) {
1855                        Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
1856                    } finally {
1857                        Binder.restoreCallingIdentity(identity);
1858                    }
1859                    mPowerState &= ~SCREEN_ON_BIT;
1860                    mScreenOffReason = reason;
1861                    if (!mScreenBrightness.animating) {
1862                        err = screenOffFinishedAnimatingLocked(reason);
1863                    } else {
1864                        err = 0;
1865                        mLastTouchDown = 0;
1866                    }
1867                }
1868            } else if (stateChanged) {
1869                // Screen on/off didn't change, but lights may have.
1870                updateLightsLocked(newState, 0);
1871            }
1872
1873            mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1874
1875            updateNativePowerStateLocked();
1876        }
1877    }
1878
1879    private void updateNativePowerStateLocked() {
1880        nativeSetPowerState(
1881                (mPowerState & SCREEN_ON_BIT) != 0,
1882                (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
1883    }
1884
1885    private int screenOffFinishedAnimatingLocked(int reason) {
1886        // I don't think we need to check the current state here because all of these
1887        // Power.setScreenState and sendNotificationLocked can both handle being
1888        // called multiple times in the same state. -joeo
1889        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime,
1890                mTouchCycles);
1891        mLastTouchDown = 0;
1892        int err = setScreenStateLocked(false);
1893        if (err == 0) {
1894            mScreenOffReason = reason;
1895            sendNotificationLocked(false, reason);
1896        }
1897        return err;
1898    }
1899
1900    private boolean batteryIsLow() {
1901        return (!mIsPowered &&
1902                mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1903    }
1904
1905    private boolean shouldDeferScreenOnLocked() {
1906        if (mPreparingForScreenOn) {
1907            // Currently waiting for confirmation from the policy that it
1908            // is okay to turn on the screen.  Don't allow the screen to go
1909            // on until that is done.
1910            if (DEBUG_SCREEN_ON) Slog.i(TAG,
1911                    "updateLights: delaying screen on due to mPreparingForScreenOn");
1912            return true;
1913        } else {
1914            // If there is a screen-on command in the notification queue, we
1915            // can't turn the screen on until it has been processed (and we
1916            // have set mPreparingForScreenOn) or it has been dropped.
1917            for (int i=0; i<mBroadcastQueue.length; i++) {
1918                if (mBroadcastQueue[i] == 1) {
1919                    if (DEBUG_SCREEN_ON) Slog.i(TAG,
1920                            "updateLights: delaying screen on due to notification queue");
1921                    return true;
1922                }
1923            }
1924        }
1925        return false;
1926    }
1927
1928    private void updateLightsLocked(int newState, int forceState) {
1929        final int oldState = mPowerState;
1930
1931        // If the screen is not currently on, we will want to delay actually
1932        // turning the lights on if we are still getting the UI put up.
1933        if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
1934            // Don't turn screen on until we know we are really ready to.
1935            // This is to avoid letting the screen go on before things like the
1936            // lock screen have been displayed.
1937            if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) {
1938                newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
1939            }
1940        }
1941
1942        if ((newState & SCREEN_ON_BIT) != 0) {
1943            // Only turn on the buttons or keyboard if the screen is also on.
1944            // We should never see the buttons on but not the screen.
1945            newState = applyButtonState(newState);
1946            newState = applyKeyboardState(newState);
1947        }
1948        final int realDifference = (newState ^ oldState);
1949        final int difference = realDifference | forceState;
1950        if (difference == 0) {
1951            return;
1952        }
1953
1954        int offMask = 0;
1955        int dimMask = 0;
1956        int onMask = 0;
1957
1958        int preferredBrightness = getPreferredBrightness();
1959
1960        if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1961            if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1962                offMask |= KEYBOARD_BRIGHT_BIT;
1963            } else {
1964                onMask |= KEYBOARD_BRIGHT_BIT;
1965            }
1966        }
1967
1968        if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1969            if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1970                offMask |= BUTTON_BRIGHT_BIT;
1971            } else {
1972                onMask |= BUTTON_BRIGHT_BIT;
1973            }
1974        }
1975
1976        if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1977            int nominalCurrentValue = -1;
1978            // If there was an actual difference in the light state, then
1979            // figure out the "ideal" current value based on the previous
1980            // state.  Otherwise, this is a change due to the brightness
1981            // override, so we want to animate from whatever the current
1982            // value is.
1983            if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1984                switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
1985                    case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
1986                        nominalCurrentValue = preferredBrightness;
1987                        break;
1988                    case SCREEN_ON_BIT:
1989                        nominalCurrentValue = mScreenBrightnessDim;
1990                        break;
1991                    case 0:
1992                        nominalCurrentValue = Power.BRIGHTNESS_OFF;
1993                        break;
1994                    case SCREEN_BRIGHT_BIT:
1995                    default:
1996                        // not possible
1997                        nominalCurrentValue = (int)mScreenBrightness.curValue;
1998                        break;
1999                }
2000            }
2001            int brightness = preferredBrightness;
2002            int steps = ANIM_STEPS;
2003            if ((newState & SCREEN_BRIGHT_BIT) == 0) {
2004                // dim or turn off backlight, depending on if the screen is on
2005                // the scale is because the brightness ramp isn't linear and this biases
2006                // it so the later parts take longer.
2007                final float scale = 1.5f;
2008                float ratio = (((float)mScreenBrightnessDim)/preferredBrightness);
2009                if (ratio > 1.0f) ratio = 1.0f;
2010                if ((newState & SCREEN_ON_BIT) == 0) {
2011                    if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
2012                        // was bright
2013                        steps = ANIM_STEPS;
2014                    } else {
2015                        // was dim
2016                        steps = (int)(ANIM_STEPS*ratio*scale);
2017                    }
2018                    brightness = Power.BRIGHTNESS_OFF;
2019                } else {
2020                    if ((oldState & SCREEN_ON_BIT) != 0) {
2021                        // was bright
2022                        steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
2023                    } else {
2024                        // was dim
2025                        steps = (int)(ANIM_STEPS*ratio);
2026                    }
2027                    if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
2028                        // If the "stay on while plugged in" option is
2029                        // turned on, then the screen will often not
2030                        // automatically turn off while plugged in.  To
2031                        // still have a sense of when it is inactive, we
2032                        // will then count going dim as turning off.
2033                        mScreenOffTime = SystemClock.elapsedRealtime();
2034                    }
2035                    brightness = mScreenBrightnessDim;
2036                }
2037            }
2038            long identity = Binder.clearCallingIdentity();
2039            try {
2040                mBatteryStats.noteScreenBrightness(brightness);
2041            } catch (RemoteException e) {
2042                // Nothing interesting to do.
2043            } finally {
2044                Binder.restoreCallingIdentity(identity);
2045            }
2046            if (!mSkippedScreenOn) {
2047                mScreenBrightness.setTargetLocked(brightness, steps,
2048                        INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue);
2049                if (DEBUG_SCREEN_ON) {
2050                    RuntimeException e = new RuntimeException("here");
2051                    e.fillInStackTrace();
2052                    Slog.i(TAG, "Setting screen brightness: " + brightness, e);
2053                }
2054            }
2055        }
2056
2057        if (mSpew) {
2058            Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
2059                    + " dimMask=0x" + Integer.toHexString(dimMask)
2060                    + " onMask=0x" + Integer.toHexString(onMask)
2061                    + " difference=0x" + Integer.toHexString(difference)
2062                    + " realDifference=0x" + Integer.toHexString(realDifference)
2063                    + " forceState=0x" + Integer.toHexString(forceState)
2064                    );
2065        }
2066
2067        if (offMask != 0) {
2068            if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
2069            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
2070        }
2071        if (dimMask != 0) {
2072            int brightness = mScreenBrightnessDim;
2073            if ((newState & BATTERY_LOW_BIT) != 0 &&
2074                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
2075                brightness = Power.BRIGHTNESS_LOW_BATTERY;
2076            }
2077            if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
2078            setLightBrightness(dimMask, brightness);
2079        }
2080        if (onMask != 0) {
2081            int brightness = getPreferredBrightness();
2082            if ((newState & BATTERY_LOW_BIT) != 0 &&
2083                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
2084                brightness = Power.BRIGHTNESS_LOW_BATTERY;
2085            }
2086            if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
2087            setLightBrightness(onMask, brightness);
2088        }
2089    }
2090
2091    private void setLightBrightness(int mask, int value) {
2092        int brightnessMode = (mAutoBrightessEnabled
2093                            ? LightsService.BRIGHTNESS_MODE_SENSOR
2094                            : LightsService.BRIGHTNESS_MODE_USER);
2095        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
2096            if (DEBUG_SCREEN_ON) {
2097                RuntimeException e = new RuntimeException("here");
2098                e.fillInStackTrace();
2099                Slog.i(TAG, "Set LCD brightness: " + value, e);
2100            }
2101            mLcdLight.setBrightness(value, brightnessMode);
2102        }
2103        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
2104            mButtonLight.setBrightness(value);
2105        }
2106        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
2107            mKeyboardLight.setBrightness(value);
2108        }
2109    }
2110
2111    class BrightnessState implements Runnable {
2112        final int mask;
2113
2114        boolean initialized;
2115        int targetValue;
2116        float curValue;
2117        float delta;
2118        boolean animating;
2119
2120        BrightnessState(int m) {
2121            mask = m;
2122        }
2123
2124        public void dump(PrintWriter pw, String prefix) {
2125            pw.println(prefix + "animating=" + animating
2126                    + " targetValue=" + targetValue
2127                    + " curValue=" + curValue
2128                    + " delta=" + delta);
2129        }
2130
2131        void forceValueLocked(int value) {
2132            targetValue = -1;
2133            curValue = value;
2134            setLightBrightness(mask, value);
2135            if (animating) {
2136                finishAnimationLocked(false, value);
2137            }
2138        }
2139
2140        void setTargetLocked(int target, int stepsToTarget, int initialValue,
2141                int nominalCurrentValue) {
2142            if (!initialized) {
2143                initialized = true;
2144                curValue = (float)initialValue;
2145            } else if (targetValue == target) {
2146                return;
2147            }
2148            targetValue = target;
2149            delta = (targetValue -
2150                    (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
2151                    / stepsToTarget;
2152            if (mSpew || DEBUG_SCREEN_ON) {
2153                String noticeMe = nominalCurrentValue == curValue ? "" : "  ******************";
2154                Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue
2155                        + " target=" + target + " targetValue=" + targetValue + " delta=" + delta
2156                        + " nominalCurrentValue=" + nominalCurrentValue
2157                        + noticeMe);
2158            }
2159            animating = true;
2160
2161            if (mSpew) {
2162                Slog.i(TAG, "scheduling light animator");
2163            }
2164            mScreenOffHandler.removeCallbacks(this);
2165            mScreenOffHandler.post(this);
2166        }
2167
2168        boolean stepLocked() {
2169            if (!animating) return false;
2170            if (false && mSpew) {
2171                Slog.i(TAG, "Step target " + mask + ": cur=" + curValue
2172                        + " target=" + targetValue + " delta=" + delta);
2173            }
2174            curValue += delta;
2175            int curIntValue = (int)curValue;
2176            boolean more = true;
2177            if (delta == 0) {
2178                curValue = curIntValue = targetValue;
2179                more = false;
2180            } else if (delta > 0) {
2181                if (curIntValue >= targetValue) {
2182                    curValue = curIntValue = targetValue;
2183                    more = false;
2184                }
2185            } else {
2186                if (curIntValue <= targetValue) {
2187                    curValue = curIntValue = targetValue;
2188                    more = false;
2189                }
2190            }
2191            if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask);
2192            setLightBrightness(mask, curIntValue);
2193            finishAnimationLocked(more, curIntValue);
2194            return more;
2195        }
2196
2197        void jumpToTargetLocked() {
2198            if (mSpew) Slog.d(TAG, "jumpToTargetLocked targetValue=" + targetValue + ": " + mask);
2199            setLightBrightness(mask, targetValue);
2200            final int tv = targetValue;
2201            curValue = tv;
2202            targetValue = -1;
2203            finishAnimationLocked(false, tv);
2204        }
2205
2206        private void finishAnimationLocked(boolean more, int curIntValue) {
2207            animating = more;
2208            if (!more) {
2209                if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
2210                    screenOffFinishedAnimatingLocked(mScreenOffReason);
2211                }
2212            }
2213        }
2214
2215        public void run() {
2216            synchronized (mLocks) {
2217                // we're turning off
2218                final boolean turningOff = animating && targetValue == Power.BRIGHTNESS_OFF;
2219                if (mAnimateScreenLights || !turningOff) {
2220                    long now = SystemClock.uptimeMillis();
2221                    boolean more = mScreenBrightness.stepLocked();
2222                    if (more) {
2223                        mScreenOffHandler.postAtTime(this, now+(1000/60));
2224                    }
2225                } else {
2226                    // It's pretty scary to hold mLocks for this long, and we should
2227                    // redesign this, but it works for now.
2228                    nativeStartSurfaceFlingerAnimation(
2229                            mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
2230                            ? 0 : mAnimationSetting);
2231                    mScreenBrightness.jumpToTargetLocked();
2232                }
2233            }
2234        }
2235    }
2236
2237    private int getPreferredBrightness() {
2238        try {
2239            if (mScreenBrightnessOverride >= 0) {
2240                return mScreenBrightnessOverride;
2241            } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
2242                    && mAutoBrightessEnabled) {
2243                return mLightSensorScreenBrightness;
2244            }
2245            final int brightness = Settings.System.getInt(mContext.getContentResolver(),
2246                                                          SCREEN_BRIGHTNESS);
2247             // Don't let applications turn the screen all the way off
2248            return Math.max(brightness, mScreenBrightnessDim);
2249        } catch (SettingNotFoundException snfe) {
2250            return Power.BRIGHTNESS_ON;
2251        }
2252    }
2253
2254    private int applyButtonState(int state) {
2255        int brightness = -1;
2256        if ((state & BATTERY_LOW_BIT) != 0) {
2257            // do not override brightness if the battery is low
2258            return state;
2259        }
2260        if (mButtonBrightnessOverride >= 0) {
2261            brightness = mButtonBrightnessOverride;
2262        } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
2263            brightness = mLightSensorButtonBrightness;
2264        }
2265        if (brightness > 0) {
2266            return state | BUTTON_BRIGHT_BIT;
2267        } else if (brightness == 0) {
2268            return state & ~BUTTON_BRIGHT_BIT;
2269        } else {
2270            return state;
2271        }
2272    }
2273
2274    private int applyKeyboardState(int state) {
2275        int brightness = -1;
2276        if ((state & BATTERY_LOW_BIT) != 0) {
2277            // do not override brightness if the battery is low
2278            return state;
2279        }
2280        if (!mKeyboardVisible) {
2281            brightness = 0;
2282        } else if (mButtonBrightnessOverride >= 0) {
2283            brightness = mButtonBrightnessOverride;
2284        } else if (mLightSensorKeyboardBrightness >= 0 && mUseSoftwareAutoBrightness) {
2285            brightness =  mLightSensorKeyboardBrightness;
2286        }
2287        if (brightness > 0) {
2288            return state | KEYBOARD_BRIGHT_BIT;
2289        } else if (brightness == 0) {
2290            return state & ~KEYBOARD_BRIGHT_BIT;
2291        } else {
2292            return state;
2293        }
2294    }
2295
2296    public boolean isScreenOn() {
2297        synchronized (mLocks) {
2298            return (mPowerState & SCREEN_ON_BIT) != 0;
2299        }
2300    }
2301
2302    boolean isScreenBright() {
2303        synchronized (mLocks) {
2304            return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
2305        }
2306    }
2307
2308    private boolean isScreenTurningOffLocked() {
2309        return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
2310    }
2311
2312    private boolean shouldLog(long time) {
2313        synchronized (mLocks) {
2314            if (time > (mWarningSpewThrottleTime + (60*60*1000))) {
2315                mWarningSpewThrottleTime = time;
2316                mWarningSpewThrottleCount = 0;
2317                return true;
2318            } else if (mWarningSpewThrottleCount < 30) {
2319                mWarningSpewThrottleCount++;
2320                return true;
2321            } else {
2322                return false;
2323            }
2324        }
2325    }
2326
2327    private void forceUserActivityLocked() {
2328        if (isScreenTurningOffLocked()) {
2329            // cancel animation so userActivity will succeed
2330            mScreenBrightness.animating = false;
2331        }
2332        boolean savedActivityAllowed = mUserActivityAllowed;
2333        mUserActivityAllowed = true;
2334        userActivity(SystemClock.uptimeMillis(), false);
2335        mUserActivityAllowed = savedActivityAllowed;
2336    }
2337
2338    public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
2339        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2340        userActivity(time, -1, noChangeLights, OTHER_EVENT, force);
2341    }
2342
2343    public void userActivity(long time, boolean noChangeLights) {
2344        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
2345                != PackageManager.PERMISSION_GRANTED) {
2346            if (shouldLog(time)) {
2347                Slog.w(TAG, "Caller does not have DEVICE_POWER permission.  pid="
2348                        + Binder.getCallingPid() + " uid=" + Binder.getCallingUid());
2349            }
2350            return;
2351        }
2352
2353        userActivity(time, -1, noChangeLights, OTHER_EVENT, false);
2354    }
2355
2356    public void userActivity(long time, boolean noChangeLights, int eventType) {
2357        userActivity(time, -1, noChangeLights, eventType, false);
2358    }
2359
2360    public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
2361        userActivity(time, -1, noChangeLights, eventType, force);
2362    }
2363
2364    /*
2365     * Reset the user activity timeout to now + timeout.  This overrides whatever else is going
2366     * on with user activity.  Don't use this function.
2367     */
2368    public void clearUserActivityTimeout(long now, long timeout) {
2369        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2370        Slog.i(TAG, "clearUserActivity for " + timeout + "ms from now");
2371        userActivity(now, timeout, false, OTHER_EVENT, false);
2372    }
2373
2374    private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
2375            int eventType, boolean force) {
2376
2377        if (((mPokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0) && (eventType == TOUCH_EVENT)) {
2378            if (false) {
2379                Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
2380            }
2381            return;
2382        }
2383
2384        synchronized (mLocks) {
2385            if (mSpew) {
2386                Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
2387                        + " mUserActivityAllowed=" + mUserActivityAllowed
2388                        + " mUserState=0x" + Integer.toHexString(mUserState)
2389                        + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
2390                        + " mProximitySensorActive=" + mProximitySensorActive
2391                        + " timeoutOverride=" + timeoutOverride
2392                        + " force=" + force);
2393            }
2394            // ignore user activity if we are in the process of turning off the screen
2395            if (isScreenTurningOffLocked()) {
2396                Slog.d(TAG, "ignoring user activity while turning off screen");
2397                return;
2398            }
2399            // Disable proximity sensor if if user presses power key while we are in the
2400            // "waiting for proximity sensor to go negative" state.
2401            if (mProximitySensorActive && mProximityWakeLockCount == 0) {
2402                mProximitySensorActive = false;
2403            }
2404            if (mLastEventTime <= time || force) {
2405                mLastEventTime = time;
2406                if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
2407                    // Only turn on button backlights if a button was pressed
2408                    // and auto brightness is disabled
2409                    if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
2410                        mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
2411                    } else {
2412                        // don't clear button/keyboard backlights when the screen is touched.
2413                        mUserState |= SCREEN_BRIGHT;
2414                    }
2415
2416                    int uid = Binder.getCallingUid();
2417                    long ident = Binder.clearCallingIdentity();
2418                    try {
2419                        mBatteryStats.noteUserActivity(uid, eventType);
2420                    } catch (RemoteException e) {
2421                        // Ignore
2422                    } finally {
2423                        Binder.restoreCallingIdentity(ident);
2424                    }
2425
2426                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
2427                    setPowerState(mUserState | mWakeLockState, noChangeLights,
2428                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2429                    setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
2430                }
2431            }
2432        }
2433
2434        if (mPolicy != null) {
2435            mPolicy.userActivity();
2436        }
2437    }
2438
2439    private int getAutoBrightnessValue(int sensorValue, int[] values) {
2440        try {
2441            int i;
2442            for (i = 0; i < mAutoBrightnessLevels.length; i++) {
2443                if (sensorValue < mAutoBrightnessLevels[i]) {
2444                    break;
2445                }
2446            }
2447            return values[i];
2448        } catch (Exception e) {
2449            // guard against null pointer or index out of bounds errors
2450            Slog.e(TAG, "getAutoBrightnessValue", e);
2451            return 255;
2452        }
2453    }
2454
2455    private Runnable mProximityTask = new Runnable() {
2456        public void run() {
2457            synchronized (mLocks) {
2458                if (mProximityPendingValue != -1) {
2459                    proximityChangedLocked(mProximityPendingValue == 1);
2460                    mProximityPendingValue = -1;
2461                }
2462                if (mProximityPartialLock.isHeld()) {
2463                    mProximityPartialLock.release();
2464                }
2465            }
2466        }
2467    };
2468
2469    private Runnable mAutoBrightnessTask = new Runnable() {
2470        public void run() {
2471            synchronized (mLocks) {
2472                if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
2473                    int value = (int)mLightSensorPendingValue;
2474                    mLightSensorPendingDecrease = false;
2475                    mLightSensorPendingIncrease = false;
2476                    lightSensorChangedLocked(value);
2477                }
2478            }
2479        }
2480    };
2481
2482    private void dockStateChanged(int state) {
2483        synchronized (mLocks) {
2484            mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);
2485            if (mIsDocked) {
2486                mHighestLightSensorValue = -1;
2487            }
2488            if ((mPowerState & SCREEN_ON_BIT) != 0) {
2489                // force lights recalculation
2490                int value = (int)mLightSensorValue;
2491                mLightSensorValue = -1;
2492                lightSensorChangedLocked(value);
2493            }
2494        }
2495    }
2496
2497    private void lightSensorChangedLocked(int value) {
2498        if (mDebugLightSensor) {
2499            Slog.d(TAG, "lightSensorChangedLocked " + value);
2500        }
2501
2502        // Don't do anything if the screen is off.
2503        if ((mPowerState & SCREEN_ON_BIT) == 0) {
2504            if (mDebugLightSensor) {
2505                Slog.d(TAG, "dropping lightSensorChangedLocked because screen is off");
2506            }
2507            return;
2508        }
2509
2510        // do not allow light sensor value to decrease
2511        if (mHighestLightSensorValue < value) {
2512            mHighestLightSensorValue = value;
2513        }
2514
2515        if (mLightSensorValue != value) {
2516            mLightSensorValue = value;
2517            if ((mPowerState & BATTERY_LOW_BIT) == 0) {
2518                // use maximum light sensor value seen since screen went on for LCD to avoid flicker
2519                // we only do this if we are undocked, since lighting should be stable when
2520                // stationary in a dock.
2521                int lcdValue = getAutoBrightnessValue(
2522                        (mIsDocked ? value : mHighestLightSensorValue),
2523                        mLcdBacklightValues);
2524                int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
2525                int keyboardValue;
2526                if (mKeyboardVisible) {
2527                    keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
2528                } else {
2529                    keyboardValue = 0;
2530                }
2531                mLightSensorScreenBrightness = lcdValue;
2532                mLightSensorButtonBrightness = buttonValue;
2533                mLightSensorKeyboardBrightness = keyboardValue;
2534
2535                if (mDebugLightSensor) {
2536                    Slog.d(TAG, "lcdValue " + lcdValue);
2537                    Slog.d(TAG, "buttonValue " + buttonValue);
2538                    Slog.d(TAG, "keyboardValue " + keyboardValue);
2539                }
2540
2541                if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
2542                    if (!mSkippedScreenOn) {
2543                        mScreenBrightness.setTargetLocked(lcdValue, AUTOBRIGHTNESS_ANIM_STEPS,
2544                                INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue);
2545                    }
2546                }
2547                if (mButtonBrightnessOverride < 0) {
2548                    mButtonLight.setBrightness(buttonValue);
2549                }
2550                if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
2551                    mKeyboardLight.setBrightness(keyboardValue);
2552                }
2553            }
2554        }
2555    }
2556
2557    /**
2558     * The user requested that we go to sleep (probably with the power button).
2559     * This overrides all wake locks that are held.
2560     */
2561    public void goToSleep(long time)
2562    {
2563        goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2564    }
2565
2566    /**
2567     * The user requested that we go to sleep (probably with the power button).
2568     * This overrides all wake locks that are held.
2569     */
2570    public void goToSleepWithReason(long time, int reason)
2571    {
2572        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2573        synchronized (mLocks) {
2574            goToSleepLocked(time, reason);
2575        }
2576    }
2577
2578    /**
2579     * Reboot the device immediately, passing 'reason' (may be null)
2580     * to the underlying __reboot system call.  Should not return.
2581     */
2582    public void reboot(String reason)
2583    {
2584        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2585
2586        if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
2587            throw new IllegalStateException("Too early to call reboot()");
2588        }
2589
2590        final String finalReason = reason;
2591        Runnable runnable = new Runnable() {
2592            public void run() {
2593                synchronized (this) {
2594                    ShutdownThread.reboot(mContext, finalReason, false);
2595                }
2596
2597            }
2598        };
2599        // ShutdownThread must run on a looper capable of displaying the UI.
2600        mHandler.post(runnable);
2601
2602        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
2603        synchronized (runnable) {
2604            while (true) {
2605                try {
2606                    runnable.wait();
2607                } catch (InterruptedException e) {
2608                }
2609            }
2610        }
2611    }
2612
2613    /**
2614     * Crash the runtime (causing a complete restart of the Android framework).
2615     * Requires REBOOT permission.  Mostly for testing.  Should not return.
2616     */
2617    public void crash(final String message)
2618    {
2619        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2620        Thread t = new Thread("PowerManagerService.crash()") {
2621            public void run() { throw new RuntimeException(message); }
2622        };
2623        try {
2624            t.start();
2625            t.join();
2626        } catch (InterruptedException e) {
2627            Log.wtf(TAG, e);
2628        }
2629    }
2630
2631    private void goToSleepLocked(long time, int reason) {
2632
2633        if (mLastEventTime <= time) {
2634            mLastEventTime = time;
2635            // cancel all of the wake locks
2636            mWakeLockState = SCREEN_OFF;
2637            int N = mLocks.size();
2638            int numCleared = 0;
2639            boolean proxLock = false;
2640            for (int i=0; i<N; i++) {
2641                WakeLock wl = mLocks.get(i);
2642                if (isScreenLock(wl.flags)) {
2643                    if (((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
2644                            && reason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
2645                        proxLock = true;
2646                    } else {
2647                        mLocks.get(i).activated = false;
2648                        numCleared++;
2649                    }
2650                }
2651            }
2652            if (!proxLock) {
2653                mProxIgnoredBecauseScreenTurnedOff = true;
2654                if (mDebugProximitySensor) {
2655                    Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");
2656                }
2657            }
2658            EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
2659            mStillNeedSleepNotification = true;
2660            mUserState = SCREEN_OFF;
2661            setPowerState(SCREEN_OFF, false, reason);
2662            cancelTimerLocked();
2663        }
2664    }
2665
2666    public long timeSinceScreenOn() {
2667        synchronized (mLocks) {
2668            if ((mPowerState & SCREEN_ON_BIT) != 0) {
2669                return 0;
2670            }
2671            return SystemClock.elapsedRealtime() - mScreenOffTime;
2672        }
2673    }
2674
2675    public void setKeyboardVisibility(boolean visible) {
2676        synchronized (mLocks) {
2677            if (mSpew) {
2678                Slog.d(TAG, "setKeyboardVisibility: " + visible);
2679            }
2680            if (mKeyboardVisible != visible) {
2681                mKeyboardVisible = visible;
2682                // don't signal user activity if the screen is off; other code
2683                // will take care of turning on due to a true change to the lid
2684                // switch and synchronized with the lock screen.
2685                if ((mPowerState & SCREEN_ON_BIT) != 0) {
2686                    if (mUseSoftwareAutoBrightness) {
2687                        // force recompute of backlight values
2688                        if (mLightSensorValue >= 0) {
2689                            int value = (int)mLightSensorValue;
2690                            mLightSensorValue = -1;
2691                            lightSensorChangedLocked(value);
2692                        }
2693                    }
2694                    userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2695                }
2696            }
2697        }
2698    }
2699
2700    /**
2701     * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
2702     * When disabling user activity we also reset user power state so the keyguard can reset its
2703     * short screen timeout when keyguard is unhidden.
2704     */
2705    public void enableUserActivity(boolean enabled) {
2706        if (mSpew) {
2707            Slog.d(TAG, "enableUserActivity " + enabled);
2708        }
2709        synchronized (mLocks) {
2710            mUserActivityAllowed = enabled;
2711            if (!enabled) {
2712                // cancel timeout and clear mUserState so the keyguard can set a short timeout
2713                setTimeoutLocked(SystemClock.uptimeMillis(), 0);
2714            }
2715        }
2716    }
2717
2718    private void setScreenBrightnessMode(int mode) {
2719        synchronized (mLocks) {
2720            boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
2721            if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
2722                mAutoBrightessEnabled = enabled;
2723                // This will get us a new value
2724                enableLightSensorLocked(mAutoBrightessEnabled && isScreenOn());
2725            }
2726        }
2727    }
2728
2729    /** Sets the screen off timeouts:
2730     *      mKeylightDelay
2731     *      mDimDelay
2732     *      mScreenOffDelay
2733     * */
2734    private void setScreenOffTimeoutsLocked() {
2735        if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
2736            mKeylightDelay = mShortKeylightDelay;  // Configurable via secure settings
2737            mDimDelay = -1;
2738            mScreenOffDelay = 0;
2739        } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
2740            mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
2741            mDimDelay = -1;
2742            mScreenOffDelay = 0;
2743        } else {
2744            int totalDelay = mScreenOffTimeoutSetting;
2745            if (totalDelay > mMaximumScreenOffTimeout) {
2746                totalDelay = mMaximumScreenOffTimeout;
2747            }
2748            mKeylightDelay = LONG_KEYLIGHT_DELAY;
2749            if (totalDelay < 0) {
2750                // negative number means stay on as long as possible.
2751                mScreenOffDelay = mMaximumScreenOffTimeout;
2752            } else if (mKeylightDelay < totalDelay) {
2753                // subtract the time that the keylight delay. This will give us the
2754                // remainder of the time that we need to sleep to get the accurate
2755                // screen off timeout.
2756                mScreenOffDelay = totalDelay - mKeylightDelay;
2757            } else {
2758                mScreenOffDelay = 0;
2759            }
2760            if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
2761                mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
2762                mScreenOffDelay = LONG_DIM_TIME;
2763            } else {
2764                mDimDelay = -1;
2765            }
2766        }
2767        if (mSpew) {
2768            Slog.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
2769                    + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
2770                    + " mDimScreen=" + mDimScreen);
2771        }
2772    }
2773
2774    /**
2775     * Refreshes cached secure settings.  Called once on startup, and
2776     * on subsequent changes to secure settings.
2777     */
2778    private void updateSettingsValues() {
2779        mShortKeylightDelay = Settings.Secure.getInt(
2780                mContext.getContentResolver(),
2781                Settings.Secure.SHORT_KEYLIGHT_DELAY_MS,
2782                SHORT_KEYLIGHT_DELAY_DEFAULT);
2783        // Slog.i(TAG, "updateSettingsValues(): mShortKeylightDelay now " + mShortKeylightDelay);
2784    }
2785
2786    private class LockList extends ArrayList<WakeLock>
2787    {
2788        void addLock(WakeLock wl)
2789        {
2790            int index = getIndex(wl.binder);
2791            if (index < 0) {
2792                this.add(wl);
2793            }
2794        }
2795
2796        WakeLock removeLock(IBinder binder)
2797        {
2798            int index = getIndex(binder);
2799            if (index >= 0) {
2800                return this.remove(index);
2801            } else {
2802                return null;
2803            }
2804        }
2805
2806        int getIndex(IBinder binder)
2807        {
2808            int N = this.size();
2809            for (int i=0; i<N; i++) {
2810                if (this.get(i).binder == binder) {
2811                    return i;
2812                }
2813            }
2814            return -1;
2815        }
2816
2817        int gatherState()
2818        {
2819            int result = 0;
2820            int N = this.size();
2821            for (int i=0; i<N; i++) {
2822                WakeLock wl = this.get(i);
2823                if (wl.activated) {
2824                    if (isScreenLock(wl.flags)) {
2825                        result |= wl.minState;
2826                    }
2827                }
2828            }
2829            return result;
2830        }
2831
2832        int reactivateScreenLocksLocked()
2833        {
2834            int result = 0;
2835            int N = this.size();
2836            for (int i=0; i<N; i++) {
2837                WakeLock wl = this.get(i);
2838                if (isScreenLock(wl.flags)) {
2839                    wl.activated = true;
2840                    result |= wl.minState;
2841                }
2842            }
2843            if (mDebugProximitySensor) {
2844                Slog.d(TAG, "reactivateScreenLocksLocked mProxIgnoredBecauseScreenTurnedOff="
2845                        + mProxIgnoredBecauseScreenTurnedOff);
2846            }
2847            mProxIgnoredBecauseScreenTurnedOff = false;
2848            return result;
2849        }
2850    }
2851
2852    public void setPolicy(WindowManagerPolicy p) {
2853        synchronized (mLocks) {
2854            mPolicy = p;
2855            mLocks.notifyAll();
2856        }
2857    }
2858
2859    WindowManagerPolicy getPolicyLocked() {
2860        while (mPolicy == null || !mDoneBooting) {
2861            try {
2862                mLocks.wait();
2863            } catch (InterruptedException e) {
2864                // Ignore
2865            }
2866        }
2867        return mPolicy;
2868    }
2869
2870    void systemReady() {
2871        mSensorManager = new SensorManager(mHandlerThread.getLooper());
2872        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
2873        // don't bother with the light sensor if auto brightness is handled in hardware
2874        if (mUseSoftwareAutoBrightness) {
2875            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
2876        }
2877
2878        // wait until sensors are enabled before turning on screen.
2879        // some devices will not activate the light sensor properly on boot
2880        // unless we do this.
2881        if (mUseSoftwareAutoBrightness) {
2882            // turn the screen on
2883            setPowerState(SCREEN_BRIGHT);
2884        } else {
2885            // turn everything on
2886            setPowerState(ALL_BRIGHT);
2887        }
2888
2889        synchronized (mLocks) {
2890            Slog.d(TAG, "system ready!");
2891            mDoneBooting = true;
2892
2893            enableLightSensorLocked(mUseSoftwareAutoBrightness && mAutoBrightessEnabled);
2894
2895            long identity = Binder.clearCallingIdentity();
2896            try {
2897                mBatteryStats.noteScreenBrightness(getPreferredBrightness());
2898                mBatteryStats.noteScreenOn();
2899            } catch (RemoteException e) {
2900                // Nothing interesting to do.
2901            } finally {
2902                Binder.restoreCallingIdentity(identity);
2903            }
2904        }
2905    }
2906
2907    void bootCompleted() {
2908        Slog.d(TAG, "bootCompleted");
2909        synchronized (mLocks) {
2910            mBootCompleted = true;
2911            userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2912            updateWakeLockLocked();
2913            mLocks.notifyAll();
2914        }
2915    }
2916
2917    // for watchdog
2918    public void monitor() {
2919        synchronized (mLocks) { }
2920    }
2921
2922    public int getSupportedWakeLockFlags() {
2923        int result = PowerManager.PARTIAL_WAKE_LOCK
2924                   | PowerManager.FULL_WAKE_LOCK
2925                   | PowerManager.SCREEN_DIM_WAKE_LOCK;
2926
2927        if (mProximitySensor != null) {
2928            result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
2929        }
2930
2931        return result;
2932    }
2933
2934    public void setBacklightBrightness(int brightness) {
2935        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2936        // Don't let applications turn the screen all the way off
2937        synchronized (mLocks) {
2938            brightness = Math.max(brightness, mScreenBrightnessDim);
2939            mLcdLight.setBrightness(brightness);
2940            mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
2941            mButtonLight.setBrightness(brightness);
2942            long identity = Binder.clearCallingIdentity();
2943            try {
2944                mBatteryStats.noteScreenBrightness(brightness);
2945            } catch (RemoteException e) {
2946                Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2947            } finally {
2948                Binder.restoreCallingIdentity(identity);
2949            }
2950
2951            // update our animation state
2952            synchronized (mLocks) {
2953                mScreenBrightness.targetValue = brightness;
2954                mScreenBrightness.jumpToTargetLocked();
2955            }
2956        }
2957    }
2958
2959    public void setAttentionLight(boolean on, int color) {
2960        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2961        mAttentionLight.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
2962    }
2963
2964    private void enableProximityLockLocked() {
2965        if (mDebugProximitySensor) {
2966            Slog.d(TAG, "enableProximityLockLocked");
2967        }
2968        if (!mProximitySensorEnabled) {
2969            // clear calling identity so sensor manager battery stats are accurate
2970            long identity = Binder.clearCallingIdentity();
2971            try {
2972                mSensorManager.registerListener(mProximityListener, mProximitySensor,
2973                        SensorManager.SENSOR_DELAY_NORMAL);
2974                mProximitySensorEnabled = true;
2975            } finally {
2976                Binder.restoreCallingIdentity(identity);
2977            }
2978        }
2979    }
2980
2981    private void disableProximityLockLocked() {
2982        if (mDebugProximitySensor) {
2983            Slog.d(TAG, "disableProximityLockLocked");
2984        }
2985        if (mProximitySensorEnabled) {
2986            // clear calling identity so sensor manager battery stats are accurate
2987            long identity = Binder.clearCallingIdentity();
2988            try {
2989                mSensorManager.unregisterListener(mProximityListener);
2990                mHandler.removeCallbacks(mProximityTask);
2991                if (mProximityPartialLock.isHeld()) {
2992                    mProximityPartialLock.release();
2993                }
2994                mProximitySensorEnabled = false;
2995            } finally {
2996                Binder.restoreCallingIdentity(identity);
2997            }
2998            if (mProximitySensorActive) {
2999                mProximitySensorActive = false;
3000                if (mDebugProximitySensor) {
3001                    Slog.d(TAG, "disableProximityLockLocked mProxIgnoredBecauseScreenTurnedOff="
3002                            + mProxIgnoredBecauseScreenTurnedOff);
3003                }
3004                if (!mProxIgnoredBecauseScreenTurnedOff) {
3005                    forceUserActivityLocked();
3006                }
3007            }
3008        }
3009    }
3010
3011    private void proximityChangedLocked(boolean active) {
3012        if (mDebugProximitySensor) {
3013            Slog.d(TAG, "proximityChangedLocked, active: " + active);
3014        }
3015        if (!mProximitySensorEnabled) {
3016            Slog.d(TAG, "Ignoring proximity change after sensor is disabled");
3017            return;
3018        }
3019        if (active) {
3020            if (mDebugProximitySensor) {
3021                Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
3022                        + mProxIgnoredBecauseScreenTurnedOff);
3023            }
3024            if (!mProxIgnoredBecauseScreenTurnedOff) {
3025                goToSleepLocked(SystemClock.uptimeMillis(),
3026                        WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
3027            }
3028            mProximitySensorActive = true;
3029        } else {
3030            // proximity sensor negative events trigger as user activity.
3031            // temporarily set mUserActivityAllowed to true so this will work
3032            // even when the keyguard is on.
3033            mProximitySensorActive = false;
3034            if (mDebugProximitySensor) {
3035                Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
3036                        + mProxIgnoredBecauseScreenTurnedOff);
3037            }
3038            if (!mProxIgnoredBecauseScreenTurnedOff) {
3039                forceUserActivityLocked();
3040            }
3041
3042            if (mProximityWakeLockCount == 0) {
3043                // disable sensor if we have no listeners left after proximity negative
3044                disableProximityLockLocked();
3045            }
3046        }
3047    }
3048
3049    private void enableLightSensorLocked(boolean enable) {
3050        if (mDebugLightSensor) {
3051            Slog.d(TAG, "enableLightSensorLocked enable=" + enable
3052                    + " mAutoBrightessEnabled=" + mAutoBrightessEnabled);
3053        }
3054        if (!mAutoBrightessEnabled) {
3055            enable = false;
3056        }
3057        if (mSensorManager != null && mLightSensorEnabled != enable) {
3058            mLightSensorEnabled = enable;
3059            // clear previous values so we will adjust to current brightness when
3060            // auto-brightness is reenabled
3061            mHighestLightSensorValue = -1;
3062            mLightSensorValue = -1;
3063
3064            // clear calling identity so sensor manager battery stats are accurate
3065            long identity = Binder.clearCallingIdentity();
3066            try {
3067                if (enable) {
3068                    mSensorManager.registerListener(mLightListener, mLightSensor,
3069                            LIGHT_SENSOR_RATE);
3070                } else {
3071                    mSensorManager.unregisterListener(mLightListener);
3072                    mHandler.removeCallbacks(mAutoBrightnessTask);
3073                }
3074            } finally {
3075                Binder.restoreCallingIdentity(identity);
3076            }
3077        }
3078    }
3079
3080    SensorEventListener mProximityListener = new SensorEventListener() {
3081        public void onSensorChanged(SensorEvent event) {
3082            long milliseconds = SystemClock.elapsedRealtime();
3083            synchronized (mLocks) {
3084                float distance = event.values[0];
3085                long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
3086                mLastProximityEventTime = milliseconds;
3087                mHandler.removeCallbacks(mProximityTask);
3088                boolean proximityTaskQueued = false;
3089
3090                // compare against getMaximumRange to support sensors that only return 0 or 1
3091                boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
3092                        distance < mProximitySensor.getMaximumRange());
3093
3094                if (mDebugProximitySensor) {
3095                    Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
3096                }
3097                if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
3098                    // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
3099                    mProximityPendingValue = (active ? 1 : 0);
3100                    mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
3101                    proximityTaskQueued = true;
3102                } else {
3103                    // process the value immediately
3104                    mProximityPendingValue = -1;
3105                    proximityChangedLocked(active);
3106                }
3107
3108                // update mProximityPartialLock state
3109                boolean held = mProximityPartialLock.isHeld();
3110                if (!held && proximityTaskQueued) {
3111                    // hold wakelock until mProximityTask runs
3112                    mProximityPartialLock.acquire();
3113                } else if (held && !proximityTaskQueued) {
3114                    mProximityPartialLock.release();
3115                }
3116            }
3117        }
3118
3119        public void onAccuracyChanged(Sensor sensor, int accuracy) {
3120            // ignore
3121        }
3122    };
3123
3124    SensorEventListener mLightListener = new SensorEventListener() {
3125        public void onSensorChanged(SensorEvent event) {
3126            synchronized (mLocks) {
3127                // ignore light sensor while screen is turning off
3128                if (isScreenTurningOffLocked()) {
3129                    return;
3130                }
3131
3132                int value = (int)event.values[0];
3133                long milliseconds = SystemClock.elapsedRealtime();
3134                if (mDebugLightSensor) {
3135                    Slog.d(TAG, "onSensorChanged: light value: " + value);
3136                }
3137                if (mLightSensorValue == -1 ||
3138                        milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
3139                    // process the value immediately if screen has just turned on
3140                    mHandler.removeCallbacks(mAutoBrightnessTask);
3141                    mLightSensorPendingDecrease = false;
3142                    mLightSensorPendingIncrease = false;
3143                    lightSensorChangedLocked(value);
3144                } else {
3145                    if ((value > mLightSensorValue && mLightSensorPendingDecrease) ||
3146                            (value < mLightSensorValue && mLightSensorPendingIncrease) ||
3147                            (value == mLightSensorValue) ||
3148                            (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) {
3149                        // delay processing to debounce the sensor
3150                        mHandler.removeCallbacks(mAutoBrightnessTask);
3151                        mLightSensorPendingDecrease = (value < mLightSensorValue);
3152                        mLightSensorPendingIncrease = (value > mLightSensorValue);
3153                        if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
3154                            mLightSensorPendingValue = value;
3155                            mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
3156                        }
3157                    } else {
3158                        mLightSensorPendingValue = value;
3159                    }
3160                }
3161            }
3162        }
3163
3164        public void onAccuracyChanged(Sensor sensor, int accuracy) {
3165            // ignore
3166        }
3167    };
3168}
3169