Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6da89844 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am 12b9c2d6: Merge "Fix issue #23214751: Get a GPS fix before going in to doze" into mnc-dev

* commit '12b9c2d6':
  Fix issue #23214751: Get a GPS fix before going in to doze
parents b16cd62c 12b9c2d6
Loading
Loading
Loading
Loading
+19 −14
Original line number Original line Diff line number Diff line
@@ -16,9 +16,6 @@


package com.android.server;
package com.android.server;


import android.app.AlarmManager;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorEventListener;
@@ -85,17 +82,12 @@ public class AnyMotionDetector {
    /** The accelerometer sampling interval. */
    /** The accelerometer sampling interval. */
    private static final int SAMPLING_INTERVAL_MILLIS = 40;
    private static final int SAMPLING_INTERVAL_MILLIS = 40;


    private AlarmManager mAlarmManager;
    private final Handler mHandler;
    private final Handler mHandler;
    private Intent mAlarmIntent;
    private final Object mLock = new Object();
    private final Object mLock = new Object();
    private Sensor mAccelSensor;
    private Sensor mAccelSensor;
    private SensorManager mSensorManager;
    private SensorManager mSensorManager;
    private PowerManager.WakeLock mWakeLock;
    private PowerManager.WakeLock mWakeLock;


    /** The time when detection was last performed. */
    private long mDetectionStartTime;

    /** The minimum number of samples required to detect AnyMotion. */
    /** The minimum number of samples required to detect AnyMotion. */
    private int mNumSufficientSamples;
    private int mNumSufficientSamples;


@@ -113,11 +105,11 @@ public class AnyMotionDetector {


    private DeviceIdleCallback mCallback = null;
    private DeviceIdleCallback mCallback = null;


    public AnyMotionDetector(AlarmManager am, PowerManager pm, Handler handler, SensorManager sm,
    public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm,
            DeviceIdleCallback callback) {
            DeviceIdleCallback callback) {
        if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
        if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated.");
        mAlarmManager = am;
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
        mWakeLock.setReferenceCounted(false);
        mHandler = handler;
        mHandler = handler;
        mSensorManager = sm;
        mSensorManager = sm;
        mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
@@ -144,6 +136,22 @@ public class AnyMotionDetector {
        }
        }
    }
    }


    public void stop() {
        if (mState == STATE_ACTIVE) {
            mState = STATE_INACTIVE;
            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE.");
            if (mMeasurementInProgress) {
                mMeasurementInProgress = false;
                mSensorManager.unregisterListener(mListener);
            }
            mHandler.removeCallbacks(mMeasurementTimeout);
            mHandler.removeCallbacks(mSensorRestart);
            mWakeLock.release();
            mCurrentGravityVector = null;
            mPreviousGravityVector = null;
        }
    }

    private void startOrientationMeasurement() {
    private void startOrientationMeasurement() {
        if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
        if (DEBUG) Slog.d(TAG, "startOrientationMeasurement: mMeasurementInProgress=" +
            mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
            mMeasurementInProgress + ", (mAccelSensor != null)=" + (mAccelSensor != null));
@@ -153,7 +161,6 @@ public class AnyMotionDetector {
                    SAMPLING_INTERVAL_MILLIS * 1000)) {
                    SAMPLING_INTERVAL_MILLIS * 1000)) {
                mWakeLock.acquire();
                mWakeLock.acquire();
                mMeasurementInProgress = true;
                mMeasurementInProgress = true;
                mDetectionStartTime = SystemClock.elapsedRealtime();
                mRunningStats.reset();
                mRunningStats.reset();
            }
            }


