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