DeviceIdleController.java revision 4cb96ca45f3334f49ebe23359001b7a636a1973b
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.Manifest;
20import android.app.ActivityManagerNative;
21import android.app.AlarmManager;
22import android.content.BroadcastReceiver;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.PackageManager;
29import android.content.pm.PackageManager.NameNotFoundException;
30import android.database.ContentObserver;
31import android.hardware.Sensor;
32import android.hardware.SensorManager;
33import android.hardware.SensorEvent;
34import android.hardware.SensorEventListener;
35import android.hardware.TriggerEvent;
36import android.hardware.TriggerEventListener;
37import android.hardware.display.DisplayManager;
38import android.location.LocationRequest;
39import android.location.Location;
40import android.location.LocationListener;
41import android.location.LocationManager;
42import android.net.ConnectivityManager;
43import android.net.INetworkPolicyManager;
44import android.net.NetworkInfo;
45import android.net.Uri;
46import android.os.BatteryStats;
47import android.os.Binder;
48import android.os.Bundle;
49import android.os.Environment;
50import android.os.FileUtils;
51import android.os.Handler;
52import android.os.IBinder;
53import android.os.IDeviceIdleController;
54import android.os.IMaintenanceActivityListener;
55import android.os.Looper;
56import android.os.Message;
57import android.os.PowerManager;
58import android.os.PowerManagerInternal;
59import android.os.Process;
60import android.os.RemoteCallbackList;
61import android.os.RemoteException;
62import android.os.ResultReceiver;
63import android.os.ServiceManager;
64import android.os.ShellCommand;
65import android.os.SystemClock;
66import android.os.UserHandle;
67import android.provider.Settings;
68import android.util.ArrayMap;
69import android.util.ArraySet;
70import android.util.KeyValueListParser;
71import android.util.MutableLong;
72import android.util.Pair;
73import android.util.Slog;
74import android.util.SparseArray;
75import android.util.SparseBooleanArray;
76import android.util.TimeUtils;
77import android.util.Xml;
78import android.view.Display;
79
80import com.android.internal.app.IBatteryStats;
81import com.android.internal.os.AtomicFile;
82import com.android.internal.os.BackgroundThread;
83import com.android.internal.util.FastXmlSerializer;
84import com.android.internal.util.XmlUtils;
85import com.android.server.am.BatteryStatsService;
86
87import org.xmlpull.v1.XmlPullParser;
88import org.xmlpull.v1.XmlPullParserException;
89import org.xmlpull.v1.XmlSerializer;
90
91import java.io.ByteArrayOutputStream;
92import java.io.File;
93import java.io.FileDescriptor;
94import java.io.FileInputStream;
95import java.io.FileNotFoundException;
96import java.io.FileOutputStream;
97import java.io.IOException;
98import java.io.PrintWriter;
99import java.nio.charset.StandardCharsets;
100import java.util.Arrays;
101
102/**
103 * Keeps track of device idleness and drives low power mode based on that.
104 */
105public class DeviceIdleController extends SystemService
106        implements AnyMotionDetector.DeviceIdleCallback {
107    private static final String TAG = "DeviceIdleController";
108
109    private static final boolean DEBUG = false;
110
111    private static final boolean COMPRESS_TIME = false;
112
113    private static final int EVENT_BUFFER_SIZE = 100;
114
115    private AlarmManager mAlarmManager;
116    private IBatteryStats mBatteryStats;
117    private PowerManagerInternal mLocalPowerManager;
118    private PowerManager mPowerManager;
119    private ConnectivityService mConnectivityService;
120    private AlarmManagerService.LocalService mLocalAlarmManager;
121    private INetworkPolicyManager mNetworkPolicyManager;
122    private DisplayManager mDisplayManager;
123    private SensorManager mSensorManager;
124    private Sensor mMotionSensor;
125    private LocationManager mLocationManager;
126    private LocationRequest mLocationRequest;
127    private Intent mIdleIntent;
128    private Intent mLightIdleIntent;
129    private Display mCurDisplay;
130    private AnyMotionDetector mAnyMotionDetector;
131    private boolean mLightEnabled;
132    private boolean mDeepEnabled;
133    private boolean mForceIdle;
134    private boolean mNetworkConnected;
135    private boolean mScreenOn;
136    private boolean mCharging;
137    private boolean mNotMoving;
138    private boolean mLocating;
139    private boolean mLocated;
140    private boolean mHasGps;
141    private boolean mHasNetworkLocation;
142    private Location mLastGenericLocation;
143    private Location mLastGpsLocation;
144
145    /** Device is currently active. */
146    private static final int STATE_ACTIVE = 0;
147    /** Device is inactive (screen off, no motion) and we are waiting to for idle. */
148    private static final int STATE_INACTIVE = 1;
149    /** Device is past the initial inactive period, and waiting for the next idle period. */
150    private static final int STATE_IDLE_PENDING = 2;
151    /** Device is currently sensing motion. */
152    private static final int STATE_SENSING = 3;
153    /** Device is currently finding location (and may still be sensing). */
154    private static final int STATE_LOCATING = 4;
155    /** Device is in the idle state, trying to stay asleep as much as possible. */
156    private static final int STATE_IDLE = 5;
157    /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
158    private static final int STATE_IDLE_MAINTENANCE = 6;
159    private static String stateToString(int state) {
160        switch (state) {
161            case STATE_ACTIVE: return "ACTIVE";
162            case STATE_INACTIVE: return "INACTIVE";
163            case STATE_IDLE_PENDING: return "IDLE_PENDING";
164            case STATE_SENSING: return "SENSING";
165            case STATE_LOCATING: return "LOCATING";
166            case STATE_IDLE: return "IDLE";
167            case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
168            default: return Integer.toString(state);
169        }
170    }
171
172    /** Device is currently active. */
173    private static final int LIGHT_STATE_ACTIVE = 0;
174    /** Device is inactive (screen off) and we are waiting to for the first light idle. */
175    private static final int LIGHT_STATE_INACTIVE = 1;
176    /** Device is about to go idle for the first time, wait for current work to complete. */
177    private static final int LIGHT_STATE_PRE_IDLE = 3;
178    /** Device is in the light idle state, trying to stay asleep as much as possible. */
179    private static final int LIGHT_STATE_IDLE = 4;
180    /** Device is in the light idle state, we want to go in to idle maintenance but are
181     * waiting for network connectivity before doing so. */
182    private static final int LIGHT_STATE_WAITING_FOR_NETWORK = 5;
183    /** Device is in the light idle state, but temporarily out of idle to do regular maintenance. */
184    private static final int LIGHT_STATE_IDLE_MAINTENANCE = 6;
185    /** Device light idle state is overriden, now applying deep doze state. */
186    private static final int LIGHT_STATE_OVERRIDE = 7;
187    private static String lightStateToString(int state) {
188        switch (state) {
189            case LIGHT_STATE_ACTIVE: return "ACTIVE";
190            case LIGHT_STATE_INACTIVE: return "INACTIVE";
191            case LIGHT_STATE_PRE_IDLE: return "PRE_IDLE";
192            case LIGHT_STATE_IDLE: return "IDLE";
193            case LIGHT_STATE_WAITING_FOR_NETWORK: return "WAITING_FOR_NETWORK";
194            case LIGHT_STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
195            case LIGHT_STATE_OVERRIDE: return "OVERRIDE";
196            default: return Integer.toString(state);
197        }
198    }
199
200    private int mState;
201    private int mLightState;
202
203    private long mInactiveTimeout;
204    private long mNextAlarmTime;
205    private long mNextIdlePendingDelay;
206    private long mNextIdleDelay;
207    private long mNextLightIdleDelay;
208    private long mNextLightAlarmTime;
209    private long mNextSensingTimeoutAlarmTime;
210    private long mCurIdleBudget;
211    private long mMaintenanceStartTime;
212
213    private int mActiveIdleOpCount;
214    private PowerManager.WakeLock mActiveIdleWakeLock;
215    private IBinder mDownloadServiceActive;
216    private boolean mJobsActive;
217    private boolean mAlarmsActive;
218    private boolean mReportedMaintenanceActivity;
219
220    public final AtomicFile mConfigFile;
221
222    private final RemoteCallbackList<IMaintenanceActivityListener> mMaintenanceActivityListeners =
223            new RemoteCallbackList<IMaintenanceActivityListener>();
224
225    /**
226     * Package names the system has white-listed to opt out of power save restrictions,
227     * except for device idle mode.
228     */
229    private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
230
231    /**
232     * Package names the system has white-listed to opt out of power save restrictions for
233     * all modes.
234     */
235    private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
236
237    /**
238     * Package names the user has white-listed to opt out of power save restrictions.
239     */
240    private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
241
242    /**
243     * App IDs of built-in system apps that have been white-listed except for idle modes.
244     */
245    private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
246            = new SparseBooleanArray();
247
248    /**
249     * App IDs of built-in system apps that have been white-listed.
250     */
251    private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
252
253    /**
254     * App IDs that have been white-listed to opt out of power save restrictions, except
255     * for device idle modes.
256     */
257    private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
258
259    /**
260     * Current app IDs that are in the complete power save white list, but shouldn't be
261     * excluded from idle modes.  This array can be shared with others because it will not be
262     * modified once set.
263     */
264    private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
265
266    /**
267     * App IDs that have been white-listed to opt out of power save restrictions.
268     */
269    private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
270
271    /**
272     * Current app IDs that are in the complete power save white list.  This array can
273     * be shared with others because it will not be modified once set.
274     */
275    private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
276
277    /**
278     * App IDs that have been white-listed by the user to opt out of power save restrictions.
279     */
280    private final SparseBooleanArray mPowerSaveWhitelistUserAppIds = new SparseBooleanArray();
281
282    /**
283     * Current app IDs that are in the user power save white list.  This array can
284     * be shared with others because it will not be modified once set.
285     */
286    private int[] mPowerSaveWhitelistUserAppIdArray = new int[0];
287
288    /**
289     * List of end times for UIDs that are temporarily marked as being allowed to access
290     * the network and acquire wakelocks. Times are in milliseconds.
291     */
292    private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
293            = new SparseArray<>();
294
295    /**
296     * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
297     */
298    Runnable mNetworkPolicyTempWhitelistCallback;
299
300    /**
301     * Current app IDs of temporarily whitelist apps for high-priority messages.
302     */
303    private int[] mTempWhitelistAppIdArray = new int[0];
304
305    private static final int EVENT_NULL = 0;
306    private static final int EVENT_NORMAL = 1;
307    private static final int EVENT_LIGHT_IDLE = 2;
308    private static final int EVENT_LIGHT_MAINTENANCE = 3;
309    private static final int EVENT_DEEP_IDLE = 4;
310    private static final int EVENT_DEEP_MAINTENANCE = 5;
311
312    private final int[] mEventCmds = new int[EVENT_BUFFER_SIZE];
313    private final long[] mEventTimes = new long[EVENT_BUFFER_SIZE];
314
315    private void addEvent(int cmd) {
316        if (mEventCmds[0] != cmd) {
317            System.arraycopy(mEventCmds, 0, mEventCmds, 1, EVENT_BUFFER_SIZE - 1);
318            System.arraycopy(mEventTimes, 0, mEventTimes, 1, EVENT_BUFFER_SIZE - 1);
319            mEventCmds[0] = cmd;
320            mEventTimes[0] = SystemClock.elapsedRealtime();
321        }
322    }
323
324    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
325        @Override public void onReceive(Context context, Intent intent) {
326            switch (intent.getAction()) {
327                case ConnectivityManager.CONNECTIVITY_ACTION: {
328                    updateConnectivityState(intent);
329                } break;
330                case Intent.ACTION_BATTERY_CHANGED: {
331                    synchronized (DeviceIdleController.this) {
332                        int plugged = intent.getIntExtra("plugged", 0);
333                        updateChargingLocked(plugged != 0);
334                    }
335                } break;
336                case Intent.ACTION_PACKAGE_REMOVED: {
337                    if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
338                        Uri data = intent.getData();
339                        String ssp;
340                        if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
341                            removePowerSaveWhitelistAppInternal(ssp);
342                        }
343                    }
344                } break;
345            }
346        }
347    };
348
349    private final AlarmManager.OnAlarmListener mLightAlarmListener
350            = new AlarmManager.OnAlarmListener() {
351        @Override
352        public void onAlarm() {
353            synchronized (DeviceIdleController.this) {
354                stepLightIdleStateLocked("s:alarm");
355            }
356        }
357    };
358
359    private final AlarmManager.OnAlarmListener mSensingTimeoutAlarmListener
360            = new AlarmManager.OnAlarmListener() {
361        @Override
362        public void onAlarm() {
363            if (mState == STATE_SENSING) {
364                synchronized (DeviceIdleController.this) {
365                    becomeInactiveIfAppropriateLocked();
366                }
367            }
368        }
369    };
370
371    private final AlarmManager.OnAlarmListener mDeepAlarmListener
372            = new AlarmManager.OnAlarmListener() {
373        @Override
374        public void onAlarm() {
375            synchronized (DeviceIdleController.this) {
376                stepIdleStateLocked("s:alarm");
377            }
378        }
379    };
380
381    private final BroadcastReceiver mIdleStartedDoneReceiver = new BroadcastReceiver() {
382        @Override public void onReceive(Context context, Intent intent) {
383            // When coming out of a deep idle, we will add in some delay before we allow
384            // the system to settle down and finish the maintenance window.  This is
385            // to give a chance for any pending work to be scheduled.
386            if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
387                mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
388                        mConstants.MIN_DEEP_MAINTENANCE_TIME);
389            } else {
390                mHandler.sendEmptyMessageDelayed(MSG_FINISH_IDLE_OP,
391                        mConstants.MIN_LIGHT_MAINTENANCE_TIME);
392            }
393        }
394    };
395
396    private final DisplayManager.DisplayListener mDisplayListener
397            = new DisplayManager.DisplayListener() {
398        @Override public void onDisplayAdded(int displayId) {
399        }
400
401        @Override public void onDisplayRemoved(int displayId) {
402        }
403
404        @Override public void onDisplayChanged(int displayId) {
405            if (displayId == Display.DEFAULT_DISPLAY) {
406                synchronized (DeviceIdleController.this) {
407                    updateDisplayLocked();
408                }
409            }
410        }
411    };
412
413    private final class MotionListener extends TriggerEventListener
414            implements SensorEventListener {
415
416        boolean active = false;
417
418        @Override
419        public void onTrigger(TriggerEvent event) {
420            synchronized (DeviceIdleController.this) {
421                active = false;
422                motionLocked();
423            }
424        }
425
426        @Override
427        public void onSensorChanged(SensorEvent event) {
428            synchronized (DeviceIdleController.this) {
429                mSensorManager.unregisterListener(this, mMotionSensor);
430                active = false;
431                motionLocked();
432            }
433        }
434
435        @Override
436        public void onAccuracyChanged(Sensor sensor, int accuracy) {}
437
438        public boolean registerLocked() {
439            boolean success;
440            if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
441                success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor);
442            } else {
443                success = mSensorManager.registerListener(
444                        mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL);
445            }
446            if (success) {
447                active = true;
448            } else {
449                Slog.e(TAG, "Unable to register for " + mMotionSensor);
450            }
451            return success;
452        }
453
454        public void unregisterLocked() {
455            if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) {
456                mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor);
457            } else {
458                mSensorManager.unregisterListener(mMotionListener);
459            }
460            active = false;
461        }
462    }
463    private final MotionListener mMotionListener = new MotionListener();
464
465    private final LocationListener mGenericLocationListener = new LocationListener() {
466        @Override
467        public void onLocationChanged(Location location) {
468            synchronized (DeviceIdleController.this) {
469                receivedGenericLocationLocked(location);
470            }
471        }
472
473        @Override
474        public void onStatusChanged(String provider, int status, Bundle extras) {
475        }
476
477        @Override
478        public void onProviderEnabled(String provider) {
479        }
480
481        @Override
482        public void onProviderDisabled(String provider) {
483        }
484    };
485
486    private final LocationListener mGpsLocationListener = new LocationListener() {
487        @Override
488        public void onLocationChanged(Location location) {
489            synchronized (DeviceIdleController.this) {
490                receivedGpsLocationLocked(location);
491            }
492        }
493
494        @Override
495        public void onStatusChanged(String provider, int status, Bundle extras) {
496        }
497
498        @Override
499        public void onProviderEnabled(String provider) {
500        }
501
502        @Override
503        public void onProviderDisabled(String provider) {
504        }
505    };
506
507    /**
508     * All times are in milliseconds. These constants are kept synchronized with the system
509     * global Settings. Any access to this class or its fields should be done while
510     * holding the DeviceIdleController lock.
511     */
512    private final class Constants extends ContentObserver {
513        // Key names stored in the settings value.
514        private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
515                = "light_after_inactive_to";
516        private static final String KEY_LIGHT_PRE_IDLE_TIMEOUT = "light_pre_idle_to";
517        private static final String KEY_LIGHT_IDLE_TIMEOUT = "light_idle_to";
518        private static final String KEY_LIGHT_IDLE_FACTOR = "light_idle_factor";
519        private static final String KEY_LIGHT_MAX_IDLE_TIMEOUT = "light_max_idle_to";
520        private static final String KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
521                = "light_idle_maintenance_min_budget";
522        private static final String KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
523                = "light_idle_maintenance_max_budget";
524        private static final String KEY_MIN_LIGHT_MAINTENANCE_TIME = "min_light_maintenance_time";
525        private static final String KEY_MIN_DEEP_MAINTENANCE_TIME = "min_deep_maintenance_time";
526        private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
527        private static final String KEY_SENSING_TIMEOUT = "sensing_to";
528        private static final String KEY_LOCATING_TIMEOUT = "locating_to";
529        private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
530        private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
531        private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
532        private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
533        private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
534        private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
535        private static final String KEY_IDLE_TIMEOUT = "idle_to";
536        private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
537        private static final String KEY_IDLE_FACTOR = "idle_factor";
538        private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
539        private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
540                "max_temp_app_whitelist_duration";
541        private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
542                "mms_temp_app_whitelist_duration";
543        private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
544                "sms_temp_app_whitelist_duration";
545
546        /**
547         * This is the time, after becoming inactive, that we go in to the first
548         * light-weight idle mode.
549         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
550         * @see #KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
551         */
552        public long LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT;
553
554        /**
555         * This is amount of time we will wait from the point where we decide we would
556         * like to go idle until we actually do, while waiting for jobs and other current
557         * activity to finish.
558         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
559         * @see #KEY_LIGHT_PRE_IDLE_TIMEOUT
560         */
561        public long LIGHT_PRE_IDLE_TIMEOUT;
562
563        /**
564         * This is the initial time that we will run in idle maintenance mode.
565         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
566         * @see #KEY_LIGHT_IDLE_TIMEOUT
567         */
568        public long LIGHT_IDLE_TIMEOUT;
569
570        /**
571         * Scaling factor to apply to the light idle mode time each time we complete a cycle.
572         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
573         * @see #KEY_LIGHT_IDLE_FACTOR
574         */
575        public float LIGHT_IDLE_FACTOR;
576
577        /**
578         * This is the maximum time we will run in idle maintenence mode.
579         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
580         * @see #KEY_LIGHT_MAX_IDLE_TIMEOUT
581         */
582        public long LIGHT_MAX_IDLE_TIMEOUT;
583
584        /**
585         * This is the minimum amount of time we want to make available for maintenance mode
586         * when lightly idling.  That is, we will always have at least this amount of time
587         * available maintenance before timing out and cutting off maintenance mode.
588         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
589         * @see #KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET
590         */
591        public long LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
592
593        /**
594         * This is the maximum amount of time we want to make available for maintenance mode
595         * when lightly idling.  That is, if the system isn't using up its minimum maintenance
596         * budget and this time is being added to the budget reserve, this is the maximum
597         * reserve size we will allow to grow and thus the maximum amount of time we will
598         * allow for the maintenance window.
599         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
600         * @see #KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET
601         */
602        public long LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
603
604        /**
605         * This is the minimum amount of time that we will stay in maintenance mode after
606         * a light doze.  We have this minimum to allow various things to respond to switching
607         * in to maintenance mode and scheduling their work -- otherwise we may
608         * see there is nothing to do (no jobs or downloads pending) and go out of maintenance
609         * mode immediately.
610         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
611         * @see #KEY_MIN_LIGHT_MAINTENANCE_TIME
612         */
613        public long MIN_LIGHT_MAINTENANCE_TIME;
614
615        /**
616         * This is the minimum amount of time that we will stay in maintenance mode after
617         * a full doze.  We have this minimum to allow various things to respond to switching
618         * in to maintenance mode and scheduling their work -- otherwise we may
619         * see there is nothing to do (no jobs or downloads pending) and go out of maintenance
620         * mode immediately.
621         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
622         * @see #KEY_MIN_DEEP_MAINTENANCE_TIME
623         */
624        public long MIN_DEEP_MAINTENANCE_TIME;
625
626        /**
627         * This is the time, after becoming inactive, at which we start looking at the
628         * motion sensor to determine if the device is being left alone.  We don't do this
629         * immediately after going inactive just because we don't want to be continually running
630         * the motion sensor whenever the screen is off.
631         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
632         * @see #KEY_INACTIVE_TIMEOUT
633         */
634        public long INACTIVE_TIMEOUT;
635
636        /**
637         * If we don't receive a callback from AnyMotion in this amount of time +
638         * {@link #LOCATING_TIMEOUT}, we will change from
639         * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
640         * will be ignored.
641         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
642         * @see #KEY_SENSING_TIMEOUT
643         */
644        public long SENSING_TIMEOUT;
645
646        /**
647         * This is how long we will wait to try to get a good location fix before going in to
648         * idle mode.
649         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
650         * @see #KEY_LOCATING_TIMEOUT
651         */
652        public long LOCATING_TIMEOUT;
653
654        /**
655         * The desired maximum accuracy (in meters) we consider the location to be good enough to go
656         * on to idle.  We will be trying to get an accuracy fix at least this good or until
657         * {@link #LOCATING_TIMEOUT} expires.
658         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
659         * @see #KEY_LOCATION_ACCURACY
660         */
661        public float LOCATION_ACCURACY;
662
663        /**
664         * This is the time, after seeing motion, that we wait after becoming inactive from
665         * that until we start looking for motion again.
666         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
667         * @see #KEY_MOTION_INACTIVE_TIMEOUT
668         */
669        public long MOTION_INACTIVE_TIMEOUT;
670
671        /**
672         * This is the time, after the inactive timeout elapses, that we will wait looking
673         * for motion until we truly consider the device to be idle.
674         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
675         * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
676         */
677        public long IDLE_AFTER_INACTIVE_TIMEOUT;
678
679        /**
680         * This is the initial time, after being idle, that we will allow ourself to be back
681         * in the IDLE_MAINTENANCE state allowing the system to run normally until we return to
682         * idle.
683         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
684         * @see #KEY_IDLE_PENDING_TIMEOUT
685         */
686        public long IDLE_PENDING_TIMEOUT;
687
688        /**
689         * Maximum pending idle timeout (time spent running) we will be allowed to use.
690         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
691         * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
692         */
693        public long MAX_IDLE_PENDING_TIMEOUT;
694
695        /**
696         * Scaling factor to apply to current pending idle timeout each time we cycle through
697         * that state.
698         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
699         * @see #KEY_IDLE_PENDING_FACTOR
700         */
701        public float IDLE_PENDING_FACTOR;
702
703        /**
704         * This is the initial time that we want to sit in the idle state before waking up
705         * again to return to pending idle and allowing normal work to run.
706         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
707         * @see #KEY_IDLE_TIMEOUT
708         */
709        public long IDLE_TIMEOUT;
710
711        /**
712         * Maximum idle duration we will be allowed to use.
713         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
714         * @see #KEY_MAX_IDLE_TIMEOUT
715         */
716        public long MAX_IDLE_TIMEOUT;
717
718        /**
719         * Scaling factor to apply to current idle timeout each time we cycle through that state.
720          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
721         * @see #KEY_IDLE_FACTOR
722         */
723        public float IDLE_FACTOR;
724
725        /**
726         * This is the minimum time we will allow until the next upcoming alarm for us to
727         * actually go in to idle mode.
728         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
729         * @see #KEY_MIN_TIME_TO_ALARM
730         */
731        public long MIN_TIME_TO_ALARM;
732
733        /**
734         * Max amount of time to temporarily whitelist an app when it receives a high priority
735         * tickle.
736         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
737         * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
738         */
739        public long MAX_TEMP_APP_WHITELIST_DURATION;
740
741        /**
742         * Amount of time we would like to whitelist an app that is receiving an MMS.
743         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
744         * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
745         */
746        public long MMS_TEMP_APP_WHITELIST_DURATION;
747
748        /**
749         * Amount of time we would like to whitelist an app that is receiving an SMS.
750         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
751         * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
752         */
753        public long SMS_TEMP_APP_WHITELIST_DURATION;
754
755        private final ContentResolver mResolver;
756        private final boolean mHasWatch;
757        private final KeyValueListParser mParser = new KeyValueListParser(',');
758
759        public Constants(Handler handler, ContentResolver resolver) {
760            super(handler);
761            mResolver = resolver;
762            mHasWatch = getContext().getPackageManager().hasSystemFeature(
763                    PackageManager.FEATURE_WATCH);
764            mResolver.registerContentObserver(Settings.Global.getUriFor(
765                    mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH
766                              : Settings.Global.DEVICE_IDLE_CONSTANTS),
767                    false, this);
768            updateConstants();
769        }
770
771        @Override
772        public void onChange(boolean selfChange, Uri uri) {
773            updateConstants();
774        }
775
776        private void updateConstants() {
777            synchronized (DeviceIdleController.this) {
778                try {
779                    mParser.setString(Settings.Global.getString(mResolver,
780                            mHasWatch ? Settings.Global.DEVICE_IDLE_CONSTANTS_WATCH
781                                      : Settings.Global.DEVICE_IDLE_CONSTANTS));
782                } catch (IllegalArgumentException e) {
783                    // Failed to parse the settings string, log this and move on
784                    // with defaults.
785                    Slog.e(TAG, "Bad device idle settings", e);
786                }
787
788                LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(
789                        KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT,
790                        !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
791                LIGHT_PRE_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_PRE_IDLE_TIMEOUT,
792                        !COMPRESS_TIME ? 10 * 60 * 1000L : 30 * 1000L);
793                LIGHT_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_IDLE_TIMEOUT,
794                        !COMPRESS_TIME ? 5 * 60 * 1000L : 15 * 1000L);
795                LIGHT_IDLE_FACTOR = mParser.getFloat(KEY_LIGHT_IDLE_FACTOR,
796                        2f);
797                LIGHT_MAX_IDLE_TIMEOUT = mParser.getLong(KEY_LIGHT_MAX_IDLE_TIMEOUT,
798                        !COMPRESS_TIME ? 15 * 60 * 1000L : 60 * 1000L);
799                LIGHT_IDLE_MAINTENANCE_MIN_BUDGET = mParser.getLong(
800                        KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET,
801                        !COMPRESS_TIME ? 1 * 60 * 1000L : 15 * 1000L);
802                LIGHT_IDLE_MAINTENANCE_MAX_BUDGET = mParser.getLong(
803                        KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET,
804                        !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
805                MIN_LIGHT_MAINTENANCE_TIME = mParser.getLong(
806                        KEY_MIN_LIGHT_MAINTENANCE_TIME,
807                        !COMPRESS_TIME ? 5 * 1000L : 1 * 1000L);
808                MIN_DEEP_MAINTENANCE_TIME = mParser.getLong(
809                        KEY_MIN_DEEP_MAINTENANCE_TIME,
810                        !COMPRESS_TIME ? 30 * 1000L : 5 * 1000L);
811                long inactiveTimeoutDefault = (mHasWatch ? 15 : 30) * 60 * 1000L;
812                INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
813                        !COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
814                SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
815                        !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
816                LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
817                        !DEBUG ? 30 * 1000L : 15 * 1000L);
818                LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
819                MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
820                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
821                long idleAfterInactiveTimeout = (mHasWatch ? 15 : 30) * 60 * 1000L;
822                IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
823                        !COMPRESS_TIME ? idleAfterInactiveTimeout
824                                       : (idleAfterInactiveTimeout / 10));
825                IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
826                        !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
827                MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
828                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
829                IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
830                        2f);
831                IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
832                        !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
833                MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
834                        !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
835                IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
836                        2f);
837                MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
838                        !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
839                MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
840                        KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
841                MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
842                        KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
843                SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
844                        KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
845            }
846        }
847
848        void dump(PrintWriter pw) {
849            pw.println("  Settings:");
850
851            pw.print("    "); pw.print(KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
852            TimeUtils.formatDuration(LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT, pw);
853            pw.println();
854
855            pw.print("    "); pw.print(KEY_LIGHT_PRE_IDLE_TIMEOUT); pw.print("=");
856            TimeUtils.formatDuration(LIGHT_PRE_IDLE_TIMEOUT, pw);
857            pw.println();
858
859            pw.print("    "); pw.print(KEY_LIGHT_IDLE_TIMEOUT); pw.print("=");
860            TimeUtils.formatDuration(LIGHT_IDLE_TIMEOUT, pw);
861            pw.println();
862
863            pw.print("    "); pw.print(KEY_LIGHT_IDLE_FACTOR); pw.print("=");
864            pw.print(LIGHT_IDLE_FACTOR);
865            pw.println();
866
867            pw.print("    "); pw.print(KEY_LIGHT_MAX_IDLE_TIMEOUT); pw.print("=");
868            TimeUtils.formatDuration(LIGHT_MAX_IDLE_TIMEOUT, pw);
869            pw.println();
870
871            pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MIN_BUDGET); pw.print("=");
872            TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MIN_BUDGET, pw);
873            pw.println();
874
875            pw.print("    "); pw.print(KEY_LIGHT_IDLE_MAINTENANCE_MAX_BUDGET); pw.print("=");
876            TimeUtils.formatDuration(LIGHT_IDLE_MAINTENANCE_MAX_BUDGET, pw);
877            pw.println();
878
879            pw.print("    "); pw.print(KEY_MIN_LIGHT_MAINTENANCE_TIME); pw.print("=");
880            TimeUtils.formatDuration(MIN_LIGHT_MAINTENANCE_TIME, pw);
881            pw.println();
882
883            pw.print("    "); pw.print(KEY_MIN_DEEP_MAINTENANCE_TIME); pw.print("=");
884            TimeUtils.formatDuration(MIN_DEEP_MAINTENANCE_TIME, pw);
885            pw.println();
886
887            pw.print("    "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
888            TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
889            pw.println();
890
891            pw.print("    "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
892            TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
893            pw.println();
894
895            pw.print("    "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
896            TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
897            pw.println();
898
899            pw.print("    "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
900            pw.print(LOCATION_ACCURACY); pw.print("m");
901            pw.println();
902
903            pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
904            TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
905            pw.println();
906
907            pw.print("    "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
908            TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
909            pw.println();
910
911            pw.print("    "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
912            TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
913            pw.println();
914
915            pw.print("    "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
916            TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
917            pw.println();
918
919            pw.print("    "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
920            pw.println(IDLE_PENDING_FACTOR);
921
922            pw.print("    "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
923            TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
924            pw.println();
925
926            pw.print("    "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
927            TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
928            pw.println();
929
930            pw.print("    "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
931            pw.println(IDLE_FACTOR);
932
933            pw.print("    "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
934            TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
935            pw.println();
936
937            pw.print("    "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
938            TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
939            pw.println();
940
941            pw.print("    "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
942            TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
943            pw.println();
944
945            pw.print("    "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
946            TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
947            pw.println();
948        }
949    }
950
951    private Constants mConstants;
952
953    @Override
954    public void onAnyMotionResult(int result) {
955        if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
956        if (result != AnyMotionDetector.RESULT_UNKNOWN) {
957            synchronized (this) {
958                cancelSensingTimeoutAlarmLocked();
959            }
960        }
961        if (result == AnyMotionDetector.RESULT_MOVED) {
962            if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
963            synchronized (this) {
964                handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
965            }
966        } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
967            if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
968            if (mState == STATE_SENSING) {
969                // If we are currently sensing, it is time to move to locating.
970                synchronized (this) {
971                    mNotMoving = true;
972                    stepIdleStateLocked("s:stationary");
973                }
974            } else if (mState == STATE_LOCATING) {
975                // If we are currently locating, note that we are not moving and step
976                // if we have located the position.
977                synchronized (this) {
978                    mNotMoving = true;
979                    if (mLocated) {
980                        stepIdleStateLocked("s:stationary");
981                    }
982                }
983            }
984        }
985    }
986
987    static final int MSG_WRITE_CONFIG = 1;
988    static final int MSG_REPORT_IDLE_ON = 2;
989    static final int MSG_REPORT_IDLE_ON_LIGHT = 3;
990    static final int MSG_REPORT_IDLE_OFF = 4;
991    static final int MSG_REPORT_ACTIVE = 5;
992    static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 6;
993    static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
994    static final int MSG_FINISH_IDLE_OP = 8;
995
996    final class MyHandler extends Handler {
997        MyHandler(Looper looper) {
998            super(looper);
999        }
1000
1001        @Override public void handleMessage(Message msg) {
1002            if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
1003            switch (msg.what) {
1004                case MSG_WRITE_CONFIG: {
1005                    handleWriteConfigFile();
1006                } break;
1007                case MSG_REPORT_IDLE_ON:
1008                case MSG_REPORT_IDLE_ON_LIGHT: {
1009                    EventLogTags.writeDeviceIdleOnStart();
1010                    final boolean deepChanged;
1011                    final boolean lightChanged;
1012                    if (msg.what == MSG_REPORT_IDLE_ON) {
1013                        deepChanged = mLocalPowerManager.setDeviceIdleMode(true);
1014                        lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1015                    } else {
1016                        deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1017                        lightChanged = mLocalPowerManager.setLightDeviceIdleMode(true);
1018                    }
1019                    try {
1020                        mNetworkPolicyManager.setDeviceIdleMode(true);
1021                        mBatteryStats.noteDeviceIdleMode(msg.what == MSG_REPORT_IDLE_ON
1022                                ? BatteryStats.DEVICE_IDLE_MODE_DEEP
1023                                : BatteryStats.DEVICE_IDLE_MODE_LIGHT, null, Process.myUid());
1024                    } catch (RemoteException e) {
1025                    }
1026                    if (deepChanged) {
1027                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1028                    }
1029                    if (lightChanged) {
1030                        getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1031                    }
1032                    EventLogTags.writeDeviceIdleOnComplete();
1033                } break;
1034                case MSG_REPORT_IDLE_OFF: {
1035                    EventLogTags.writeDeviceIdleOffStart("unknown");
1036                    final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1037                    final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1038                    try {
1039                        mNetworkPolicyManager.setDeviceIdleMode(false);
1040                        mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1041                                null, Process.myUid());
1042                    } catch (RemoteException e) {
1043                    }
1044                    if (deepChanged) {
1045                        incActiveIdleOps();
1046                        getContext().sendOrderedBroadcastAsUser(mIdleIntent, UserHandle.ALL,
1047                                null, mIdleStartedDoneReceiver, null, 0, null, null);
1048                    }
1049                    if (lightChanged) {
1050                        incActiveIdleOps();
1051                        getContext().sendOrderedBroadcastAsUser(mLightIdleIntent, UserHandle.ALL,
1052                                null, mIdleStartedDoneReceiver, null, 0, null, null);
1053                    }
1054                    // Always start with one active op for the message being sent here.
1055                    // Now we are done!
1056                    decActiveIdleOps();
1057                    EventLogTags.writeDeviceIdleOffComplete();
1058                } break;
1059                case MSG_REPORT_ACTIVE: {
1060                    String activeReason = (String)msg.obj;
1061                    int activeUid = msg.arg1;
1062                    EventLogTags.writeDeviceIdleOffStart(
1063                            activeReason != null ? activeReason : "unknown");
1064                    final boolean deepChanged = mLocalPowerManager.setDeviceIdleMode(false);
1065                    final boolean lightChanged = mLocalPowerManager.setLightDeviceIdleMode(false);
1066                    try {
1067                        mNetworkPolicyManager.setDeviceIdleMode(false);
1068                        mBatteryStats.noteDeviceIdleMode(BatteryStats.DEVICE_IDLE_MODE_OFF,
1069                                activeReason, activeUid);
1070                    } catch (RemoteException e) {
1071                    }
1072                    if (deepChanged) {
1073                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
1074                    }
1075                    if (lightChanged) {
1076                        getContext().sendBroadcastAsUser(mLightIdleIntent, UserHandle.ALL);
1077                    }
1078                    EventLogTags.writeDeviceIdleOffComplete();
1079                } break;
1080                case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
1081                    int uid = msg.arg1;
1082                    checkTempAppWhitelistTimeout(uid);
1083                } break;
1084                case MSG_REPORT_MAINTENANCE_ACTIVITY: {
1085                    boolean active = (msg.arg1 == 1);
1086                    final int size = mMaintenanceActivityListeners.beginBroadcast();
1087                    try {
1088                        for (int i = 0; i < size; i++) {
1089                            try {
1090                                mMaintenanceActivityListeners.getBroadcastItem(i)
1091                                        .onMaintenanceActivityChanged(active);
1092                            } catch (RemoteException ignored) {
1093                            }
1094                        }
1095                    } finally {
1096                        mMaintenanceActivityListeners.finishBroadcast();
1097                    }
1098                } break;
1099                case MSG_FINISH_IDLE_OP: {
1100                    decActiveIdleOps();
1101                } break;
1102            }
1103        }
1104    }
1105
1106    final MyHandler mHandler;
1107
1108    BinderService mBinderService;
1109
1110    private final class BinderService extends IDeviceIdleController.Stub {
1111        @Override public void addPowerSaveWhitelistApp(String name) {
1112            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1113                    null);
1114            long ident = Binder.clearCallingIdentity();
1115            try {
1116                addPowerSaveWhitelistAppInternal(name);
1117            } finally {
1118                Binder.restoreCallingIdentity(ident);
1119            }
1120        }
1121
1122        @Override public void removePowerSaveWhitelistApp(String name) {
1123            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
1124                    null);
1125            long ident = Binder.clearCallingIdentity();
1126            try {
1127                removePowerSaveWhitelistAppInternal(name);
1128            } finally {
1129                Binder.restoreCallingIdentity(ident);
1130            }
1131        }
1132
1133        @Override public String[] getSystemPowerWhitelistExceptIdle() {
1134            return getSystemPowerWhitelistExceptIdleInternal();
1135        }
1136
1137        @Override public String[] getSystemPowerWhitelist() {
1138            return getSystemPowerWhitelistInternal();
1139        }
1140
1141        @Override public String[] getUserPowerWhitelist() {
1142            return getUserPowerWhitelistInternal();
1143        }
1144
1145        @Override public String[] getFullPowerWhitelistExceptIdle() {
1146            return getFullPowerWhitelistExceptIdleInternal();
1147        }
1148
1149        @Override public String[] getFullPowerWhitelist() {
1150            return getFullPowerWhitelistInternal();
1151        }
1152
1153        @Override public int[] getAppIdWhitelistExceptIdle() {
1154            return getAppIdWhitelistExceptIdleInternal();
1155        }
1156
1157        @Override public int[] getAppIdWhitelist() {
1158            return getAppIdWhitelistInternal();
1159        }
1160
1161        @Override public int[] getAppIdUserWhitelist() {
1162            return getAppIdUserWhitelistInternal();
1163        }
1164
1165        @Override public int[] getAppIdTempWhitelist() {
1166            return getAppIdTempWhitelistInternal();
1167        }
1168
1169        @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
1170            return isPowerSaveWhitelistExceptIdleAppInternal(name);
1171        }
1172
1173        @Override public boolean isPowerSaveWhitelistApp(String name) {
1174            return isPowerSaveWhitelistAppInternal(name);
1175        }
1176
1177        @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
1178                int userId, String reason) throws RemoteException {
1179            addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1180        }
1181
1182        @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
1183                int userId, String reason) throws RemoteException {
1184            long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
1185            addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1186            return duration;
1187        }
1188
1189        @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
1190                int userId, String reason) throws RemoteException {
1191            long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
1192            addPowerSaveTempWhitelistAppChecked(packageName, duration, userId, reason);
1193            return duration;
1194        }
1195
1196        @Override public void exitIdle(String reason) {
1197            getContext().enforceCallingOrSelfPermission(Manifest.permission.DEVICE_POWER,
1198                    null);
1199            long ident = Binder.clearCallingIdentity();
1200            try {
1201                exitIdleInternal(reason);
1202            } finally {
1203                Binder.restoreCallingIdentity(ident);
1204            }
1205        }
1206
1207        @Override public void downloadServiceActive(IBinder token) {
1208            getContext().enforceCallingOrSelfPermission(
1209                    "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS", null);
1210            long ident = Binder.clearCallingIdentity();
1211            try {
1212                DeviceIdleController.this.downloadServiceActive(token);
1213            } finally {
1214                Binder.restoreCallingIdentity(ident);
1215            }
1216        }
1217
1218        @Override public void downloadServiceInactive() {
1219            getContext().enforceCallingOrSelfPermission(
1220                    "android.permission.SEND_DOWNLOAD_COMPLETED_INTENTS", null);
1221            long ident = Binder.clearCallingIdentity();
1222            try {
1223                DeviceIdleController.this.downloadServiceInactive();
1224            } finally {
1225                Binder.restoreCallingIdentity(ident);
1226            }
1227        }
1228
1229        @Override public boolean registerMaintenanceActivityListener(
1230                IMaintenanceActivityListener listener) {
1231            return DeviceIdleController.this.registerMaintenanceActivityListener(listener);
1232        }
1233
1234        @Override public void unregisterMaintenanceActivityListener(
1235                IMaintenanceActivityListener listener) {
1236            DeviceIdleController.this.unregisterMaintenanceActivityListener(listener);
1237        }
1238
1239        @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1240            DeviceIdleController.this.dump(fd, pw, args);
1241        }
1242
1243        @Override public void onShellCommand(FileDescriptor in, FileDescriptor out,
1244                FileDescriptor err, String[] args, ResultReceiver resultReceiver) {
1245            (new Shell()).exec(this, in, out, err, args, resultReceiver);
1246        }
1247    }
1248
1249    public final class LocalService {
1250        public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
1251                String reason) {
1252            addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
1253        }
1254
1255        public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
1256            setNetworkPolicyTempWhitelistCallbackInternal(callback);
1257        }
1258
1259        public void setJobsActive(boolean active) {
1260            DeviceIdleController.this.setJobsActive(active);
1261        }
1262
1263        // Up-call from alarm manager.
1264        public void setAlarmsActive(boolean active) {
1265            DeviceIdleController.this.setAlarmsActive(active);
1266        }
1267
1268        /**
1269         * Returns the array of app ids whitelisted by user. Take care not to
1270         * modify this, as it is a reference to the original copy. But the reference
1271         * can change when the list changes, so it needs to be re-acquired when
1272         * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
1273         */
1274        public int[] getPowerSaveWhitelistUserAppIds() {
1275            return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
1276        }
1277    }
1278
1279    public DeviceIdleController(Context context) {
1280        super(context);
1281        mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
1282        mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
1283    }
1284
1285    int[] getPowerSaveWhitelistUserAppIds() {
1286        synchronized (this) {
1287            return mPowerSaveWhitelistUserAppIdArray;
1288        }
1289    }
1290
1291    private static File getSystemDir() {
1292        return new File(Environment.getDataDirectory(), "system");
1293    }
1294
1295    @Override
1296    public void onStart() {
1297        final PackageManager pm = getContext().getPackageManager();
1298
1299        synchronized (this) {
1300            mLightEnabled = mDeepEnabled = getContext().getResources().getBoolean(
1301                    com.android.internal.R.bool.config_enableAutoPowerModes);
1302            SystemConfig sysConfig = SystemConfig.getInstance();
1303            ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
1304            for (int i=0; i<allowPowerExceptIdle.size(); i++) {
1305                String pkg = allowPowerExceptIdle.valueAt(i);
1306                try {
1307                    ApplicationInfo ai = pm.getApplicationInfo(pkg,
1308                            PackageManager.MATCH_SYSTEM_ONLY);
1309                    int appid = UserHandle.getAppId(ai.uid);
1310                    mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1311                    mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1312                } catch (PackageManager.NameNotFoundException e) {
1313                }
1314            }
1315            ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
1316            for (int i=0; i<allowPower.size(); i++) {
1317                String pkg = allowPower.valueAt(i);
1318                try {
1319                    ApplicationInfo ai = pm.getApplicationInfo(pkg,
1320                            PackageManager.MATCH_SYSTEM_ONLY);
1321                    int appid = UserHandle.getAppId(ai.uid);
1322                    // These apps are on both the whitelist-except-idle as well
1323                    // as the full whitelist, so they apply in all cases.
1324                    mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
1325                    mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
1326                    mPowerSaveWhitelistApps.put(ai.packageName, appid);
1327                    mPowerSaveWhitelistSystemAppIds.put(appid, true);
1328                } catch (PackageManager.NameNotFoundException e) {
1329                }
1330            }
1331
1332            mConstants = new Constants(mHandler, getContext().getContentResolver());
1333
1334            readConfigFileLocked();
1335            updateWhitelistAppIdsLocked();
1336
1337            mNetworkConnected = true;
1338            mScreenOn = true;
1339            // Start out assuming we are charging.  If we aren't, we will at least get
1340            // a battery update the next time the level drops.
1341            mCharging = true;
1342            mState = STATE_ACTIVE;
1343            mLightState = LIGHT_STATE_ACTIVE;
1344            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1345        }
1346
1347        mBinderService = new BinderService();
1348        publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
1349        publishLocalService(LocalService.class, new LocalService());
1350    }
1351
1352    @Override
1353    public void onBootPhase(int phase) {
1354        if (phase == PHASE_SYSTEM_SERVICES_READY) {
1355            synchronized (this) {
1356                mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
1357                mBatteryStats = BatteryStatsService.getService();
1358                mLocalPowerManager = getLocalService(PowerManagerInternal.class);
1359                mPowerManager = getContext().getSystemService(PowerManager.class);
1360                mActiveIdleWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
1361                        "deviceidle_maint");
1362                mActiveIdleWakeLock.setReferenceCounted(false);
1363                mConnectivityService = (ConnectivityService)ServiceManager.getService(
1364                        Context.CONNECTIVITY_SERVICE);
1365                mLocalAlarmManager = getLocalService(AlarmManagerService.LocalService.class);
1366                mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
1367                        ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
1368                mDisplayManager = (DisplayManager) getContext().getSystemService(
1369                        Context.DISPLAY_SERVICE);
1370                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
1371                int sigMotionSensorId = getContext().getResources().getInteger(
1372                        com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor);
1373                if (sigMotionSensorId > 0) {
1374                    mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true);
1375                }
1376                if (mMotionSensor == null && getContext().getResources().getBoolean(
1377                        com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) {
1378                    mMotionSensor = mSensorManager.getDefaultSensor(
1379                            Sensor.TYPE_WRIST_TILT_GESTURE, true);
1380                }
1381                if (mMotionSensor == null) {
1382                    // As a last ditch, fall back to SMD.
1383                    mMotionSensor = mSensorManager.getDefaultSensor(
1384                            Sensor.TYPE_SIGNIFICANT_MOTION, true);
1385                }
1386
1387                if (getContext().getResources().getBoolean(
1388                        com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) {
1389                    mLocationManager = (LocationManager) getContext().getSystemService(
1390                            Context.LOCATION_SERVICE);
1391                    mLocationRequest = new LocationRequest()
1392                        .setQuality(LocationRequest.ACCURACY_FINE)
1393                        .setInterval(0)
1394                        .setFastestInterval(0)
1395                        .setNumUpdates(1);
1396                }
1397
1398                float angleThreshold = getContext().getResources().getInteger(
1399                        com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
1400                mAnyMotionDetector = new AnyMotionDetector(
1401                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
1402                        mHandler, mSensorManager, this, angleThreshold);
1403
1404                mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
1405                mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1406                        | Intent.FLAG_RECEIVER_FOREGROUND);
1407                mLightIdleIntent = new Intent(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
1408                mLightIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
1409                        | Intent.FLAG_RECEIVER_FOREGROUND);
1410
1411                IntentFilter filter = new IntentFilter();
1412                filter.addAction(Intent.ACTION_BATTERY_CHANGED);
1413                getContext().registerReceiver(mReceiver, filter);
1414
1415                filter = new IntentFilter();
1416                filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
1417                filter.addDataScheme("package");
1418                getContext().registerReceiver(mReceiver, filter);
1419
1420                filter = new IntentFilter();
1421                filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
1422                getContext().registerReceiver(mReceiver, filter);
1423
1424                mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
1425                mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
1426                mDisplayManager.registerDisplayListener(mDisplayListener, null);
1427                updateDisplayLocked();
1428            }
1429            updateConnectivityState(null);
1430        }
1431    }
1432
1433    public boolean addPowerSaveWhitelistAppInternal(String name) {
1434        synchronized (this) {
1435            try {
1436                ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name,
1437                        PackageManager.MATCH_UNINSTALLED_PACKAGES);
1438                if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
1439                    reportPowerSaveWhitelistChangedLocked();
1440                    updateWhitelistAppIdsLocked();
1441                    writeConfigFileLocked();
1442                }
1443                return true;
1444            } catch (PackageManager.NameNotFoundException e) {
1445                return false;
1446            }
1447        }
1448    }
1449
1450    public boolean removePowerSaveWhitelistAppInternal(String name) {
1451        synchronized (this) {
1452            if (mPowerSaveWhitelistUserApps.remove(name) != null) {
1453                reportPowerSaveWhitelistChangedLocked();
1454                updateWhitelistAppIdsLocked();
1455                writeConfigFileLocked();
1456                return true;
1457            }
1458        }
1459        return false;
1460    }
1461
1462    public boolean getPowerSaveWhitelistAppInternal(String name) {
1463        synchronized (this) {
1464            return mPowerSaveWhitelistUserApps.containsKey(name);
1465        }
1466    }
1467
1468    public String[] getSystemPowerWhitelistExceptIdleInternal() {
1469        synchronized (this) {
1470            int size = mPowerSaveWhitelistAppsExceptIdle.size();
1471            String[] apps = new String[size];
1472            for (int i = 0; i < size; i++) {
1473                apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1474            }
1475            return apps;
1476        }
1477    }
1478
1479    public String[] getSystemPowerWhitelistInternal() {
1480        synchronized (this) {
1481            int size = mPowerSaveWhitelistApps.size();
1482            String[] apps = new String[size];
1483            for (int i = 0; i < size; i++) {
1484                apps[i] = mPowerSaveWhitelistApps.keyAt(i);
1485            }
1486            return apps;
1487        }
1488    }
1489
1490    public String[] getUserPowerWhitelistInternal() {
1491        synchronized (this) {
1492            int size = mPowerSaveWhitelistUserApps.size();
1493            String[] apps = new String[size];
1494            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1495                apps[i] = mPowerSaveWhitelistUserApps.keyAt(i);
1496            }
1497            return apps;
1498        }
1499    }
1500
1501    public String[] getFullPowerWhitelistExceptIdleInternal() {
1502        synchronized (this) {
1503            int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
1504            String[] apps = new String[size];
1505            int cur = 0;
1506            for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
1507                apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
1508                cur++;
1509            }
1510            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1511                apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1512                cur++;
1513            }
1514            return apps;
1515        }
1516    }
1517
1518    public String[] getFullPowerWhitelistInternal() {
1519        synchronized (this) {
1520            int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
1521            String[] apps = new String[size];
1522            int cur = 0;
1523            for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
1524                apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
1525                cur++;
1526            }
1527            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1528                apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1529                cur++;
1530            }
1531            return apps;
1532        }
1533    }
1534
1535    public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1536        synchronized (this) {
1537            return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1538                    || mPowerSaveWhitelistUserApps.containsKey(packageName);
1539        }
1540    }
1541
1542    public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1543        synchronized (this) {
1544            return mPowerSaveWhitelistApps.containsKey(packageName)
1545                    || mPowerSaveWhitelistUserApps.containsKey(packageName);
1546        }
1547    }
1548
1549    public int[] getAppIdWhitelistExceptIdleInternal() {
1550        synchronized (this) {
1551            return mPowerSaveWhitelistExceptIdleAppIdArray;
1552        }
1553    }
1554
1555    public int[] getAppIdWhitelistInternal() {
1556        synchronized (this) {
1557            return mPowerSaveWhitelistAllAppIdArray;
1558        }
1559    }
1560
1561    public int[] getAppIdUserWhitelistInternal() {
1562        synchronized (this) {
1563            return mPowerSaveWhitelistUserAppIdArray;
1564        }
1565    }
1566
1567    public int[] getAppIdTempWhitelistInternal() {
1568        synchronized (this) {
1569            return mTempWhitelistAppIdArray;
1570        }
1571    }
1572
1573    void addPowerSaveTempWhitelistAppChecked(String packageName, long duration,
1574            int userId, String reason) throws RemoteException {
1575        getContext().enforceCallingPermission(
1576                Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
1577                "No permission to change device idle whitelist");
1578        final int callingUid = Binder.getCallingUid();
1579        userId = ActivityManagerNative.getDefault().handleIncomingUser(
1580                Binder.getCallingPid(),
1581                callingUid,
1582                userId,
1583                /*allowAll=*/ false,
1584                /*requireFull=*/ false,
1585                "addPowerSaveTempWhitelistApp", null);
1586        final long token = Binder.clearCallingIdentity();
1587        try {
1588            addPowerSaveTempWhitelistAppInternal(callingUid,
1589                    packageName, duration, userId, true, reason);
1590        } finally {
1591            Binder.restoreCallingIdentity(token);
1592        }
1593    }
1594
1595    /**
1596     * Adds an app to the temporary whitelist and resets the endTime for granting the
1597     * app an exemption to access network and acquire wakelocks.
1598     */
1599    void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
1600            long duration, int userId, boolean sync, String reason) {
1601        try {
1602            int uid = getContext().getPackageManager().getPackageUidAsUser(packageName, userId);
1603            int appId = UserHandle.getAppId(uid);
1604            addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
1605        } catch (NameNotFoundException e) {
1606        }
1607    }
1608
1609    /**
1610     * Adds an app to the temporary whitelist and resets the endTime for granting the
1611     * app an exemption to access network and acquire wakelocks.
1612     */
1613    void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
1614            long duration, boolean sync, String reason) {
1615        final long timeNow = SystemClock.elapsedRealtime();
1616        Runnable networkPolicyTempWhitelistCallback = null;
1617        synchronized (this) {
1618            int callingAppId = UserHandle.getAppId(callingUid);
1619            if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1620                if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1621                    throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1622                            + " is not on whitelist");
1623                }
1624            }
1625            duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
1626            Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1627            final boolean newEntry = entry == null;
1628            // Set the new end time
1629            if (newEntry) {
1630                entry = new Pair<>(new MutableLong(0), reason);
1631                mTempWhitelistAppIdEndTimes.put(appId, entry);
1632            }
1633            entry.first.value = timeNow + duration;
1634            if (DEBUG) {
1635                Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1636            }
1637            if (newEntry) {
1638                // No pending timeout for the app id, post a delayed message
1639                try {
1640                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1641                            reason, appId);
1642                } catch (RemoteException e) {
1643                }
1644                postTempActiveTimeoutMessage(appId, duration);
1645                updateTempWhitelistAppIdsLocked();
1646                if (mNetworkPolicyTempWhitelistCallback != null) {
1647                    if (!sync) {
1648                        mHandler.post(mNetworkPolicyTempWhitelistCallback);
1649                    } else {
1650                        networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1651                    }
1652                }
1653                reportTempWhitelistChangedLocked();
1654            }
1655        }
1656        if (networkPolicyTempWhitelistCallback != null) {
1657            networkPolicyTempWhitelistCallback.run();
1658        }
1659    }
1660
1661    public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1662        synchronized (this) {
1663            mNetworkPolicyTempWhitelistCallback = callback;
1664        }
1665    }
1666
1667    private void postTempActiveTimeoutMessage(int uid, long delay) {
1668        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1669                delay);
1670    }
1671
1672    void checkTempAppWhitelistTimeout(int uid) {
1673        final long timeNow = SystemClock.elapsedRealtime();
1674        synchronized (this) {
1675            Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1676            if (entry == null) {
1677                // Nothing to do
1678                return;
1679            }
1680            if (timeNow >= entry.first.value) {
1681                mTempWhitelistAppIdEndTimes.delete(uid);
1682                if (DEBUG) {
1683                    Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1684                }
1685                updateTempWhitelistAppIdsLocked();
1686                if (mNetworkPolicyTempWhitelistCallback != null) {
1687                    mHandler.post(mNetworkPolicyTempWhitelistCallback);
1688                }
1689                reportTempWhitelistChangedLocked();
1690                try {
1691                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1692                            entry.second, uid);
1693                } catch (RemoteException e) {
1694                }
1695            } else {
1696                // Need more time
1697                postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
1698            }
1699        }
1700    }
1701
1702    public void exitIdleInternal(String reason) {
1703        synchronized (this) {
1704            becomeActiveLocked(reason, Binder.getCallingUid());
1705        }
1706    }
1707
1708    void updateConnectivityState(Intent connIntent) {
1709        ConnectivityService cm;
1710        synchronized (this) {
1711            cm = mConnectivityService;
1712        }
1713        if (cm == null) {
1714            return;
1715        }
1716        // Note: can't call out to ConnectivityService with our lock held.
1717        NetworkInfo ni = cm.getActiveNetworkInfo();
1718        synchronized (this) {
1719            boolean conn;
1720            if (ni == null) {
1721                conn = false;
1722            } else {
1723                if (connIntent == null) {
1724                    conn = ni.isConnected();
1725                } else {
1726                    final int networkType =
1727                            connIntent.getIntExtra(ConnectivityManager.EXTRA_NETWORK_TYPE,
1728                                    ConnectivityManager.TYPE_NONE);
1729                    if (ni.getType() != networkType) {
1730                        return;
1731                    }
1732                    conn = !connIntent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY,
1733                            false);
1734                }
1735            }
1736            if (conn != mNetworkConnected) {
1737                mNetworkConnected = conn;
1738                if (conn && mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
1739                    stepLightIdleStateLocked("network");
1740                }
1741            }
1742        }
1743    }
1744
1745    void updateDisplayLocked() {
1746        mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1747        // We consider any situation where the display is showing something to be it on,
1748        // because if there is anything shown we are going to be updating it at some
1749        // frequency so can't be allowed to go into deep sleeps.
1750        boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
1751        if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
1752        if (!screenOn && mScreenOn) {
1753            mScreenOn = false;
1754            if (!mForceIdle) {
1755                becomeInactiveIfAppropriateLocked();
1756            }
1757        } else if (screenOn) {
1758            mScreenOn = true;
1759            if (!mForceIdle) {
1760                becomeActiveLocked("screen", Process.myUid());
1761            }
1762        }
1763    }
1764
1765    void updateChargingLocked(boolean charging) {
1766        if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
1767        if (!charging && mCharging) {
1768            mCharging = false;
1769            if (!mForceIdle) {
1770                becomeInactiveIfAppropriateLocked();
1771            }
1772        } else if (charging) {
1773            mCharging = charging;
1774            if (!mForceIdle) {
1775                becomeActiveLocked("charging", Process.myUid());
1776            }
1777        }
1778    }
1779
1780    void scheduleReportActiveLocked(String activeReason, int activeUid) {
1781        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid, 0, activeReason);
1782        mHandler.sendMessage(msg);
1783    }
1784
1785    void becomeActiveLocked(String activeReason, int activeUid) {
1786        if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
1787        if (mState != STATE_ACTIVE || mLightState != STATE_ACTIVE) {
1788            EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1789            EventLogTags.writeDeviceIdleLight(LIGHT_STATE_ACTIVE, activeReason);
1790            scheduleReportActiveLocked(activeReason, activeUid);
1791            mState = STATE_ACTIVE;
1792            mLightState = LIGHT_STATE_ACTIVE;
1793            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1794            mCurIdleBudget = 0;
1795            mMaintenanceStartTime = 0;
1796            resetIdleManagementLocked();
1797            resetLightIdleManagementLocked();
1798            addEvent(EVENT_NORMAL);
1799        }
1800    }
1801
1802    void becomeInactiveIfAppropriateLocked() {
1803        if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
1804        if ((!mScreenOn && !mCharging) || mForceIdle) {
1805            // Screen has turned off; we are now going to become inactive and start
1806            // waiting to see if we will ultimately go idle.
1807            if (mState == STATE_ACTIVE && mDeepEnabled) {
1808                mState = STATE_INACTIVE;
1809                if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
1810                resetIdleManagementLocked();
1811                scheduleAlarmLocked(mInactiveTimeout, false);
1812                EventLogTags.writeDeviceIdle(mState, "no activity");
1813            }
1814            if (mLightState == LIGHT_STATE_ACTIVE && mLightEnabled) {
1815                mLightState = LIGHT_STATE_INACTIVE;
1816                if (DEBUG) Slog.d(TAG, "Moved from LIGHT_STATE_ACTIVE to LIGHT_STATE_INACTIVE");
1817                resetLightIdleManagementLocked();
1818                scheduleLightAlarmLocked(mConstants.LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT);
1819                EventLogTags.writeDeviceIdleLight(mLightState, "no activity");
1820            }
1821        }
1822    }
1823
1824    void resetIdleManagementLocked() {
1825        mNextIdlePendingDelay = 0;
1826        mNextIdleDelay = 0;
1827        mNextLightIdleDelay = 0;
1828        cancelAlarmLocked();
1829        cancelSensingTimeoutAlarmLocked();
1830        cancelLocatingLocked();
1831        stopMonitoringMotionLocked();
1832        mAnyMotionDetector.stop();
1833    }
1834
1835    void resetLightIdleManagementLocked() {
1836        cancelLightAlarmLocked();
1837    }
1838
1839    void exitForceIdleLocked() {
1840        if (mForceIdle) {
1841            mForceIdle = false;
1842            if (mScreenOn || mCharging) {
1843                becomeActiveLocked("exit-force", Process.myUid());
1844            }
1845        }
1846    }
1847
1848    void stepLightIdleStateLocked(String reason) {
1849        if (mLightState == LIGHT_STATE_OVERRIDE) {
1850            // If we are already in deep device idle mode, then
1851            // there is nothing left to do for light mode.
1852            return;
1853        }
1854
1855        if (DEBUG) Slog.d(TAG, "stepLightIdleStateLocked: mLightState=" + mLightState);
1856        EventLogTags.writeDeviceIdleLightStep();
1857
1858        switch (mLightState) {
1859            case LIGHT_STATE_INACTIVE:
1860                mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
1861                // Reset the upcoming idle delays.
1862                mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
1863                mMaintenanceStartTime = 0;
1864                if (!isOpsInactiveLocked()) {
1865                    // We have some active ops going on...  give them a chance to finish
1866                    // before going in to our first idle.
1867                    mLightState = LIGHT_STATE_PRE_IDLE;
1868                    EventLogTags.writeDeviceIdleLight(mLightState, reason);
1869                    scheduleLightAlarmLocked(mConstants.LIGHT_PRE_IDLE_TIMEOUT);
1870                    break;
1871                }
1872                // Nothing active, fall through to immediately idle.
1873            case LIGHT_STATE_PRE_IDLE:
1874            case LIGHT_STATE_IDLE_MAINTENANCE:
1875                if (mMaintenanceStartTime != 0) {
1876                    long duration = SystemClock.elapsedRealtime() - mMaintenanceStartTime;
1877                    if (duration < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
1878                        // We didn't use up all of our minimum budget; add this to the reserve.
1879                        mCurIdleBudget += (mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET-duration);
1880                    } else {
1881                        // We used more than our minimum budget; this comes out of the reserve.
1882                        mCurIdleBudget -= (duration-mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET);
1883                    }
1884                }
1885                mMaintenanceStartTime = 0;
1886                scheduleLightAlarmLocked(mNextLightIdleDelay);
1887                mNextLightIdleDelay = Math.min(mConstants.LIGHT_MAX_IDLE_TIMEOUT,
1888                        (long)(mNextLightIdleDelay * mConstants.LIGHT_IDLE_FACTOR));
1889                if (mNextLightIdleDelay < mConstants.LIGHT_IDLE_TIMEOUT) {
1890                    mNextLightIdleDelay = mConstants.LIGHT_IDLE_TIMEOUT;
1891                }
1892                if (DEBUG) Slog.d(TAG, "Moved to LIGHT_STATE_IDLE.");
1893                mLightState = LIGHT_STATE_IDLE;
1894                EventLogTags.writeDeviceIdleLight(mLightState, reason);
1895                addEvent(EVENT_LIGHT_IDLE);
1896                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON_LIGHT);
1897                break;
1898            case LIGHT_STATE_IDLE:
1899            case LIGHT_STATE_WAITING_FOR_NETWORK:
1900                if (mNetworkConnected || mLightState == LIGHT_STATE_WAITING_FOR_NETWORK) {
1901                    // We have been idling long enough, now it is time to do some work.
1902                    mActiveIdleOpCount = 1;
1903                    mActiveIdleWakeLock.acquire();
1904                    mMaintenanceStartTime = SystemClock.elapsedRealtime();
1905                    if (mCurIdleBudget < mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET) {
1906                        mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MIN_BUDGET;
1907                    } else if (mCurIdleBudget > mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET) {
1908                        mCurIdleBudget = mConstants.LIGHT_IDLE_MAINTENANCE_MAX_BUDGET;
1909                    }
1910                    scheduleLightAlarmLocked(mCurIdleBudget);
1911                    if (DEBUG) Slog.d(TAG,
1912                            "Moved from LIGHT_STATE_IDLE to LIGHT_STATE_IDLE_MAINTENANCE.");
1913                    mLightState = LIGHT_STATE_IDLE_MAINTENANCE;
1914                    EventLogTags.writeDeviceIdleLight(mLightState, reason);
1915                    addEvent(EVENT_LIGHT_MAINTENANCE);
1916                    mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1917                } else {
1918                    // We'd like to do maintenance, but currently don't have network
1919                    // connectivity...  let's try to wait until the network comes back.
1920                    // We'll only wait for another full idle period, however, and then give up.
1921                    scheduleLightAlarmLocked(mNextLightIdleDelay);
1922                    if (DEBUG) Slog.d(TAG, "Moved to LIGHT_WAITING_FOR_NETWORK.");
1923                    mLightState = LIGHT_STATE_WAITING_FOR_NETWORK;
1924                    EventLogTags.writeDeviceIdleLight(mLightState, reason);
1925                }
1926                break;
1927        }
1928    }
1929
1930    void stepIdleStateLocked(String reason) {
1931        if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
1932        EventLogTags.writeDeviceIdleStep();
1933
1934        final long now = SystemClock.elapsedRealtime();
1935        if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
1936            // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
1937            if (mState != STATE_ACTIVE) {
1938                becomeActiveLocked("alarm", Process.myUid());
1939                becomeInactiveIfAppropriateLocked();
1940            }
1941            return;
1942        }
1943
1944        switch (mState) {
1945            case STATE_INACTIVE:
1946                // We have now been inactive long enough, it is time to start looking
1947                // for motion and sleep some more while doing so.
1948                startMonitoringMotionLocked();
1949                scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
1950                // Reset the upcoming idle delays.
1951                mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1952                mNextIdleDelay = mConstants.IDLE_TIMEOUT;
1953                mState = STATE_IDLE_PENDING;
1954                if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
1955                EventLogTags.writeDeviceIdle(mState, reason);
1956                break;
1957            case STATE_IDLE_PENDING:
1958                mState = STATE_SENSING;
1959                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
1960                EventLogTags.writeDeviceIdle(mState, reason);
1961                scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
1962                cancelLocatingLocked();
1963                mNotMoving = false;
1964                mLocated = false;
1965                mLastGenericLocation = null;
1966                mLastGpsLocation = null;
1967                mAnyMotionDetector.checkForAnyMotion();
1968                break;
1969            case STATE_SENSING:
1970                cancelSensingTimeoutAlarmLocked();
1971                mState = STATE_LOCATING;
1972                if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1973                EventLogTags.writeDeviceIdle(mState, reason);
1974                scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
1975                if (mLocationManager != null
1976                        && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) {
1977                    mLocationManager.requestLocationUpdates(mLocationRequest,
1978                            mGenericLocationListener, mHandler.getLooper());
1979                    mLocating = true;
1980                } else {
1981                    mHasNetworkLocation = false;
1982                }
1983                if (mLocationManager != null
1984                        && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1985                    mHasGps = true;
1986                    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1987                            mGpsLocationListener, mHandler.getLooper());
1988                    mLocating = true;
1989                } else {
1990                    mHasGps = false;
1991                }
1992                // If we have a location provider, we're all set, the listeners will move state
1993                // forward.
1994                if (mLocating) {
1995                    break;
1996                }
1997
1998                // Otherwise, we have to move from locating into idle maintenance.
1999            case STATE_LOCATING:
2000                cancelAlarmLocked();
2001                cancelLocatingLocked();
2002                mAnyMotionDetector.stop();
2003
2004            case STATE_IDLE_MAINTENANCE:
2005                scheduleAlarmLocked(mNextIdleDelay, true);
2006                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
2007                        " ms.");
2008                mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
2009                if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
2010                mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
2011                if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
2012                    mNextIdleDelay = mConstants.IDLE_TIMEOUT;
2013                }
2014                mState = STATE_IDLE;
2015                if (mLightState != LIGHT_STATE_OVERRIDE) {
2016                    mLightState = LIGHT_STATE_OVERRIDE;
2017                    cancelLightAlarmLocked();
2018                }
2019                EventLogTags.writeDeviceIdle(mState, reason);
2020                addEvent(EVENT_DEEP_IDLE);
2021                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
2022                break;
2023            case STATE_IDLE:
2024                // We have been idling long enough, now it is time to do some work.
2025                mActiveIdleOpCount = 1;
2026                mActiveIdleWakeLock.acquire();
2027                scheduleAlarmLocked(mNextIdlePendingDelay, false);
2028                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
2029                        "Next alarm in " + mNextIdlePendingDelay + " ms.");
2030                mMaintenanceStartTime = SystemClock.elapsedRealtime();
2031                mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
2032                        (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
2033                if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
2034                    mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
2035                }
2036                mState = STATE_IDLE_MAINTENANCE;
2037                EventLogTags.writeDeviceIdle(mState, reason);
2038                addEvent(EVENT_DEEP_MAINTENANCE);
2039                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
2040                break;
2041        }
2042    }
2043
2044    void incActiveIdleOps() {
2045        synchronized (this) {
2046            mActiveIdleOpCount++;
2047        }
2048    }
2049
2050    void decActiveIdleOps() {
2051        synchronized (this) {
2052            mActiveIdleOpCount--;
2053            if (mActiveIdleOpCount <= 0) {
2054                exitMaintenanceEarlyIfNeededLocked();
2055                mActiveIdleWakeLock.release();
2056            }
2057        }
2058    }
2059
2060    void downloadServiceActive(IBinder token) {
2061        synchronized (this) {
2062            mDownloadServiceActive = token;
2063            reportMaintenanceActivityIfNeededLocked();
2064            try {
2065                token.linkToDeath(new IBinder.DeathRecipient() {
2066                    @Override public void binderDied() {
2067                        downloadServiceInactive();
2068                    }
2069                }, 0);
2070            } catch (RemoteException e) {
2071                mDownloadServiceActive = null;
2072            }
2073        }
2074    }
2075
2076    void downloadServiceInactive() {
2077        synchronized (this) {
2078            mDownloadServiceActive = null;
2079            reportMaintenanceActivityIfNeededLocked();
2080            exitMaintenanceEarlyIfNeededLocked();
2081        }
2082    }
2083
2084    void setJobsActive(boolean active) {
2085        synchronized (this) {
2086            mJobsActive = active;
2087            reportMaintenanceActivityIfNeededLocked();
2088            if (!active) {
2089                exitMaintenanceEarlyIfNeededLocked();
2090            }
2091        }
2092    }
2093
2094    void setAlarmsActive(boolean active) {
2095        synchronized (this) {
2096            mAlarmsActive = active;
2097            if (!active) {
2098                exitMaintenanceEarlyIfNeededLocked();
2099            }
2100        }
2101    }
2102
2103    boolean registerMaintenanceActivityListener(IMaintenanceActivityListener listener) {
2104        synchronized (this) {
2105            mMaintenanceActivityListeners.register(listener);
2106            return mReportedMaintenanceActivity;
2107        }
2108    }
2109
2110    void unregisterMaintenanceActivityListener(IMaintenanceActivityListener listener) {
2111        synchronized (this) {
2112            mMaintenanceActivityListeners.unregister(listener);
2113        }
2114    }
2115
2116    void reportMaintenanceActivityIfNeededLocked() {
2117        boolean active = mJobsActive | (mDownloadServiceActive != null);
2118        if (active == mReportedMaintenanceActivity) {
2119            return;
2120        }
2121        mReportedMaintenanceActivity = active;
2122        Message msg = mHandler.obtainMessage(MSG_REPORT_MAINTENANCE_ACTIVITY,
2123                mReportedMaintenanceActivity ? 1 : 0, 0);
2124        mHandler.sendMessage(msg);
2125    }
2126
2127    boolean isOpsInactiveLocked() {
2128        return mActiveIdleOpCount <= 0 && mDownloadServiceActive == null
2129                && !mJobsActive && !mAlarmsActive;
2130    }
2131
2132    void exitMaintenanceEarlyIfNeededLocked() {
2133        if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE
2134                || mLightState == LIGHT_STATE_PRE_IDLE) {
2135            if (isOpsInactiveLocked()) {
2136                final long now = SystemClock.elapsedRealtime();
2137                if (DEBUG) {
2138                    StringBuilder sb = new StringBuilder();
2139                    sb.append("Exit: start=");
2140                    TimeUtils.formatDuration(mMaintenanceStartTime, sb);
2141                    sb.append(" now=");
2142                    TimeUtils.formatDuration(now, sb);
2143                    Slog.d(TAG, sb.toString());
2144                }
2145                if (mState == STATE_IDLE_MAINTENANCE) {
2146                    stepIdleStateLocked("s:early");
2147                } else if (mLightState == LIGHT_STATE_PRE_IDLE) {
2148                    stepLightIdleStateLocked("s:predone");
2149                } else {
2150                    stepLightIdleStateLocked("s:early");
2151                }
2152            }
2153        }
2154    }
2155
2156    void motionLocked() {
2157        if (DEBUG) Slog.d(TAG, "motionLocked()");
2158        // The motion sensor will have been disabled at this point
2159        handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
2160    }
2161
2162    void handleMotionDetectedLocked(long timeout, String type) {
2163        // The device is not yet active, so we want to go back to the pending idle
2164        // state to wait again for no motion.  Note that we only monitor for motion
2165        // after moving out of the inactive state, so no need to worry about that.
2166        boolean becomeInactive = false;
2167        if (mState != STATE_ACTIVE) {
2168            scheduleReportActiveLocked(type, Process.myUid());
2169            mState = STATE_ACTIVE;
2170            mInactiveTimeout = timeout;
2171            mCurIdleBudget = 0;
2172            mMaintenanceStartTime = 0;
2173            EventLogTags.writeDeviceIdle(mState, type);
2174            addEvent(EVENT_NORMAL);
2175            becomeInactive = true;
2176        }
2177        if (mLightState == LIGHT_STATE_OVERRIDE) {
2178            // We went out of light idle mode because we had started deep idle mode...  let's
2179            // now go back and reset things so we resume light idling if appropriate.
2180            mLightState = STATE_ACTIVE;
2181            EventLogTags.writeDeviceIdleLight(mLightState, type);
2182            becomeInactive = true;
2183        }
2184        if (becomeInactive) {
2185            becomeInactiveIfAppropriateLocked();
2186        }
2187    }
2188
2189    void receivedGenericLocationLocked(Location location) {
2190        if (mState != STATE_LOCATING) {
2191            cancelLocatingLocked();
2192            return;
2193        }
2194        if (DEBUG) Slog.d(TAG, "Generic location: " + location);
2195        mLastGenericLocation = new Location(location);
2196        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) {
2197            return;
2198        }
2199        mLocated = true;
2200        if (mNotMoving) {
2201            stepIdleStateLocked("s:location");
2202        }
2203    }
2204
2205    void receivedGpsLocationLocked(Location location) {
2206        if (mState != STATE_LOCATING) {
2207            cancelLocatingLocked();
2208            return;
2209        }
2210        if (DEBUG) Slog.d(TAG, "GPS location: " + location);
2211        mLastGpsLocation = new Location(location);
2212        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
2213            return;
2214        }
2215        mLocated = true;
2216        if (mNotMoving) {
2217            stepIdleStateLocked("s:gps");
2218        }
2219    }
2220
2221    void startMonitoringMotionLocked() {
2222        if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()");
2223        if (mMotionSensor != null && !mMotionListener.active) {
2224            mMotionListener.registerLocked();
2225        }
2226    }
2227
2228    void stopMonitoringMotionLocked() {
2229        if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()");
2230        if (mMotionSensor != null && mMotionListener.active) {
2231            mMotionListener.unregisterLocked();
2232        }
2233    }
2234
2235    void cancelAlarmLocked() {
2236        if (mNextAlarmTime != 0) {
2237            mNextAlarmTime = 0;
2238            mAlarmManager.cancel(mDeepAlarmListener);
2239        }
2240    }
2241
2242    void cancelLightAlarmLocked() {
2243        if (mNextLightAlarmTime != 0) {
2244            mNextLightAlarmTime = 0;
2245            mAlarmManager.cancel(mLightAlarmListener);
2246        }
2247    }
2248
2249    void cancelLocatingLocked() {
2250        if (mLocating) {
2251            mLocationManager.removeUpdates(mGenericLocationListener);
2252            mLocationManager.removeUpdates(mGpsLocationListener);
2253            mLocating = false;
2254        }
2255    }
2256
2257    void cancelSensingTimeoutAlarmLocked() {
2258        if (mNextSensingTimeoutAlarmTime != 0) {
2259            mNextSensingTimeoutAlarmTime = 0;
2260            mAlarmManager.cancel(mSensingTimeoutAlarmListener);
2261        }
2262    }
2263
2264    void scheduleAlarmLocked(long delay, boolean idleUntil) {
2265        if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
2266        if (mMotionSensor == null) {
2267            // If there is no motion sensor on this device, then we won't schedule
2268            // alarms, because we can't determine if the device is not moving.  This effectively
2269            // turns off normal execution of device idling, although it is still possible to
2270            // manually poke it by pretending like the alarm is going off.
2271            return;
2272        }
2273        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
2274        if (idleUntil) {
2275            mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2276                    mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
2277        } else {
2278            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2279                    mNextAlarmTime, "DeviceIdleController.deep", mDeepAlarmListener, mHandler);
2280        }
2281    }
2282
2283    void scheduleLightAlarmLocked(long delay) {
2284        if (DEBUG) Slog.d(TAG, "scheduleLightAlarmLocked(" + delay + ")");
2285        mNextLightAlarmTime = SystemClock.elapsedRealtime() + delay;
2286        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
2287                mNextLightAlarmTime, "DeviceIdleController.light", mLightAlarmListener, mHandler);
2288    }
2289
2290    void scheduleSensingTimeoutAlarmLocked(long delay) {
2291        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
2292        mNextSensingTimeoutAlarmTime = SystemClock.elapsedRealtime() + delay;
2293        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, mNextSensingTimeoutAlarmTime,
2294            "DeviceIdleController.sensing", mSensingTimeoutAlarmListener, mHandler);
2295    }
2296
2297    private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
2298            ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
2299        outAppIds.clear();
2300        if (systemApps != null) {
2301            for (int i = 0; i < systemApps.size(); i++) {
2302                outAppIds.put(systemApps.valueAt(i), true);
2303            }
2304        }
2305        if (userApps != null) {
2306            for (int i = 0; i < userApps.size(); i++) {
2307                outAppIds.put(userApps.valueAt(i), true);
2308            }
2309        }
2310        int size = outAppIds.size();
2311        int[] appids = new int[size];
2312        for (int i = 0; i < size; i++) {
2313            appids[i] = outAppIds.keyAt(i);
2314        }
2315        return appids;
2316    }
2317
2318    private void updateWhitelistAppIdsLocked() {
2319        mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
2320                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
2321        mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
2322                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
2323        mPowerSaveWhitelistUserAppIdArray = buildAppIdArray(null,
2324                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistUserAppIds);
2325        if (mLocalPowerManager != null) {
2326            if (DEBUG) {
2327                Slog.d(TAG, "Setting wakelock whitelist to "
2328                        + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
2329            }
2330            mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
2331        }
2332        if (mLocalAlarmManager != null) {
2333            if (DEBUG) {
2334                Slog.d(TAG, "Setting alarm whitelist to "
2335                        + Arrays.toString(mPowerSaveWhitelistUserAppIdArray));
2336            }
2337            mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
2338        }
2339    }
2340
2341    private void updateTempWhitelistAppIdsLocked() {
2342        final int size = mTempWhitelistAppIdEndTimes.size();
2343        if (mTempWhitelistAppIdArray.length != size) {
2344            mTempWhitelistAppIdArray = new int[size];
2345        }
2346        for (int i = 0; i < size; i++) {
2347            mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
2348        }
2349        if (mLocalPowerManager != null) {
2350            if (DEBUG) {
2351                Slog.d(TAG, "Setting wakelock temp whitelist to "
2352                        + Arrays.toString(mTempWhitelistAppIdArray));
2353            }
2354            mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
2355        }
2356    }
2357
2358    private void reportPowerSaveWhitelistChangedLocked() {
2359        Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
2360        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2361        getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
2362    }
2363
2364    private void reportTempWhitelistChangedLocked() {
2365        Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
2366        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
2367        getContext().sendBroadcastAsUser(intent, UserHandle.SYSTEM);
2368    }
2369
2370    void readConfigFileLocked() {
2371        if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
2372        mPowerSaveWhitelistUserApps.clear();
2373        FileInputStream stream;
2374        try {
2375            stream = mConfigFile.openRead();
2376        } catch (FileNotFoundException e) {
2377            return;
2378        }
2379        try {
2380            XmlPullParser parser = Xml.newPullParser();
2381            parser.setInput(stream, StandardCharsets.UTF_8.name());
2382            readConfigFileLocked(parser);
2383        } catch (XmlPullParserException e) {
2384        } finally {
2385            try {
2386                stream.close();
2387            } catch (IOException e) {
2388            }
2389        }
2390    }
2391
2392    private void readConfigFileLocked(XmlPullParser parser) {
2393        final PackageManager pm = getContext().getPackageManager();
2394
2395        try {
2396            int type;
2397            while ((type = parser.next()) != XmlPullParser.START_TAG
2398                    && type != XmlPullParser.END_DOCUMENT) {
2399                ;
2400            }
2401
2402            if (type != XmlPullParser.START_TAG) {
2403                throw new IllegalStateException("no start tag found");
2404            }
2405
2406            int outerDepth = parser.getDepth();
2407            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
2408                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
2409                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
2410                    continue;
2411                }
2412
2413                String tagName = parser.getName();
2414                if (tagName.equals("wl")) {
2415                    String name = parser.getAttributeValue(null, "n");
2416                    if (name != null) {
2417                        try {
2418                            ApplicationInfo ai = pm.getApplicationInfo(name,
2419                                    PackageManager.MATCH_UNINSTALLED_PACKAGES);
2420                            mPowerSaveWhitelistUserApps.put(ai.packageName,
2421                                    UserHandle.getAppId(ai.uid));
2422                        } catch (PackageManager.NameNotFoundException e) {
2423                        }
2424                    }
2425                } else {
2426                    Slog.w(TAG, "Unknown element under <config>: "
2427                            + parser.getName());
2428                    XmlUtils.skipCurrentTag(parser);
2429                }
2430            }
2431
2432        } catch (IllegalStateException e) {
2433            Slog.w(TAG, "Failed parsing config " + e);
2434        } catch (NullPointerException e) {
2435            Slog.w(TAG, "Failed parsing config " + e);
2436        } catch (NumberFormatException e) {
2437            Slog.w(TAG, "Failed parsing config " + e);
2438        } catch (XmlPullParserException e) {
2439            Slog.w(TAG, "Failed parsing config " + e);
2440        } catch (IOException e) {
2441            Slog.w(TAG, "Failed parsing config " + e);
2442        } catch (IndexOutOfBoundsException e) {
2443            Slog.w(TAG, "Failed parsing config " + e);
2444        }
2445    }
2446
2447    void writeConfigFileLocked() {
2448        mHandler.removeMessages(MSG_WRITE_CONFIG);
2449        mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
2450    }
2451
2452    void handleWriteConfigFile() {
2453        final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
2454
2455        try {
2456            synchronized (this) {
2457                XmlSerializer out = new FastXmlSerializer();
2458                out.setOutput(memStream, StandardCharsets.UTF_8.name());
2459                writeConfigFileLocked(out);
2460            }
2461        } catch (IOException e) {
2462        }
2463
2464        synchronized (mConfigFile) {
2465            FileOutputStream stream = null;
2466            try {
2467                stream = mConfigFile.startWrite();
2468                memStream.writeTo(stream);
2469                stream.flush();
2470                FileUtils.sync(stream);
2471                stream.close();
2472                mConfigFile.finishWrite(stream);
2473            } catch (IOException e) {
2474                Slog.w(TAG, "Error writing config file", e);
2475                mConfigFile.failWrite(stream);
2476            }
2477        }
2478    }
2479
2480    void writeConfigFileLocked(XmlSerializer out) throws IOException {
2481        out.startDocument(null, true);
2482        out.startTag(null, "config");
2483        for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
2484            String name = mPowerSaveWhitelistUserApps.keyAt(i);
2485            out.startTag(null, "wl");
2486            out.attribute(null, "n", name);
2487            out.endTag(null, "wl");
2488        }
2489        out.endTag(null, "config");
2490        out.endDocument();
2491    }
2492
2493    static void dumpHelp(PrintWriter pw) {
2494        pw.println("Device idle controller (deviceidle) commands:");
2495        pw.println("  help");
2496        pw.println("    Print this help text.");
2497        pw.println("  step [light|deep]");
2498        pw.println("    Immediately step to next state, without waiting for alarm.");
2499        pw.println("  force-idle [light|deep]");
2500        pw.println("    Force directly into idle mode, regardless of other device state.");
2501        pw.println("  force-inactive");
2502        pw.println("    Force to be inactive, ready to freely step idle states.");
2503        pw.println("  unforce");
2504        pw.println("    Resume normal functioning after force-idle or force-inactive.");
2505        pw.println("  get [light|deep|force|screen|charging|network]");
2506        pw.println("    Retrieve the current given state.");
2507        pw.println("  disable [light|deep|all]");
2508        pw.println("    Completely disable device idle mode.");
2509        pw.println("  enable [light|deep|all]");
2510        pw.println("    Re-enable device idle mode after it had previously been disabled.");
2511        pw.println("  enabled [light|deep|all]");
2512        pw.println("    Print 1 if device idle mode is currently enabled, else 0.");
2513        pw.println("  whitelist");
2514        pw.println("    Print currently whitelisted apps.");
2515        pw.println("  whitelist [package ...]");
2516        pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
2517        pw.println("  tempwhitelist [-u] [package ..]");
2518        pw.println("    Temporarily place packages in whitelist for 10 seconds.");
2519    }
2520
2521    class Shell extends ShellCommand {
2522        int userId = UserHandle.USER_SYSTEM;
2523
2524        @Override
2525        public int onCommand(String cmd) {
2526            return onShellCommand(this, cmd);
2527        }
2528
2529        @Override
2530        public void onHelp() {
2531            PrintWriter pw = getOutPrintWriter();
2532            dumpHelp(pw);
2533        }
2534    }
2535
2536    int onShellCommand(Shell shell, String cmd) {
2537        PrintWriter pw = shell.getOutPrintWriter();
2538        if ("step".equals(cmd)) {
2539            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2540                    null);
2541            synchronized (this) {
2542                long token = Binder.clearCallingIdentity();
2543                String arg = shell.getNextArg();
2544                try {
2545                    if (arg == null || "deep".equals(arg)) {
2546                        stepIdleStateLocked("s:shell");
2547                        pw.print("Stepped to deep: ");
2548                        pw.println(stateToString(mState));
2549                    } else if ("light".equals(arg)) {
2550                        stepLightIdleStateLocked("s:shell");
2551                        pw.print("Stepped to light: "); pw.println(lightStateToString(mLightState));
2552                    } else {
2553                        pw.println("Unknown idle mode: " + arg);
2554                    }
2555                } finally {
2556                    Binder.restoreCallingIdentity(token);
2557                }
2558            }
2559        } else if ("force-idle".equals(cmd)) {
2560            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2561                    null);
2562            synchronized (this) {
2563                long token = Binder.clearCallingIdentity();
2564                String arg = shell.getNextArg();
2565                try {
2566                    if (arg == null || "deep".equals(arg)) {
2567                        if (!mDeepEnabled) {
2568                            pw.println("Unable to go deep idle; not enabled");
2569                            return -1;
2570                        }
2571                        mForceIdle = true;
2572                        becomeInactiveIfAppropriateLocked();
2573                        int curState = mState;
2574                        while (curState != STATE_IDLE) {
2575                            stepIdleStateLocked("s:shell");
2576                            if (curState == mState) {
2577                                pw.print("Unable to go deep idle; stopped at ");
2578                                pw.println(stateToString(mState));
2579                                exitForceIdleLocked();
2580                                return -1;
2581                            }
2582                            curState = mState;
2583                        }
2584                        pw.println("Now forced in to deep idle mode");
2585                    } else if ("light".equals(arg)) {
2586                        mForceIdle = true;
2587                        becomeInactiveIfAppropriateLocked();
2588                        int curLightState = mLightState;
2589                        while (curLightState != LIGHT_STATE_IDLE) {
2590                            stepIdleStateLocked("s:shell");
2591                            if (curLightState == mLightState) {
2592                                pw.print("Unable to go light idle; stopped at ");
2593                                pw.println(lightStateToString(mLightState));
2594                                exitForceIdleLocked();
2595                                return -1;
2596                            }
2597                            curLightState = mLightState;
2598                        }
2599                        pw.println("Now forced in to light idle mode");
2600                    } else {
2601                        pw.println("Unknown idle mode: " + arg);
2602                    }
2603                } finally {
2604                    Binder.restoreCallingIdentity(token);
2605                }
2606            }
2607        } else if ("force-inactive".equals(cmd)) {
2608            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2609                    null);
2610            synchronized (this) {
2611                long token = Binder.clearCallingIdentity();
2612                try {
2613                    mForceIdle = true;
2614                    becomeInactiveIfAppropriateLocked();
2615                    pw.print("Light state: ");
2616                    pw.print(lightStateToString(mLightState));
2617                    pw.print(", deep state: ");
2618                    pw.println(stateToString(mState));
2619                } finally {
2620                    Binder.restoreCallingIdentity(token);
2621                }
2622            }
2623        } else if ("unforce".equals(cmd)) {
2624            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2625                    null);
2626            synchronized (this) {
2627                long token = Binder.clearCallingIdentity();
2628                try {
2629                    exitForceIdleLocked();
2630                    pw.print("Light state: ");
2631                    pw.print(lightStateToString(mLightState));
2632                    pw.print(", deep state: ");
2633                    pw.println(stateToString(mState));
2634                } finally {
2635                    Binder.restoreCallingIdentity(token);
2636                }
2637            }
2638        } else if ("get".equals(cmd)) {
2639            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2640                    null);
2641            synchronized (this) {
2642                String arg = shell.getNextArg();
2643                if (arg != null) {
2644                    long token = Binder.clearCallingIdentity();
2645                    try {
2646                        switch (arg) {
2647                            case "light": pw.println(lightStateToString(mLightState)); break;
2648                            case "deep": pw.println(stateToString(mState)); break;
2649                            case "force": pw.println(mForceIdle); break;
2650                            case "screen": pw.println(mScreenOn); break;
2651                            case "charging": pw.println(mCharging); break;
2652                            case "network": pw.println(mNetworkConnected); break;
2653                            default: pw.println("Unknown get option: " + arg); break;
2654                        }
2655                    } finally {
2656                        Binder.restoreCallingIdentity(token);
2657                    }
2658                } else {
2659                    pw.println("Argument required");
2660                }
2661            }
2662        } else if ("disable".equals(cmd)) {
2663            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2664                    null);
2665            synchronized (this) {
2666                long token = Binder.clearCallingIdentity();
2667                String arg = shell.getNextArg();
2668                try {
2669                    boolean becomeActive = false;
2670                    boolean valid = false;
2671                    if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
2672                        valid = true;
2673                        if (mDeepEnabled) {
2674                            mDeepEnabled = false;
2675                            becomeActive = true;
2676                            pw.println("Deep idle mode disabled");
2677                        }
2678                    }
2679                    if (arg == null || "light".equals(arg) || "all".equals(arg)) {
2680                        valid = true;
2681                        if (mLightEnabled) {
2682                            mLightEnabled = false;
2683                            becomeActive = true;
2684                            pw.println("Light idle mode disabled");
2685                        }
2686                    }
2687                    if (becomeActive) {
2688                        becomeActiveLocked((arg == null ? "all" : arg) + "-disabled",
2689                                Process.myUid());
2690                    }
2691                    if (!valid) {
2692                        pw.println("Unknown idle mode: " + arg);
2693                    }
2694                } finally {
2695                    Binder.restoreCallingIdentity(token);
2696                }
2697            }
2698        } else if ("enable".equals(cmd)) {
2699            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
2700                    null);
2701            synchronized (this) {
2702                long token = Binder.clearCallingIdentity();
2703                String arg = shell.getNextArg();
2704                try {
2705                    boolean becomeInactive = false;
2706                    boolean valid = false;
2707                    if (arg == null || "deep".equals(arg) || "all".equals(arg)) {
2708                        valid = true;
2709                        if (!mDeepEnabled) {
2710                            mDeepEnabled = true;
2711                            becomeInactive = true;
2712                            pw.println("Deep idle mode enabled");
2713                        }
2714                    }
2715                    if (arg == null || "light".equals(arg) || "all".equals(arg)) {
2716                        valid = true;
2717                        if (!mLightEnabled) {
2718                            mLightEnabled = true;
2719                            becomeInactive = true;
2720                            pw.println("Light idle mode enable");
2721                        }
2722                    }
2723                    if (becomeInactive) {
2724                        becomeInactiveIfAppropriateLocked();
2725                    }
2726                    if (!valid) {
2727                        pw.println("Unknown idle mode: " + arg);
2728                    }
2729                } finally {
2730                    Binder.restoreCallingIdentity(token);
2731                }
2732            }
2733        } else if ("enabled".equals(cmd)) {
2734            synchronized (this) {
2735                String arg = shell.getNextArg();
2736                if (arg == null || "all".equals(arg)) {
2737                    pw.println(mDeepEnabled && mLightEnabled ? "1" : 0);
2738                } else if ("deep".equals(arg)) {
2739                    pw.println(mDeepEnabled ? "1" : 0);
2740                } else if ("light".equals(arg)) {
2741                    pw.println(mLightEnabled ? "1" : 0);
2742                } else {
2743                    pw.println("Unknown idle mode: " + arg);
2744                }
2745            }
2746        } else if ("whitelist".equals(cmd)) {
2747            long token = Binder.clearCallingIdentity();
2748            try {
2749                String arg = shell.getNextArg();
2750                if (arg != null) {
2751                    getContext().enforceCallingOrSelfPermission(
2752                            android.Manifest.permission.DEVICE_POWER, null);
2753                    do {
2754                        if (arg.length() < 1 || (arg.charAt(0) != '-'
2755                                && arg.charAt(0) != '+' && arg.charAt(0) != '=')) {
2756                            pw.println("Package must be prefixed with +, -, or =: " + arg);
2757                            return -1;
2758                        }
2759                        char op = arg.charAt(0);
2760                        String pkg = arg.substring(1);
2761                        if (op == '+') {
2762                            if (addPowerSaveWhitelistAppInternal(pkg)) {
2763                                pw.println("Added: " + pkg);
2764                            } else {
2765                                pw.println("Unknown package: " + pkg);
2766                            }
2767                        } else if (op == '-') {
2768                            if (removePowerSaveWhitelistAppInternal(pkg)) {
2769                                pw.println("Removed: " + pkg);
2770                            }
2771                        } else {
2772                            pw.println(getPowerSaveWhitelistAppInternal(pkg));
2773                        }
2774                    } while ((arg=shell.getNextArg()) != null);
2775                } else {
2776                    synchronized (this) {
2777                        for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
2778                            pw.print("system-excidle,");
2779                            pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
2780                            pw.print(",");
2781                            pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
2782                        }
2783                        for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
2784                            pw.print("system,");
2785                            pw.print(mPowerSaveWhitelistApps.keyAt(j));
2786                            pw.print(",");
2787                            pw.println(mPowerSaveWhitelistApps.valueAt(j));
2788                        }
2789                        for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
2790                            pw.print("user,");
2791                            pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
2792                            pw.print(",");
2793                            pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
2794                        }
2795                    }
2796                }
2797            } finally {
2798                Binder.restoreCallingIdentity(token);
2799            }
2800        } else if ("tempwhitelist".equals(cmd)) {
2801            String opt;
2802            while ((opt=shell.getNextOption()) != null) {
2803                if ("-u".equals(opt)) {
2804                    opt = shell.getNextArg();
2805                    if (opt == null) {
2806                        pw.println("-u requires a user number");
2807                        return -1;
2808                    }
2809                    shell.userId = Integer.parseInt(opt);
2810                }
2811            }
2812            String arg = shell.getNextArg();
2813            if (arg != null) {
2814                try {
2815                    addPowerSaveTempWhitelistAppChecked(arg, 10000L, shell.userId, "shell");
2816                } catch (RemoteException re) {
2817                    pw.println("Failed: " + re);
2818                }
2819            } else {
2820                pw.println("At least one package name must be specified");
2821                return -1;
2822            }
2823        } else {
2824            return shell.handleDefaultCommands(cmd);
2825        }
2826        return 0;
2827    }
2828
2829    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2830        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
2831                != PackageManager.PERMISSION_GRANTED) {
2832            pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
2833                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
2834                    + " without permission " + android.Manifest.permission.DUMP);
2835            return;
2836        }
2837
2838        if (args != null) {
2839            int userId = UserHandle.USER_SYSTEM;
2840            for (int i=0; i<args.length; i++) {
2841                String arg = args[i];
2842                if ("-h".equals(arg)) {
2843                    dumpHelp(pw);
2844                    return;
2845                } else if ("-u".equals(arg)) {
2846                    i++;
2847                    if (i < args.length) {
2848                        arg = args[i];
2849                        userId = Integer.parseInt(arg);
2850                    }
2851                } else if ("-a".equals(arg)) {
2852                    // Ignore, we always dump all.
2853                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
2854                    pw.println("Unknown option: " + arg);
2855                    return;
2856                } else {
2857                    Shell shell = new Shell();
2858                    shell.userId = userId;
2859                    String[] newArgs = new String[args.length-i];
2860                    System.arraycopy(args, i, newArgs, 0, args.length-i);
2861                    shell.exec(mBinderService, null, fd, null, newArgs, new ResultReceiver(null));
2862                    return;
2863                }
2864            }
2865        }
2866
2867        synchronized (this) {
2868            mConstants.dump(pw);
2869
2870            if (mEventCmds[0] != EVENT_NULL) {
2871                pw.println("  Idling history:");
2872                long now = SystemClock.elapsedRealtime();
2873                for (int i=EVENT_BUFFER_SIZE-1; i>=0; i--) {
2874                    int cmd = mEventCmds[i];
2875                    if (cmd == EVENT_NULL) {
2876                        continue;
2877                    }
2878                    String label;
2879                    switch (mEventCmds[i]) {
2880                        case EVENT_NORMAL:              label = "     normal"; break;
2881                        case EVENT_LIGHT_IDLE:          label = " light-idle"; break;
2882                        case EVENT_LIGHT_MAINTENANCE:   label = "light-maint"; break;
2883                        case EVENT_DEEP_IDLE:           label = "  deep-idle"; break;
2884                        case EVENT_DEEP_MAINTENANCE:    label = " deep-maint"; break;
2885                        default:                        label = "         ??"; break;
2886                    }
2887                    pw.print("    ");
2888                    pw.print(label);
2889                    pw.print(": ");
2890                    TimeUtils.formatDuration(mEventTimes[i], now, pw);;
2891                    pw.println();
2892                }
2893            }
2894
2895            int size = mPowerSaveWhitelistAppsExceptIdle.size();
2896            if (size > 0) {
2897                pw.println("  Whitelist (except idle) system apps:");
2898                for (int i = 0; i < size; i++) {
2899                    pw.print("    ");
2900                    pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
2901                }
2902            }
2903            size = mPowerSaveWhitelistApps.size();
2904            if (size > 0) {
2905                pw.println("  Whitelist system apps:");
2906                for (int i = 0; i < size; i++) {
2907                    pw.print("    ");
2908                    pw.println(mPowerSaveWhitelistApps.keyAt(i));
2909                }
2910            }
2911            size = mPowerSaveWhitelistUserApps.size();
2912            if (size > 0) {
2913                pw.println("  Whitelist user apps:");
2914                for (int i = 0; i < size; i++) {
2915                    pw.print("    ");
2916                    pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
2917                }
2918            }
2919            size = mPowerSaveWhitelistExceptIdleAppIds.size();
2920            if (size > 0) {
2921                pw.println("  Whitelist (except idle) all app ids:");
2922                for (int i = 0; i < size; i++) {
2923                    pw.print("    ");
2924                    pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
2925                    pw.println();
2926                }
2927            }
2928            size = mPowerSaveWhitelistUserAppIds.size();
2929            if (size > 0) {
2930                pw.println("  Whitelist user app ids:");
2931                for (int i = 0; i < size; i++) {
2932                    pw.print("    ");
2933                    pw.print(mPowerSaveWhitelistUserAppIds.keyAt(i));
2934                    pw.println();
2935                }
2936            }
2937            size = mPowerSaveWhitelistAllAppIds.size();
2938            if (size > 0) {
2939                pw.println("  Whitelist all app ids:");
2940                for (int i = 0; i < size; i++) {
2941                    pw.print("    ");
2942                    pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
2943                    pw.println();
2944                }
2945            }
2946            size = mTempWhitelistAppIdEndTimes.size();
2947            if (size > 0) {
2948                pw.println("  Temp whitelist schedule:");
2949                final long timeNow = SystemClock.elapsedRealtime();
2950                for (int i = 0; i < size; i++) {
2951                    pw.print("    UID=");
2952                    pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
2953                    pw.print(": ");
2954                    Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
2955                    TimeUtils.formatDuration(entry.first.value, timeNow, pw);
2956                    pw.print(" - ");
2957                    pw.println(entry.second);
2958                }
2959            }
2960            size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
2961            if (size > 0) {
2962                pw.println("  Temp whitelist app ids:");
2963                for (int i = 0; i < size; i++) {
2964                    pw.print("    ");
2965                    pw.print(mTempWhitelistAppIdArray[i]);
2966                    pw.println();
2967                }
2968            }
2969
2970            pw.print("  mLightEnabled="); pw.print(mLightEnabled);
2971            pw.print(" mDeepEnabled="); pw.println(mDeepEnabled);
2972            pw.print("  mForceIdle="); pw.println(mForceIdle);
2973            pw.print("  mMotionSensor="); pw.println(mMotionSensor);
2974            pw.print("  mCurDisplay="); pw.println(mCurDisplay);
2975            pw.print("  mScreenOn="); pw.println(mScreenOn);
2976            pw.print("  mNetworkConnected="); pw.println(mNetworkConnected);
2977            pw.print("  mCharging="); pw.println(mCharging);
2978            pw.print("  mMotionActive="); pw.println(mMotionListener.active);
2979            pw.print("  mNotMoving="); pw.println(mNotMoving);
2980            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
2981                    pw.print(mHasGps); pw.print(" mHasNetwork=");
2982                    pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated);
2983            if (mLastGenericLocation != null) {
2984                pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
2985            }
2986            if (mLastGpsLocation != null) {
2987                pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
2988            }
2989            pw.print("  mState="); pw.print(stateToString(mState));
2990            pw.print(" mLightState=");
2991            pw.println(lightStateToString(mLightState));
2992            pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
2993            pw.println();
2994            if (mActiveIdleOpCount != 0) {
2995                pw.print("  mActiveIdleOpCount="); pw.println(mActiveIdleOpCount);
2996            }
2997            if (mNextAlarmTime != 0) {
2998                pw.print("  mNextAlarmTime=");
2999                TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
3000                pw.println();
3001            }
3002            if (mNextIdlePendingDelay != 0) {
3003                pw.print("  mNextIdlePendingDelay=");
3004                TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
3005                pw.println();
3006            }
3007            if (mNextIdleDelay != 0) {
3008                pw.print("  mNextIdleDelay=");
3009                TimeUtils.formatDuration(mNextIdleDelay, pw);
3010                pw.println();
3011            }
3012            if (mNextLightIdleDelay != 0) {
3013                pw.print("  mNextIdleDelay=");
3014                TimeUtils.formatDuration(mNextLightIdleDelay, pw);
3015                pw.println();
3016            }
3017            if (mNextLightAlarmTime != 0) {
3018                pw.print("  mNextLightAlarmTime=");
3019                TimeUtils.formatDuration(mNextLightAlarmTime, SystemClock.elapsedRealtime(), pw);
3020                pw.println();
3021            }
3022            if (mCurIdleBudget != 0) {
3023                pw.print("  mCurIdleBudget=");
3024                TimeUtils.formatDuration(mCurIdleBudget, pw);
3025                pw.println();
3026            }
3027            if (mMaintenanceStartTime != 0) {
3028                pw.print("  mMaintenanceStartTime=");
3029                TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
3030                pw.println();
3031            }
3032            if (mJobsActive) {
3033                pw.print("  mJobsActive="); pw.println(mJobsActive);
3034            }
3035            if (mAlarmsActive) {
3036                pw.print("  mAlarmsActive="); pw.println(mAlarmsActive);
3037            }
3038            if (mDownloadServiceActive != null) {
3039                pw.print("  mDownloadServiceActive="); pw.println(mDownloadServiceActive);
3040            }
3041        }
3042    }
3043}
3044