/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import com.android.internal.app.IBatteryStats;
import com.android.server.am.BatteryStatsService;

import android.app.ActivityManagerNative;
import android.app.IActivityManager;
import android.content.BroadcastReceiver;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.Cursor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IPowerManager;
import android.os.LocalPowerManager;
import android.os.Power;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings.SettingNotFoundException;
import android.provider.Settings;
import android.util.EventLog;
import android.util.Log;
import android.view.WindowManagerPolicy;
import static android.provider.Settings.System.DIM_SCREEN;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;
import java.util.Observer;

class PowerManagerService extends IPowerManager.Stub
        implements LocalPowerManager, Watchdog.Monitor {

    private static final String TAG = "PowerManagerService";
    static final String PARTIAL_NAME = "PowerManagerService";

    private static final boolean LOG_PARTIAL_WL = false;

    // Indicates whether touch-down cycles should be logged as part of the
    // LOG_POWER_SCREEN_STATE log events
    private static final boolean LOG_TOUCH_DOWNS = true;

    private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
                                        | PowerManager.SCREEN_DIM_WAKE_LOCK
                                        | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
                                        | PowerManager.FULL_WAKE_LOCK
                                        | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;

    //                       time since last state:               time since last event:
    // The short keylight delay comes from Gservices; this is the default.
    private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
    private static final int MEDIUM_KEYLIGHT_DELAY = 15000;       // t+15 sec
    private static final int LONG_KEYLIGHT_DELAY = 6000;        // t+6 sec
    private static final int LONG_DIM_TIME = 7000;              // t+N-5 sec

    // How long to wait to debounce light sensor changes.
    private static final int LIGHT_SENSOR_DELAY = 2000;

    // For debouncing the proximity sensor.
    private static final int PROXIMITY_SENSOR_DELAY = 1000;

    // trigger proximity if distance is less than 5 cm
    private static final float PROXIMITY_THRESHOLD = 5.0f;

    // Cached Gservices settings; see updateGservicesValues()
    private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;

    // flags for setPowerState
    private static final int SCREEN_ON_BIT          = 0x00000001;
    private static final int SCREEN_BRIGHT_BIT      = 0x00000002;
    private static final int BUTTON_BRIGHT_BIT      = 0x00000004;
    private static final int KEYBOARD_BRIGHT_BIT    = 0x00000008;
    private static final int BATTERY_LOW_BIT        = 0x00000010;

    // values for setPowerState

    // SCREEN_OFF == everything off
    private static final int SCREEN_OFF         = 0x00000000;

    // SCREEN_DIM == screen on, screen backlight dim
    private static final int SCREEN_DIM         = SCREEN_ON_BIT;

    // SCREEN_BRIGHT == screen on, screen backlight bright
    private static final int SCREEN_BRIGHT      = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;

    // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
    private static final int SCREEN_BUTTON_BRIGHT  = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;

    // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
    private static final int ALL_BRIGHT         = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;

    // used for noChangeLights in setPowerState()
    private static final int LIGHTS_MASK        = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;

    static final boolean ANIMATE_SCREEN_LIGHTS = true;
    static final boolean ANIMATE_BUTTON_LIGHTS = false;
    static final boolean ANIMATE_KEYBOARD_LIGHTS = false;
    
    static final int ANIM_STEPS = 60/4;
    // Slower animation for autobrightness changes
    static final int AUTOBRIGHTNESS_ANIM_STEPS = 60;

    // These magic numbers are the initial state of the LEDs at boot.  Ideally
    // we should read them from the driver, but our current hardware returns 0
    // for the initial value.  Oops!
    static final int INITIAL_SCREEN_BRIGHTNESS = 255;
    static final int INITIAL_BUTTON_BRIGHTNESS = Power.BRIGHTNESS_OFF;
    static final int INITIAL_KEYBOARD_BRIGHTNESS = Power.BRIGHTNESS_OFF;
    
    static final int LOG_POWER_SLEEP_REQUESTED = 2724;
    static final int LOG_POWER_SCREEN_BROADCAST_SEND = 2725;
    static final int LOG_POWER_SCREEN_BROADCAST_DONE = 2726;
    static final int LOG_POWER_SCREEN_BROADCAST_STOP = 2727;
    static final int LOG_POWER_SCREEN_STATE = 2728;
    static final int LOG_POWER_PARTIAL_WAKE_STATE = 2729;
    
    private final int MY_UID;

    private boolean mDoneBooting = false;
    private int mStayOnConditions = 0;
    private int[] mBroadcastQueue = new int[] { -1, -1, -1 };
    private int[] mBroadcastWhy = new int[3];
    private int mPartialCount = 0;
    private int mPowerState;
    private boolean mOffBecauseOfUser;
    private int mUserState;
    private boolean mKeyboardVisible = false;
    private boolean mUserActivityAllowed = true;
    private int mProximityWakeLockCount = 0;
    private boolean mProximitySensorEnabled = false;
    private boolean mProximitySensorActive = false;
    private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
    private long mLastProximityEventTime;
    private int mTotalDelaySetting;
    private int mKeylightDelay;
    private int mDimDelay;
    private int mScreenOffDelay;
    private int mWakeLockState;
    private long mLastEventTime = 0;
    private long mScreenOffTime;
    private volatile WindowManagerPolicy mPolicy;
    private final LockList mLocks = new LockList();
    private Intent mScreenOffIntent;
    private Intent mScreenOnIntent;
    private HardwareService mHardware;
    private Context mContext;
    private UnsynchronizedWakeLock mBroadcastWakeLock;
    private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
    private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
    private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
    private HandlerThread mHandlerThread;
    private Handler mHandler;
    private TimeoutTask mTimeoutTask = new TimeoutTask();
    private LightAnimator mLightAnimator = new LightAnimator();
    private final BrightnessState mScreenBrightness
            = new BrightnessState(SCREEN_BRIGHT_BIT);
    private final BrightnessState mKeyboardBrightness
            = new BrightnessState(KEYBOARD_BRIGHT_BIT);
    private final BrightnessState mButtonBrightness
            = new BrightnessState(BUTTON_BRIGHT_BIT);
    private boolean mStillNeedSleepNotification;
    private boolean mIsPowered = false;
    private IActivityManager mActivityService;
    private IBatteryStats mBatteryStats;
    private BatteryService mBatteryService;
    private SensorManager mSensorManager;
    private Sensor mProximitySensor;
    private Sensor mLightSensor;
    private boolean mLightSensorEnabled;
    private float mLightSensorValue = -1;
    private float mLightSensorPendingValue = -1;
    private int mLightSensorBrightness = -1;
    private boolean mDimScreen = true;
    private long mNextTimeout;
    private volatile int mPokey = 0;
    private volatile boolean mPokeAwakeOnSet = false;
    private volatile boolean mInitComplete = false;
    private HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
    // mScreenOnTime and mScreenOnStartTime are used for computing total time screen
    // has been on since boot
    private long mScreenOnTime;
    private long mScreenOnStartTime;
    // mLastScreenOnTime is the time the screen was last turned on
    private long mLastScreenOnTime;
    private boolean mPreventScreenOn;
    private int mScreenBrightnessOverride = -1;
    private boolean mUseSoftwareAutoBrightness;
    private boolean mAutoBrightessEnabled;
    private int[] mAutoBrightnessLevels;
    private int[] mLcdBacklightValues;
    private int[] mButtonBacklightValues;
    private int[] mKeyboardBacklightValues;
    private int mLightSensorWarmupTime;

    // Used when logging number and duration of touch-down cycles
    private long mTotalTouchDownTime;
    private long mLastTouchDown;
    private int mTouchCycles;

    // could be either static or controllable at runtime
    private static final boolean mSpew = false;
    private static final boolean mDebugProximitySensor = (true || mSpew);
    private static final boolean mDebugLightSensor = (false || mSpew);

    /*
    static PrintStream mLog;
    static {
        try {
            mLog = new PrintStream("/data/power.log");
        }
        catch (FileNotFoundException e) {
            android.util.Log.e(TAG, "Life is hard", e);
        }
    }
    static class Log {
        static void d(String tag, String s) {
            mLog.println(s);
            android.util.Log.d(tag, s);
        }
        static void i(String tag, String s) {
            mLog.println(s);
            android.util.Log.i(tag, s);
        }
        static void w(String tag, String s) {
            mLog.println(s);
            android.util.Log.w(tag, s);
        }
        static void e(String tag, String s) {
            mLog.println(s);
            android.util.Log.e(tag, s);
        }
    }
    */

    /**
     * This class works around a deadlock between the lock in PowerManager.WakeLock
     * and our synchronizing on mLocks.  PowerManager.WakeLock synchronizes on its
     * mToken object so it can be accessed from any thread, but it calls into here
     * with its lock held.  This class is essentially a reimplementation of
     * PowerManager.WakeLock, but without that extra synchronized block, because we'll
     * only call it with our own locks held.
     */
    private class UnsynchronizedWakeLock {
        int mFlags;
        String mTag;
        IBinder mToken;
        int mCount = 0;
        boolean mRefCounted;

        UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
            mFlags = flags;
            mTag = tag;
            mToken = new Binder();
            mRefCounted = refCounted;
        }

        public void acquire() {
            if (!mRefCounted || mCount++ == 0) {
                long ident = Binder.clearCallingIdentity();
                try {
                    PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
                            MY_UID, mTag);
                } finally {
                    Binder.restoreCallingIdentity(ident);
                }
            }
        }

        public void release() {
            if (!mRefCounted || --mCount == 0) {
                PowerManagerService.this.releaseWakeLockLocked(mToken, false);
            }
            if (mCount < 0) {
                throw new RuntimeException("WakeLock under-locked " + mTag);
            }
        }

        public String toString() {
            return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
                    + " mCount=" + mCount + ")";
        }
    }

    private final class BatteryReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            synchronized (mLocks) {
                boolean wasPowered = mIsPowered;
                mIsPowered = mBatteryService.isPowered();

                if (mIsPowered != wasPowered) {
                    // update mStayOnWhilePluggedIn wake lock
                    updateWakeLockLocked();

                    // treat plugging and unplugging the devices as a user activity.
                    // users find it disconcerting when they unplug the device
                    // and it shuts off right away.
                    // temporarily set mUserActivityAllowed to true so this will work
                    // even when the keyguard is on.
                    synchronized (mLocks) {
                        forceUserActivityLocked();
                    }
                }
            }
        }
    }

    /**
     * Set the setting that determines whether the device stays on when plugged in.
     * The argument is a bit string, with each bit specifying a power source that,
     * when the device is connected to that source, causes the device to stay on.
     * See {@link android.os.BatteryManager} for the list of power sources that
     * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
     * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
     * @param val an {@code int} containing the bits that specify which power sources
     * should cause the device to stay on.
     */
    public void setStayOnSetting(int val) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
        Settings.System.putInt(mContext.getContentResolver(),
                Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
    }

    private class SettingsObserver implements Observer {
        private int getInt(String name) {
            return mSettings.getValues(name).getAsInteger(Settings.System.VALUE);
        }

        public void update(Observable o, Object arg) {
            synchronized (mLocks) {
                // STAY_ON_WHILE_PLUGGED_IN
                mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN);
                updateWakeLockLocked();

                // SCREEN_OFF_TIMEOUT
                mTotalDelaySetting = getInt(SCREEN_OFF_TIMEOUT);

                 // DIM_SCREEN
                //mDimScreen = getInt(DIM_SCREEN) != 0;

                // SCREEN_BRIGHTNESS_MODE
                setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE));

                // recalculate everything
                setScreenOffTimeoutsLocked();
            }
        }
    }

    PowerManagerService()
    {
        // Hack to get our uid...  should have a func for this.
        long token = Binder.clearCallingIdentity();
        MY_UID = Binder.getCallingUid();
        Binder.restoreCallingIdentity(token);

        // XXX remove this when the kernel doesn't timeout wake locks
        Power.setLastUserActivityTimeout(7*24*3600*1000); // one week

        // assume nothing is on yet
        mUserState = mPowerState = 0;
        
        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);
        mScreenOnStartTime = SystemClock.elapsedRealtime();
    }

    private ContentQueryMap mSettings;

    void init(Context context, HardwareService hardware, IActivityManager activity,
            BatteryService battery) {
        mHardware = hardware;
        mContext = context;
        mActivityService = activity;
        mBatteryStats = BatteryStatsService.getService();
        mBatteryService = battery;

        mHandlerThread = new HandlerThread("PowerManagerService") {
            @Override
            protected void onLooperPrepared() {
                super.onLooperPrepared();
                initInThread();
            }
        };
        mHandlerThread.start();
        
        synchronized (mHandlerThread) {
            while (!mInitComplete) {
                try {
                    mHandlerThread.wait();
                } catch (InterruptedException e) {
                    // Ignore
                }
            }
        }
    }
    
    void initInThread() {
        mHandler = new Handler();

        mBroadcastWakeLock = new UnsynchronizedWakeLock(
                                PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
        mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
                                PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
        mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
                                PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
        mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
                                PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);

        mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
        mScreenOnIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
        mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
        mScreenOffIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);

        Resources resources = mContext.getResources();

        // read settings for auto-brightness
        mUseSoftwareAutoBrightness = resources.getBoolean(
                com.android.internal.R.bool.config_automatic_brightness_available);
        if (mUseSoftwareAutoBrightness) {
            mAutoBrightnessLevels = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessLevels);
            mLcdBacklightValues = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
            mButtonBacklightValues = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
            mKeyboardBacklightValues = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
            mLightSensorWarmupTime = resources.getInteger(
                    com.android.internal.R.integer.config_lightSensorWarmupTime);
        }

       ContentResolver resolver = mContext.getContentResolver();
        Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
                "(" + Settings.System.NAME + "=?) or ("
                        + Settings.System.NAME + "=?) or ("
                        + Settings.System.NAME + "=?) or ("
                        + Settings.System.NAME + "=?)",
                new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN,
                        SCREEN_BRIGHTNESS_MODE},
                null);
        mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
        SettingsObserver settingsObserver = new SettingsObserver();
        mSettings.addObserver(settingsObserver);

        // pretend that the settings changed so we will get their initial state
        settingsObserver.update(mSettings, null);

        // register for the battery changed notifications
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_BATTERY_CHANGED);
        mContext.registerReceiver(new BatteryReceiver(), filter);

        // Listen for Gservices changes
        IntentFilter gservicesChangedFilter =
                new IntentFilter(Settings.Gservices.CHANGED_ACTION);
        mContext.registerReceiver(new GservicesChangedReceiver(), gservicesChangedFilter);
        // And explicitly do the initial update of our cached settings
        updateGservicesValues();

        if (mUseSoftwareAutoBrightness) {
            // turn the screen on
            setPowerState(SCREEN_BRIGHT);
        } else {
            // turn everything on
            setPowerState(ALL_BRIGHT);
        }

        synchronized (mHandlerThread) {
            mInitComplete = true;
            mHandlerThread.notifyAll();
        }
    }

    private class WakeLock implements IBinder.DeathRecipient
    {
        WakeLock(int f, IBinder b, String t, int u) {
            super();
            flags = f;
            binder = b;
            tag = t;
            uid = u == MY_UID ? Process.SYSTEM_UID : u;
            if (u != MY_UID || (
                    !"KEEP_SCREEN_ON_FLAG".equals(tag)
                    && !"KeyInputQueue".equals(tag))) {
                monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
                        ? BatteryStats.WAKE_TYPE_PARTIAL
                        : BatteryStats.WAKE_TYPE_FULL;
            } else {
                monitorType = -1;
            }
            try {
                b.linkToDeath(this, 0);
            } catch (RemoteException e) {
                binderDied();
            }
        }
        public void binderDied() {
            synchronized (mLocks) {
                releaseWakeLockLocked(this.binder, true);
            }
        }
        final int flags;
        final IBinder binder;
        final String tag;
        final int uid;
        final int monitorType;
        boolean activated = true;
        int minState;
    }

    private void updateWakeLockLocked() {
        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
            // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
            mStayOnWhilePluggedInScreenDimLock.acquire();
            mStayOnWhilePluggedInPartialLock.acquire();
        } else {
            mStayOnWhilePluggedInScreenDimLock.release();
            mStayOnWhilePluggedInPartialLock.release();
        }
    }

    private boolean isScreenLock(int flags)
    {
        int n = flags & LOCK_MASK;
        return n == PowerManager.FULL_WAKE_LOCK
                || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
                || n == PowerManager.SCREEN_DIM_WAKE_LOCK;
    }

    public void acquireWakeLock(int flags, IBinder lock, String tag) {
        int uid = Binder.getCallingUid();
        if (uid != Process.myUid()) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
        }
        long ident = Binder.clearCallingIdentity();
        try {
            synchronized (mLocks) {
                acquireWakeLockLocked(flags, lock, uid, tag);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) {
        int acquireUid = -1;
        String acquireName = null;
        int acquireType = -1;

        if (mSpew) {
            Log.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
        }

        int index = mLocks.getIndex(lock);
        WakeLock wl;
        boolean newlock;
        if (index < 0) {
            wl = new WakeLock(flags, lock, tag, uid);
            switch (wl.flags & LOCK_MASK)
            {
                case PowerManager.FULL_WAKE_LOCK:
                    if (mUseSoftwareAutoBrightness) {
                        wl.minState = SCREEN_BRIGHT;
                    } else {
                        wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
                    }
                    break;
                case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                    wl.minState = SCREEN_BRIGHT;
                    break;
                case PowerManager.SCREEN_DIM_WAKE_LOCK:
                    wl.minState = SCREEN_DIM;
                    break;
                case PowerManager.PARTIAL_WAKE_LOCK:
                case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
                    break;
                default:
                    // just log and bail.  we're in the server, so don't
                    // throw an exception.
                    Log.e(TAG, "bad wakelock type for lock '" + tag + "' "
                            + " flags=" + flags);
                    return;
            }
            mLocks.addLock(wl);
            newlock = true;
        } else {
            wl = mLocks.get(index);
            newlock = false;
        }
        if (isScreenLock(flags)) {
            // if this causes a wakeup, we reactivate all of the locks and
            // set it to whatever they want.  otherwise, we modulate that
            // by the current state so we never turn it more on than
            // it already is.
            if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
                int oldWakeLockState = mWakeLockState;
                mWakeLockState = mLocks.reactivateScreenLocksLocked();
                if (mSpew) {
                    Log.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
                            + " mWakeLockState=0x"
                            + Integer.toHexString(mWakeLockState)
                            + " previous wakeLockState=0x" + Integer.toHexString(oldWakeLockState));
                }
            } else {
                if (mSpew) {
                    Log.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
                            + " mLocks.gatherState()=0x"
                            + Integer.toHexString(mLocks.gatherState())
                            + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
                }
                mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
            }
            setPowerState(mWakeLockState | mUserState);
        }
        else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
            if (newlock) {
                mPartialCount++;
                if (mPartialCount == 1) {
                    if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 1, tag);
                }
            }
            Power.acquireWakeLock(Power.PARTIAL_WAKE_LOCK,PARTIAL_NAME);
        } else if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
            mProximityWakeLockCount++;
            if (mProximityWakeLockCount == 1) {
                enableProximityLockLocked();
            }
        }
        if (newlock) {
            acquireUid = wl.uid;
            acquireName = wl.tag;
            acquireType = wl.monitorType;
        }

        if (acquireType >= 0) {
            try {
                mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType);
            } catch (RemoteException e) {
                // Ignore
            }
        }
    }

    public void releaseWakeLock(IBinder lock) {
        int uid = Binder.getCallingUid();
        if (uid != Process.myUid()) {
            mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
        }

        synchronized (mLocks) {
            releaseWakeLockLocked(lock, false);
        }
    }

    private void releaseWakeLockLocked(IBinder lock, boolean death) {
        int releaseUid;
        String releaseName;
        int releaseType;

        WakeLock wl = mLocks.removeLock(lock);
        if (wl == null) {
            return;
        }
        
        if (mSpew) {
            Log.d(TAG, "releaseWakeLock flags=0x"
                    + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
        }

        if (isScreenLock(wl.flags)) {
            mWakeLockState = mLocks.gatherState();
            // goes in the middle to reduce flicker
            if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
                userActivity(SystemClock.uptimeMillis(), false);
            }
            setPowerState(mWakeLockState | mUserState);
        }
        else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
            mPartialCount--;
            if (mPartialCount == 0) {
                if (LOG_PARTIAL_WL) EventLog.writeEvent(LOG_POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
                Power.releaseWakeLock(PARTIAL_NAME);
            }
        } else if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
            mProximityWakeLockCount--;
            if (mProximityWakeLockCount == 0) {
                if (mProximitySensorActive) {
                    // wait for proximity sensor to go negative before disabling sensor
                    if (mDebugProximitySensor) {
                        Log.d(TAG, "waiting for proximity sensor to go negative");
                    }
                } else {
                    disableProximityLockLocked();
                }
            }
        }
        // Unlink the lock from the binder.
        wl.binder.unlinkToDeath(wl, 0);
        releaseUid = wl.uid;
        releaseName = wl.tag;
        releaseType = wl.monitorType;

        if (releaseType >= 0) {
            long origId = Binder.clearCallingIdentity();
            try {
                mBatteryStats.noteStopWakelock(releaseUid, releaseName, releaseType);
            } catch (RemoteException e) {
                // Ignore
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
        }
    }

    private class PokeLock implements IBinder.DeathRecipient
    {
        PokeLock(int p, IBinder b, String t) {
            super();
            this.pokey = p;
            this.binder = b;
            this.tag = t;
            try {
                b.linkToDeath(this, 0);
            } catch (RemoteException e) {
                binderDied();
            }
        }
        public void binderDied() {
            setPokeLock(0, this.binder, this.tag);
        }
        int pokey;
        IBinder binder;
        String tag;
        boolean awakeOnSet;
    }

    public void setPokeLock(int pokey, IBinder token, String tag) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        if (token == null) {
            Log.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
            return;
        }

        if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
            throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
                    + " and POKE_LOCK_MEDIUM_TIMEOUT");
        }

        synchronized (mLocks) {
            if (pokey != 0) {
                PokeLock p = mPokeLocks.get(token);
                int oldPokey = 0;
                if (p != null) {
                    oldPokey = p.pokey;
                    p.pokey = pokey;
                } else {
                    p = new PokeLock(pokey, token, tag);
                    mPokeLocks.put(token, p);
                }
                int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
                int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
                if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
                    p.awakeOnSet = true;
                }
            } else {
                PokeLock rLock = mPokeLocks.remove(token);
                if (rLock != null) {
                    token.unlinkToDeath(rLock, 0);
                }
            }

            int oldPokey = mPokey;
            int cumulative = 0;
            boolean oldAwakeOnSet = mPokeAwakeOnSet;
            boolean awakeOnSet = false;
            for (PokeLock p: mPokeLocks.values()) {
                cumulative |= p.pokey;
                if (p.awakeOnSet) {
                    awakeOnSet = true;
                }
            }
            mPokey = cumulative;
            mPokeAwakeOnSet = awakeOnSet;

            int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
            int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
            
            if (oldCumulativeTimeout != newCumulativeTimeout) {
                setScreenOffTimeoutsLocked();
                // reset the countdown timer, but use the existing nextState so it doesn't
                // change anything
                setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
            }
        }
    }

    private static String lockType(int type)
    {
        switch (type)
        {
            case PowerManager.FULL_WAKE_LOCK:
                return "FULL_WAKE_LOCK                ";
            case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
                return "SCREEN_BRIGHT_WAKE_LOCK       ";
            case PowerManager.SCREEN_DIM_WAKE_LOCK:
                return "SCREEN_DIM_WAKE_LOCK          ";
            case PowerManager.PARTIAL_WAKE_LOCK:
                return "PARTIAL_WAKE_LOCK             ";
            case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
                return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
            default:
                return "???                           ";
        }
    }

    private static String dumpPowerState(int state) {
        return (((state & KEYBOARD_BRIGHT_BIT) != 0)
                        ? "KEYBOARD_BRIGHT_BIT " : "")
                + (((state & SCREEN_BRIGHT_BIT) != 0)
                        ? "SCREEN_BRIGHT_BIT " : "")
                + (((state & SCREEN_ON_BIT) != 0)
                        ? "SCREEN_ON_BIT " : "")
                + (((state & BATTERY_LOW_BIT) != 0)
                        ? "BATTERY_LOW_BIT " : "");
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                != PackageManager.PERMISSION_GRANTED) {
            pw.println("Permission Denial: can't dump PowerManager from from pid="
                    + Binder.getCallingPid()
                    + ", uid=" + Binder.getCallingUid());
            return;
        }

        long now = SystemClock.uptimeMillis();

        pw.println("Power Manager State:");
        pw.println("  mIsPowered=" + mIsPowered
                + " mPowerState=" + mPowerState
                + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
                + " ms");
        pw.println("  mPartialCount=" + mPartialCount);
        pw.println("  mWakeLockState=" + dumpPowerState(mWakeLockState));
        pw.println("  mUserState=" + dumpPowerState(mUserState));
        pw.println("  mPowerState=" + dumpPowerState(mPowerState));
        pw.println("  mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
        pw.println("  mNextTimeout=" + mNextTimeout + " now=" + now
                + " " + ((mNextTimeout-now)/1000) + "s from now");
        pw.println("  mDimScreen=" + mDimScreen
                + " mStayOnConditions=" + mStayOnConditions);
        pw.println("  mOffBecauseOfUser=" + mOffBecauseOfUser
                + " mUserState=" + mUserState);
        pw.println("  mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
                + ',' + mBroadcastQueue[2] + "}");
        pw.println("  mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
                + ',' + mBroadcastWhy[2] + "}");
        pw.println("  mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
        pw.println("  mKeyboardVisible=" + mKeyboardVisible
                + " mUserActivityAllowed=" + mUserActivityAllowed);
        pw.println("  mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
                + " mScreenOffDelay=" + mScreenOffDelay);
        pw.println("  mPreventScreenOn=" + mPreventScreenOn
                + "  mScreenBrightnessOverride=" + mScreenBrightnessOverride);
        pw.println("  mTotalDelaySetting=" + mTotalDelaySetting);
        pw.println("  mLastScreenOnTime=" + mLastScreenOnTime);
        pw.println("  mBroadcastWakeLock=" + mBroadcastWakeLock);
        pw.println("  mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
        pw.println("  mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
        pw.println("  mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
        pw.println("  mProximityWakeLockCount=" + mProximityWakeLockCount);
        pw.println("  mProximitySensorEnabled=" + mProximitySensorEnabled);
        pw.println("  mProximitySensorActive=" + mProximitySensorActive);
        pw.println("  mProximityPendingValue=" + mProximityPendingValue);
        pw.println("  mLastProximityEventTime=" + mLastProximityEventTime);
        pw.println("  mLightSensorEnabled=" + mLightSensorEnabled);
        pw.println("  mLightSensorValue=" + mLightSensorValue);
        pw.println("  mLightSensorPendingValue=" + mLightSensorPendingValue);
        pw.println("  mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
        pw.println("  mAutoBrightessEnabled=" + mAutoBrightessEnabled);
        mScreenBrightness.dump(pw, "  mScreenBrightness: ");
        mKeyboardBrightness.dump(pw, "  mKeyboardBrightness: ");
        mButtonBrightness.dump(pw, "  mButtonBrightness: ");
        
        int N = mLocks.size();
        pw.println();
        pw.println("mLocks.size=" + N + ":");
        for (int i=0; i<N; i++) {
            WakeLock wl = mLocks.get(i);
            String type = lockType(wl.flags & LOCK_MASK);
            String acquireCausesWakeup = "";
            if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
                acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
            }
            String activated = "";
            if (wl.activated) {
               activated = " activated";
            }
            pw.println("  " + type + " '" + wl.tag + "'" + acquireCausesWakeup
                    + activated + " (minState=" + wl.minState + ")");
        }
        
        pw.println();
        pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
        for (PokeLock p: mPokeLocks.values()) {
            pw.println("    poke lock '" + p.tag + "':"
                    + ((p.pokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0
                            ? " POKE_LOCK_IGNORE_CHEEK_EVENTS" : "")
                    + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0
                            ? " POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS" : "")
                    + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
                            ? " POKE_LOCK_SHORT_TIMEOUT" : "")
                    + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
                            ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
        }

        pw.println();
    }

    private void setTimeoutLocked(long now, int nextState)
    {
        if (mDoneBooting) {
            mHandler.removeCallbacks(mTimeoutTask);
            mTimeoutTask.nextState = nextState;
            long when = now;
            switch (nextState)
            {
                case SCREEN_BRIGHT:
                    when += mKeylightDelay;
                    break;
                case SCREEN_DIM:
                    if (mDimDelay >= 0) {
                        when += mDimDelay;
                        break;
                    } else {
                        Log.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
                    }
                case SCREEN_OFF:
                    synchronized (mLocks) {
                        when += mScreenOffDelay;
                    }
                    break;
            }
            if (mSpew) {
                Log.d(TAG, "setTimeoutLocked now=" + now + " nextState=" + nextState
                        + " when=" + when);
            }
            mHandler.postAtTime(mTimeoutTask, when);
            mNextTimeout = when; // for debugging
        }
    }

    private void cancelTimerLocked()
    {
        mHandler.removeCallbacks(mTimeoutTask);
        mTimeoutTask.nextState = -1;
    }

    private class TimeoutTask implements Runnable
    {
        int nextState; // access should be synchronized on mLocks
        public void run()
        {
            synchronized (mLocks) {
                if (mSpew) {
                    Log.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
                }

                if (nextState == -1) {
                    return;
                }

                mUserState = this.nextState;
                setPowerState(this.nextState | mWakeLockState);

                long now = SystemClock.uptimeMillis();

                switch (this.nextState)
                {
                    case SCREEN_BRIGHT:
                        if (mDimDelay >= 0) {
                            setTimeoutLocked(now, SCREEN_DIM);
                            break;
                        }
                    case SCREEN_DIM:
                        setTimeoutLocked(now, SCREEN_OFF);
                        break;
                }
            }
        }
    }

    private void sendNotificationLocked(boolean on, int why)
    {
        if (!on) {
            mStillNeedSleepNotification = false;
        }

        // Add to the queue.
        int index = 0;
        while (mBroadcastQueue[index] != -1) {
            index++;
        }
        mBroadcastQueue[index] = on ? 1 : 0;
        mBroadcastWhy[index] = why;

        // If we added it position 2, then there is a pair that can be stripped.
        // If we added it position 1 and we're turning the screen off, we can strip
        // the pair and do nothing, because the screen is already off, and therefore
        // keyguard has already been enabled.
        // However, if we added it at position 1 and we're turning it on, then position
        // 0 was to turn it off, and we can't strip that, because keyguard needs to come
        // on, so have to run the queue then.
        if (index == 2) {
            // Also, while we're collapsing them, if it's going to be an "off," and one
            // is off because of user, then use that, regardless of whether it's the first
            // or second one.
            if (!on && why == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
                mBroadcastWhy[0] = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
            }
            mBroadcastQueue[0] = on ? 1 : 0;
            mBroadcastQueue[1] = -1;
            mBroadcastQueue[2] = -1;
            index = 0;
        }
        if (index == 1 && !on) {
            mBroadcastQueue[0] = -1;
            mBroadcastQueue[1] = -1;
            index = -1;
            // The wake lock was being held, but we're not actually going to do any
            // broadcasts, so release the wake lock.
            EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
            mBroadcastWakeLock.release();
        }

        // Now send the message.
        if (index >= 0) {
            // Acquire the broadcast wake lock before changing the power
            // state. It will be release after the broadcast is sent.
            // We always increment the ref count for each notification in the queue
            // and always decrement when that notification is handled.
            mBroadcastWakeLock.acquire();
            EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
            mHandler.post(mNotificationTask);
        }
    }

    private Runnable mNotificationTask = new Runnable()
    {
        public void run()
        {
            while (true) {
                int value;
                int why;
                WindowManagerPolicy policy;
                synchronized (mLocks) {
                    value = mBroadcastQueue[0];
                    why = mBroadcastWhy[0];
                    for (int i=0; i<2; i++) {
                        mBroadcastQueue[i] = mBroadcastQueue[i+1];
                        mBroadcastWhy[i] = mBroadcastWhy[i+1];
                    }
                    policy = getPolicyLocked();
                }
                if (value == 1) {
                    mScreenOnStart = SystemClock.uptimeMillis();
                    
                    policy.screenTurnedOn();
                    try {
                        ActivityManagerNative.getDefault().wakingUp();
                    } catch (RemoteException e) {
                        // ignore it
                    }

                    if (mSpew) {
                        Log.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
                    }
                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
                        mContext.sendOrderedBroadcast(mScreenOnIntent, null,
                                mScreenOnBroadcastDone, mHandler, 0, null, null);
                    } else {
                        synchronized (mLocks) {
                            EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 2,
                                    mBroadcastWakeLock.mCount);
                            mBroadcastWakeLock.release();
                        }
                    }
                }
                else if (value == 0) {
                    mScreenOffStart = SystemClock.uptimeMillis();
                    
                    policy.screenTurnedOff(why);
                    try {
                        ActivityManagerNative.getDefault().goingToSleep();
                    } catch (RemoteException e) {
                        // ignore it.
                    }

                    if (mContext != null && ActivityManagerNative.isSystemReady()) {
                        mContext.sendOrderedBroadcast(mScreenOffIntent, null,
                                mScreenOffBroadcastDone, mHandler, 0, null, null);
                    } else {
                        synchronized (mLocks) {
                            EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_STOP, 3,
                                    mBroadcastWakeLock.mCount);
                            mBroadcastWakeLock.release();
                        }
                    }
                }
                else {
                    // If we're in this case, then this handler is running for a previous
                    // paired transaction.  mBroadcastWakeLock will already have been released.
                    break;
                }
            }
        }
    };

    long mScreenOnStart;
    private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            synchronized (mLocks) {
                EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 1,
                        SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
                mBroadcastWakeLock.release();
            }
        }
    };

    long mScreenOffStart;
    private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            synchronized (mLocks) {
                EventLog.writeEvent(LOG_POWER_SCREEN_BROADCAST_DONE, 0,
                        SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
                mBroadcastWakeLock.release();
            }
        }
    };

    void logPointerUpEvent() {
        if (LOG_TOUCH_DOWNS) {
            mTotalTouchDownTime += SystemClock.elapsedRealtime() - mLastTouchDown;
            mLastTouchDown = 0;
        }
    }

    void logPointerDownEvent() {
        if (LOG_TOUCH_DOWNS) {
            // If we are not already timing a down/up sequence
            if (mLastTouchDown == 0) {
                mLastTouchDown = SystemClock.elapsedRealtime();
                mTouchCycles++;
            }
        }
    }

    /**
     * Prevents the screen from turning on even if it *should* turn on due
     * to a subsequent full wake lock being acquired.
     * <p>
     * This is a temporary hack that allows an activity to "cover up" any
     * display glitches that happen during the activity's startup
     * sequence.  (Specifically, this API was added to work around a
     * cosmetic bug in the "incoming call" sequence, where the lock screen
     * would flicker briefly before the incoming call UI became visible.)
     * TODO: There ought to be a more elegant way of doing this,
     * probably by having the PowerManager and ActivityManager
     * work together to let apps specify that the screen on/off
     * state should be synchronized with the Activity lifecycle.
     * <p>
     * Note that calling preventScreenOn(true) will NOT turn the screen
     * off if it's currently on.  (This API only affects *future*
     * acquisitions of full wake locks.)
     * But calling preventScreenOn(false) WILL turn the screen on if
     * it's currently off because of a prior preventScreenOn(true) call.
     * <p>
     * Any call to preventScreenOn(true) MUST be followed promptly by a call
     * to preventScreenOn(false).  In fact, if the preventScreenOn(false)
     * call doesn't occur within 5 seconds, we'll turn the screen back on
     * ourselves (and log a warning about it); this prevents a buggy app
     * from disabling the screen forever.)
     * <p>
     * TODO: this feature should really be controlled by a new type of poke
     * lock (rather than an IPowerManager call).
     */
    public void preventScreenOn(boolean prevent) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

        synchronized (mLocks) {
            if (prevent) {
                // First of all, grab a partial wake lock to
                // make sure the CPU stays on during the entire
                // preventScreenOn(true) -> preventScreenOn(false) sequence.
                mPreventScreenOnPartialLock.acquire();

                // Post a forceReenableScreen() call (for 5 seconds in the
                // future) to make sure the matching preventScreenOn(false) call
                // has happened by then.
                mHandler.removeCallbacks(mForceReenableScreenTask);
                mHandler.postDelayed(mForceReenableScreenTask, 5000);

                // Finally, set the flag that prevents the screen from turning on.
                // (Below, in setPowerState(), we'll check mPreventScreenOn and
                // we *won't* call setScreenStateLocked(true) if it's set.)
                mPreventScreenOn = true;
            } else {
                // (Re)enable the screen.
                mPreventScreenOn = false;

                // We're "undoing" a the prior preventScreenOn(true) call, so we
                // no longer need the 5-second safeguard.
                mHandler.removeCallbacks(mForceReenableScreenTask);

                // Forcibly turn on the screen if it's supposed to be on.  (This
                // handles the case where the screen is currently off because of
                // a prior preventScreenOn(true) call.)
                if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
                    if (mSpew) {
                        Log.d(TAG,
                              "preventScreenOn: turning on after a prior preventScreenOn(true)!");
                    }
                    int err = setScreenStateLocked(true);
                    if (err != 0) {
                        Log.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
                    }
                }

                // Release the partial wake lock that we held during the
                // preventScreenOn(true) -> preventScreenOn(false) sequence.
                mPreventScreenOnPartialLock.release();
            }
        }
    }

    public void setScreenBrightnessOverride(int brightness) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

        synchronized (mLocks) {
            if (mScreenBrightnessOverride != brightness) {
                mScreenBrightnessOverride = brightness;
                updateLightsLocked(mPowerState, SCREEN_ON_BIT);
            }
        }
    }
    
    /**
     * Sanity-check that gets called 5 seconds after any call to
     * preventScreenOn(true).  This ensures that the original call
     * is followed promptly by a call to preventScreenOn(false).
     */
    private void forceReenableScreen() {
        // We shouldn't get here at all if mPreventScreenOn is false, since
        // we should have already removed any existing
        // mForceReenableScreenTask messages...
        if (!mPreventScreenOn) {
            Log.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
            return;
        }

        // Uh oh.  It's been 5 seconds since a call to
        // preventScreenOn(true) and we haven't re-enabled the screen yet.
        // This means the app that called preventScreenOn(true) is either
        // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
        // or buggy (i.e. it forgot to call preventScreenOn(false), or
        // crashed before doing so.)

        // Log a warning, and forcibly turn the screen back on.
        Log.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
              + "Forcing the screen back on...");
        preventScreenOn(false);
    }

    private Runnable mForceReenableScreenTask = new Runnable() {
            public void run() {
                forceReenableScreen();
            }
        };

    private int setScreenStateLocked(boolean on) {
        int err = Power.setScreenState(on);
        if (err == 0) {
            mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
            if (mUseSoftwareAutoBrightness) {
                enableLightSensor(on);
                if (!on) {
                    // make sure button and key backlights are off too
                    int brightnessMode = (mUseSoftwareAutoBrightness
                            ? HardwareService.BRIGHTNESS_MODE_SENSOR
                            : HardwareService.BRIGHTNESS_MODE_USER);
                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, 0,
                        brightnessMode);
                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, 0,
                        brightnessMode);
                    // clear current value so we will update based on the new conditions
                    // when the sensor is reenabled.
                    mLightSensorValue = -1;
                }
            }
        }
        return err;
    }

    private void setPowerState(int state)
    {
        setPowerState(state, false, false);
    }

    private void setPowerState(int newState, boolean noChangeLights, boolean becauseOfUser)
    {
        synchronized (mLocks) {
            int err;

            if (mSpew) {
                Log.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
                        + " newState=0x" + Integer.toHexString(newState)
                        + " noChangeLights=" + noChangeLights);
            }

            if (noChangeLights) {
                newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
            }
            if (mProximitySensorActive) {
                // don't turn on the screen when the proximity sensor lock is held
                newState = (newState & ~SCREEN_BRIGHT);
            }

            if (batteryIsLow()) {
                newState |= BATTERY_LOW_BIT;
            } else {
                newState &= ~BATTERY_LOW_BIT;
            }
            if (newState == mPowerState) {
                return;
            }

            if (!mDoneBooting && !mUseSoftwareAutoBrightness) {
                newState |= ALL_BRIGHT;
            }

            boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
            boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;

            if (mPowerState != newState) {
                Log.d(TAG, "setPowerState: mPowerState=" + mPowerState
                        + " newState=" + newState + " noChangeLights=" + noChangeLights);
                Log.d(TAG, "  oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
                         + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
                Log.d(TAG, "  oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
                         + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
                Log.d(TAG, "  oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
                         + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
                Log.d(TAG, "  oldScreenOn=" + oldScreenOn
                         + " newScreenOn=" + newScreenOn);
                Log.d(TAG, "  oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
                         + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
            }

            if (mPowerState != newState) {
                updateLightsLocked(newState, 0);
                mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
            }

            if (oldScreenOn != newScreenOn) {
                if (newScreenOn) {
                    // When the user presses the power button, we need to always send out the
                    // notification that it's going to sleep so the keyguard goes on.  But
                    // we can't do that until the screen fades out, so we don't show the keyguard
                    // too early.
                    if (mStillNeedSleepNotification) {
                        sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
                    }

                    // Turn on the screen UNLESS there was a prior
                    // preventScreenOn(true) request.  (Note that the lifetime
                    // of a single preventScreenOn() request is limited to 5
                    // seconds to prevent a buggy app from disabling the
                    // screen forever; see forceReenableScreen().)
                    boolean reallyTurnScreenOn = true;
                    if (mSpew) {
                        Log.d(TAG, "- turning screen on...  mPreventScreenOn = "
                              + mPreventScreenOn);
                    }

                    if (mPreventScreenOn) {
                        if (mSpew) {
                            Log.d(TAG, "- PREVENTING screen from really turning on!");
                        }
                        reallyTurnScreenOn = false;
                    }
                    if (reallyTurnScreenOn) {
                        err = setScreenStateLocked(true);
                        long identity = Binder.clearCallingIdentity();
                        try {
                            mBatteryStats.noteScreenBrightness(
                                    getPreferredBrightness());
                            mBatteryStats.noteScreenOn();
                        } catch (RemoteException e) {
                            Log.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
                        } finally {
                            Binder.restoreCallingIdentity(identity);
                        }
                    } else {
                        setScreenStateLocked(false);
                        // But continue as if we really did turn the screen on...
                        err = 0;
                    }

                    mScreenOnStartTime = SystemClock.elapsedRealtime();
                    mLastTouchDown = 0;
                    mTotalTouchDownTime = 0;
                    mTouchCycles = 0;
                    EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 1, becauseOfUser ? 1 : 0,
                            mTotalTouchDownTime, mTouchCycles);
                    if (err == 0) {
                        mPowerState |= SCREEN_ON_BIT;
                        sendNotificationLocked(true, -1);
                    }
                } else {
                    // cancel light sensor task
                    mHandler.removeCallbacks(mAutoBrightnessTask);
                    mScreenOffTime = SystemClock.elapsedRealtime();
                    long identity = Binder.clearCallingIdentity();
                    try {
                        mBatteryStats.noteScreenOff();
                    } catch (RemoteException e) {
                        Log.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
                    } finally {
                        Binder.restoreCallingIdentity(identity);
                    }
                    mPowerState &= ~SCREEN_ON_BIT;
                    if (!mScreenBrightness.animating) {
                        err = screenOffFinishedAnimatingLocked(becauseOfUser);
                    } else {
                        mOffBecauseOfUser = becauseOfUser;
                        err = 0;
                        mLastTouchDown = 0;
                    }
                }
            }
        }
    }
    
    private int screenOffFinishedAnimatingLocked(boolean becauseOfUser) {
        // I don't think we need to check the current state here because all of these
        // Power.setScreenState and sendNotificationLocked can both handle being 
        // called multiple times in the same state. -joeo
        EventLog.writeEvent(LOG_POWER_SCREEN_STATE, 0, becauseOfUser ? 1 : 0,
                mTotalTouchDownTime, mTouchCycles);
        mLastTouchDown = 0;
        int err = setScreenStateLocked(false);
        if (mScreenOnStartTime != 0) {
            mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime;
            mScreenOnStartTime = 0;
        }
        if (err == 0) {
            int why = becauseOfUser
                    ? WindowManagerPolicy.OFF_BECAUSE_OF_USER
                    : WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
            sendNotificationLocked(false, why);
        }
        return err;
    }

    private boolean batteryIsLow() {
        return (!mIsPowered &&
                mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
    }

    private void updateLightsLocked(int newState, int forceState) {
        final int oldState = mPowerState;
        final int realDifference = (newState ^ oldState);
        final int difference = realDifference | forceState;
        if (difference == 0) {
            return;
        }
        
        int offMask = 0;
        int dimMask = 0;
        int onMask = 0;

        int preferredBrightness = getPreferredBrightness();
        boolean startAnimation = false;
        
        if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
            if (ANIMATE_KEYBOARD_LIGHTS) {
                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
                    mKeyboardBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
                            preferredBrightness);
                } else {
                    mKeyboardBrightness.setTargetLocked(preferredBrightness,
                            ANIM_STEPS, INITIAL_KEYBOARD_BRIGHTNESS,
                            Power.BRIGHTNESS_OFF);
                }
                startAnimation = true;
            } else {
                if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
                    offMask |= KEYBOARD_BRIGHT_BIT;
                } else {
                    onMask |= KEYBOARD_BRIGHT_BIT;
                }
            }
        }

        if ((difference & BUTTON_BRIGHT_BIT) != 0) {
            if (ANIMATE_BUTTON_LIGHTS) {
                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
                    mButtonBrightness.setTargetLocked(Power.BRIGHTNESS_OFF,
                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
                            preferredBrightness);
                } else {
                    mButtonBrightness.setTargetLocked(preferredBrightness,
                            ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
                            Power.BRIGHTNESS_OFF);
                }
                startAnimation = true;
            } else {
                if ((newState & BUTTON_BRIGHT_BIT) == 0) {
                    offMask |= BUTTON_BRIGHT_BIT;
                } else {
                    onMask |= BUTTON_BRIGHT_BIT;
                }
            }
        }

        if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
            if (ANIMATE_SCREEN_LIGHTS) {
                int nominalCurrentValue = -1;
                // If there was an actual difference in the light state, then
                // figure out the "ideal" current value based on the previous
                // state.  Otherwise, this is a change due to the brightness
                // override, so we want to animate from whatever the current
                // value is.
                if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
                    switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
                        case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
                            nominalCurrentValue = preferredBrightness;
                            break;
                        case SCREEN_ON_BIT:
                            nominalCurrentValue = Power.BRIGHTNESS_DIM;
                            break;
                        case 0:
                            nominalCurrentValue = Power.BRIGHTNESS_OFF;
                            break;
                        case SCREEN_BRIGHT_BIT:
                        default:
                            // not possible
                            nominalCurrentValue = (int)mScreenBrightness.curValue;
                            break;
                    }
                }
                int brightness = preferredBrightness;
                int steps = ANIM_STEPS;
                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
                    // dim or turn off backlight, depending on if the screen is on
                    // the scale is because the brightness ramp isn't linear and this biases
                    // it so the later parts take longer.
                    final float scale = 1.5f;
                    float ratio = (((float)Power.BRIGHTNESS_DIM)/preferredBrightness);
                    if (ratio > 1.0f) ratio = 1.0f;
                    if ((newState & SCREEN_ON_BIT) == 0) {
                        if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
                            // was bright
                            steps = ANIM_STEPS;
                        } else {
                            // was dim
                            steps = (int)(ANIM_STEPS*ratio*scale);
                        }
                        brightness = Power.BRIGHTNESS_OFF;
                    } else {
                        if ((oldState & SCREEN_ON_BIT) != 0) {
                            // was bright
                            steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
                        } else {
                            // was dim
                            steps = (int)(ANIM_STEPS*ratio);
                        }
                        if (mStayOnConditions != 0 && mBatteryService.isPowered(mStayOnConditions)) {
                            // If the "stay on while plugged in" option is
                            // turned on, then the screen will often not
                            // automatically turn off while plugged in.  To
                            // still have a sense of when it is inactive, we
                            // will then count going dim as turning off.
                            mScreenOffTime = SystemClock.elapsedRealtime();
                        }
                        brightness = Power.BRIGHTNESS_DIM;
                    }
                }
                long identity = Binder.clearCallingIdentity();
                try {
                    mBatteryStats.noteScreenBrightness(brightness);
                } catch (RemoteException e) {
                    // Nothing interesting to do.
                } finally {
                    Binder.restoreCallingIdentity(identity);
                }
                if (mScreenBrightness.setTargetLocked(brightness,
                        steps, INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue)) {
                    startAnimation = true;
                }
            } else {
                if ((newState & SCREEN_BRIGHT_BIT) == 0) {
                    // dim or turn off backlight, depending on if the screen is on
                    if ((newState & SCREEN_ON_BIT) == 0) {
                        offMask |= SCREEN_BRIGHT_BIT;
                    } else {
                        dimMask |= SCREEN_BRIGHT_BIT;
                    }
                } else {
                    onMask |= SCREEN_BRIGHT_BIT;
                }
            }
        }

        if (startAnimation) {
            if (mSpew) {
                Log.i(TAG, "Scheduling light animator!");
            }
            mHandler.removeCallbacks(mLightAnimator);
            mHandler.post(mLightAnimator);
        }
        
        if (offMask != 0) {
            //Log.i(TAG, "Setting brightess off: " + offMask);
            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
        }
        if (dimMask != 0) {
            int brightness = Power.BRIGHTNESS_DIM;
            if ((newState & BATTERY_LOW_BIT) != 0 &&
                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
                brightness = Power.BRIGHTNESS_LOW_BATTERY;
            }
            //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
            setLightBrightness(dimMask, brightness);
        }
        if (onMask != 0) {
            int brightness = getPreferredBrightness();
            if ((newState & BATTERY_LOW_BIT) != 0 &&
                    brightness > Power.BRIGHTNESS_LOW_BATTERY) {
                brightness = Power.BRIGHTNESS_LOW_BATTERY;
            }
            //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
            setLightBrightness(onMask, brightness);
        }
    }

    private void setLightBrightness(int mask, int value) {
        int brightnessMode = (mAutoBrightessEnabled
                            ? HardwareService.BRIGHTNESS_MODE_SENSOR
                            : HardwareService.BRIGHTNESS_MODE_USER);
        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value,
                brightnessMode);
        }
        brightnessMode = (mUseSoftwareAutoBrightness
                            ? HardwareService.BRIGHTNESS_MODE_SENSOR
                            : HardwareService.BRIGHTNESS_MODE_USER);
        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value,
                brightnessMode);
        }
        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value,
                brightnessMode);
        }
    }

    class BrightnessState {
        final int mask;
        
        boolean initialized;
        int targetValue;
        float curValue;
        float delta;
        boolean animating;
        
        BrightnessState(int m) {
            mask = m;
        }
        
        public void dump(PrintWriter pw, String prefix) {
            pw.println(prefix + "animating=" + animating
                    + " targetValue=" + targetValue
                    + " curValue=" + curValue
                    + " delta=" + delta);
        }
        
        boolean setTargetLocked(int target, int stepsToTarget, int initialValue,
                int nominalCurrentValue) {
            if (!initialized) {
                initialized = true;
                curValue = (float)initialValue;
            } else if (targetValue == target) {
                return false;
            }
            targetValue = target;
            delta = (targetValue -
                    (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue))
                    / stepsToTarget;
            if (mSpew) {
                String noticeMe = nominalCurrentValue == curValue ? "" : "  ******************";
                Log.i(TAG, "Setting target " + mask + ": cur=" + curValue
                        + " target=" + targetValue + " delta=" + delta
                        + " nominalCurrentValue=" + nominalCurrentValue
                        + noticeMe);
            }
            animating = true;
            return true;
        }
        
        boolean stepLocked() {
            if (!animating) return false;
            if (false && mSpew) {
                Log.i(TAG, "Step target " + mask + ": cur=" + curValue
                        + " target=" + targetValue + " delta=" + delta);
            }
            curValue += delta;
            int curIntValue = (int)curValue;
            boolean more = true;
            if (delta == 0) {
                curValue = curIntValue = targetValue;
                more = false;
            } else if (delta > 0) {
                if (curIntValue >= targetValue) {
                    curValue = curIntValue = targetValue;
                    more = false;
                }
            } else {
                if (curIntValue <= targetValue) {
                    curValue = curIntValue = targetValue;
                    more = false;
                }
            }
            //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
            setLightBrightness(mask, curIntValue);
            animating = more;
            if (!more) {
                if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
                    screenOffFinishedAnimatingLocked(mOffBecauseOfUser);
                }
            }
            return more;
        }
    }
    
    private class LightAnimator implements Runnable {
        public void run() {
            synchronized (mLocks) {
                long now = SystemClock.uptimeMillis();
                boolean more = mScreenBrightness.stepLocked();
                if (mKeyboardBrightness.stepLocked()) {
                    more = true;
                }
                if (mButtonBrightness.stepLocked()) {
                    more = true;
                }
                if (more) {
                    mHandler.postAtTime(mLightAnimator, now+(1000/60));
                }
            }
        }
    }
    
    private int getPreferredBrightness() {
        try {
            if (mScreenBrightnessOverride >= 0) {
                return mScreenBrightnessOverride;
            } else if (mLightSensorBrightness >= 0 && mUseSoftwareAutoBrightness
                    && mAutoBrightessEnabled) {
                return mLightSensorBrightness;
            }
            final int brightness = Settings.System.getInt(mContext.getContentResolver(),
                                                          SCREEN_BRIGHTNESS);
             // Don't let applications turn the screen all the way off
            return Math.max(brightness, Power.BRIGHTNESS_DIM);
        } catch (SettingNotFoundException snfe) {
            return Power.BRIGHTNESS_ON;
        }
    }

    public boolean isScreenOn() {
        synchronized (mLocks) {
            return (mPowerState & SCREEN_ON_BIT) != 0;
        }
    }

    boolean isScreenBright() {
        synchronized (mLocks) {
            return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
        }
    }

    private boolean isScreenTurningOffLocked() {
        return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0);
    }

    private void forceUserActivityLocked() {
        if (isScreenTurningOffLocked()) {
            // cancel animation so userActivity will succeed
            mScreenBrightness.animating = false;
        }
        boolean savedActivityAllowed = mUserActivityAllowed;
        mUserActivityAllowed = true;
        userActivity(SystemClock.uptimeMillis(), false);
        mUserActivityAllowed = savedActivityAllowed;
    }

    public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        userActivity(time, noChangeLights, OTHER_EVENT, force);
    }

    public void userActivity(long time, boolean noChangeLights) {
        userActivity(time, noChangeLights, OTHER_EVENT, false);
    }

    public void userActivity(long time, boolean noChangeLights, int eventType) {
        userActivity(time, noChangeLights, eventType, false);
    }

    public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
        //mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);

        if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)
                && (eventType == CHEEK_EVENT || eventType == TOUCH_EVENT)) {
            if (false) {
                Log.d(TAG, "dropping cheek or short event mPokey=0x" + Integer.toHexString(mPokey));
            }
            return;
        }

        if (((mPokey & POKE_LOCK_IGNORE_TOUCH_AND_CHEEK_EVENTS) != 0)
                && (eventType == TOUCH_EVENT || eventType == TOUCH_UP_EVENT
                    || eventType == LONG_TOUCH_EVENT || eventType == CHEEK_EVENT)) {
            if (false) {
                Log.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
            }
            return;
        }

        if (false) {
            if (((mPokey & POKE_LOCK_IGNORE_CHEEK_EVENTS) != 0)) {
                Log.d(TAG, "userActivity !!!");//, new RuntimeException());
            } else {
                Log.d(TAG, "mPokey=0x" + Integer.toHexString(mPokey));
            }
        }

        synchronized (mLocks) {
            if (mSpew) {
                Log.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
                        + " mUserActivityAllowed=" + mUserActivityAllowed
                        + " mUserState=0x" + Integer.toHexString(mUserState)
                        + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
                        + " mProximitySensorActive=" + mProximitySensorActive
                        + " force=" + force);
            }
            // ignore user activity if we are in the process of turning off the screen
            if (isScreenTurningOffLocked()) {
                Log.d(TAG, "ignoring user activity while turning off screen");
                return;
            }
            if (mLastEventTime <= time || force) {
                mLastEventTime = time;
                if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
                    // Only turn on button backlights if a button was pressed
                    // and auto brightness is disabled
                    if (eventType == BUTTON_EVENT && !mUseSoftwareAutoBrightness) {
                        mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
                    } else {
                        // don't clear button/keyboard backlights when the screen is touched.
                        mUserState |= SCREEN_BRIGHT;
                    }

                    int uid = Binder.getCallingUid();
                    long ident = Binder.clearCallingIdentity();
                    try {
                        mBatteryStats.noteUserActivity(uid, eventType);
                    } catch (RemoteException e) {
                        // Ignore
                    } finally {
                        Binder.restoreCallingIdentity(ident);
                    }
                    
                    mWakeLockState = mLocks.reactivateScreenLocksLocked();
                    setPowerState(mUserState | mWakeLockState, noChangeLights, true);
                    setTimeoutLocked(time, SCREEN_BRIGHT);
                }
            }
        }
    }

    private int getAutoBrightnessValue(int sensorValue, int[] values) {
        try {
            int i;
            for (i = 0; i < mAutoBrightnessLevels.length; i++) {
                if (sensorValue < mAutoBrightnessLevels[i]) {
                    break;
                }
            }
            return values[i];
        } catch (Exception e) {
            // guard against null pointer or index out of bounds errors
            Log.e(TAG, "getAutoBrightnessValue", e);
            return 255;
        }
    }

    private Runnable mProximityTask = new Runnable() {
        public void run() {
            synchronized (mLocks) {
                if (mProximityPendingValue != -1) {
                    proximityChangedLocked(mProximityPendingValue == 1);
                    mProximityPendingValue = -1;
                }
            }
        }
    };

    private Runnable mAutoBrightnessTask = new Runnable() {
        public void run() {
            synchronized (mLocks) {
                int value = (int)mLightSensorPendingValue;
                if (value >= 0) {
                    mLightSensorPendingValue = -1;
                    lightSensorChangedLocked(value);
                }
            }
        }
    };

    private void lightSensorChangedLocked(int value) {
        if (mDebugLightSensor) {
            Log.d(TAG, "lightSensorChangedLocked " + value);
        }

        if (mLightSensorValue != value) {
            mLightSensorValue = value;
            if ((mPowerState & BATTERY_LOW_BIT) == 0) {
                int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
                int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
                int keyboardValue;
                if (mKeyboardVisible) {
                    keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
                } else {
                    keyboardValue = 0;
                }
                mLightSensorBrightness = lcdValue;

                if (mDebugLightSensor) {
                    Log.d(TAG, "lcdValue " + lcdValue);
                    Log.d(TAG, "buttonValue " + buttonValue);
                    Log.d(TAG, "keyboardValue " + keyboardValue);
                }

                boolean startAnimation = false;
                if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
                    if (ANIMATE_SCREEN_LIGHTS) {
                        if (mScreenBrightness.setTargetLocked(lcdValue,
                                AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_SCREEN_BRIGHTNESS,
                                (int)mScreenBrightness.curValue)) {
                            startAnimation = true;
                        }
                    } else {
                        int brightnessMode = (mAutoBrightessEnabled
                                            ? HardwareService.BRIGHTNESS_MODE_SENSOR
                                            : HardwareService.BRIGHTNESS_MODE_USER);
                        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT,
                                lcdValue, brightnessMode);
                    }
                }
                if (ANIMATE_BUTTON_LIGHTS) {
                    if (mButtonBrightness.setTargetLocked(buttonValue,
                            AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
                            (int)mButtonBrightness.curValue)) {
                        startAnimation = true;
                    }
                } else {
                    int brightnessMode = (mUseSoftwareAutoBrightness
                                        ? HardwareService.BRIGHTNESS_MODE_SENSOR
                                        : HardwareService.BRIGHTNESS_MODE_USER);
                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS,
                            buttonValue, brightnessMode);
                }
                if (ANIMATE_KEYBOARD_LIGHTS) {
                    if (mKeyboardBrightness.setTargetLocked(keyboardValue,
                            AUTOBRIGHTNESS_ANIM_STEPS, INITIAL_BUTTON_BRIGHTNESS,
                            (int)mKeyboardBrightness.curValue)) {
                        startAnimation = true;
                    }
                } else {
                    int brightnessMode = (mUseSoftwareAutoBrightness
                                        ? HardwareService.BRIGHTNESS_MODE_SENSOR
                                        : HardwareService.BRIGHTNESS_MODE_USER);
                    mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
                            keyboardValue, brightnessMode);
                }
                if (startAnimation) {
                    if (mDebugLightSensor) {
                        Log.i(TAG, "lightSensorChangedLocked scheduling light animator");
                    }
                    mHandler.removeCallbacks(mLightAnimator);
                    mHandler.post(mLightAnimator);
                }
            }
        }
    }

    /**
     * The user requested that we go to sleep (probably with the power button).
     * This overrides all wake locks that are held.
     */
    public void goToSleep(long time)
    {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        synchronized (mLocks) {
            goToSleepLocked(time);
        }
    }
    
    /**
     * Returns the time the screen has been on since boot, in millis.
     * @return screen on time
     */
    public long getScreenOnTime() {
        synchronized (mLocks) {
            if (mScreenOnStartTime == 0) {
                return mScreenOnTime;
            } else {
                return SystemClock.elapsedRealtime() - mScreenOnStartTime + mScreenOnTime;
            }
        }
    }

    private void goToSleepLocked(long time) {

        if (mLastEventTime <= time) {
            mLastEventTime = time;
            // cancel all of the wake locks
            mWakeLockState = SCREEN_OFF;
            int N = mLocks.size();
            int numCleared = 0;
            for (int i=0; i<N; i++) {
                WakeLock wl = mLocks.get(i);
                if (isScreenLock(wl.flags)) {
                    mLocks.get(i).activated = false;
                    numCleared++;
                }
            }
            EventLog.writeEvent(LOG_POWER_SLEEP_REQUESTED, numCleared);
            mStillNeedSleepNotification = true;
            mUserState = SCREEN_OFF;
            setPowerState(SCREEN_OFF, false, true);
            cancelTimerLocked();
        }
    }

    public long timeSinceScreenOn() {
        synchronized (mLocks) {
            if ((mPowerState & SCREEN_ON_BIT) != 0) {
                return 0;
            }
            return SystemClock.elapsedRealtime() - mScreenOffTime;
        }
    }
    
    public void setKeyboardVisibility(boolean visible) {
        synchronized (mLocks) {
            if (mSpew) {
                Log.d(TAG, "setKeyboardVisibility: " + visible);
            }
            if (mKeyboardVisible != visible) {
                mKeyboardVisible = visible;
                // don't signal user activity if the screen is off; other code
                // will take care of turning on due to a true change to the lid
                // switch and synchronized with the lock screen.
                if ((mPowerState & SCREEN_ON_BIT) != 0) {
                    if (mUseSoftwareAutoBrightness) {
                        // force recompute of backlight values
                        if (mLightSensorValue >= 0) {
                            int value = (int)mLightSensorValue;
                            mLightSensorValue = -1;
                            lightSensorChangedLocked(value);
                        }
                    }
                    userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
                }
            }
        }
    }

    /**
     * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
     * When disabling user activity we also reset user power state so the keyguard can reset its
     * short screen timeout when keyguard is unhidden.
     */
    public void enableUserActivity(boolean enabled) {
        if (mSpew) {
            Log.d(TAG, "enableUserActivity " + enabled);
        }
        synchronized (mLocks) {
            mUserActivityAllowed = enabled;
            if (!enabled) {
                // cancel timeout and clear mUserState so the keyguard can set a short timeout
                setTimeoutLocked(SystemClock.uptimeMillis(), 0);
            }
        }
    }

    private void setScreenBrightnessMode(int mode) {
        boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
        if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
            mAutoBrightessEnabled = enabled;
            if (isScreenOn()) {
                // force recompute of backlight values
                if (mLightSensorValue >= 0) {
                    int value = (int)mLightSensorValue;
                    mLightSensorValue = -1;
                    lightSensorChangedLocked(value);
                }
            }
        }
    }

    /** Sets the screen off timeouts:
     *      mKeylightDelay
     *      mDimDelay
     *      mScreenOffDelay
     * */
    private void setScreenOffTimeoutsLocked() {
        if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
            mKeylightDelay = mShortKeylightDelay;  // Configurable via Gservices
            mDimDelay = -1;
            mScreenOffDelay = 0;
        } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
            mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
            mDimDelay = -1;
            mScreenOffDelay = 0;
        } else {
            int totalDelay = mTotalDelaySetting;
            mKeylightDelay = LONG_KEYLIGHT_DELAY;
            if (totalDelay < 0) {
                mScreenOffDelay = Integer.MAX_VALUE;
            } else if (mKeylightDelay < totalDelay) {
                // subtract the time that the keylight delay. This will give us the
                // remainder of the time that we need to sleep to get the accurate
                // screen off timeout.
                mScreenOffDelay = totalDelay - mKeylightDelay;
            } else {
                mScreenOffDelay = 0;
            }
            if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
                mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
                mScreenOffDelay = LONG_DIM_TIME;
            } else {
                mDimDelay = -1;
            }
        }
        if (mSpew) {
            Log.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
                    + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
                    + " mDimScreen=" + mDimScreen);
        }
    }

    /**
     * Refreshes cached Gservices settings.  Called once on startup, and
     * on subsequent Settings.Gservices.CHANGED_ACTION broadcasts (see
     * GservicesChangedReceiver).
     */
    private void updateGservicesValues() {
        mShortKeylightDelay = Settings.Gservices.getInt(
                mContext.getContentResolver(),
                Settings.Gservices.SHORT_KEYLIGHT_DELAY_MS,
                SHORT_KEYLIGHT_DELAY_DEFAULT);
        // Log.i(TAG, "updateGservicesValues(): mShortKeylightDelay now " + mShortKeylightDelay);
    }

    /**
     * Receiver for the Gservices.CHANGED_ACTION broadcast intent,
     * which tells us we need to refresh our cached Gservices settings.
     */
    private class GservicesChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Log.i(TAG, "GservicesChangedReceiver.onReceive(): " + intent);
            updateGservicesValues();
        }
    }

    private class LockList extends ArrayList<WakeLock>
    {
        void addLock(WakeLock wl)
        {
            int index = getIndex(wl.binder);
            if (index < 0) {
                this.add(wl);
            }
        }

        WakeLock removeLock(IBinder binder)
        {
            int index = getIndex(binder);
            if (index >= 0) {
                return this.remove(index);
            } else {
                return null;
            }
        }

        int getIndex(IBinder binder)
        {
            int N = this.size();
            for (int i=0; i<N; i++) {
                if (this.get(i).binder == binder) {
                    return i;
                }
            }
            return -1;
        }

        int gatherState()
        {
            int result = 0;
            int N = this.size();
            for (int i=0; i<N; i++) {
                WakeLock wl = this.get(i);
                if (wl.activated) {
                    if (isScreenLock(wl.flags)) {
                        result |= wl.minState;
                    }
                }
            }
            return result;
        }
        
        int reactivateScreenLocksLocked()
        {
            int result = 0;
            int N = this.size();
            for (int i=0; i<N; i++) {
                WakeLock wl = this.get(i);
                if (isScreenLock(wl.flags)) {
                    wl.activated = true;
                    result |= wl.minState;
                }
            }
            return result;
        }
    }

    void setPolicy(WindowManagerPolicy p) {
        synchronized (mLocks) {
            mPolicy = p;
            mLocks.notifyAll();
        }
    }

    WindowManagerPolicy getPolicyLocked() {
        while (mPolicy == null || !mDoneBooting) {
            try {
                mLocks.wait();
            } catch (InterruptedException e) {
                // Ignore
            }
        }
        return mPolicy;
    }
    
    void systemReady() {
        mSensorManager = new SensorManager(mHandlerThread.getLooper());
        mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        // don't bother with the light sensor if auto brightness is handled in hardware
        if (mUseSoftwareAutoBrightness) {
            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
            enableLightSensor(true);
        }

        synchronized (mLocks) {
            Log.d(TAG, "system ready!");
            mDoneBooting = true;
            long identity = Binder.clearCallingIdentity();
            try {
                mBatteryStats.noteScreenBrightness(getPreferredBrightness());
                mBatteryStats.noteScreenOn();
            } catch (RemoteException e) {
                // Nothing interesting to do.
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
            updateWakeLockLocked();
            mLocks.notifyAll();
        }
    }

    public void monitor() {
        synchronized (mLocks) { }
    }

    public int getSupportedWakeLockFlags() {
        int result = PowerManager.PARTIAL_WAKE_LOCK
                   | PowerManager.FULL_WAKE_LOCK
                   | PowerManager.SCREEN_DIM_WAKE_LOCK;

        if (mProximitySensor != null) {
            result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
        }

        return result;
    }

    public void setBacklightBrightness(int brightness) {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
        // Don't let applications turn the screen all the way off
        brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, brightness,
                HardwareService.BRIGHTNESS_MODE_USER);
        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD,
            (mKeyboardVisible ? brightness : 0), HardwareService.BRIGHTNESS_MODE_USER);
        mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, brightness,
            HardwareService.BRIGHTNESS_MODE_USER);
        long identity = Binder.clearCallingIdentity();
        try {
            mBatteryStats.noteScreenBrightness(brightness);
        } catch (RemoteException e) {
            Log.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }

        // update our animation state
        if (ANIMATE_SCREEN_LIGHTS) {
            mScreenBrightness.curValue = brightness;
            mScreenBrightness.animating = false;
            mScreenBrightness.targetValue = -1;
        }
        if (ANIMATE_KEYBOARD_LIGHTS) {
            mKeyboardBrightness.curValue = brightness;
            mKeyboardBrightness.animating = false;
            mKeyboardBrightness.targetValue = -1;
        }
        if (ANIMATE_BUTTON_LIGHTS) {
            mButtonBrightness.curValue = brightness;
            mButtonBrightness.animating = false;
            mButtonBrightness.targetValue = -1;
        }
    }

    private void enableProximityLockLocked() {
        if (mDebugProximitySensor) {
            Log.d(TAG, "enableProximityLockLocked");
        }
        if (!mProximitySensorEnabled) {
            // clear calling identity so sensor manager battery stats are accurate
            long identity = Binder.clearCallingIdentity();
            try {
                mSensorManager.registerListener(mProximityListener, mProximitySensor,
                        SensorManager.SENSOR_DELAY_NORMAL);
                mProximitySensorEnabled = true;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private void disableProximityLockLocked() {
        if (mDebugProximitySensor) {
            Log.d(TAG, "disableProximityLockLocked");
        }
        if (mProximitySensorEnabled) {
            // clear calling identity so sensor manager battery stats are accurate
            long identity = Binder.clearCallingIdentity();
            try {
                mSensorManager.unregisterListener(mProximityListener);
                mHandler.removeCallbacks(mProximityTask);
                mProximitySensorEnabled = false;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
            if (mProximitySensorActive) {
                mProximitySensorActive = false;
                forceUserActivityLocked();
            }
        }
    }

    private void proximityChangedLocked(boolean active) {
        if (mDebugProximitySensor) {
            Log.d(TAG, "proximityChangedLocked, active: " + active);
        }
        if (!mProximitySensorEnabled) {
            Log.d(TAG, "Ignoring proximity change after sensor is disabled");
            return;
        }
        if (active) {
            goToSleepLocked(SystemClock.uptimeMillis());
            mProximitySensorActive = true;
        } else {
            // proximity sensor negative events trigger as user activity.
            // temporarily set mUserActivityAllowed to true so this will work
            // even when the keyguard is on.
            mProximitySensorActive = false;
            forceUserActivityLocked();

            if (mProximityWakeLockCount == 0) {
                // disable sensor if we have no listeners left after proximity negative
                disableProximityLockLocked();
            }
        }
    }

    private void enableLightSensor(boolean enable) {
        if (mDebugLightSensor) {
            Log.d(TAG, "enableLightSensor " + enable);
        }
        if (mSensorManager != null && mLightSensorEnabled != enable) {
            mLightSensorEnabled = enable;
            // clear calling identity so sensor manager battery stats are accurate
            long identity = Binder.clearCallingIdentity();
            try {
                if (enable) {
                    mSensorManager.registerListener(mLightListener, mLightSensor,
                            SensorManager.SENSOR_DELAY_NORMAL);
                } else {
                    mSensorManager.unregisterListener(mLightListener);
                    mHandler.removeCallbacks(mAutoBrightnessTask);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    SensorEventListener mProximityListener = new SensorEventListener() {
        public void onSensorChanged(SensorEvent event) {
            long milliseconds = SystemClock.elapsedRealtime();
            synchronized (mLocks) {
                float distance = event.values[0];
                long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
                mLastProximityEventTime = milliseconds;
                mHandler.removeCallbacks(mProximityTask);

                // compare against getMaximumRange to support sensors that only return 0 or 1
                boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
                        distance < mProximitySensor.getMaximumRange());

                if (mDebugProximitySensor) {
                    Log.d(TAG, "mProximityListener.onSensorChanged active: " + active);
                }
                if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
                    // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
                    mProximityPendingValue = (active ? 1 : 0);
                    mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
                } else {
                    // process the value immediately
                    mProximityPendingValue = -1;
                    proximityChangedLocked(active);
                }
            }
        }

        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // ignore
        }
    };

    SensorEventListener mLightListener = new SensorEventListener() {
        public void onSensorChanged(SensorEvent event) {
            synchronized (mLocks) {
                // ignore light sensor while screen is turning off
                if (isScreenTurningOffLocked()) {
                    return;
                }

                int value = (int)event.values[0];
                long milliseconds = SystemClock.elapsedRealtime();
                if (mDebugLightSensor) {
                    Log.d(TAG, "onSensorChanged: light value: " + value);
                }
                mHandler.removeCallbacks(mAutoBrightnessTask);
                if (mLightSensorValue != value) {
                    if (mLightSensorValue == -1 ||
                            milliseconds < mLastScreenOnTime + mLightSensorWarmupTime) {
                        // process the value immediately if screen has just turned on
                        lightSensorChangedLocked(value);
                    } else {
                        // delay processing to debounce the sensor
                        mLightSensorPendingValue = value;
                        mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
                    }
                } else {
                    mLightSensorPendingValue = -1;
                }
            }
        }

        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // ignore
        }
    };
}
