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            pid = Binder.getCallingPid();
575            if (u != MY_UID || (
576                    !"KEEP_SCREEN_ON_FLAG".equals(tag)
577                    && !"KeyInputQueue".equals(tag))) {
578                monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
579                        ? BatteryStats.WAKE_TYPE_PARTIAL
580                        : BatteryStats.WAKE_TYPE_FULL;
581            } else {
582                monitorType = -1;
583            }
584            try {
585                b.linkToDeath(this, 0);
586            } catch (RemoteException e) {
587                binderDied();
588            }
589        }
590        public void binderDied() {
591            synchronized (mLocks) {
592                releaseWakeLockLocked(this.binder, 0, true);
593            }
594        }
595        final int flags;
596        final IBinder binder;
597        final String tag;
598        final int uid;
599        final int pid;
600        final int monitorType;
601        boolean activated = true;
602        int minState;
603    }
604
605    private void updateWakeLockLocked() {
606        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
607            // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
608            mStayOnWhilePluggedInScreenDimLock.acquire();
609            mStayOnWhilePluggedInPartialLock.acquire();
610        } else {
611            mStayOnWhilePluggedInScreenDimLock.release();
612            mStayOnWhilePluggedInPartialLock.release();
613        }
614    }
615
616    private boolean isScreenLock(int flags)
617    {
618        int n = flags & LOCK_MASK;
619        return n == PowerManager.FULL_WAKE_LOCK
620                || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
621                || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
622    }
623
624    public void acquireWakeLock(int flags, IBinder lock, String tag) {
625        int uid = Binder.getCallingUid();
626        if (uid != Process.myUid()) {
627            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
628        }
629        long ident = Binder.clearCallingIdentity();
630        try {
631            synchronized (mLocks) {
632                acquireWakeLockLocked(flags, lock, uid, tag);
633            }
634        } finally {
635            Binder.restoreCallingIdentity(ident);
636        }
637    }
638
639    public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
640        int acquireUid = -1;
641        String acquireName = null;
642        int acquireType = -1;
643
644        if (mSpew) {
645            Slog.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
646        }
647
648        int index = mLocks.getIndex(lock);
649        WakeLock wl;
650        boolean newlock;
651        if (index < 0) {
652            wl = new WakeLock(flags, lock, tag, uid);
653            switch (wl.flags & LOCK_MASK)
654            {
655                case PowerManager.FULL_WAKE_LOCK:
656                    if (mUseSoftwareAutoBrightness) {
657                        wl.minState = SCREEN_BRIGHT;
658                    } else {
659                        wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
660                    }
661                    break;
662                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
663                    wl.minState = SCREEN_BRIGHT;
664                    break;
665                case PowerManager.SCREEN_DIM_WAKE_LOCK:
666                    wl.minState = SCREEN_DIM;
667                    break;
668                case PowerManager.PARTIAL_WAKE_LOCK:
669                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
670                    break;
671                default:
672                    // just log and bail.  we're in the server, so don't
673                    // throw an exception.
674                    Slog.e(TAG, "bad wakelock type for lock '" + tag + "' "
675                            + " flags=" + flags);
676                    return;
677            }
678            mLocks.addLock(wl);
679            newlock = true;
680        } else {
681            wl = mLocks.get(index);
682            newlock = false;
683        }
684        if (isScreenLock(flags)) {
685            // if this causes a wakeup, we reactivate all of the locks and
686            // set it to whatever they want.  otherwise, we modulate that
687            // by the current state so we never turn it more on than
688            // it already is.
689            if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
690                int oldWakeLockState = mWakeLockState;
691                mWakeLockState = mLocks.reactivateScreenLocksLocked();
692                if (mSpew) {
693                    Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
694                            + " mWakeLockState=0x"
695                            + Integer.toHexString(mWakeLockState)
696                            + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
697                }
698            } else {
699                if (mSpew) {
700                    Slog.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
701                            + " mLocks.gatherState()=0x"
702                            + Integer.toHexString(mLocks.gatherState())
703                            + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
704                }
705                mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
706            }
707            setPowerState(mWakeLockState | mUserState);
708        }
709        else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
710            if (newlock) {
711                mPartialCount++;
712                if (mPartialCount == 1) {
713                    if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
714                }
715            }
716            Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
717        } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
718            mProximityWakeLockCount++;
719            if (mProximityWakeLockCount == 1) {
720                enableProximityLockLocked();
721            }
722        }
723        if (newlock) {
724            acquireUid = wl.uid;
725            acquireName = wl.tag;
726            acquireType = wl.monitorType;
727        }
728
729        if (acquireType >= 0) {
730            try {
731                mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
732            } catch (RemoteException e) {
733                // Ignore
734            }
735        }
736    }
737
738    public void releaseWakeLock(IBinder lock, int flags) {
739        int uid = Binder.getCallingUid();
740        if (uid != Process.myUid()) {
741            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
742        }
743
744        synchronized (mLocks) {
745            releaseWakeLockLocked(lock, flags, false);
746        }
747    }
748
749    private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
750        int releaseUid;
751        String releaseName;
752        int releaseType;
753
754        WakeLock wl = mLocks.removeLock(lock);
755        if (wl == null) {
756            return;
757        }
758
759        if (mSpew) {
760            Slog.d(TAG, "releaseWakeLock flags=0x"
761                    + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
762        }
763
764        if (isScreenLock(wl.flags)) {
765            mWakeLockState = mLocks.gatherState();
766            // goes in the middle to reduce flicker
767            if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
768                userActivity(SystemClock.uptimeMillis(), false);
769            }
770            setPowerState(mWakeLockState | mUserState);
771        }
772        else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
773            mPartialCount--;
774            if (mPartialCount == 0) {
775                if (LOG_PARTIAL_WL) EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
776                Power.releaseWakeLock(PARTIAL_NAME);
777            }
778        } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
779            mProximityWakeLockCount--;
780            if (mProximityWakeLockCount == 0) {
781                if (mProximitySensorActive &&
782                        ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
783                    // wait for proximity sensor to go negative before disabling sensor
784                    if (mDebugProximitySensor) {
785                        Slog.d(TAG, "waiting for proximity sensor to go negative");
786                    }
787                } else {
788                    disableProximityLockLocked();
789                }
790            }
791        }
792        // Unlink the lock from the binder.
793        wl.binder.unlinkToDeath(wl, 0);
794        releaseUid = wl.uid;
795        releaseName = wl.tag;
796        releaseType = wl.monitorType;
797
798        if (releaseType >= 0) {
799            long origId = Binder.clearCallingIdentity();
800            try {
801                mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
802            } catch (RemoteException e) {
803                // Ignore
804            } finally {
805                Binder.restoreCallingIdentity(origId);
806            }
807        }
808    }
809
810    private class PokeLock implements IBinder.DeathRecipient
811    {
812        PokeLock(int p, IBinder b, String t) {
813            super();
814            this.pokey = p;
815            this.binder = b;
816            this.tag = t;
817            try {
818                b.linkToDeath(this, 0);
819            } catch (RemoteException e) {
820                binderDied();
821            }
822        }
823        public void binderDied() {
824            setPokeLock(0, this.binder, this.tag);
825        }
826        int pokey;
827        IBinder binder;
828        String tag;
829        boolean awakeOnSet;
830    }
831
832    public void setPokeLock(int pokey, IBinder token, String tag) {
833        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
834        if (token == null) {
835            Slog.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
836            return;
837        }
838
839        if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
840            throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
841                    + " and POKE_LOCK_MEDIUM_TIMEOUT");
842        }
843
844        synchronized (mLocks) {
845            if (pokey != 0) {
846                PokeLock p = mPokeLocks.get(token);
847                int oldPokey = 0;
848                if (p != null) {
849                    oldPokey = p.pokey;
850                    p.pokey = pokey;
851                } else {
852                    p = new PokeLock(pokey, token, tag);
853                    mPokeLocks.put(token, p);
854                }
855                int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
856                int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
857                if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
858                    p.awakeOnSet = true;
859                }
860            } else {
861                PokeLock rLock = mPokeLocks.remove(token);
862                if (rLock != null) {
863                    token.unlinkToDeath(rLock, 0);
864                }
865            }
866
867            int oldPokey = mPokey;
868            int cumulative = 0;
869            boolean oldAwakeOnSet = mPokeAwakeOnSet;
870            boolean awakeOnSet = false;
871            for (PokeLock p: mPokeLocks.values()) {
872                cumulative |= p.pokey;
873                if (p.awakeOnSet) {
874                    awakeOnSet = true;
875                }
876            }
877            mPokey = cumulative;
878            mPokeAwakeOnSet = awakeOnSet;
879
880            int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
881            int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
882
883            if (oldCumulativeTimeout != newCumulativeTimeout) {
884                setScreenOffTimeoutsLocked();
885                // reset the countdown timer, but use the existing nextState so it doesn't
886                // change anything
887                setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
888            }
889        }
890    }
891
892    private static String lockType(int type)
893    {
894        switch (type)
895        {
896            case PowerManager.FULL_WAKE_LOCK:
897                return "FULL_WAKE_LOCK                ";
898            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
899                return "SCREEN_BRIGHT_WAKE_LOCK       ";
900            case PowerManager.SCREEN_DIM_WAKE_LOCK:
901                return "SCREEN_DIM_WAKE_LOCK          ";
902            case PowerManager.PARTIAL_WAKE_LOCK:
903                return "PARTIAL_WAKE_LOCK             ";
904            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
905                return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
906            default:
907                return "???                           ";
908        }
909    }
910
911    private static String dumpPowerState(int state) {
912        return (((state & KEYBOARD_BRIGHT_BIT) != 0)
913                        ? "KEYBOARD_BRIGHT_BIT " : "")
914                + (((state & SCREEN_BRIGHT_BIT) != 0)
915                        ? "SCREEN_BRIGHT_BIT " : "")
916                + (((state & SCREEN_ON_BIT) != 0)
917                        ? "SCREEN_ON_BIT " : "")
918                + (((state & BATTERY_LOW_BIT) != 0)
919                        ? "BATTERY_LOW_BIT " : "");
920    }
921
922    @Override
923    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
924        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
925                != PackageManager.PERMISSION_GRANTED) {
926            pw.println("Permission Denial: can't dump PowerManager from from pid="
927                    + Binder.getCallingPid()
928                    + ", uid=" + Binder.getCallingUid());
929            return;
930        }
931
932        long now = SystemClock.uptimeMillis();
933
934        synchronized (mLocks) {
935            pw.println("Power Manager State:");
936            pw.println("  mIsPowered=" + mIsPowered
937                    + " mPowerState=" + mPowerState
938                    + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
939                    + " ms");
940            pw.println("  mPartialCount=" + mPartialCount);
941            pw.println("  mWakeLockState=" + dumpPowerState(mWakeLockState));
942            pw.println("  mUserState=" + dumpPowerState(mUserState));
943            pw.println("  mPowerState=" + dumpPowerState(mPowerState));
944            pw.println("  mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
945            pw.println("  mNextTimeout=" + mNextTimeout + " now=" + now
946                    + " " + ((mNextTimeout-now)/1000) + "s from now");
947            pw.println("  mDimScreen=" + mDimScreen
948                    + " mStayOnConditions=" + mStayOnConditions);
949            pw.println("  mScreenOffReason=" + mScreenOffReason
950                    + " mUserState=" + mUserState);
951            pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
952                    + ',' + mBroadcastQueue[2] + "}");
953            pw.println("  mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
954                    + ',' + mBroadcastWhy[2] + "}");
955            pw.println("  mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
956            pw.println("  mKeyboardVisible=" + mKeyboardVisible
957                    + " mUserActivityAllowed=" + mUserActivityAllowed);
958            pw.println("  mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
959                    + " mScreenOffDelay=" + mScreenOffDelay);
960            pw.println("  mPreventScreenOn=" + mPreventScreenOn
961                    + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride
962                    + "  mButtonBrightnessOverride=" + mButtonBrightnessOverride);
963            pw.println("  mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting
964                    + " mMaximumScreenOffTimeout=" + mMaximumScreenOffTimeout);
965            pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
966            pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
967            pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
968            pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
969            pw.println("  mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
970            pw.println("  mProximityPartialLock=" + mProximityPartialLock);
971            pw.println("  mProximityWakeLockCount=" + mProximityWakeLockCount);
972            pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
973            pw.println("  mProximitySensorActive=" + mProximitySensorActive);
974            pw.println("  mProximityPendingValue=" + mProximityPendingValue);
975            pw.println("  mLastProximityEventTime=" + mLastProximityEventTime);
976            pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
977            pw.println("  mLightSensorValue=" + mLightSensorValue
978                    + " mLightSensorPendingValue=" + mLightSensorPendingValue);
979            pw.println("  mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
980                    + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
981                    + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
982            pw.println("  mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
983            pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
984            mScreenBrightness.dump(pw, "  mScreenBrightness: ");
985            mKeyboardBrightness.dump(pw, "  mKeyboardBrightness: ");
986            mButtonBrightness.dump(pw, "  mButtonBrightness: ");
987
988            int N = mLocks.size();
989            pw.println();
990            pw.println("mLocks.size=" + N + ":");
991            for (int i=0; i<N; i++) {
992                WakeLock wl = mLocks.get(i);
993                String type = lockType(wl.flags & LOCK_MASK);
994                String acquireCausesWakeup = "";
995                if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
996                    acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
997                }
998                String activated = "";
999                if (wl.activated) {
1000                   activated = " activated";
1001                }
1002                pw.println("  " + type + " '" + wl.tag + "'" + acquireCausesWakeup
1003                        + activated + " (minState=" + wl.minState + ", uid=" + wl.uid
1004                        + ", pid=" + wl.pid + ")");
1005            }
1006
1007            pw.println();
1008            pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
1009            for (PokeLock p: mPokeLocks.values()) {
1010                pw.println("    poke lock '" + p.tag + "':"
1011                        + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
1012                                ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
1013                        + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0
1014                                ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "")
1015                        + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
1016                                ? " POKE_LOCK_SHORT_TIMEOUT" : "")
1017                        + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
1018                                ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
1019            }
1020
1021            pw.println();
1022        }
1023    }
1024
1025    private void setTimeoutLocked(long now, int nextState) {
1026        setTimeoutLocked(now, -1, nextState);
1027    }
1028
1029    // If they gave a timeoutOverride it is the number of seconds
1030    // to screen-off.  Figure out where in the countdown cycle we
1031    // should jump to.
1032    private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
1033        long timeoutOverride = originalTimeoutOverride;
1034        if (mBootCompleted) {
1035            synchronized (mLocks) {
1036                long when = 0;
1037                if (timeoutOverride <= 0) {
1038                    switch (nextState)
1039                    {
1040                        case SCREEN_BRIGHT:
1041                            when = now + mKeylightDelay;
1042                            break;
1043                        case SCREEN_DIM:
1044                            if (mDimDelay >= 0) {
1045                                when = now + mDimDelay;
1046                                break;
1047                            } else {
1048                                Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
1049                            }
1050                       case SCREEN_OFF:
1051                            synchronized (mLocks) {
1052                                when = now + mScreenOffDelay;
1053                            }
1054                            break;
1055                        default:
1056                            when = now;
1057                            break;
1058                    }
1059                } else {
1060                    override: {
1061                        if (timeoutOverride <= mScreenOffDelay) {
1062                            when = now + timeoutOverride;
1063                            nextState = SCREEN_OFF;
1064                            break override;
1065                        }
1066                        timeoutOverride -= mScreenOffDelay;
1067
1068                        if (mDimDelay >= 0) {
1069                             if (timeoutOverride <= mDimDelay) {
1070                                when = now + timeoutOverride;
1071                                nextState = SCREEN_DIM;
1072                                break override;
1073                            }
1074                            timeoutOverride -= mDimDelay;
1075                        }
1076
1077                        when = now + timeoutOverride;
1078                        nextState = SCREEN_BRIGHT;
1079                    }
1080                }
1081                if (mSpew) {
1082                    Slog.d(TAG, "setTimeoutLocked now=" + now
1083                            + " timeoutOverride=" + timeoutOverride
1084                            + " nextState=" + nextState + " when=" + when);
1085                }
1086
1087                mHandler.removeCallbacks(mTimeoutTask);
1088                mTimeoutTask.nextState = nextState;
1089                mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
1090                        ? (originalTimeoutOverride - timeoutOverride)
1091                        : -1;
1092                mHandler.postAtTime(mTimeoutTask, when);
1093                mNextTimeout = when; // for debugging
1094            }
1095        }
1096    }
1097
1098    private void cancelTimerLocked()
1099    {
1100        mHandler.removeCallbacks(mTimeoutTask);
1101        mTimeoutTask.nextState = -1;
1102    }
1103
1104    private class TimeoutTask implements Runnable
1105    {
1106        int nextState; // access should be synchronized on mLocks
1107        long remainingTimeoutOverride;
1108        public void run()
1109        {
1110            synchronized (mLocks) {
1111                if (mSpew) {
1112                    Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
1113                }
1114
1115                if (nextState == -1) {
1116                    return;
1117                }
1118
1119                mUserState = this.nextState;
1120                setPowerState(this.nextState | mWakeLockState);
1121
1122                long now = SystemClock.uptimeMillis();
1123
1124                switch (this.nextState)
1125                {
1126                    case SCREEN_BRIGHT:
1127                        if (mDimDelay >= 0) {
1128                            setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
1129                            break;
1130                        }
1131                    case SCREEN_DIM:
1132                        setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
1133                        break;
1134                }
1135            }
1136        }
1137    }
1138
1139    private void sendNotificationLocked(boolean on, int why)
1140    {
1141        if (!on) {
1142            mStillNeedSleepNotification = false;
1143        }
1144
1145        // Add to the queue.
1146        int index = 0;
1147        while (mBroadcastQueue[index] != -1) {
1148            index++;
1149        }
1150        mBroadcastQueue[index] = on ? 1 : 0;
1151        mBroadcastWhy[index] = why;
1152
1153        // If we added it position 2, then there is a pair that can be stripped.
1154        // If we added it position 1 and we're turning the screen off, we can strip
1155        // the pair and do nothing, because the screen is already off, and therefore
1156        // keyguard has already been enabled.
1157        // However, if we added it at position 1 and we're turning it on, then position
1158        // 0 was to turn it off, and we can't strip that, because keyguard needs to come
1159        // on, so have to run the queue then.
1160        if (index == 2) {
1161            // While we're collapsing them, if it's going off, and the new reason
1162            // is more significant than the first, then use the new one.
1163            if (!on && mBroadcastWhy[0] > why) {
1164                mBroadcastWhy[0] = why;
1165            }
1166            mBroadcastQueue[0] = on ? 1 : 0;
1167            mBroadcastQueue[1] = -1;
1168            mBroadcastQueue[2] = -1;
1169            mBroadcastWakeLock.release();
1170            mBroadcastWakeLock.release();
1171            index = 0;
1172        }
1173        if (index == 1 && !on) {
1174            mBroadcastQueue[0] = -1;
1175            mBroadcastQueue[1] = -1;
1176            index = -1;
1177            // The wake lock was being held, but we're not actually going to do any
1178            // broadcasts, so release the wake lock.
1179            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
1180            mBroadcastWakeLock.release();
1181        }
1182
1183        // Now send the message.
1184        if (index >= 0) {
1185            // Acquire the broadcast wake lock before changing the power
1186            // state. It will be release after the broadcast is sent.
1187            // We always increment the ref count for each notification in the queue
1188            // and always decrement when that notification is handled.
1189            mBroadcastWakeLock.acquire();
1190            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
1191            mHandler.post(mNotificationTask);
1192        }
1193    }
1194
1195    private Runnable mNotificationTask = new Runnable()
1196    {
1197        public void run()
1198        {
1199            while (true) {
1200                int value;
1201                int why;
1202                WindowManagerPolicy policy;
1203                synchronized (mLocks) {
1204                    value = mBroadcastQueue[0];
1205                    why = mBroadcastWhy[0];
1206                    for (int i=0; i<2; i++) {
1207                        mBroadcastQueue[i] = mBroadcastQueue[i+1];
1208                        mBroadcastWhy[i] = mBroadcastWhy[i+1];
1209                    }
1210                    policy = getPolicyLocked();
1211                }
1212                if (value == 1) {
1213                    mScreenOnStart = SystemClock.uptimeMillis();
1214
1215                    policy.screenTurnedOn();
1216                    try {
1217                        ActivityManagerNative.getDefault().wakingUp();
1218                    } catch (RemoteException e) {
1219                        // ignore it
1220                    }
1221
1222                    if (mSpew) {
1223                        Slog.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
1224                    }
1225                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
1226                        mContext.sendOrderedBroadcast(mScreenOnIntent, null,
1227                                mScreenOnBroadcastDone, mHandler, 0, null, null);
1228                    } else {
1229                        synchronized (mLocks) {
1230                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2,
1231                                    mBroadcastWakeLock.mCount);
1232                            mBroadcastWakeLock.release();
1233                        }
1234                    }
1235                }
1236                else if (value == 0) {
1237                    mScreenOffStart = SystemClock.uptimeMillis();
1238
1239                    policy.screenTurnedOff(why);
1240                    try {
1241                        ActivityManagerNative.getDefault().goingToSleep();
1242                    } catch (RemoteException e) {
1243                        // ignore it.
1244                    }
1245
1246                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
1247                        mContext.sendOrderedBroadcast(mScreenOffIntent, null,
1248                                mScreenOffBroadcastDone, mHandler, 0, null, null);
1249                    } else {
1250                        synchronized (mLocks) {
1251                            EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
1252                                    mBroadcastWakeLock.mCount);
1253                            mBroadcastWakeLock.release();
1254                        }
1255                    }
1256                }
1257                else {
1258                    // If we're in this case, then this handler is running for a previous
1259                    // paired transaction.  mBroadcastWakeLock will already have been released.
1260                    break;
1261                }
1262            }
1263        }
1264    };
1265
1266    long mScreenOnStart;
1267    private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
1268        public void onReceive(Context context, Intent intent) {
1269            synchronized (mLocks) {
1270                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
1271                        SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
1272                mBroadcastWakeLock.release();
1273            }
1274        }
1275    };
1276
1277    long mScreenOffStart;
1278    private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
1279        public void onReceive(Context context, Intent intent) {
1280            synchronized (mLocks) {
1281                EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
1282                        SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
1283                mBroadcastWakeLock.release();
1284            }
1285        }
1286    };
1287
1288    void logPointerUpEvent() {
1289        if (LOG_TOUCH_DOWNS) {
1290            mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
1291            mLastTouchDown = 0;
1292        }
1293    }
1294
1295    void logPointerDownEvent() {
1296        if (LOG_TOUCH_DOWNS) {
1297            // If we are not already timing a down/up sequence
1298            if (mLastTouchDown == 0) {
1299                mLastTouchDown = SystemClock.elapsedRealtime();
1300                mTouchCycles++;
1301            }
1302        }
1303    }
1304
1305    /**
1306     * Prevents the screen from turning on even if it *should* turn on due
1307     * to a subsequent full wake lock being acquired.
1308     * <p>
1309     * This is a temporary hack that allows an activity to "cover up" any
1310     * display glitches that happen during the activity's startup
1311     * sequence.  (Specifically, this API was added to work around a
1312     * cosmetic bug in the "incoming call" sequence, where the lock screen
1313     * would flicker briefly before the incoming call UI became visible.)
1314     * TODO: There ought to be a more elegant way of doing this,
1315     * probably by having the PowerManager and ActivityManager
1316     * work together to let apps specify that the screen on/off
1317     * state should be synchronized with the Activity lifecycle.
1318     * <p>
1319     * Note that calling preventScreenOn(true) will NOT turn the screen
1320     * off if it's currently on.  (This API only affects *future*
1321     * acquisitions of full wake locks.)
1322     * But calling preventScreenOn(false) WILL turn the screen on if
1323     * it's currently off because of a prior preventScreenOn(true) call.
1324     * <p>
1325     * Any call to preventScreenOn(true) MUST be followed promptly by a call
1326     * to preventScreenOn(false).  In fact, if the preventScreenOn(false)
1327     * call doesn't occur within 5 seconds, we'll turn the screen back on
1328     * ourselves (and log a warning about it); this prevents a buggy app
1329     * from disabling the screen forever.)
1330     * <p>
1331     * TODO: this feature should really be controlled by a new type of poke
1332     * lock (rather than an IPowerManager call).
1333     */
1334    public void preventScreenOn(boolean prevent) {
1335        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1336
1337        synchronized (mLocks) {
1338            if (prevent) {
1339                // First of all, grab a partial wake lock to
1340                // make sure the CPU stays on during the entire
1341                // preventScreenOn(true) -> preventScreenOn(false) sequence.
1342                mPreventScreenOnPartialLock.acquire();
1343
1344                // Post a forceReenableScreen() call (for 5 seconds in the
1345                // future) to make sure the matching preventScreenOn(false) call
1346                // has happened by then.
1347                mHandler.removeCallbacks(mForceReenableScreenTask);
1348                mHandler.postDelayed(mForceReenableScreenTask, 5000);
1349
1350                // Finally, set the flag that prevents the screen from turning on.
1351                // (Below, in setPowerState(), we'll check mPreventScreenOn and
1352                // we *won't* call setScreenStateLocked(true) if it's set.)
1353                mPreventScreenOn = true;
1354            } else {
1355                // (Re)enable the screen.
1356                mPreventScreenOn = false;
1357
1358                // We're "undoing" a the prior preventScreenOn(true) call, so we
1359                // no longer need the 5-second safeguard.
1360                mHandler.removeCallbacks(mForceReenableScreenTask);
1361
1362                // Forcibly turn on the screen if it's supposed to be on.  (This
1363                // handles the case where the screen is currently off because of
1364                // a prior preventScreenOn(true) call.)
1365                if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
1366                    if (mSpew) {
1367                        Slog.d(TAG,
1368                              "preventScreenOn: turning on after a prior preventScreenOn(true)!");
1369                    }
1370                    int err = setScreenStateLocked(true);
1371                    if (err != 0) {
1372                        Slog.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
1373                    }
1374                }
1375
1376                // Release the partial wake lock that we held during the
1377                // preventScreenOn(true) -> preventScreenOn(false) sequence.
1378                mPreventScreenOnPartialLock.release();
1379            }
1380        }
1381    }
1382
1383    public void setScreenBrightnessOverride(int brightness) {
1384        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1385
1386        if (mSpew) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
1387        synchronized (mLocks) {
1388            if (mScreenBrightnessOverride != brightness) {
1389                mScreenBrightnessOverride = brightness;
1390                if (isScreenOn()) {
1391                    updateLightsLocked(mPowerState, SCREEN_ON_BIT);
1392                }
1393            }
1394        }
1395    }
1396
1397    public void setButtonBrightnessOverride(int brightness) {
1398        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
1399
1400        if (mSpew) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
1401         synchronized (mLocks) {
1402           if (mButtonBrightnessOverride != brightness) {
1403                mButtonBrightnessOverride = brightness;
1404                if (isScreenOn()) {
1405                    updateLightsLocked(mPowerState, BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT);
1406                }
1407            }
1408        }
1409    }
1410
1411    /**
1412     * Sanity-check that gets called 5 seconds after any call to
1413     * preventScreenOn(true).  This ensures that the original call
1414     * is followed promptly by a call to preventScreenOn(false).
1415     */
1416    private void forceReenableScreen() {
1417        // We shouldn't get here at all if mPreventScreenOn is false, since
1418        // we should have already removed any existing
1419        // mForceReenableScreenTask messages...
1420        if (!mPreventScreenOn) {
1421            Slog.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
1422            return;
1423        }
1424
1425        // Uh oh.  It's been 5 seconds since a call to
1426        // preventScreenOn(true) and we haven't re-enabled the screen yet.
1427        // This means the app that called preventScreenOn(true) is either
1428        // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
1429        // or buggy (i.e. it forgot to call preventScreenOn(false), or
1430        // crashed before doing so.)
1431
1432        // Log a warning, and forcibly turn the screen back on.
1433        Slog.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
1434              + "Forcing the screen back on...");
1435        preventScreenOn(false);
1436    }
1437
1438    private Runnable mForceReenableScreenTask = new Runnable() {
1439            public void run() {
1440                forceReenableScreen();
1441            }
1442        };
1443
1444    private int setScreenStateLocked(boolean on) {
1445        int err = Power.setScreenState(on);
1446        if (err == 0) {
1447            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
1448            if (mUseSoftwareAutoBrightness) {
1449                enableLightSensor(on);
1450                if (!on) {
1451                    // make sure button and key backlights are off too
1452                    mButtonLight.turnOff();
1453                    mKeyboardLight.turnOff();
1454                    // clear current value so we will update based on the new conditions
1455                    // when the sensor is reenabled.
1456                    mLightSensorValue = -1;
1457                    // reset our highest light sensor value when the screen turns off
1458                    mHighestLightSensorValue = -1;
1459                }
1460            }
1461        }
1462        return err;
1463    }
1464
1465    private void setPowerState(int state)
1466    {
1467        setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
1468    }
1469
1470    private void setPowerState(int newState, boolean noChangeLights, int reason)
1471    {
1472        synchronized (mLocks) {
1473            int err;
1474
1475            if (mSpew) {
1476                Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
1477                        + " newState=0x" + Integer.toHexString(newState)
1478                        + " noChangeLights=" + noChangeLights
1479                        + " reason=" + reason);
1480            }
1481
1482            if (noChangeLights) {
1483                newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
1484            }
1485            if (mProximitySensorActive) {
1486                // don't turn on the screen when the proximity sensor lock is held
1487                newState = (newState & ~SCREEN_BRIGHT);
1488            }
1489
1490            if (batteryIsLow()) {
1491                newState |= BATTERY_LOW_BIT;
1492            } else {
1493                newState &= ~BATTERY_LOW_BIT;
1494            }
1495            if (newState == mPowerState) {
1496                return;
1497            }
1498
1499            if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
1500                newState |= ALL_BRIGHT;
1501            }
1502
1503            boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
1504            boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
1505
1506            if (mSpew) {
1507                Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
1508                        + " newState=" + newState + " noChangeLights=" + noChangeLights);
1509                Slog.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
1510                         + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
1511                Slog.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
1512                         + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
1513                Slog.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
1514                         + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
1515                Slog.d(TAG, "  oldScreenOn=" + oldScreenOn
1516                         + " newScreenOn=" + newScreenOn);
1517                Slog.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
1518                         + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
1519            }
1520
1521            if (mPowerState != newState) {
1522                updateLightsLocked(newState, 0);
1523                mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
1524            }
1525
1526            if (oldScreenOn != newScreenOn) {
1527                if (newScreenOn) {
1528                    // When the user presses the power button, we need to always send out the
1529                    // notification that it's going to sleep so the keyguard goes on.  But
1530                    // we can't do that until the screen fades out, so we don't show the keyguard
1531                    // too early.
1532                    if (mStillNeedSleepNotification) {
1533                        sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
1534                    }
1535
1536                    // Turn on the screen UNLESS there was a prior
1537                    // preventScreenOn(true) request.  (Note that the lifetime
1538                    // of a single preventScreenOn() request is limited to 5
1539                    // seconds to prevent a buggy app from disabling the
1540                    // screen forever; see forceReenableScreen().)
1541                    boolean reallyTurnScreenOn = true;
1542                    if (mSpew) {
1543                        Slog.d(TAG, "- turning screen on...  mPreventScreenOn = "
1544                              + mPreventScreenOn);
1545                    }
1546
1547                    if (mPreventScreenOn) {
1548                        if (mSpew) {
1549                            Slog.d(TAG, "- PREVENTING screen from really turning on!");
1550                        }
1551                        reallyTurnScreenOn = false;
1552                    }
1553                    if (reallyTurnScreenOn) {
1554                        err = setScreenStateLocked(true);
1555                        long identity = Binder.clearCallingIdentity();
1556                        try {
1557                            mBatteryStats.noteScreenBrightness(getPreferredBrightness());
1558                            mBatteryStats.noteScreenOn();
1559                        } catch (RemoteException e) {
1560                            Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
1561                        } finally {
1562                            Binder.restoreCallingIdentity(identity);
1563                        }
1564                    } else {
1565                        setScreenStateLocked(false);
1566                        // But continue as if we really did turn the screen on...
1567                        err = 0;
1568                    }
1569
1570                    mLastTouchDown = 0;
1571                    mTotalTouchDownTime = 0;
1572                    mTouchCycles = 0;
1573                    EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason,
1574                            mTotalTouchDownTime, mTouchCycles);
1575                    if (err == 0) {
1576                        mPowerState |= SCREEN_ON_BIT;
1577                        sendNotificationLocked(true, -1);
1578                    }
1579                } else {
1580                    // cancel light sensor task
1581                    mHandler.removeCallbacks(mAutoBrightnessTask);
1582                    mScreenOffTime = SystemClock.elapsedRealtime();
1583                    long identity = Binder.clearCallingIdentity();
1584                    try {
1585                        mBatteryStats.noteScreenOff();
1586                    } catch (RemoteException e) {
1587                        Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
1588                    } finally {
1589                        Binder.restoreCallingIdentity(identity);
1590                    }
1591                    mPowerState &= ~SCREEN_ON_BIT;
1592                    mScreenOffReason = reason;
1593                    if (!mScreenBrightness.animating) {
1594                        err = screenOffFinishedAnimatingLocked(reason);
1595                    } else {
1596                        err = 0;
1597                        mLastTouchDown = 0;
1598                    }
1599                }
1600            }
1601        }
1602    }
1603
1604    private int screenOffFinishedAnimatingLocked(int reason) {
1605        // I don't think we need to check the current state here because all of these
1606        // Power.setScreenState and sendNotificationLocked can both handle being
1607        // called multiple times in the same state. -joeo
1608        EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, mTotalTouchDownTime, mTouchCycles);
1609        mLastTouchDown = 0;
1610        int err = setScreenStateLocked(false);
1611        if (err == 0) {
1612            mScreenOffReason = reason;
1613            sendNotificationLocked(false, reason);
1614        }
1615        return err;
1616    }
1617
1618    private boolean batteryIsLow() {
1619        return (!mIsPowered &&
1620                mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
1621    }
1622
1623    private void updateLightsLocked(int newState, int forceState) {
1624        final int oldState = mPowerState;
1625        newState = applyButtonState(newState);
1626        newState = applyKeyboardState(newState);
1627        final int realDifference = (newState ^ oldState);
1628        final int difference = realDifference | forceState;
1629        if (difference == 0) {
1630            return;
1631        }
1632
1633        int offMask = 0;
1634        int dimMask = 0;
1635        int onMask = 0;
1636
1637        int preferredBrightness = getPreferredBrightness();
1638        boolean startAnimation = false;
1639
1640        if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
1641            if (ANIMATE_KEYBOARD_LIGHTS) {
1642                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1643                    mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
1644                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1645                            Power.BRIGHTNESS_ON);
1646                } else {
1647                    mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
1648                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
1649                            Power.BRIGHTNESS_OFF);
1650                }
1651                startAnimation = true;
1652            } else {
1653                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
1654                    offMask |= KEYBOARD_BRIGHT_BIT;
1655                } else {
1656                    onMask |= KEYBOARD_BRIGHT_BIT;
1657                }
1658            }
1659        }
1660
1661        if ((difference & BUTTON_BRIGHT_BIT) != 0) {
1662            if (ANIMATE_BUTTON_LIGHTS) {
1663                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1664                    mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
1665                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1666                            Power.BRIGHTNESS_ON);
1667                } else {
1668                    mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_ON,
1669                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
1670                            Power.BRIGHTNESS_OFF);
1671                }
1672                startAnimation = true;
1673            } else {
1674                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
1675                    offMask |= BUTTON_BRIGHT_BIT;
1676                } else {
1677                    onMask |= BUTTON_BRIGHT_BIT;
1678                }
1679            }
1680        }
1681
1682        if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1683            if (ANIMATE_SCREEN_LIGHTS) {
1684                int nominalCurrentValue = -1;
1685                // If there was an actual difference in the light state, then
1686                // figure out the "ideal" current value based on the previous
1687                // state.  Otherwise, this is a change due to the brightness
1688                // override, so we want to animate from whatever the current
1689                // value is.
1690                if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
1691                    switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
1692                        case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
1693                            nominalCurrentValue = preferredBrightness;
1694                            break;
1695                        case SCREEN_ON_BIT:
1696                            nominalCurrentValue = Power.BRIGHTNESS_DIM;
1697                            break;
1698                        case 0:
1699                            nominalCurrentValue = Power.BRIGHTNESS_OFF;
1700                            break;
1701                        case SCREEN_BRIGHT_BIT:
1702                        default:
1703                            // not possible
1704                            nominalCurrentValue = (int)mScreenBrightness.curValue;
1705                            break;
1706                    }
1707                }
1708                int brightness = preferredBrightness;
1709                int steps = ANIM_STEPS;
1710                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1711                    // dim or turn off backlight, depending on if the screen is on
1712                    // the scale is because the brightness ramp isn't linear and this biases
1713                    // it so the later parts take longer.
1714                    final float scale = 1.5f;
1715                    float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
1716                    if (ratio > 1.0f) ratio = 1.0f;
1717                    if ((newState & SCREEN_ON_BIT) == 0) {
1718                        if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
1719                            // was bright
1720                            steps = ANIM_STEPS;
1721                        } else {
1722                            // was dim
1723                            steps = (int)(ANIM_STEPS*ratio*scale);
1724                        }
1725                        brightness = Power.BRIGHTNESS_OFF;
1726                    } else {
1727                        if ((oldState & SCREEN_ON_BIT) != 0) {
1728                            // was bright
1729                            steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
1730                        } else {
1731                            // was dim
1732                            steps = (int)(ANIM_STEPS*ratio);
1733                        }
1734                        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
1735                            // If the "stay on while plugged in" option is
1736                            // turned on, then the screen will often not
1737                            // automatically turn off while plugged in.  To
1738                            // still have a sense of when it is inactive, we
1739                            // will then count going dim as turning off.
1740                            mScreenOffTime = SystemClock.elapsedRealtime();
1741                        }
1742                        brightness = Power.BRIGHTNESS_DIM;
1743                    }
1744                }
1745                long identity = Binder.clearCallingIdentity();
1746                try {
1747                    mBatteryStats.noteScreenBrightness(brightness);
1748                } catch (RemoteException e) {
1749                    // Nothing interesting to do.
1750                } finally {
1751                    Binder.restoreCallingIdentity(identity);
1752                }
1753                if (mScreenBrightness.setTargetLocked(brightness,
1754                        steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
1755                    startAnimation = true;
1756                }
1757            } else {
1758                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
1759                    // dim or turn off backlight, depending on if the screen is on
1760                    if ((newState & SCREEN_ON_BIT) == 0) {
1761                        offMask |= SCREEN_BRIGHT_BIT;
1762                    } else {
1763                        dimMask |= SCREEN_BRIGHT_BIT;
1764                    }
1765                } else {
1766                    onMask |= SCREEN_BRIGHT_BIT;
1767                }
1768            }
1769        }
1770
1771        if (startAnimation) {
1772            if (mSpew) {
1773                Slog.i(TAG, "Scheduling light animator!");
1774            }
1775            mHandler.removeCallbacks(mLightAnimator);
1776            mHandler.post(mLightAnimator);
1777        }
1778
1779        if (offMask != 0) {
1780            if (mSpew) Slog.i(TAG, "Setting brightess off: " + offMask);
1781            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
1782        }
1783        if (dimMask != 0) {
1784            int brightness = Power.BRIGHTNESS_DIM;
1785            if ((newState & BATTERY_LOW_BIT) != 0 &&
1786                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1787                brightness = Power.BRIGHTNESS_LOW_BATTERY;
1788            }
1789            if (mSpew) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
1790            setLightBrightness(dimMask, brightness);
1791        }
1792        if (onMask != 0) {
1793            int brightness = getPreferredBrightness();
1794            if ((newState & BATTERY_LOW_BIT) != 0 &&
1795                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
1796                brightness = Power.BRIGHTNESS_LOW_BATTERY;
1797            }
1798            if (mSpew) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
1799            setLightBrightness(onMask, brightness);
1800        }
1801    }
1802
1803    private void setLightBrightness(int mask, int value) {
1804        int brightnessMode = (mAutoBrightessEnabled
1805                            ? LightsService.BRIGHTNESS_MODE_SENSOR
1806                            : LightsService.BRIGHTNESS_MODE_USER);
1807        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
1808            mLcdLight.setBrightness(value, brightnessMode);
1809        }
1810        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
1811            mButtonLight.setBrightness(value);
1812        }
1813        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
1814            mKeyboardLight.setBrightness(value);
1815        }
1816    }
1817
1818    class BrightnessState {
1819        final int mask;
1820
1821        boolean initialized;
1822        int targetValue;
1823        float curValue;
1824        float delta;
1825        boolean animating;
1826
1827        BrightnessState(int m) {
1828            mask = m;
1829        }
1830
1831        public void dump(PrintWriter pw, String prefix) {
1832            pw.println(prefix + "animating=" + animating
1833                    + " targetValue=" + targetValue
1834                    + " curValue=" + curValue
1835                    + " delta=" + delta);
1836        }
1837
1838        boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
1839                int nominalCurrentValue) {
1840            if (!initialized) {
1841                initialized = true;
1842                curValue = (float)initialValue;
1843            } else if (targetValue == target) {
1844                return false;
1845            }
1846            targetValue = target;
1847            delta = (targetValue -
1848                    (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
1849                    / stepsToTarget;
1850            if (mSpew) {
1851                String noticeMe = nominalCurrentValue == curValue ? "" : "  ******************";
1852                Slog.i(TAG, "Setting target " + mask + ": cur=" + curValue
1853                        + " target=" + targetValue + " delta=" + delta
1854                        + " nominalCurrentValue=" + nominalCurrentValue
1855                        + noticeMe);
1856            }
1857            animating = true;
1858            return true;
1859        }
1860
1861        boolean stepLocked() {
1862            if (!animating) return false;
1863            if (false && mSpew) {
1864                Slog.i(TAG, "Step target " + mask + ": cur=" + curValue
1865                        + " target=" + targetValue + " delta=" + delta);
1866            }
1867            curValue += delta;
1868            int curIntValue = (int)curValue;
1869            boolean more = true;
1870            if (delta == 0) {
1871                curValue = curIntValue = targetValue;
1872                more = false;
1873            } else if (delta > 0) {
1874                if (curIntValue >= targetValue) {
1875                    curValue = curIntValue = targetValue;
1876                    more = false;
1877                }
1878            } else {
1879                if (curIntValue <= targetValue) {
1880                    curValue = curIntValue = targetValue;
1881                    more = false;
1882                }
1883            }
1884            //Slog.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
1885            setLightBrightness(mask, curIntValue);
1886            animating = more;
1887            if (!more) {
1888                if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
1889                    screenOffFinishedAnimatingLocked(mScreenOffReason);
1890                }
1891            }
1892            return more;
1893        }
1894    }
1895
1896    private class LightAnimator implements Runnable {
1897        public void run() {
1898            synchronized (mLocks) {
1899                long now = SystemClock.uptimeMillis();
1900                boolean more = mScreenBrightness.stepLocked();
1901                if (mKeyboardBrightness.stepLocked()) {
1902                    more = true;
1903                }
1904                if (mButtonBrightness.stepLocked()) {
1905                    more = true;
1906                }
1907                if (more) {
1908                    mHandler.postAtTime(mLightAnimator, now+(1000/60));
1909                }
1910            }
1911        }
1912    }
1913
1914    private int getPreferredBrightness() {
1915        try {
1916            if (mScreenBrightnessOverride >= 0) {
1917                return mScreenBrightnessOverride;
1918            } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
1919                    && mAutoBrightessEnabled) {
1920                return mLightSensorScreenBrightness;
1921            }
1922            final int brightness = Settings.System.getInt(mContext.getContentResolver(),
1923                                                          SCREEN_BRIGHTNESS);
1924             // Don't let applications turn the screen all the way off
1925            return Math.max(brightness, Power.BRIGHTNESS_DIM);
1926        } catch (SettingNotFoundException snfe) {
1927            return Power.BRIGHTNESS_ON;
1928        }
1929    }
1930
1931    private int applyButtonState(int state) {
1932        int brightness = -1;
1933        if ((state & BATTERY_LOW_BIT) != 0) {
1934            // do not override brightness if the battery is low
1935            return state;
1936        }
1937        if (mButtonBrightnessOverride >= 0) {
1938            brightness = mButtonBrightnessOverride;
1939        } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
1940            brightness = mLightSensorButtonBrightness;
1941        }
1942        if (brightness > 0) {
1943            return state | BUTTON_BRIGHT_BIT;
1944        } else if (brightness == 0) {
1945            return state & ~BUTTON_BRIGHT_BIT;
1946        } else {
1947            return state;
1948        }
1949    }
1950
1951    private int applyKeyboardState(int state) {
1952        int brightness = -1;
1953        if ((state & BATTERY_LOW_BIT) != 0) {
1954            // do not override brightness if the battery is low
1955            return state;
1956        }
1957        if (!mKeyboardVisible) {
1958            brightness = 0;
1959        } else if (mButtonBrightnessOverride >= 0) {
1960            brightness = mButtonBrightnessOverride;
1961        } else if (mLightSensorKeyboardBrightness >= 0 && mUseSoftwareAutoBrightness) {
1962            brightness =  mLightSensorKeyboardBrightness;
1963        }
1964        if (brightness > 0) {
1965            return state | KEYBOARD_BRIGHT_BIT;
1966        } else if (brightness == 0) {
1967            return state & ~KEYBOARD_BRIGHT_BIT;
1968        } else {
1969            return state;
1970        }
1971    }
1972
1973    public boolean isScreenOn() {
1974        synchronized (mLocks) {
1975            return (mPowerState & SCREEN_ON_BIT) != 0;
1976        }
1977    }
1978
1979    boolean isScreenBright() {
1980        synchronized (mLocks) {
1981            return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
1982        }
1983    }
1984
1985    private boolean isScreenTurningOffLocked() {
1986        return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
1987    }
1988
1989    private void forceUserActivityLocked() {
1990        if (isScreenTurningOffLocked()) {
1991            // cancel animation so userActivity will succeed
1992            mScreenBrightness.animating = false;
1993        }
1994        boolean savedActivityAllowed = mUserActivityAllowed;
1995        mUserActivityAllowed = true;
1996        userActivity(SystemClock.uptimeMillis(), false);
1997        mUserActivityAllowed = savedActivityAllowed;
1998    }
1999
2000    public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
2001        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2002        userActivity(time, -1, noChangeLights, OTHER_EVENT, force);
2003    }
2004
2005    public void userActivity(long time, boolean noChangeLights) {
2006        userActivity(time, -1, noChangeLights, OTHER_EVENT, false);
2007    }
2008
2009    public void userActivity(long time, boolean noChangeLights, int eventType) {
2010        userActivity(time, -1, noChangeLights, eventType, false);
2011    }
2012
2013    public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
2014        userActivity(time, -1, noChangeLights, eventType, force);
2015    }
2016
2017    /*
2018     * Reset the user activity timeout to now + timeout.  This overrides whatever else is going
2019     * on with user activity.  Don't use this function.
2020     */
2021    public void clearUserActivityTimeout(long now, long timeout) {
2022        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2023        Slog.i(TAG, "clearUserActivity for " + timeout + "ms from now");
2024        userActivity(now, timeout, false, OTHER_EVENT, false);
2025    }
2026
2027    private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
2028            int eventType, boolean force) {
2029        //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2030
2031        if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
2032                && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
2033            if (false) {
2034                Slog.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey));
2035            }
2036            return;
2037        }
2038
2039        if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
2040                && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
2041                    || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
2042            if (false) {
2043                Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
2044            }
2045            return;
2046        }
2047
2048        if (false) {
2049            if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
2050                Slog.d(TAG, "userActivity !!!");//, new RuntimeException());
2051            } else {
2052                Slog.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
2053            }
2054        }
2055
2056        synchronized (mLocks) {
2057            if (mSpew) {
2058                Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
2059                        + " mUserActivityAllowed=" + mUserActivityAllowed
2060                        + " mUserState=0x" + Integer.toHexString(mUserState)
2061                        + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
2062                        + " mProximitySensorActive=" + mProximitySensorActive
2063                        + " timeoutOverride=" + timeoutOverride
2064                        + " force=" + force);
2065            }
2066            // ignore user activity if we are in the process of turning off the screen
2067            if (isScreenTurningOffLocked()) {
2068                Slog.d(TAG, "ignoring user activity while turning off screen");
2069                return;
2070            }
2071            // Disable proximity sensor if if user presses power key while we are in the
2072            // "waiting for proximity sensor to go negative" state.
2073            if (mProximitySensorActive && mProximityWakeLockCount == 0) {
2074                mProximitySensorActive = false;
2075            }
2076            if (mLastEventTime <= time || force) {
2077                mLastEventTime = time;
2078                if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
2079                    // Only turn on button backlights if a button was pressed
2080                    // and auto brightness is disabled
2081                    if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
2082                        mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
2083                    } else {
2084                        // don't clear button/keyboard backlights when the screen is touched.
2085                        mUserState |= SCREEN_BRIGHT;
2086                    }
2087
2088                    int uid = Binder.getCallingUid();
2089                    long ident = Binder.clearCallingIdentity();
2090                    try {
2091                        mBatteryStats.noteUserActivity(uid, eventType);
2092                    } catch (RemoteException e) {
2093                        // Ignore
2094                    } finally {
2095                        Binder.restoreCallingIdentity(ident);
2096                    }
2097
2098                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
2099                    setPowerState(mUserState | mWakeLockState, noChangeLights,
2100                            WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2101                    setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
2102                }
2103            }
2104        }
2105
2106        if (mPolicy != null) {
2107            mPolicy.userActivity();
2108        }
2109    }
2110
2111    private int getAutoBrightnessValue(int sensorValue, int[] values) {
2112        try {
2113            int i;
2114            for (i = 0; i < mAutoBrightnessLevels.length; i++) {
2115                if (sensorValue < mAutoBrightnessLevels[i]) {
2116                    break;
2117                }
2118            }
2119            return values[i];
2120        } catch (Exception e) {
2121            // guard against null pointer or index out of bounds errors
2122            Slog.e(TAG, "getAutoBrightnessValue", e);
2123            return 255;
2124        }
2125    }
2126
2127    private Runnable mProximityTask = new Runnable() {
2128        public void run() {
2129            synchronized (mLocks) {
2130                if (mProximityPendingValue != -1) {
2131                    proximityChangedLocked(mProximityPendingValue == 1);
2132                    mProximityPendingValue = -1;
2133                }
2134                if (mProximityPartialLock.isHeld()) {
2135                    mProximityPartialLock.release();
2136                }
2137            }
2138        }
2139    };
2140
2141    private Runnable mAutoBrightnessTask = new Runnable() {
2142        public void run() {
2143            synchronized (mLocks) {
2144                int value = (int)mLightSensorPendingValue;
2145                if (value >= 0) {
2146                    mLightSensorPendingValue = -1;
2147                    lightSensorChangedLocked(value);
2148                }
2149            }
2150        }
2151    };
2152
2153    private void dockStateChanged(int state) {
2154        synchronized (mLocks) {
2155            mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);
2156            if (mIsDocked) {
2157                mHighestLightSensorValue = -1;
2158            }
2159            if ((mPowerState & SCREEN_ON_BIT) != 0) {
2160                // force lights recalculation
2161                int value = (int)mLightSensorValue;
2162                mLightSensorValue = -1;
2163                lightSensorChangedLocked(value);
2164            }
2165        }
2166    }
2167
2168    private void lightSensorChangedLocked(int value) {
2169        if (mDebugLightSensor) {
2170            Slog.d(TAG, "lightSensorChangedLocked " + value);
2171        }
2172
2173        // do not allow light sensor value to decrease
2174        if (mHighestLightSensorValue < value) {
2175            mHighestLightSensorValue = value;
2176        }
2177
2178        if (mLightSensorValue != value) {
2179            mLightSensorValue = value;
2180            if ((mPowerState & BATTERY_LOW_BIT) == 0) {
2181                // use maximum light sensor value seen since screen went on for LCD to avoid flicker
2182                // we only do this if we are undocked, since lighting should be stable when
2183                // stationary in a dock.
2184                int lcdValue = getAutoBrightnessValue(
2185                        (mIsDocked ? value : mHighestLightSensorValue),
2186                        mLcdBacklightValues);
2187                int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
2188                int keyboardValue;
2189                if (mKeyboardVisible) {
2190                    keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
2191                } else {
2192                    keyboardValue = 0;
2193                }
2194                mLightSensorScreenBrightness = lcdValue;
2195                mLightSensorButtonBrightness = buttonValue;
2196                mLightSensorKeyboardBrightness = keyboardValue;
2197
2198                if (mDebugLightSensor) {
2199                    Slog.d(TAG, "lcdValue " + lcdValue);
2200                    Slog.d(TAG, "buttonValue " + buttonValue);
2201                    Slog.d(TAG, "keyboardValue " + keyboardValue);
2202                }
2203
2204                boolean startAnimation = false;
2205                if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
2206                    if (ANIMATE_SCREEN_LIGHTS) {
2207                        if (mScreenBrightness.setTargetLocked(lcdValue,
2208                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
2209                                (int)mScreenBrightness.curValue)) {
2210                            startAnimation = true;
2211                        }
2212                    } else {
2213                        int brightnessMode = (mAutoBrightessEnabled
2214                                            ? LightsService.BRIGHTNESS_MODE_SENSOR
2215                                            : LightsService.BRIGHTNESS_MODE_USER);
2216                        mLcdLight.setBrightness(lcdValue, brightnessMode);
2217                    }
2218                }
2219                if (mButtonBrightnessOverride < 0) {
2220                    if (ANIMATE_BUTTON_LIGHTS) {
2221                        if (mButtonBrightness.setTargetLocked(buttonValue,
2222                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2223                                (int)mButtonBrightness.curValue)) {
2224                            startAnimation = true;
2225                        }
2226                    } else {
2227                         mButtonLight.setBrightness(buttonValue);
2228                    }
2229                }
2230                if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
2231                    if (ANIMATE_KEYBOARD_LIGHTS) {
2232                        if (mKeyboardBrightness.setTargetLocked(keyboardValue,
2233                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
2234                                (int)mKeyboardBrightness.curValue)) {
2235                            startAnimation = true;
2236                        }
2237                    } else {
2238                        mKeyboardLight.setBrightness(keyboardValue);
2239                    }
2240                }
2241                if (startAnimation) {
2242                    if (mDebugLightSensor) {
2243                        Slog.i(TAG, "lightSensorChangedLocked scheduling light animator");
2244                    }
2245                    mHandler.removeCallbacks(mLightAnimator);
2246                    mHandler.post(mLightAnimator);
2247                }
2248            }
2249        }
2250    }
2251
2252    /**
2253     * The user requested that we go to sleep (probably with the power button).
2254     * This overrides all wake locks that are held.
2255     */
2256    public void goToSleep(long time)
2257    {
2258        goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
2259    }
2260
2261    /**
2262     * The user requested that we go to sleep (probably with the power button).
2263     * This overrides all wake locks that are held.
2264     */
2265    public void goToSleepWithReason(long time, int reason)
2266    {
2267        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2268        synchronized (mLocks) {
2269            goToSleepLocked(time, reason);
2270        }
2271    }
2272
2273    /**
2274     * Reboot the device immediately, passing 'reason' (may be null)
2275     * to the underlying __reboot system call.  Should not return.
2276     */
2277    public void reboot(String reason)
2278    {
2279        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2280
2281        if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
2282            throw new IllegalStateException("Too early to call reboot()");
2283        }
2284
2285        final String finalReason = reason;
2286        Runnable runnable = new Runnable() {
2287            public void run() {
2288                synchronized (this) {
2289                    ShutdownThread.reboot(mContext, finalReason, false);
2290                }
2291
2292            }
2293        };
2294        // ShutdownThread must run on a looper capable of displaying the UI.
2295        mHandler.post(runnable);
2296
2297        // PowerManager.reboot() is documented not to return so just wait for the inevitable.
2298        synchronized (runnable) {
2299            while (true) {
2300                try {
2301                    runnable.wait();
2302                } catch (InterruptedException e) {
2303                }
2304            }
2305        }
2306    }
2307
2308    /**
2309     * Crash the runtime (causing a complete restart of the Android framework).
2310     * Requires REBOOT permission.  Mostly for testing.  Should not return.
2311     */
2312    public void crash(final String message)
2313    {
2314        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
2315        Thread t = new Thread("PowerManagerService.crash()") {
2316            public void run() { throw new RuntimeException(message); }
2317        };
2318        try {
2319            t.start();
2320            t.join();
2321        } catch (InterruptedException e) {
2322            Log.wtf(TAG, e);
2323        }
2324    }
2325
2326    private void goToSleepLocked(long time, int reason) {
2327
2328        if (mLastEventTime <= time) {
2329            mLastEventTime = time;
2330            // cancel all of the wake locks
2331            mWakeLockState = SCREEN_OFF;
2332            int N = mLocks.size();
2333            int numCleared = 0;
2334            for (int i=0; i<N; i++) {
2335                WakeLock wl = mLocks.get(i);
2336                if (isScreenLock(wl.flags)) {
2337                    mLocks.get(i).activated = false;
2338                    numCleared++;
2339                }
2340            }
2341            EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
2342            mStillNeedSleepNotification = true;
2343            mUserState = SCREEN_OFF;
2344            setPowerState(SCREEN_OFF, false, reason);
2345            cancelTimerLocked();
2346        }
2347    }
2348
2349    public long timeSinceScreenOn() {
2350        synchronized (mLocks) {
2351            if ((mPowerState & SCREEN_ON_BIT) != 0) {
2352                return 0;
2353            }
2354            return SystemClock.elapsedRealtime() - mScreenOffTime;
2355        }
2356    }
2357
2358    public void setKeyboardVisibility(boolean visible) {
2359        synchronized (mLocks) {
2360            if (mSpew) {
2361                Slog.d(TAG, "setKeyboardVisibility: " + visible);
2362            }
2363            if (mKeyboardVisible != visible) {
2364                mKeyboardVisible = visible;
2365                // don't signal user activity if the screen is off; other code
2366                // will take care of turning on due to a true change to the lid
2367                // switch and synchronized with the lock screen.
2368                if ((mPowerState & SCREEN_ON_BIT) != 0) {
2369                    if (mUseSoftwareAutoBrightness) {
2370                        // force recompute of backlight values
2371                        if (mLightSensorValue >= 0) {
2372                            int value = (int)mLightSensorValue;
2373                            mLightSensorValue = -1;
2374                            lightSensorChangedLocked(value);
2375                        }
2376                    }
2377                    userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2378                }
2379            }
2380        }
2381    }
2382
2383    /**
2384     * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
2385     * When disabling user activity we also reset user power state so the keyguard can reset its
2386     * short screen timeout when keyguard is unhidden.
2387     */
2388    public void enableUserActivity(boolean enabled) {
2389        if (mSpew) {
2390            Slog.d(TAG, "enableUserActivity " + enabled);
2391        }
2392        synchronized (mLocks) {
2393            mUserActivityAllowed = enabled;
2394            if (!enabled) {
2395                // cancel timeout and clear mUserState so the keyguard can set a short timeout
2396                setTimeoutLocked(SystemClock.uptimeMillis(), 0);
2397            }
2398        }
2399    }
2400
2401    private void setScreenBrightnessMode(int mode) {
2402        boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
2403        if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
2404            mAutoBrightessEnabled = enabled;
2405            if (isScreenOn()) {
2406                // force recompute of backlight values
2407                if (mLightSensorValue >= 0) {
2408                    int value = (int)mLightSensorValue;
2409                    mLightSensorValue = -1;
2410                    lightSensorChangedLocked(value);
2411                }
2412            }
2413        }
2414    }
2415
2416    /** Sets the screen off timeouts:
2417     *      mKeylightDelay
2418     *      mDimDelay
2419     *      mScreenOffDelay
2420     * */
2421    private void setScreenOffTimeoutsLocked() {
2422        if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
2423            mKeylightDelay = mShortKeylightDelay;  // Configurable via secure settings
2424            mDimDelay = -1;
2425            mScreenOffDelay = 0;
2426        } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
2427            mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
2428            mDimDelay = -1;
2429            mScreenOffDelay = 0;
2430        } else {
2431            int totalDelay = mScreenOffTimeoutSetting;
2432            if (totalDelay > mMaximumScreenOffTimeout) {
2433                totalDelay = mMaximumScreenOffTimeout;
2434            }
2435            mKeylightDelay = LONG_KEYLIGHT_DELAY;
2436            if (totalDelay < 0) {
2437                mScreenOffDelay = Integer.MAX_VALUE;
2438            } else if (mKeylightDelay < totalDelay) {
2439                // subtract the time that the keylight delay. This will give us the
2440                // remainder of the time that we need to sleep to get the accurate
2441                // screen off timeout.
2442                mScreenOffDelay = totalDelay - mKeylightDelay;
2443            } else {
2444                mScreenOffDelay = 0;
2445            }
2446            if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
2447                mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
2448                mScreenOffDelay = LONG_DIM_TIME;
2449            } else {
2450                mDimDelay = -1;
2451            }
2452        }
2453        if (mSpew) {
2454            Slog.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
2455                    + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
2456                    + " mDimScreen=" + mDimScreen);
2457        }
2458    }
2459
2460    /**
2461     * Refreshes cached secure settings.  Called once on startup, and
2462     * on subsequent changes to secure settings.
2463     */
2464    private void updateSettingsValues() {
2465        mShortKeylightDelay = Settings.Secure.getInt(
2466                mContext.getContentResolver(),
2467                Settings.Secure.SHORT_KEYLIGHT_DELAY_MS,
2468                SHORT_KEYLIGHT_DELAY_DEFAULT);
2469        // Slog.i(TAG, "updateSettingsValues(): mShortKeylightDelay now " + mShortKeylightDelay);
2470    }
2471
2472    private class LockList extends ArrayList<WakeLock>
2473    {
2474        void addLock(WakeLock wl)
2475        {
2476            int index = getIndex(wl.binder);
2477            if (index < 0) {
2478                this.add(wl);
2479            }
2480        }
2481
2482        WakeLock removeLock(IBinder binder)
2483        {
2484            int index = getIndex(binder);
2485            if (index >= 0) {
2486                return this.remove(index);
2487            } else {
2488                return null;
2489            }
2490        }
2491
2492        int getIndex(IBinder binder)
2493        {
2494            int N = this.size();
2495            for (int i=0; i<N; i++) {
2496                if (this.get(i).binder == binder) {
2497                    return i;
2498                }
2499            }
2500            return -1;
2501        }
2502
2503        int gatherState()
2504        {
2505            int result = 0;
2506            int N = this.size();
2507            for (int i=0; i<N; i++) {
2508                WakeLock wl = this.get(i);
2509                if (wl.activated) {
2510                    if (isScreenLock(wl.flags)) {
2511                        result |= wl.minState;
2512                    }
2513                }
2514            }
2515            return result;
2516        }
2517
2518        int reactivateScreenLocksLocked()
2519        {
2520            int result = 0;
2521            int N = this.size();
2522            for (int i=0; i<N; i++) {
2523                WakeLock wl = this.get(i);
2524                if (isScreenLock(wl.flags)) {
2525                    wl.activated = true;
2526                    result |= wl.minState;
2527                }
2528            }
2529            return result;
2530        }
2531    }
2532
2533    void setPolicy(WindowManagerPolicy p) {
2534        synchronized (mLocks) {
2535            mPolicy = p;
2536            mLocks.notifyAll();
2537        }
2538    }
2539
2540    WindowManagerPolicy getPolicyLocked() {
2541        while (mPolicy == null || !mDoneBooting) {
2542            try {
2543                mLocks.wait();
2544            } catch (InterruptedException e) {
2545                // Ignore
2546            }
2547        }
2548        return mPolicy;
2549    }
2550
2551    void systemReady() {
2552        mSensorManager = new SensorManager(mHandlerThread.getLooper());
2553        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
2554        // don't bother with the light sensor if auto brightness is handled in hardware
2555        if (mUseSoftwareAutoBrightness) {
2556            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
2557            enableLightSensor(true);
2558        }
2559
2560        // wait until sensors are enabled before turning on screen.
2561        // some devices will not activate the light sensor properly on boot
2562        // unless we do this.
2563        if (mUseSoftwareAutoBrightness) {
2564            // turn the screen on
2565            setPowerState(SCREEN_BRIGHT);
2566        } else {
2567            // turn everything on
2568            setPowerState(ALL_BRIGHT);
2569        }
2570
2571        synchronized (mLocks) {
2572            Slog.d(TAG, "system ready!");
2573            mDoneBooting = true;
2574
2575            long identity = Binder.clearCallingIdentity();
2576            try {
2577                mBatteryStats.noteScreenBrightness(getPreferredBrightness());
2578                mBatteryStats.noteScreenOn();
2579            } catch (RemoteException e) {
2580                // Nothing interesting to do.
2581            } finally {
2582                Binder.restoreCallingIdentity(identity);
2583            }
2584        }
2585    }
2586
2587    void bootCompleted() {
2588        Slog.d(TAG, "bootCompleted");
2589        synchronized (mLocks) {
2590            mBootCompleted = true;
2591            userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
2592            updateWakeLockLocked();
2593            mLocks.notifyAll();
2594        }
2595    }
2596
2597    public void monitor() {
2598        synchronized (mLocks) { }
2599    }
2600
2601    public int getSupportedWakeLockFlags() {
2602        int result = PowerManager.PARTIAL_WAKE_LOCK
2603                   | PowerManager.FULL_WAKE_LOCK
2604                   | PowerManager.SCREEN_DIM_WAKE_LOCK;
2605
2606        if (mProximitySensor != null) {
2607            result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
2608        }
2609
2610        return result;
2611    }
2612
2613    public void setBacklightBrightness(int brightness) {
2614        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2615        // Don't let applications turn the screen all the way off
2616        brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
2617        mLcdLight.setBrightness(brightness);
2618        mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
2619        mButtonLight.setBrightness(brightness);
2620        long identity = Binder.clearCallingIdentity();
2621        try {
2622            mBatteryStats.noteScreenBrightness(brightness);
2623        } catch (RemoteException e) {
2624            Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
2625        } finally {
2626            Binder.restoreCallingIdentity(identity);
2627        }
2628
2629        // update our animation state
2630        if (ANIMATE_SCREEN_LIGHTS) {
2631            mScreenBrightness.curValue = brightness;
2632            mScreenBrightness.animating = false;
2633            mScreenBrightness.targetValue = -1;
2634        }
2635        if (ANIMATE_KEYBOARD_LIGHTS) {
2636            mKeyboardBrightness.curValue = brightness;
2637            mKeyboardBrightness.animating = false;
2638            mKeyboardBrightness.targetValue = -1;
2639        }
2640        if (ANIMATE_BUTTON_LIGHTS) {
2641            mButtonBrightness.curValue = brightness;
2642            mButtonBrightness.animating = false;
2643            mButtonBrightness.targetValue = -1;
2644        }
2645    }
2646
2647    public void setAttentionLight(boolean on, int color) {
2648        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
2649        mAttentionLight.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
2650    }
2651
2652    private void enableProximityLockLocked() {
2653        if (mDebugProximitySensor) {
2654            Slog.d(TAG, "enableProximityLockLocked");
2655        }
2656        if (!mProximitySensorEnabled) {
2657            // clear calling identity so sensor manager battery stats are accurate
2658            long identity = Binder.clearCallingIdentity();
2659            try {
2660                mSensorManager.registerListener(mProximityListener, mProximitySensor,
2661                        SensorManager.SENSOR_DELAY_NORMAL);
2662                mProximitySensorEnabled = true;
2663            } finally {
2664                Binder.restoreCallingIdentity(identity);
2665            }
2666        }
2667    }
2668
2669    private void disableProximityLockLocked() {
2670        if (mDebugProximitySensor) {
2671            Slog.d(TAG, "disableProximityLockLocked");
2672        }
2673        if (mProximitySensorEnabled) {
2674            // clear calling identity so sensor manager battery stats are accurate
2675            long identity = Binder.clearCallingIdentity();
2676            try {
2677                mSensorManager.unregisterListener(mProximityListener);
2678                mHandler.removeCallbacks(mProximityTask);
2679                if (mProximityPartialLock.isHeld()) {
2680                    mProximityPartialLock.release();
2681                }
2682                mProximitySensorEnabled = false;
2683            } finally {
2684                Binder.restoreCallingIdentity(identity);
2685            }
2686            if (mProximitySensorActive) {
2687                mProximitySensorActive = false;
2688                forceUserActivityLocked();
2689            }
2690        }
2691    }
2692
2693    private void proximityChangedLocked(boolean active) {
2694        if (mDebugProximitySensor) {
2695            Slog.d(TAG, "proximityChangedLocked, active: " + active);
2696        }
2697        if (!mProximitySensorEnabled) {
2698            Slog.d(TAG, "Ignoring proximity change after sensor is disabled");
2699            return;
2700        }
2701        if (active) {
2702            goToSleepLocked(SystemClock.uptimeMillis(),
2703                    WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
2704            mProximitySensorActive = true;
2705        } else {
2706            // proximity sensor negative events trigger as user activity.
2707            // temporarily set mUserActivityAllowed to true so this will work
2708            // even when the keyguard is on.
2709            mProximitySensorActive = false;
2710            forceUserActivityLocked();
2711
2712            if (mProximityWakeLockCount == 0) {
2713                // disable sensor if we have no listeners left after proximity negative
2714                disableProximityLockLocked();
2715            }
2716        }
2717    }
2718
2719    private void enableLightSensor(boolean enable) {
2720        if (mDebugLightSensor) {
2721            Slog.d(TAG, "enableLightSensor " + enable);
2722        }
2723        if (mSensorManager != null && mLightSensorEnabled != enable) {
2724            mLightSensorEnabled = enable;
2725            // clear calling identity so sensor manager battery stats are accurate
2726            long identity = Binder.clearCallingIdentity();
2727            try {
2728                if (enable) {
2729                    mSensorManager.registerListener(mLightListener, mLightSensor,
2730                            SensorManager.SENSOR_DELAY_NORMAL);
2731                } else {
2732                    mSensorManager.unregisterListener(mLightListener);
2733                    mHandler.removeCallbacks(mAutoBrightnessTask);
2734                }
2735            } finally {
2736                Binder.restoreCallingIdentity(identity);
2737            }
2738        }
2739    }
2740
2741    SensorEventListener mProximityListener = new SensorEventListener() {
2742        public void onSensorChanged(SensorEvent event) {
2743            long milliseconds = SystemClock.elapsedRealtime();
2744            synchronized (mLocks) {
2745                float distance = event.values[0];
2746                long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
2747                mLastProximityEventTime = milliseconds;
2748                mHandler.removeCallbacks(mProximityTask);
2749                boolean proximityTaskQueued = false;
2750
2751                // compare against getMaximumRange to support sensors that only return 0 or 1
2752                boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
2753                        distance < mProximitySensor.getMaximumRange());
2754
2755                if (mDebugProximitySensor) {
2756                    Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
2757                }
2758                if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
2759                    // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
2760                    mProximityPendingValue = (active ? 1 : 0);
2761                    mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
2762                    proximityTaskQueued = true;
2763                } else {
2764                    // process the value immediately
2765                    mProximityPendingValue = -1;
2766                    proximityChangedLocked(active);
2767                }
2768
2769                // update mProximityPartialLock state
2770                boolean held = mProximityPartialLock.isHeld();
2771                if (!held && proximityTaskQueued) {
2772                    // hold wakelock until mProximityTask runs
2773                    mProximityPartialLock.acquire();
2774                } else if (held && !proximityTaskQueued) {
2775                    mProximityPartialLock.release();
2776                }
2777            }
2778        }
2779
2780        public void onAccuracyChanged(Sensor sensor, int accuracy) {
2781            // ignore
2782        }
2783    };
2784
2785    SensorEventListener mLightListener = new SensorEventListener() {
2786        public void onSensorChanged(SensorEvent event) {
2787            synchronized (mLocks) {
2788                // ignore light sensor while screen is turning off
2789                if (isScreenTurningOffLocked()) {
2790                    return;
2791                }
2792
2793                int value = (int)event.values[0];
2794                long milliseconds = SystemClock.elapsedRealtime();
2795                if (mDebugLightSensor) {
2796                    Slog.d(TAG, "onSensorChanged: light value: " + value);
2797                }
2798                mHandler.removeCallbacks(mAutoBrightnessTask);
2799                if (mLightSensorValue != value) {
2800                    if (mLightSensorValue == -1 ||
2801                            milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
2802                        // process the value immediately if screen has just turned on
2803                        lightSensorChangedLocked(value);
2804                    } else {
2805                        // delay processing to debounce the sensor
2806                        mLightSensorPendingValue = value;
2807                        mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
2808                    }
2809                } else {
2810                    mLightSensorPendingValue = -1;
2811                }
2812            }
2813        }
2814
2815        public void onAccuracyChanged(Sensor sensor, int accuracy) {
2816            // ignore
2817        }
2818    };
2819}
2820