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