@@ -170,9 +177,7 @@ public class AnyMotionDetector {
        if (mMeasurementInProgress) {
        if (mMeasurementInProgress) {
            mSensorManager.unregisterListener(mListener);
            mSensorManager.unregisterListener(mListener);
            mHandler.removeCallbacks(mMeasurementTimeout);
            mHandler.removeCallbacks(mMeasurementTimeout);
            if (mWakeLock.isHeld()) {
            mWakeLock.release();
            mWakeLock.release();
            }
            long detectionEndTime = SystemClock.elapsedRealtime();
            long detectionEndTime = SystemClock.elapsedRealtime();
            mMeasurementInProgress = false;
            mMeasurementInProgress = false;
            mPreviousGravityVector = mCurrentGravityVector;
            mPreviousGravityVector = mCurrentGravityVector;
+225 −36
Original line number Original line Diff line number Diff line
@@ -34,10 +34,15 @@ import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.hardware.TriggerEventListener;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager;
import android.location.LocationRequest;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.INetworkPolicyManager;
import android.net.INetworkPolicyManager;
import android.net.Uri;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Binder;
import android.os.Bundle;
import android.os.Environment;
import android.os.Environment;
import android.os.FileUtils;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Handler;
@@ -107,6 +112,8 @@ public class DeviceIdleController extends SystemService
    private DisplayManager mDisplayManager;
    private DisplayManager mDisplayManager;
    private SensorManager mSensorManager;
    private SensorManager mSensorManager;
    private Sensor mSigMotionSensor;
    private Sensor mSigMotionSensor;
    private LocationManager mLocationManager;
    private LocationRequest mLocationRequest;
    private PendingIntent mSensingAlarmIntent;
    private PendingIntent mSensingAlarmIntent;
    private PendingIntent mAlarmIntent;
    private PendingIntent mAlarmIntent;
    private Intent mIdleIntent;
    private Intent mIdleIntent;
@@ -117,6 +124,13 @@ public class DeviceIdleController extends SystemService
    private boolean mScreenOn;
    private boolean mScreenOn;
    private boolean mCharging;
    private boolean mCharging;
    private boolean mSigMotionActive;
    private boolean mSigMotionActive;
    private boolean mSensing;
    private boolean mNotMoving;
    private boolean mLocating;
    private boolean mLocated;
    private boolean mHaveGps;
    private Location mLastGenericLocation;
    private Location mLastGpsLocation;


    /** Device is currently active. */
    /** Device is currently active. */
    private static final int STATE_ACTIVE = 0;
    private static final int STATE_ACTIVE = 0;
@@ -126,16 +140,19 @@ public class DeviceIdleController extends SystemService
    private static final int STATE_IDLE_PENDING = 2;
    private static final int STATE_IDLE_PENDING = 2;
    /** Device is currently sensing motion. */
    /** Device is currently sensing motion. */
    private static final int STATE_SENSING = 3;
    private static final int STATE_SENSING = 3;
    /** Device is currently finding location (and may still be sensing). */
    private static final int STATE_LOCATING = 4;
    /** Device is in the idle state, trying to stay asleep as much as possible. */
    /** Device is in the idle state, trying to stay asleep as much as possible. */
    private static final int STATE_IDLE = 4;
    private static final int STATE_IDLE = 5;
    /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
    /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
    private static final int STATE_IDLE_MAINTENANCE = 5;
    private static final int STATE_IDLE_MAINTENANCE = 6;
    private static String stateToString(int state) {
    private static String stateToString(int state) {
        switch (state) {
        switch (state) {
            case STATE_ACTIVE: return "ACTIVE";
            case STATE_ACTIVE: return "ACTIVE";
            case STATE_INACTIVE: return "INACTIVE";
            case STATE_INACTIVE: return "INACTIVE";
            case STATE_IDLE_PENDING: return "IDLE_PENDING";
            case STATE_IDLE_PENDING: return "IDLE_PENDING";
            case STATE_SENSING: return "SENSING";
            case STATE_SENSING: return "SENSING";
            case STATE_LOCATING: return "LOCATING";
            case STATE_IDLE: return "IDLE";
            case STATE_IDLE: return "IDLE";
            case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
            case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
            default: return Integer.toString(state);
            default: return Integer.toString(state);
@@ -258,6 +275,48 @@ public class DeviceIdleController extends SystemService
        }
        }
    };
    };


    private final LocationListener mGenericLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            synchronized (DeviceIdleController.this) {
                receivedGenericLocationLocked(location);
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };

    private final LocationListener mGpsLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            synchronized (DeviceIdleController.this) {
                receivedGpsLocationLocked(location);
            }
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
        }

        @Override
        public void onProviderEnabled(String provider) {
        }

        @Override
        public void onProviderDisabled(String provider) {
        }
    };

    /**
    /**
     * All times are in milliseconds. These constants are kept synchronized with the system
     * All times are in milliseconds. These constants are kept synchronized with the system
     * global Settings. Any access to this class or its fields should be done while
     * global Settings. Any access to this class or its fields should be done while
@@ -267,6 +326,8 @@ public class DeviceIdleController extends SystemService
        // Key names stored in the settings value.
        // Key names stored in the settings value.
        private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
        private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
        private static final String KEY_SENSING_TIMEOUT = "sensing_to";
        private static final String KEY_SENSING_TIMEOUT = "sensing_to";
        private static final String KEY_LOCATING_TIMEOUT = "locating_to";
        private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
        private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
        private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
        private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
        private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
        private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
        private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
@@ -294,7 +355,8 @@ public class DeviceIdleController extends SystemService
        public long INACTIVE_TIMEOUT;
        public long INACTIVE_TIMEOUT;


        /**
        /**
         * If we don't receive a callback from AnyMotion in this amount of time, we will change from
         * If we don't receive a callback from AnyMotion in this amount of time +
         * {@link #LOCATING_TIMEOUT}, we will change from
         * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
         * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
         * will be ignored.
         * will be ignored.
         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
@@ -302,6 +364,23 @@ public class DeviceIdleController extends SystemService
         */
         */
        public long SENSING_TIMEOUT;
        public long SENSING_TIMEOUT;


        /**
         * This is how long we will wait to try to get a good location fix before going in to
         * idle mode.
         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
         * @see #KEY_LOCATING_TIMEOUT
         */
        public long LOCATING_TIMEOUT;

        /**
         * The desired maximum accuracy (in meters) we consider the location to be good enough to go
         * on to idle.  We will be trying to get an accuracy fix at least this good or until
         * {@link #LOCATING_TIMEOUT} expires.
         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
         * @see #KEY_LOCATION_ACCURACY
         */
        public float LOCATION_ACCURACY;

        /**
        /**
         * This is the time, after seeing motion, that we wait after becoming inactive from
         * This is the time, after seeing motion, that we wait after becoming inactive from
         * that until we start looking for motion again.
         * that until we start looking for motion again.
@@ -423,7 +502,10 @@ public class DeviceIdleController extends SystemService
                INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
                INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
                        !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
                        !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
                SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
                SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
                        !DEBUG ? 5 * 60 * 1000L : 60 * 1000L);
                        !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
                LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
                        !DEBUG ? 30 * 1000L : 15 * 1000L);
                LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
                MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
                MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
                IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
                IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
@@ -462,6 +544,14 @@ public class DeviceIdleController extends SystemService
            TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
            TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
            pw.println();
            pw.println();


            pw.print("    "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
            TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
            pw.println();

            pw.print("    "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
            pw.print(LOCATION_ACCURACY); pw.print("m");
            pw.println();

            pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
            pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
            TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
            TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
            pw.println();
            pw.println();
@@ -515,17 +605,27 @@ public class DeviceIdleController extends SystemService
    @Override
    @Override
    public void onAnyMotionResult(int result) {
    public void onAnyMotionResult(int result) {
        if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
        if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
        if (mState == STATE_SENSING) {
        if (result == AnyMotionDetector.RESULT_MOVED) {
            if (result == AnyMotionDetector.RESULT_STATIONARY) {
            if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
            synchronized (this) {
                handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
            }
        } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
            if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
            if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
            if (mState == STATE_SENSING) {
                // If we are currently sensing, it is time to move to locating.
                synchronized (this) {
                synchronized (this) {
                    mNotMoving = true;
                    stepIdleStateLocked();
                    stepIdleStateLocked();
                }
                }
            } else if (result == AnyMotionDetector.RESULT_MOVED) {
            } else if (mState == STATE_LOCATING) {
                if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
                // If we are currently locating, note that we are not moving and step
                // if we have located the position.
                synchronized (this) {
                synchronized (this) {
                    EventLogTags.writeDeviceIdle(mState, "sense_moved");
                    mNotMoving = true;
                    enterInactiveStateLocked();
                    if (mLocated) {
                        stepIdleStateLocked();
                    }
                }
                }
            }
            }
        }
        }
@@ -783,8 +883,14 @@ public class DeviceIdleController extends SystemService
                        Context.DISPLAY_SERVICE);
                        Context.DISPLAY_SERVICE);
                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
                mLocationManager = (LocationManager) getContext().getSystemService(
                        Context.LOCATION_SERVICE);
                mLocationRequest = new LocationRequest()
                    .setQuality(LocationRequest.ACCURACY_FINE)
                    .setInterval(0)
                    .setFastestInterval(0)
                    .setNumUpdates(1);
                mAnyMotionDetector = new AnyMotionDetector(
                mAnyMotionDetector = new AnyMotionDetector(
                        mAlarmManager,
                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
                        mHandler, mSensorManager, this);
                        mHandler, mSensorManager, this);


@@ -1049,7 +1155,7 @@ public class DeviceIdleController extends SystemService
        // We consider any situation where the display is showing something to be it on,
        // We consider any situation where the display is showing something to be it on,
        // because if there is anything shown we are going to be updating it at some
        // because if there is anything shown we are going to be updating it at some
        // frequency so can't be allowed to go into deep sleeps.
        // frequency so can't be allowed to go into deep sleeps.
        boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;;
        boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
        if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
        if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
        if (!screenOn && mScreenOn) {
        if (!screenOn && mScreenOn) {
            mScreenOn = false;
            mScreenOn = false;
@@ -1092,10 +1198,7 @@ public class DeviceIdleController extends SystemService
            scheduleReportActiveLocked(activeReason, activeUid);
            scheduleReportActiveLocked(activeReason, activeUid);
            mState = STATE_ACTIVE;
            mState = STATE_ACTIVE;
            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
            mNextIdlePendingDelay = 0;
            resetIdleManagementLocked();
            mNextIdleDelay = 0;
            cancelAlarmLocked();
            stopMonitoringSignificantMotion();
        }
        }
    }
    }


@@ -1106,20 +1209,20 @@ public class DeviceIdleController extends SystemService
            // waiting to see if we will ultimately go idle.
            // waiting to see if we will ultimately go idle.
            mState = STATE_INACTIVE;
            mState = STATE_INACTIVE;
            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
            mNextIdlePendingDelay = 0;
            resetIdleManagementLocked();
            mNextIdleDelay = 0;
            scheduleAlarmLocked(mInactiveTimeout, false);
            scheduleAlarmLocked(mInactiveTimeout, false);
            EventLogTags.writeDeviceIdle(mState, "no activity");
            EventLogTags.writeDeviceIdle(mState, "no activity");
        }
        }
    }
    }


    /**
    void resetIdleManagementLocked() {
     * This is called when we've failed to receive a callback from AnyMotionDetector
        mNextIdlePendingDelay = 0;
     * within the DEFAULT_SENSING_TIMEOUT, to return to STATE_INACTIVE.
        mNextIdleDelay = 0;
     */
        cancelAlarmLocked();
    void enterInactiveStateLocked() {
        cancelSensingAlarmLocked();
        mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
        cancelLocatingLocked();
        becomeInactiveIfAppropriateLocked();
        stopMonitoringSignificantMotion();
        mAnyMotionDetector.stop();
    }
    }


    void exitForceIdleLocked() {
    void exitForceIdleLocked() {
@@ -1160,11 +1263,37 @@ public class DeviceIdleController extends SystemService
            case STATE_IDLE_PENDING:
            case STATE_IDLE_PENDING:
                mState = STATE_SENSING;
                mState = STATE_SENSING;
                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
                EventLogTags.writeDeviceIdle(mState, "step");
                scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
                scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
                cancelSensingAlarmLocked();
                cancelLocatingLocked();
                mAnyMotionDetector.checkForAnyMotion();
                mAnyMotionDetector.checkForAnyMotion();
                mNotMoving = false;
                mLocated = false;
                mLastGenericLocation = null;
                mLastGpsLocation = null;
                break;
                break;
            case STATE_SENSING:
            case STATE_SENSING:
                mState = STATE_LOCATING;
                if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
                EventLogTags.writeDeviceIdle(mState, "step");
                cancelSensingAlarmLocked();
                cancelSensingAlarmLocked();
                scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
                mLocating = true;
                mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
                        mHandler.getLooper());
                if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
                    mHaveGps = true;
                    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
                            mGpsLocationListener, mHandler.getLooper());
                } else {
                    mHaveGps = false;
                }
                break;
            case STATE_LOCATING:
                cancelSensingAlarmLocked();
                cancelLocatingLocked();
                mAnyMotionDetector.stop();
            case STATE_IDLE_MAINTENANCE:
            case STATE_IDLE_MAINTENANCE:
                scheduleAlarmLocked(mNextIdleDelay, true);
                scheduleAlarmLocked(mNextIdleDelay, true);
                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
