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