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