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