@@ -1173,6 +1302,7 @@ public class DeviceIdleController extends SystemService
                if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
                if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
                mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
                mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
                mState = STATE_IDLE;
                mState = STATE_IDLE;
                EventLogTags.writeDeviceIdle(mState, "step");
                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
                break;
                break;
            case STATE_IDLE:
            case STATE_IDLE:
@@ -1193,18 +1323,54 @@ public class DeviceIdleController extends SystemService
        if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
        if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
        // When the sensor goes off, its trigger is automatically removed.
        // When the sensor goes off, its trigger is automatically removed.
        mSigMotionActive = false;
        mSigMotionActive = false;
        handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
    }

    void handleMotionDetectedLocked(long timeout, String type) {
        // The device is not yet active, so we want to go back to the pending idle
        // The device is not yet active, so we want to go back to the pending idle
        // state to wait again for no motion.  Note that we only monitor for significant
        // state to wait again for no motion.  Note that we only monitor for significant
        // motion after moving out of the inactive state, so no need to worry about that.
        // motion after moving out of the inactive state, so no need to worry about that.
        if (mState != STATE_ACTIVE) {
        if (mState != STATE_ACTIVE) {
            scheduleReportActiveLocked("motion", Process.myUid());
            scheduleReportActiveLocked(type, Process.myUid());
            mState = STATE_ACTIVE;
            mState = STATE_ACTIVE;
            mInactiveTimeout = mConstants.MOTION_INACTIVE_TIMEOUT;
            mInactiveTimeout = timeout;
            EventLogTags.writeDeviceIdle(mState, "motion");
            EventLogTags.writeDeviceIdle(mState, type);
            becomeInactiveIfAppropriateLocked();
            becomeInactiveIfAppropriateLocked();
        }
        }
    }
    }


    void receivedGenericLocationLocked(Location location) {
        if (mState != STATE_LOCATING) {
            cancelLocatingLocked();
            return;
        }
        if (DEBUG) Slog.d(TAG, "Generic location: " + location);
        mLastGenericLocation = new Location(location);
        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) {
            return;
        }
        mLocated = true;
        if (mNotMoving) {
            stepIdleStateLocked();
        }
    }

    void receivedGpsLocationLocked(Location location) {
        if (mState != STATE_LOCATING) {
            cancelLocatingLocked();
            return;
        }
        if (DEBUG) Slog.d(TAG, "GPS location: " + location);
        mLastGpsLocation = new Location(location);
        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
            return;
        }
        mLocated = true;
        if (mNotMoving) {
            stepIdleStateLocked();
        }
    }

    void startMonitoringSignificantMotion() {
    void startMonitoringSignificantMotion() {
        if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
        if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
        if (mSigMotionSensor != null && !mSigMotionActive) {
        if (mSigMotionSensor != null && !mSigMotionActive) {
@@ -1229,8 +1395,19 @@ public class DeviceIdleController extends SystemService
    }
    }


    void cancelSensingAlarmLocked() {
    void cancelSensingAlarmLocked() {
        if (mSensing) {
            if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
            if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
            mAlarmManager.cancel(mSensingAlarmIntent);
            mAlarmManager.cancel(mSensingAlarmIntent);
            mSensing = false;
        }
    }

    void cancelLocatingLocked() {
        if (mLocating) {
            mLocationManager.removeUpdates(mGenericLocationListener);
            mLocationManager.removeUpdates(mGpsLocationListener);
            mLocating = false;
        }
    }
    }


    void scheduleAlarmLocked(long delay, boolean idleUntil) {
    void scheduleAlarmLocked(long delay, boolean idleUntil) {
@@ -1254,9 +1431,11 @@ public class DeviceIdleController extends SystemService


    void scheduleSensingAlarmLocked(long delay) {
    void scheduleSensingAlarmLocked(long delay) {
        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
        cancelSensingAlarmLocked();
        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
            mNextAlarmTime, mSensingAlarmIntent);
            mNextAlarmTime, mSensingAlarmIntent);
        mSensing = true;
    }
    }


    private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
    private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
@@ -1721,6 +1900,16 @@ public class DeviceIdleController extends SystemService
            pw.print("  mScreenOn="); pw.println(mScreenOn);
            pw.print("  mScreenOn="); pw.println(mScreenOn);
            pw.print("  mCharging="); pw.println(mCharging);
            pw.print("  mCharging="); pw.println(mCharging);
            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
            pw.print("  mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
                    pw.println(mNotMoving);
            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHaveGps=");
                    pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated);
            if (mLastGenericLocation != null) {
                pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
            }
            if (mLastGpsLocation != null) {
                pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
            }
            pw.print("  mState="); pw.println(stateToString(mState));
            pw.print("  mState="); pw.println(stateToString(mState));
            pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
            pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
            pw.println();
            pw.println();