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.app.PendingIntent;
23import android.content.BroadcastReceiver;
24import android.content.ContentResolver;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.ApplicationInfo;
29import android.content.pm.PackageManager;
30import android.content.pm.PackageManager.NameNotFoundException;
31import android.database.ContentObserver;
32import android.hardware.Sensor;
33import android.hardware.SensorManager;
34import android.hardware.TriggerEvent;
35import android.hardware.TriggerEventListener;
36import android.hardware.display.DisplayManager;
37import android.location.LocationRequest;
38import android.location.Location;
39import android.location.LocationListener;
40import android.location.LocationManager;
41import android.net.INetworkPolicyManager;
42import android.net.Uri;
43import android.os.BatteryStats;
44import android.os.Binder;
45import android.os.Bundle;
46import android.os.Environment;
47import android.os.FileUtils;
48import android.os.Handler;
49import android.os.IDeviceIdleController;
50import android.os.Looper;
51import android.os.Message;
52import android.os.PowerManager;
53import android.os.PowerManagerInternal;
54import android.os.Process;
55import android.os.RemoteException;
56import android.os.ServiceManager;
57import android.os.SystemClock;
58import android.os.UserHandle;
59import android.provider.Settings;
60import android.util.ArrayMap;
61import android.util.ArraySet;
62import android.util.KeyValueListParser;
63import android.util.MutableLong;
64import android.util.Pair;
65import android.util.Slog;
66import android.util.SparseArray;
67import android.util.SparseBooleanArray;
68import android.util.TimeUtils;
69import android.util.Xml;
70import android.view.Display;
71
72import com.android.internal.app.IBatteryStats;
73import com.android.internal.os.AtomicFile;
74import com.android.internal.os.BackgroundThread;
75import com.android.internal.util.FastXmlSerializer;
76import com.android.internal.util.XmlUtils;
77import com.android.server.am.BatteryStatsService;
78
79import org.xmlpull.v1.XmlPullParser;
80import org.xmlpull.v1.XmlPullParserException;
81import org.xmlpull.v1.XmlSerializer;
82
83import java.io.ByteArrayOutputStream;
84import java.io.File;
85import java.io.FileDescriptor;
86import java.io.FileInputStream;
87import java.io.FileNotFoundException;
88import java.io.FileOutputStream;
89import java.io.IOException;
90import java.io.PrintWriter;
91import java.nio.charset.StandardCharsets;
92import java.util.Arrays;
93
94/**
95 * Keeps track of device idleness and drives low power mode based on that.
96 */
97public class DeviceIdleController extends SystemService
98        implements AnyMotionDetector.DeviceIdleCallback {
99    private static final String TAG = "DeviceIdleController";
100
101    private static final boolean DEBUG = false;
102
103    private static final boolean COMPRESS_TIME = false;
104
105    private static final String ACTION_STEP_IDLE_STATE =
106            "com.android.server.device_idle.STEP_IDLE_STATE";
107
108    private AlarmManager mAlarmManager;
109    private IBatteryStats mBatteryStats;
110    private PowerManagerInternal mLocalPowerManager;
111    private INetworkPolicyManager mNetworkPolicyManager;
112    private DisplayManager mDisplayManager;
113    private SensorManager mSensorManager;
114    private Sensor mSigMotionSensor;
115    private LocationManager mLocationManager;
116    private LocationRequest mLocationRequest;
117    private PendingIntent mSensingAlarmIntent;
118    private PendingIntent mAlarmIntent;
119    private Intent mIdleIntent;
120    private Display mCurDisplay;
121    private AnyMotionDetector mAnyMotionDetector;
122    private boolean mEnabled;
123    private boolean mForceIdle;
124    private boolean mScreenOn;
125    private boolean mCharging;
126    private boolean mSigMotionActive;
127    private boolean mSensing;
128    private boolean mNotMoving;
129    private boolean mLocating;
130    private boolean mLocated;
131    private boolean mHaveGps;
132    private Location mLastGenericLocation;
133    private Location mLastGpsLocation;
134
135    /** Device is currently active. */
136    private static final int STATE_ACTIVE = 0;
137    /** Device is inactve (screen off, no motion) and we are waiting to for idle. */
138    private static final int STATE_INACTIVE = 1;
139    /** Device is past the initial inactive period, and waiting for the next idle period. */
140    private static final int STATE_IDLE_PENDING = 2;
141    /** Device is currently sensing motion. */
142    private static final int STATE_SENSING = 3;
143    /** Device is currently finding location (and may still be sensing). */
144    private static final int STATE_LOCATING = 4;
145    /** Device is in the idle state, trying to stay asleep as much as possible. */
146    private static final int STATE_IDLE = 5;
147    /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */
148    private static final int STATE_IDLE_MAINTENANCE = 6;
149    private static String stateToString(int state) {
150        switch (state) {
151            case STATE_ACTIVE: return "ACTIVE";
152            case STATE_INACTIVE: return "INACTIVE";
153            case STATE_IDLE_PENDING: return "IDLE_PENDING";
154            case STATE_SENSING: return "SENSING";
155            case STATE_LOCATING: return "LOCATING";
156            case STATE_IDLE: return "IDLE";
157            case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE";
158            default: return Integer.toString(state);
159        }
160    }
161
162    private int mState;
163
164    private long mInactiveTimeout;
165    private long mNextAlarmTime;
166    private long mNextIdlePendingDelay;
167    private long mNextIdleDelay;
168
169    public final AtomicFile mConfigFile;
170
171    /**
172     * Package names the system has white-listed to opt out of power save restrictions,
173     * except for device idle mode.
174     */
175    private final ArrayMap<String, Integer> mPowerSaveWhitelistAppsExceptIdle = new ArrayMap<>();
176
177    /**
178     * Package names the system has white-listed to opt out of power save restrictions for
179     * all modes.
180     */
181    private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>();
182
183    /**
184     * Package names the user has white-listed to opt out of power save restrictions.
185     */
186    private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>();
187
188    /**
189     * App IDs of built-in system apps that have been white-listed except for idle modes.
190     */
191    private final SparseBooleanArray mPowerSaveWhitelistSystemAppIdsExceptIdle
192            = new SparseBooleanArray();
193
194    /**
195     * App IDs of built-in system apps that have been white-listed.
196     */
197    private final SparseBooleanArray mPowerSaveWhitelistSystemAppIds = new SparseBooleanArray();
198
199    /**
200     * App IDs that have been white-listed to opt out of power save restrictions, except
201     * for device idle modes.
202     */
203    private final SparseBooleanArray mPowerSaveWhitelistExceptIdleAppIds = new SparseBooleanArray();
204
205    /**
206     * Current app IDs that are in the complete power save white list, but shouldn't be
207     * excluded from idle modes.  This array can be shared with others because it will not be
208     * modified once set.
209     */
210    private int[] mPowerSaveWhitelistExceptIdleAppIdArray = new int[0];
211
212    /**
213     * App IDs that have been white-listed to opt out of power save restrictions.
214     */
215    private final SparseBooleanArray mPowerSaveWhitelistAllAppIds = new SparseBooleanArray();
216
217    /**
218     * Current app IDs that are in the complete power save white list.  This array can
219     * be shared with others because it will not be modified once set.
220     */
221    private int[] mPowerSaveWhitelistAllAppIdArray = new int[0];
222
223    /**
224     * List of end times for UIDs that are temporarily marked as being allowed to access
225     * the network and acquire wakelocks. Times are in milliseconds.
226     */
227    private final SparseArray<Pair<MutableLong, String>> mTempWhitelistAppIdEndTimes
228            = new SparseArray<>();
229
230    /**
231     * Callback to the NetworkPolicyManagerService to tell it that the temp whitelist has changed.
232     */
233    Runnable mNetworkPolicyTempWhitelistCallback;
234
235    /**
236     * Current app IDs of temporarily whitelist apps for high-priority messages.
237     */
238    private int[] mTempWhitelistAppIdArray = new int[0];
239
240    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
241        @Override public void onReceive(Context context, Intent intent) {
242            if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
243                int plugged = intent.getIntExtra("plugged", 0);
244                updateChargingLocked(plugged != 0);
245            } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) {
246                synchronized (DeviceIdleController.this) {
247                    stepIdleStateLocked();
248                }
249            }
250        }
251    };
252
253    private final DisplayManager.DisplayListener mDisplayListener
254            = new DisplayManager.DisplayListener() {
255        @Override public void onDisplayAdded(int displayId) {
256        }
257
258        @Override public void onDisplayRemoved(int displayId) {
259        }
260
261        @Override public void onDisplayChanged(int displayId) {
262            if (displayId == Display.DEFAULT_DISPLAY) {
263                synchronized (DeviceIdleController.this) {
264                    updateDisplayLocked();
265                }
266            }
267        }
268    };
269
270    private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
271        @Override public void onTrigger(TriggerEvent event) {
272            synchronized (DeviceIdleController.this) {
273                significantMotionLocked();
274            }
275        }
276    };
277
278    private final LocationListener mGenericLocationListener = new LocationListener() {
279        @Override
280        public void onLocationChanged(Location location) {
281            synchronized (DeviceIdleController.this) {
282                receivedGenericLocationLocked(location);
283            }
284        }
285
286        @Override
287        public void onStatusChanged(String provider, int status, Bundle extras) {
288        }
289
290        @Override
291        public void onProviderEnabled(String provider) {
292        }
293
294        @Override
295        public void onProviderDisabled(String provider) {
296        }
297    };
298
299    private final LocationListener mGpsLocationListener = new LocationListener() {
300        @Override
301        public void onLocationChanged(Location location) {
302            synchronized (DeviceIdleController.this) {
303                receivedGpsLocationLocked(location);
304            }
305        }
306
307        @Override
308        public void onStatusChanged(String provider, int status, Bundle extras) {
309        }
310
311        @Override
312        public void onProviderEnabled(String provider) {
313        }
314
315        @Override
316        public void onProviderDisabled(String provider) {
317        }
318    };
319
320    /**
321     * All times are in milliseconds. These constants are kept synchronized with the system
322     * global Settings. Any access to this class or its fields should be done while
323     * holding the DeviceIdleController lock.
324     */
325    private final class Constants extends ContentObserver {
326        // Key names stored in the settings value.
327        private static final String KEY_INACTIVE_TIMEOUT = "inactive_to";
328        private static final String KEY_SENSING_TIMEOUT = "sensing_to";
329        private static final String KEY_LOCATING_TIMEOUT = "locating_to";
330        private static final String KEY_LOCATION_ACCURACY = "location_accuracy";
331        private static final String KEY_MOTION_INACTIVE_TIMEOUT = "motion_inactive_to";
332        private static final String KEY_IDLE_AFTER_INACTIVE_TIMEOUT = "idle_after_inactive_to";
333        private static final String KEY_IDLE_PENDING_TIMEOUT = "idle_pending_to";
334        private static final String KEY_MAX_IDLE_PENDING_TIMEOUT = "max_idle_pending_to";
335        private static final String KEY_IDLE_PENDING_FACTOR = "idle_pending_factor";
336        private static final String KEY_IDLE_TIMEOUT = "idle_to";
337        private static final String KEY_MAX_IDLE_TIMEOUT = "max_idle_to";
338        private static final String KEY_IDLE_FACTOR = "idle_factor";
339        private static final String KEY_MIN_TIME_TO_ALARM = "min_time_to_alarm";
340        private static final String KEY_MAX_TEMP_APP_WHITELIST_DURATION =
341                "max_temp_app_whitelist_duration";
342        private static final String KEY_MMS_TEMP_APP_WHITELIST_DURATION =
343                "mms_temp_app_whitelist_duration";
344        private static final String KEY_SMS_TEMP_APP_WHITELIST_DURATION =
345                "sms_temp_app_whitelist_duration";
346
347        /**
348         * This is the time, after becoming inactive, at which we start looking at the
349         * motion sensor to determine if the device is being left alone.  We don't do this
350         * immediately after going inactive just because we don't want to be continually running
351         * the significant motion sensor whenever the screen is off.
352         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
353         * @see #KEY_INACTIVE_TIMEOUT
354         */
355        public long INACTIVE_TIMEOUT;
356
357        /**
358         * If we don't receive a callback from AnyMotion in this amount of time +
359         * {@link #LOCATING_TIMEOUT}, we will change from
360         * STATE_SENSING to STATE_INACTIVE, and any AnyMotion callbacks while not in STATE_SENSING
361         * will be ignored.
362         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
363         * @see #KEY_SENSING_TIMEOUT
364         */
365        public long SENSING_TIMEOUT;
366
367        /**
368         * This is how long we will wait to try to get a good location fix before going in to
369         * idle mode.
370         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
371         * @see #KEY_LOCATING_TIMEOUT
372         */
373        public long LOCATING_TIMEOUT;
374
375        /**
376         * The desired maximum accuracy (in meters) we consider the location to be good enough to go
377         * on to idle.  We will be trying to get an accuracy fix at least this good or until
378         * {@link #LOCATING_TIMEOUT} expires.
379         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
380         * @see #KEY_LOCATION_ACCURACY
381         */
382        public float LOCATION_ACCURACY;
383
384        /**
385         * This is the time, after seeing motion, that we wait after becoming inactive from
386         * that until we start looking for motion again.
387         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
388         * @see #KEY_MOTION_INACTIVE_TIMEOUT
389         */
390        public long MOTION_INACTIVE_TIMEOUT;
391
392        /**
393         * This is the time, after the inactive timeout elapses, that we will wait looking
394         * for significant motion until we truly consider the device to be idle.
395         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
396         * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT
397         */
398        public long IDLE_AFTER_INACTIVE_TIMEOUT;
399
400        /**
401         * This is the initial time, after being idle, that we will allow ourself to be back
402         * in the IDLE_PENDING state allowing the system to run normally until we return to idle.
403         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
404         * @see #KEY_IDLE_PENDING_TIMEOUT
405         */
406        public long IDLE_PENDING_TIMEOUT;
407
408        /**
409         * Maximum pending idle timeout (time spent running) we will be allowed to use.
410         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
411         * @see #KEY_MAX_IDLE_PENDING_TIMEOUT
412         */
413        public long MAX_IDLE_PENDING_TIMEOUT;
414
415        /**
416         * Scaling factor to apply to current pending idle timeout each time we cycle through
417         * that state.
418         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
419         * @see #KEY_IDLE_PENDING_FACTOR
420         */
421        public float IDLE_PENDING_FACTOR;
422
423        /**
424         * This is the initial time that we want to sit in the idle state before waking up
425         * again to return to pending idle and allowing normal work to run.
426         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
427         * @see #KEY_IDLE_TIMEOUT
428         */
429        public long IDLE_TIMEOUT;
430
431        /**
432         * Maximum idle duration we will be allowed to use.
433         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
434         * @see #KEY_MAX_IDLE_TIMEOUT
435         */
436        public long MAX_IDLE_TIMEOUT;
437
438        /**
439         * Scaling factor to apply to current idle timeout each time we cycle through that state.
440          * @see Settings.Global#DEVICE_IDLE_CONSTANTS
441         * @see #KEY_IDLE_FACTOR
442         */
443        public float IDLE_FACTOR;
444
445        /**
446         * This is the minimum time we will allow until the next upcoming alarm for us to
447         * actually go in to idle mode.
448         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
449         * @see #KEY_MIN_TIME_TO_ALARM
450         */
451        public long MIN_TIME_TO_ALARM;
452
453        /**
454         * Max amount of time to temporarily whitelist an app when it receives a high priority
455         * tickle.
456         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
457         * @see #KEY_MAX_TEMP_APP_WHITELIST_DURATION
458         */
459        public long MAX_TEMP_APP_WHITELIST_DURATION;
460
461        /**
462         * Amount of time we would like to whitelist an app that is receiving an MMS.
463         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
464         * @see #KEY_MMS_TEMP_APP_WHITELIST_DURATION
465         */
466        public long MMS_TEMP_APP_WHITELIST_DURATION;
467
468        /**
469         * Amount of time we would like to whitelist an app that is receiving an SMS.
470         * @see Settings.Global#DEVICE_IDLE_CONSTANTS
471         * @see #KEY_SMS_TEMP_APP_WHITELIST_DURATION
472         */
473        public long SMS_TEMP_APP_WHITELIST_DURATION;
474
475        private final ContentResolver mResolver;
476        private final KeyValueListParser mParser = new KeyValueListParser(',');
477
478        public Constants(Handler handler, ContentResolver resolver) {
479            super(handler);
480            mResolver = resolver;
481            mResolver.registerContentObserver(
482                    Settings.Global.getUriFor(Settings.Global.DEVICE_IDLE_CONSTANTS), false, this);
483            updateConstants();
484        }
485
486        @Override
487        public void onChange(boolean selfChange, Uri uri) {
488            updateConstants();
489        }
490
491        private void updateConstants() {
492            synchronized (DeviceIdleController.this) {
493                try {
494                    mParser.setString(Settings.Global.getString(mResolver,
495                            Settings.Global.DEVICE_IDLE_CONSTANTS));
496                } catch (IllegalArgumentException e) {
497                    // Failed to parse the settings string, log this and move on
498                    // with defaults.
499                    Slog.e(TAG, "Bad device idle settings", e);
500                }
501
502                INACTIVE_TIMEOUT = mParser.getLong(KEY_INACTIVE_TIMEOUT,
503                        !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
504                SENSING_TIMEOUT = mParser.getLong(KEY_SENSING_TIMEOUT,
505                        !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
506                LOCATING_TIMEOUT = mParser.getLong(KEY_LOCATING_TIMEOUT,
507                        !DEBUG ? 30 * 1000L : 15 * 1000L);
508                LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
509                MOTION_INACTIVE_TIMEOUT = mParser.getLong(KEY_MOTION_INACTIVE_TIMEOUT,
510                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
511                IDLE_AFTER_INACTIVE_TIMEOUT = mParser.getLong(KEY_IDLE_AFTER_INACTIVE_TIMEOUT,
512                        !COMPRESS_TIME ? 30 * 60 * 1000L : 3 * 60 * 1000L);
513                IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_IDLE_PENDING_TIMEOUT,
514                        !COMPRESS_TIME ? 5 * 60 * 1000L : 30 * 1000L);
515                MAX_IDLE_PENDING_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_PENDING_TIMEOUT,
516                        !COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
517                IDLE_PENDING_FACTOR = mParser.getFloat(KEY_IDLE_PENDING_FACTOR,
518                        2f);
519                IDLE_TIMEOUT = mParser.getLong(KEY_IDLE_TIMEOUT,
520                        !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
521                MAX_IDLE_TIMEOUT = mParser.getLong(KEY_MAX_IDLE_TIMEOUT,
522                        !COMPRESS_TIME ? 6 * 60 * 60 * 1000L : 30 * 60 * 1000L);
523                IDLE_FACTOR = mParser.getFloat(KEY_IDLE_FACTOR,
524                        2f);
525                MIN_TIME_TO_ALARM = mParser.getLong(KEY_MIN_TIME_TO_ALARM,
526                        !COMPRESS_TIME ? 60 * 60 * 1000L : 6 * 60 * 1000L);
527                MAX_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
528                        KEY_MAX_TEMP_APP_WHITELIST_DURATION, 5 * 60 * 1000L);
529                MMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
530                        KEY_MMS_TEMP_APP_WHITELIST_DURATION, 60 * 1000L);
531                SMS_TEMP_APP_WHITELIST_DURATION = mParser.getLong(
532                        KEY_SMS_TEMP_APP_WHITELIST_DURATION, 20 * 1000L);
533            }
534        }
535
536        void dump(PrintWriter pw) {
537            pw.println("  Settings:");
538
539            pw.print("    "); pw.print(KEY_INACTIVE_TIMEOUT); pw.print("=");
540            TimeUtils.formatDuration(INACTIVE_TIMEOUT, pw);
541            pw.println();
542
543            pw.print("    "); pw.print(KEY_SENSING_TIMEOUT); pw.print("=");
544            TimeUtils.formatDuration(SENSING_TIMEOUT, pw);
545            pw.println();
546
547            pw.print("    "); pw.print(KEY_LOCATING_TIMEOUT); pw.print("=");
548            TimeUtils.formatDuration(LOCATING_TIMEOUT, pw);
549            pw.println();
550
551            pw.print("    "); pw.print(KEY_LOCATION_ACCURACY); pw.print("=");
552            pw.print(LOCATION_ACCURACY); pw.print("m");
553            pw.println();
554
555            pw.print("    "); pw.print(KEY_MOTION_INACTIVE_TIMEOUT); pw.print("=");
556            TimeUtils.formatDuration(MOTION_INACTIVE_TIMEOUT, pw);
557            pw.println();
558
559            pw.print("    "); pw.print(KEY_IDLE_AFTER_INACTIVE_TIMEOUT); pw.print("=");
560            TimeUtils.formatDuration(IDLE_AFTER_INACTIVE_TIMEOUT, pw);
561            pw.println();
562
563            pw.print("    "); pw.print(KEY_IDLE_PENDING_TIMEOUT); pw.print("=");
564            TimeUtils.formatDuration(IDLE_PENDING_TIMEOUT, pw);
565            pw.println();
566
567            pw.print("    "); pw.print(KEY_MAX_IDLE_PENDING_TIMEOUT); pw.print("=");
568            TimeUtils.formatDuration(MAX_IDLE_PENDING_TIMEOUT, pw);
569            pw.println();
570
571            pw.print("    "); pw.print(KEY_IDLE_PENDING_FACTOR); pw.print("=");
572            pw.println(IDLE_PENDING_FACTOR);
573
574            pw.print("    "); pw.print(KEY_IDLE_TIMEOUT); pw.print("=");
575            TimeUtils.formatDuration(IDLE_TIMEOUT, pw);
576            pw.println();
577
578            pw.print("    "); pw.print(KEY_MAX_IDLE_TIMEOUT); pw.print("=");
579            TimeUtils.formatDuration(MAX_IDLE_TIMEOUT, pw);
580            pw.println();
581
582            pw.print("    "); pw.print(KEY_IDLE_FACTOR); pw.print("=");
583            pw.println(IDLE_FACTOR);
584
585            pw.print("    "); pw.print(KEY_MIN_TIME_TO_ALARM); pw.print("=");
586            TimeUtils.formatDuration(MIN_TIME_TO_ALARM, pw);
587            pw.println();
588
589            pw.print("    "); pw.print(KEY_MAX_TEMP_APP_WHITELIST_DURATION); pw.print("=");
590            TimeUtils.formatDuration(MAX_TEMP_APP_WHITELIST_DURATION, pw);
591            pw.println();
592
593            pw.print("    "); pw.print(KEY_MMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
594            TimeUtils.formatDuration(MMS_TEMP_APP_WHITELIST_DURATION, pw);
595            pw.println();
596
597            pw.print("    "); pw.print(KEY_SMS_TEMP_APP_WHITELIST_DURATION); pw.print("=");
598            TimeUtils.formatDuration(SMS_TEMP_APP_WHITELIST_DURATION, pw);
599            pw.println();
600        }
601    }
602
603    private Constants mConstants;
604
605    @Override
606    public void onAnyMotionResult(int result) {
607        if (DEBUG) Slog.d(TAG, "onAnyMotionResult(" + result + ")");
608        if (result == AnyMotionDetector.RESULT_MOVED) {
609            if (DEBUG) Slog.d(TAG, "RESULT_MOVED received.");
610            synchronized (this) {
611                handleMotionDetectedLocked(mConstants.INACTIVE_TIMEOUT, "sense_motion");
612            }
613        } else if (result == AnyMotionDetector.RESULT_STATIONARY) {
614            if (DEBUG) Slog.d(TAG, "RESULT_STATIONARY received.");
615            if (mState == STATE_SENSING) {
616                // If we are currently sensing, it is time to move to locating.
617                synchronized (this) {
618                    mNotMoving = true;
619                    stepIdleStateLocked();
620                }
621            } else if (mState == STATE_LOCATING) {
622                // If we are currently locating, note that we are not moving and step
623                // if we have located the position.
624                synchronized (this) {
625                    mNotMoving = true;
626                    if (mLocated) {
627                        stepIdleStateLocked();
628                    }
629                }
630            }
631        }
632    }
633
634    static final int MSG_WRITE_CONFIG = 1;
635    static final int MSG_REPORT_IDLE_ON = 2;
636    static final int MSG_REPORT_IDLE_OFF = 3;
637    static final int MSG_REPORT_ACTIVE = 4;
638    static final int MSG_TEMP_APP_WHITELIST_TIMEOUT = 5;
639
640    final class MyHandler extends Handler {
641        MyHandler(Looper looper) {
642            super(looper);
643        }
644
645        @Override public void handleMessage(Message msg) {
646            if (DEBUG) Slog.d(TAG, "handleMessage(" + msg.what + ")");
647            switch (msg.what) {
648                case MSG_WRITE_CONFIG: {
649                    handleWriteConfigFile();
650                } break;
651                case MSG_REPORT_IDLE_ON: {
652                    EventLogTags.writeDeviceIdleOnStart();
653                    mLocalPowerManager.setDeviceIdleMode(true);
654                    try {
655                        mNetworkPolicyManager.setDeviceIdleMode(true);
656                        mBatteryStats.noteDeviceIdleMode(true, null, Process.myUid());
657                    } catch (RemoteException e) {
658                    }
659                    getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
660                    EventLogTags.writeDeviceIdleOnComplete();
661                } break;
662                case MSG_REPORT_IDLE_OFF: {
663                    EventLogTags.writeDeviceIdleOffStart("unknown");
664                    mLocalPowerManager.setDeviceIdleMode(false);
665                    try {
666                        mNetworkPolicyManager.setDeviceIdleMode(false);
667                        mBatteryStats.noteDeviceIdleMode(false, null, Process.myUid());
668                    } catch (RemoteException e) {
669                    }
670                    getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
671                    EventLogTags.writeDeviceIdleOffComplete();
672                } break;
673                case MSG_REPORT_ACTIVE: {
674                    String activeReason = (String)msg.obj;
675                    int activeUid = msg.arg1;
676                    boolean needBroadcast = msg.arg2 != 0;
677                    EventLogTags.writeDeviceIdleOffStart(
678                            activeReason != null ? activeReason : "unknown");
679                    mLocalPowerManager.setDeviceIdleMode(false);
680                    try {
681                        mNetworkPolicyManager.setDeviceIdleMode(false);
682                        mBatteryStats.noteDeviceIdleMode(false, activeReason, activeUid);
683                    } catch (RemoteException e) {
684                    }
685                    if (needBroadcast) {
686                        getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
687                    }
688                    EventLogTags.writeDeviceIdleOffComplete();
689                } break;
690                case MSG_TEMP_APP_WHITELIST_TIMEOUT: {
691                    int uid = msg.arg1;
692                    checkTempAppWhitelistTimeout(uid);
693                } break;
694            }
695        }
696    }
697
698    final MyHandler mHandler;
699
700    private final class BinderService extends IDeviceIdleController.Stub {
701        @Override public void addPowerSaveWhitelistApp(String name) {
702            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
703                    null);
704            addPowerSaveWhitelistAppInternal(name);
705        }
706
707        @Override public void removePowerSaveWhitelistApp(String name) {
708            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
709                    null);
710            removePowerSaveWhitelistAppInternal(name);
711        }
712
713        @Override public String[] getSystemPowerWhitelistExceptIdle() {
714            return getSystemPowerWhitelistExceptIdleInternal();
715        }
716
717        @Override public String[] getSystemPowerWhitelist() {
718            return getSystemPowerWhitelistInternal();
719        }
720
721        @Override public String[] getFullPowerWhitelistExceptIdle() {
722            return getFullPowerWhitelistExceptIdleInternal();
723        }
724
725        @Override public String[] getFullPowerWhitelist() {
726            return getFullPowerWhitelistInternal();
727        }
728
729        @Override public int[] getAppIdWhitelistExceptIdle() {
730            return getAppIdWhitelistExceptIdleInternal();
731        }
732
733        @Override public int[] getAppIdWhitelist() {
734            return getAppIdWhitelistInternal();
735        }
736
737        @Override public int[] getAppIdTempWhitelist() {
738            return getAppIdTempWhitelistInternal();
739        }
740
741        @Override public boolean isPowerSaveWhitelistExceptIdleApp(String name) {
742            return isPowerSaveWhitelistExceptIdleAppInternal(name);
743        }
744
745        @Override public boolean isPowerSaveWhitelistApp(String name) {
746            return isPowerSaveWhitelistAppInternal(name);
747        }
748
749        @Override public void addPowerSaveTempWhitelistApp(String packageName, long duration,
750                int userId, String reason) throws RemoteException {
751            getContext().enforceCallingPermission(
752                    Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST,
753                    "No permission to change device idle whitelist");
754            final int callingUid = Binder.getCallingUid();
755            userId = ActivityManagerNative.getDefault().handleIncomingUser(
756                    Binder.getCallingPid(),
757                    callingUid,
758                    userId,
759                    /*allowAll=*/ false,
760                    /*requireFull=*/ false,
761                    "addPowerSaveTempWhitelistApp", null);
762            final long token = Binder.clearCallingIdentity();
763            try {
764                DeviceIdleController.this.addPowerSaveTempWhitelistAppInternal(callingUid,
765                        packageName, duration, userId, true, reason);
766            } finally {
767                Binder.restoreCallingIdentity(token);
768            }
769        }
770
771        @Override public long addPowerSaveTempWhitelistAppForMms(String packageName,
772                int userId, String reason) throws RemoteException {
773            long duration = mConstants.MMS_TEMP_APP_WHITELIST_DURATION;
774            addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
775            return duration;
776        }
777
778        @Override public long addPowerSaveTempWhitelistAppForSms(String packageName,
779                int userId, String reason) throws RemoteException {
780            long duration = mConstants.SMS_TEMP_APP_WHITELIST_DURATION;
781            addPowerSaveTempWhitelistApp(packageName, duration, userId, reason);
782            return duration;
783        }
784
785        @Override public void exitIdle(String reason) {
786            getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
787                    null);
788            exitIdleInternal(reason);
789        }
790
791        @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
792            DeviceIdleController.this.dump(fd, pw, args);
793        }
794    }
795
796    public final class LocalService {
797        public void addPowerSaveTempWhitelistAppDirect(int appId, long duration, boolean sync,
798                String reason) {
799            addPowerSaveTempWhitelistAppDirectInternal(0, appId, duration, sync, reason);
800        }
801
802        public void setNetworkPolicyTempWhitelistCallback(Runnable callback) {
803            setNetworkPolicyTempWhitelistCallbackInternal(callback);
804        }
805    }
806
807    public DeviceIdleController(Context context) {
808        super(context);
809        mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
810        mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
811    }
812
813    private static File getSystemDir() {
814        return new File(Environment.getDataDirectory(), "system");
815    }
816
817    @Override
818    public void onStart() {
819        final PackageManager pm = getContext().getPackageManager();
820
821        synchronized (this) {
822            mEnabled = getContext().getResources().getBoolean(
823                    com.android.internal.R.bool.config_enableAutoPowerModes);
824            SystemConfig sysConfig = SystemConfig.getInstance();
825            ArraySet<String> allowPowerExceptIdle = sysConfig.getAllowInPowerSaveExceptIdle();
826            for (int i=0; i<allowPowerExceptIdle.size(); i++) {
827                String pkg = allowPowerExceptIdle.valueAt(i);
828                try {
829                    ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
830                    if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
831                        int appid = UserHandle.getAppId(ai.uid);
832                        mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
833                        mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
834                    }
835                } catch (PackageManager.NameNotFoundException e) {
836                }
837            }
838            ArraySet<String> allowPower = sysConfig.getAllowInPowerSave();
839            for (int i=0; i<allowPower.size(); i++) {
840                String pkg = allowPower.valueAt(i);
841                try {
842                    ApplicationInfo ai = pm.getApplicationInfo(pkg, 0);
843                    if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
844                        int appid = UserHandle.getAppId(ai.uid);
845                        // These apps are on both the whitelist-except-idle as well
846                        // as the full whitelist, so they apply in all cases.
847                        mPowerSaveWhitelistAppsExceptIdle.put(ai.packageName, appid);
848                        mPowerSaveWhitelistSystemAppIdsExceptIdle.put(appid, true);
849                        mPowerSaveWhitelistApps.put(ai.packageName, appid);
850                        mPowerSaveWhitelistSystemAppIds.put(appid, true);
851                    }
852                } catch (PackageManager.NameNotFoundException e) {
853                }
854            }
855
856            mConstants = new Constants(mHandler, getContext().getContentResolver());
857
858            readConfigFileLocked();
859            updateWhitelistAppIdsLocked();
860
861            mScreenOn = true;
862            // Start out assuming we are charging.  If we aren't, we will at least get
863            // a battery update the next time the level drops.
864            mCharging = true;
865            mState = STATE_ACTIVE;
866            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
867        }
868
869        publishBinderService(Context.DEVICE_IDLE_CONTROLLER, new BinderService());
870        publishLocalService(LocalService.class, new LocalService());
871    }
872
873    @Override
874    public void onBootPhase(int phase) {
875        if (phase == PHASE_SYSTEM_SERVICES_READY) {
876            synchronized (this) {
877                mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
878                mBatteryStats = BatteryStatsService.getService();
879                mLocalPowerManager = getLocalService(PowerManagerInternal.class);
880                mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
881                        ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
882                mDisplayManager = (DisplayManager) getContext().getSystemService(
883                        Context.DISPLAY_SERVICE);
884                mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
885                mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
886                mLocationManager = (LocationManager) getContext().getSystemService(
887                        Context.LOCATION_SERVICE);
888                mLocationRequest = new LocationRequest()
889                    .setQuality(LocationRequest.ACCURACY_FINE)
890                    .setInterval(0)
891                    .setFastestInterval(0)
892                    .setNumUpdates(1);
893                mAnyMotionDetector = new AnyMotionDetector(
894                        (PowerManager) getContext().getSystemService(Context.POWER_SERVICE),
895                        mHandler, mSensorManager, this);
896
897                Intent intent = new Intent(ACTION_STEP_IDLE_STATE)
898                        .setPackage("android")
899                        .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
900                mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
901
902                Intent intentSensing = new Intent(ACTION_STEP_IDLE_STATE)
903                        .setPackage("android")
904                        .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
905                mSensingAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intentSensing, 0);
906
907                mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
908                mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
909                        | Intent.FLAG_RECEIVER_FOREGROUND);
910
911                IntentFilter filter = new IntentFilter();
912                filter.addAction(Intent.ACTION_BATTERY_CHANGED);
913                filter.addAction(ACTION_STEP_IDLE_STATE);
914                getContext().registerReceiver(mReceiver, filter);
915
916                mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
917
918                mDisplayManager.registerDisplayListener(mDisplayListener, null);
919                updateDisplayLocked();
920            }
921        }
922    }
923
924    public boolean addPowerSaveWhitelistAppInternal(String name) {
925        synchronized (this) {
926            try {
927                ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0);
928                if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) {
929                    reportPowerSaveWhitelistChangedLocked();
930                    updateWhitelistAppIdsLocked();
931                    writeConfigFileLocked();
932                }
933                return true;
934            } catch (PackageManager.NameNotFoundException e) {
935                return false;
936            }
937        }
938    }
939
940    public boolean removePowerSaveWhitelistAppInternal(String name) {
941        synchronized (this) {
942            if (mPowerSaveWhitelistUserApps.remove(name) != null) {
943                reportPowerSaveWhitelistChangedLocked();
944                updateWhitelistAppIdsLocked();
945                writeConfigFileLocked();
946                return true;
947            }
948        }
949        return false;
950    }
951
952    public String[] getSystemPowerWhitelistExceptIdleInternal() {
953        synchronized (this) {
954            int size = mPowerSaveWhitelistAppsExceptIdle.size();
955            String[] apps = new String[size];
956            for (int i = 0; i < size; i++) {
957                apps[i] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
958            }
959            return apps;
960        }
961    }
962
963    public String[] getSystemPowerWhitelistInternal() {
964        synchronized (this) {
965            int size = mPowerSaveWhitelistApps.size();
966            String[] apps = new String[size];
967            for (int i = 0; i < size; i++) {
968                apps[i] = mPowerSaveWhitelistApps.keyAt(i);
969            }
970            return apps;
971        }
972    }
973
974    public String[] getFullPowerWhitelistExceptIdleInternal() {
975        synchronized (this) {
976            int size = mPowerSaveWhitelistAppsExceptIdle.size() + mPowerSaveWhitelistUserApps.size();
977            String[] apps = new String[size];
978            int cur = 0;
979            for (int i = 0; i < mPowerSaveWhitelistAppsExceptIdle.size(); i++) {
980                apps[cur] = mPowerSaveWhitelistAppsExceptIdle.keyAt(i);
981                cur++;
982            }
983            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
984                apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
985                cur++;
986            }
987            return apps;
988        }
989    }
990
991    public String[] getFullPowerWhitelistInternal() {
992        synchronized (this) {
993            int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size();
994            String[] apps = new String[size];
995            int cur = 0;
996            for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) {
997                apps[cur] = mPowerSaveWhitelistApps.keyAt(i);
998                cur++;
999            }
1000            for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) {
1001                apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i);
1002                cur++;
1003            }
1004            return apps;
1005        }
1006    }
1007
1008    public boolean isPowerSaveWhitelistExceptIdleAppInternal(String packageName) {
1009        synchronized (this) {
1010            return mPowerSaveWhitelistAppsExceptIdle.containsKey(packageName)
1011                    || mPowerSaveWhitelistUserApps.containsKey(packageName);
1012        }
1013    }
1014
1015    public boolean isPowerSaveWhitelistAppInternal(String packageName) {
1016        synchronized (this) {
1017            return mPowerSaveWhitelistApps.containsKey(packageName)
1018                    || mPowerSaveWhitelistUserApps.containsKey(packageName);
1019        }
1020    }
1021
1022    public int[] getAppIdWhitelistExceptIdleInternal() {
1023        synchronized (this) {
1024            return mPowerSaveWhitelistExceptIdleAppIdArray;
1025        }
1026    }
1027
1028    public int[] getAppIdWhitelistInternal() {
1029        synchronized (this) {
1030            return mPowerSaveWhitelistAllAppIdArray;
1031        }
1032    }
1033
1034    public int[] getAppIdTempWhitelistInternal() {
1035        synchronized (this) {
1036            return mTempWhitelistAppIdArray;
1037        }
1038    }
1039
1040    /**
1041     * Adds an app to the temporary whitelist and resets the endTime for granting the
1042     * app an exemption to access network and acquire wakelocks.
1043     */
1044    public void addPowerSaveTempWhitelistAppInternal(int callingUid, String packageName,
1045            long duration, int userId, boolean sync, String reason) {
1046        try {
1047            int uid = getContext().getPackageManager().getPackageUid(packageName, userId);
1048            int appId = UserHandle.getAppId(uid);
1049            addPowerSaveTempWhitelistAppDirectInternal(callingUid, appId, duration, sync, reason);
1050        } catch (NameNotFoundException e) {
1051        }
1052    }
1053
1054    /**
1055     * Adds an app to the temporary whitelist and resets the endTime for granting the
1056     * app an exemption to access network and acquire wakelocks.
1057     */
1058    public void addPowerSaveTempWhitelistAppDirectInternal(int callingUid, int appId,
1059            long duration, boolean sync, String reason) {
1060        final long timeNow = SystemClock.elapsedRealtime();
1061        Runnable networkPolicyTempWhitelistCallback = null;
1062        synchronized (this) {
1063            int callingAppId = UserHandle.getAppId(callingUid);
1064            if (callingAppId >= Process.FIRST_APPLICATION_UID) {
1065                if (!mPowerSaveWhitelistSystemAppIds.get(callingAppId)) {
1066                    throw new SecurityException("Calling app " + UserHandle.formatUid(callingUid)
1067                            + " is not on whitelist");
1068                }
1069            }
1070            duration = Math.min(duration, mConstants.MAX_TEMP_APP_WHITELIST_DURATION);
1071            Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(appId);
1072            final boolean newEntry = entry == null;
1073            // Set the new end time
1074            if (newEntry) {
1075                entry = new Pair<>(new MutableLong(0), reason);
1076                mTempWhitelistAppIdEndTimes.put(appId, entry);
1077            }
1078            entry.first.value = timeNow + duration;
1079            if (DEBUG) {
1080                Slog.d(TAG, "Adding AppId " + appId + " to temp whitelist");
1081            }
1082            if (newEntry) {
1083                // No pending timeout for the app id, post a delayed message
1084                try {
1085                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_START,
1086                            reason, appId);
1087                } catch (RemoteException e) {
1088                }
1089                postTempActiveTimeoutMessage(appId, duration);
1090                updateTempWhitelistAppIdsLocked();
1091                if (mNetworkPolicyTempWhitelistCallback != null) {
1092                    if (!sync) {
1093                        mHandler.post(mNetworkPolicyTempWhitelistCallback);
1094                    } else {
1095                        networkPolicyTempWhitelistCallback = mNetworkPolicyTempWhitelistCallback;
1096                    }
1097                }
1098                reportTempWhitelistChangedLocked();
1099            }
1100        }
1101        if (networkPolicyTempWhitelistCallback != null) {
1102            networkPolicyTempWhitelistCallback.run();
1103        }
1104    }
1105
1106    public void setNetworkPolicyTempWhitelistCallbackInternal(Runnable callback) {
1107        synchronized (this) {
1108            mNetworkPolicyTempWhitelistCallback = callback;
1109        }
1110    }
1111
1112    private void postTempActiveTimeoutMessage(int uid, long delay) {
1113        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_TEMP_APP_WHITELIST_TIMEOUT, uid, 0),
1114                delay);
1115    }
1116
1117    void checkTempAppWhitelistTimeout(int uid) {
1118        final long timeNow = SystemClock.elapsedRealtime();
1119        synchronized (this) {
1120            Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.get(uid);
1121            if (entry == null) {
1122                // Nothing to do
1123                return;
1124            }
1125            if (timeNow >= entry.first.value) {
1126                mTempWhitelistAppIdEndTimes.delete(uid);
1127                if (DEBUG) {
1128                    Slog.d(TAG, "Removing UID " + uid + " from temp whitelist");
1129                }
1130                updateTempWhitelistAppIdsLocked();
1131                if (mNetworkPolicyTempWhitelistCallback != null) {
1132                    mHandler.post(mNetworkPolicyTempWhitelistCallback);
1133                }
1134                reportTempWhitelistChangedLocked();
1135                try {
1136                    mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_TEMP_WHITELIST_FINISH,
1137                            entry.second, uid);
1138                } catch (RemoteException e) {
1139                }
1140            } else {
1141                // Need more time
1142                postTempActiveTimeoutMessage(uid, entry.first.value - timeNow);
1143            }
1144        }
1145    }
1146
1147    public void exitIdleInternal(String reason) {
1148        synchronized (this) {
1149            becomeActiveLocked(reason, Binder.getCallingUid());
1150        }
1151    }
1152
1153    void updateDisplayLocked() {
1154        mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
1155        // We consider any situation where the display is showing something to be it on,
1156        // because if there is anything shown we are going to be updating it at some
1157        // frequency so can't be allowed to go into deep sleeps.
1158        boolean screenOn = mCurDisplay.getState() == Display.STATE_ON;
1159        if (DEBUG) Slog.d(TAG, "updateDisplayLocked: screenOn=" + screenOn);
1160        if (!screenOn && mScreenOn) {
1161            mScreenOn = false;
1162            if (!mForceIdle) {
1163                becomeInactiveIfAppropriateLocked();
1164            }
1165        } else if (screenOn) {
1166            mScreenOn = true;
1167            if (!mForceIdle) {
1168                becomeActiveLocked("screen", Process.myUid());
1169            }
1170        }
1171    }
1172
1173    void updateChargingLocked(boolean charging) {
1174        if (DEBUG) Slog.i(TAG, "updateChargingLocked: charging=" + charging);
1175        if (!charging && mCharging) {
1176            mCharging = false;
1177            if (!mForceIdle) {
1178                becomeInactiveIfAppropriateLocked();
1179            }
1180        } else if (charging) {
1181            mCharging = charging;
1182            if (!mForceIdle) {
1183                becomeActiveLocked("charging", Process.myUid());
1184            }
1185        }
1186    }
1187
1188    void scheduleReportActiveLocked(String activeReason, int activeUid) {
1189        Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, activeUid,
1190                mState == STATE_IDLE ? 1 : 0, activeReason);
1191        mHandler.sendMessage(msg);
1192    }
1193
1194    void becomeActiveLocked(String activeReason, int activeUid) {
1195        if (DEBUG) Slog.i(TAG, "becomeActiveLocked, reason = " + activeReason);
1196        if (mState != STATE_ACTIVE) {
1197            EventLogTags.writeDeviceIdle(STATE_ACTIVE, activeReason);
1198            scheduleReportActiveLocked(activeReason, activeUid);
1199            mState = STATE_ACTIVE;
1200            mInactiveTimeout = mConstants.INACTIVE_TIMEOUT;
1201            resetIdleManagementLocked();
1202        }
1203    }
1204
1205    void becomeInactiveIfAppropriateLocked() {
1206        if (DEBUG) Slog.d(TAG, "becomeInactiveIfAppropriateLocked()");
1207        if (((!mScreenOn && !mCharging) || mForceIdle) && mEnabled && mState == STATE_ACTIVE) {
1208            // Screen has turned off; we are now going to become inactive and start
1209            // waiting to see if we will ultimately go idle.
1210            mState = STATE_INACTIVE;
1211            if (DEBUG) Slog.d(TAG, "Moved from STATE_ACTIVE to STATE_INACTIVE");
1212            resetIdleManagementLocked();
1213            scheduleAlarmLocked(mInactiveTimeout, false);
1214            EventLogTags.writeDeviceIdle(mState, "no activity");
1215        }
1216    }
1217
1218    void resetIdleManagementLocked() {
1219        mNextIdlePendingDelay = 0;
1220        mNextIdleDelay = 0;
1221        cancelAlarmLocked();
1222        cancelSensingAlarmLocked();
1223        cancelLocatingLocked();
1224        stopMonitoringSignificantMotion();
1225        mAnyMotionDetector.stop();
1226    }
1227
1228    void exitForceIdleLocked() {
1229        if (mForceIdle) {
1230            mForceIdle = false;
1231            if (mScreenOn || mCharging) {
1232                becomeActiveLocked("exit-force-idle", Process.myUid());
1233            }
1234        }
1235    }
1236
1237    void stepIdleStateLocked() {
1238        if (DEBUG) Slog.d(TAG, "stepIdleStateLocked: mState=" + mState);
1239        EventLogTags.writeDeviceIdleStep();
1240
1241        final long now = SystemClock.elapsedRealtime();
1242        if ((now+mConstants.MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) {
1243            // Whoops, there is an upcoming alarm.  We don't actually want to go idle.
1244            if (mState != STATE_ACTIVE) {
1245                becomeActiveLocked("alarm", Process.myUid());
1246            }
1247            return;
1248        }
1249
1250        switch (mState) {
1251            case STATE_INACTIVE:
1252                // We have now been inactive long enough, it is time to start looking
1253                // for significant motion and sleep some more while doing so.
1254                startMonitoringSignificantMotion();
1255                scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
1256                // Reset the upcoming idle delays.
1257                mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
1258                mNextIdleDelay = mConstants.IDLE_TIMEOUT;
1259                mState = STATE_IDLE_PENDING;
1260                if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
1261                EventLogTags.writeDeviceIdle(mState, "step");
1262                break;
1263            case STATE_IDLE_PENDING:
1264                mState = STATE_SENSING;
1265                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
1266                EventLogTags.writeDeviceIdle(mState, "step");
1267                scheduleSensingAlarmLocked(mConstants.SENSING_TIMEOUT);
1268                cancelSensingAlarmLocked();
1269                cancelLocatingLocked();
1270                mAnyMotionDetector.checkForAnyMotion();
1271                mNotMoving = false;
1272                mLocated = false;
1273                mLastGenericLocation = null;
1274                mLastGpsLocation = null;
1275                break;
1276            case STATE_SENSING:
1277                mState = STATE_LOCATING;
1278                if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
1279                EventLogTags.writeDeviceIdle(mState, "step");
1280                cancelSensingAlarmLocked();
1281                scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT);
1282                mLocating = true;
1283                mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener,
1284                        mHandler.getLooper());
1285                if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) {
1286                    mHaveGps = true;
1287                    mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5,
1288                            mGpsLocationListener, mHandler.getLooper());
1289                } else {
1290                    mHaveGps = false;
1291                }
1292                break;
1293            case STATE_LOCATING:
1294                cancelSensingAlarmLocked();
1295                cancelLocatingLocked();
1296                mAnyMotionDetector.stop();
1297            case STATE_IDLE_MAINTENANCE:
1298                scheduleAlarmLocked(mNextIdleDelay, true);
1299                if (DEBUG) Slog.d(TAG, "Moved to STATE_IDLE. Next alarm in " + mNextIdleDelay +
1300                        " ms.");
1301                mNextIdleDelay = (long)(mNextIdleDelay * mConstants.IDLE_FACTOR);
1302                if (DEBUG) Slog.d(TAG, "Setting mNextIdleDelay = " + mNextIdleDelay);
1303                mNextIdleDelay = Math.min(mNextIdleDelay, mConstants.MAX_IDLE_TIMEOUT);
1304                mState = STATE_IDLE;
1305                EventLogTags.writeDeviceIdle(mState, "step");
1306                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
1307                break;
1308            case STATE_IDLE:
1309                // We have been idling long enough, now it is time to do some work.
1310                scheduleAlarmLocked(mNextIdlePendingDelay, false);
1311                if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE to STATE_IDLE_MAINTENANCE. " +
1312                        "Next alarm in " + mNextIdlePendingDelay + " ms.");
1313                mNextIdlePendingDelay = Math.min(mConstants.MAX_IDLE_PENDING_TIMEOUT,
1314                        (long)(mNextIdlePendingDelay * mConstants.IDLE_PENDING_FACTOR));
1315                mState = STATE_IDLE_MAINTENANCE;
1316                EventLogTags.writeDeviceIdle(mState, "step");
1317                mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
1318                break;
1319        }
1320    }
1321
1322    void significantMotionLocked() {
1323        if (DEBUG) Slog.d(TAG, "significantMotionLocked()");
1324        // When the sensor goes off, its trigger is automatically removed.
1325        mSigMotionActive = false;
1326        handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion");
1327    }
1328
1329    void handleMotionDetectedLocked(long timeout, String type) {
1330        // The device is not yet active, so we want to go back to the pending idle
1331        // state to wait again for no motion.  Note that we only monitor for significant
1332        // motion after moving out of the inactive state, so no need to worry about that.
1333        if (mState != STATE_ACTIVE) {
1334            scheduleReportActiveLocked(type, Process.myUid());
1335            mState = STATE_ACTIVE;
1336            mInactiveTimeout = timeout;
1337            EventLogTags.writeDeviceIdle(mState, type);
1338            becomeInactiveIfAppropriateLocked();
1339        }
1340    }
1341
1342    void receivedGenericLocationLocked(Location location) {
1343        if (mState != STATE_LOCATING) {
1344            cancelLocatingLocked();
1345            return;
1346        }
1347        if (DEBUG) Slog.d(TAG, "Generic location: " + location);
1348        mLastGenericLocation = new Location(location);
1349        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) {
1350            return;
1351        }
1352        mLocated = true;
1353        if (mNotMoving) {
1354            stepIdleStateLocked();
1355        }
1356    }
1357
1358    void receivedGpsLocationLocked(Location location) {
1359        if (mState != STATE_LOCATING) {
1360            cancelLocatingLocked();
1361            return;
1362        }
1363        if (DEBUG) Slog.d(TAG, "GPS location: " + location);
1364        mLastGpsLocation = new Location(location);
1365        if (location.getAccuracy() > mConstants.LOCATION_ACCURACY) {
1366            return;
1367        }
1368        mLocated = true;
1369        if (mNotMoving) {
1370            stepIdleStateLocked();
1371        }
1372    }
1373
1374    void startMonitoringSignificantMotion() {
1375        if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()");
1376        if (mSigMotionSensor != null && !mSigMotionActive) {
1377            mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor);
1378            mSigMotionActive = true;
1379        }
1380    }
1381
1382    void stopMonitoringSignificantMotion() {
1383        if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()");
1384        if (mSigMotionActive) {
1385            mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor);
1386            mSigMotionActive = false;
1387        }
1388    }
1389
1390    void cancelAlarmLocked() {
1391        if (mNextAlarmTime != 0) {
1392            mNextAlarmTime = 0;
1393            mAlarmManager.cancel(mAlarmIntent);
1394        }
1395    }
1396
1397    void cancelSensingAlarmLocked() {
1398        if (mSensing) {
1399            if (DEBUG) Slog.d(TAG, "cancelSensingAlarmLocked()");
1400            mAlarmManager.cancel(mSensingAlarmIntent);
1401            mSensing = false;
1402        }
1403    }
1404
1405    void cancelLocatingLocked() {
1406        if (mLocating) {
1407            mLocationManager.removeUpdates(mGenericLocationListener);
1408            mLocationManager.removeUpdates(mGpsLocationListener);
1409            mLocating = false;
1410        }
1411    }
1412
1413    void scheduleAlarmLocked(long delay, boolean idleUntil) {
1414        if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")");
1415        if (mSigMotionSensor == null) {
1416            // If there is no significant motion sensor on this device, then we won't schedule
1417            // alarms, because we can't determine if the device is not moving.  This effectively
1418            // turns off normal exeuction of device idling, although it is still possible to
1419            // manually poke it by pretending like the alarm is going off.
1420            return;
1421        }
1422        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1423        if (idleUntil) {
1424            mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1425                    mNextAlarmTime, mAlarmIntent);
1426        } else {
1427            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1428                    mNextAlarmTime, mAlarmIntent);
1429        }
1430    }
1431
1432    void scheduleSensingAlarmLocked(long delay) {
1433        if (DEBUG) Slog.d(TAG, "scheduleSensingAlarmLocked(" + delay + ")");
1434        cancelSensingAlarmLocked();
1435        mNextAlarmTime = SystemClock.elapsedRealtime() + delay;
1436        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
1437            mNextAlarmTime, mSensingAlarmIntent);
1438        mSensing = true;
1439    }
1440
1441    private static int[] buildAppIdArray(ArrayMap<String, Integer> systemApps,
1442            ArrayMap<String, Integer> userApps, SparseBooleanArray outAppIds) {
1443        outAppIds.clear();
1444        for (int i=0; i<systemApps.size(); i++) {
1445            outAppIds.put(systemApps.valueAt(i), true);
1446        }
1447        for (int i=0; i<userApps.size(); i++) {
1448            outAppIds.put(userApps.valueAt(i), true);
1449        }
1450        int size = outAppIds.size();
1451        int[] appids = new int[size];
1452        for (int i = 0; i < size; i++) {
1453            appids[i] = outAppIds.keyAt(i);
1454        }
1455        return appids;
1456    }
1457
1458    private void updateWhitelistAppIdsLocked() {
1459        mPowerSaveWhitelistExceptIdleAppIdArray = buildAppIdArray(mPowerSaveWhitelistAppsExceptIdle,
1460                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistExceptIdleAppIds);
1461        mPowerSaveWhitelistAllAppIdArray = buildAppIdArray(mPowerSaveWhitelistApps,
1462                mPowerSaveWhitelistUserApps, mPowerSaveWhitelistAllAppIds);
1463        if (mLocalPowerManager != null) {
1464            if (DEBUG) {
1465                Slog.d(TAG, "Setting wakelock whitelist to "
1466                        + Arrays.toString(mPowerSaveWhitelistAllAppIdArray));
1467            }
1468            mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
1469        }
1470    }
1471
1472    private void updateTempWhitelistAppIdsLocked() {
1473        final int size = mTempWhitelistAppIdEndTimes.size();
1474        if (mTempWhitelistAppIdArray.length != size) {
1475            mTempWhitelistAppIdArray = new int[size];
1476        }
1477        for (int i = 0; i < size; i++) {
1478            mTempWhitelistAppIdArray[i] = mTempWhitelistAppIdEndTimes.keyAt(i);
1479        }
1480        if (mLocalPowerManager != null) {
1481            if (DEBUG) {
1482                Slog.d(TAG, "Setting wakelock temp whitelist to "
1483                        + Arrays.toString(mTempWhitelistAppIdArray));
1484            }
1485            mLocalPowerManager.setDeviceIdleTempWhitelist(mTempWhitelistAppIdArray);
1486        }
1487    }
1488
1489    private void reportPowerSaveWhitelistChangedLocked() {
1490        Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
1491        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1492        getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
1493    }
1494
1495    private void reportTempWhitelistChangedLocked() {
1496        Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_TEMP_WHITELIST_CHANGED);
1497        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1498        getContext().sendBroadcastAsUser(intent, UserHandle.OWNER);
1499    }
1500
1501    void readConfigFileLocked() {
1502        if (DEBUG) Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile());
1503        mPowerSaveWhitelistUserApps.clear();
1504        FileInputStream stream;
1505        try {
1506            stream = mConfigFile.openRead();
1507        } catch (FileNotFoundException e) {
1508            return;
1509        }
1510        try {
1511            XmlPullParser parser = Xml.newPullParser();
1512            parser.setInput(stream, StandardCharsets.UTF_8.name());
1513            readConfigFileLocked(parser);
1514        } catch (XmlPullParserException e) {
1515        } finally {
1516            try {
1517                stream.close();
1518            } catch (IOException e) {
1519            }
1520        }
1521
1522    }
1523
1524    private void readConfigFileLocked(XmlPullParser parser) {
1525        final PackageManager pm = getContext().getPackageManager();
1526
1527        try {
1528            int type;
1529            while ((type = parser.next()) != XmlPullParser.START_TAG
1530                    && type != XmlPullParser.END_DOCUMENT) {
1531                ;
1532            }
1533
1534            if (type != XmlPullParser.START_TAG) {
1535                throw new IllegalStateException("no start tag found");
1536            }
1537
1538            int outerDepth = parser.getDepth();
1539            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
1540                    && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
1541                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
1542                    continue;
1543                }
1544
1545                String tagName = parser.getName();
1546                if (tagName.equals("wl")) {
1547                    String name = parser.getAttributeValue(null, "n");
1548                    if (name != null) {
1549                        try {
1550                            ApplicationInfo ai = pm.getApplicationInfo(name, 0);
1551                            mPowerSaveWhitelistUserApps.put(ai.packageName,
1552                                    UserHandle.getAppId(ai.uid));
1553                        } catch (PackageManager.NameNotFoundException e) {
1554                        }
1555                    }
1556                } else {
1557                    Slog.w(TAG, "Unknown element under <config>: "
1558                            + parser.getName());
1559                    XmlUtils.skipCurrentTag(parser);
1560                }
1561            }
1562
1563        } catch (IllegalStateException e) {
1564            Slog.w(TAG, "Failed parsing config " + e);
1565        } catch (NullPointerException e) {
1566            Slog.w(TAG, "Failed parsing config " + e);
1567        } catch (NumberFormatException e) {
1568            Slog.w(TAG, "Failed parsing config " + e);
1569        } catch (XmlPullParserException e) {
1570            Slog.w(TAG, "Failed parsing config " + e);
1571        } catch (IOException e) {
1572            Slog.w(TAG, "Failed parsing config " + e);
1573        } catch (IndexOutOfBoundsException e) {
1574            Slog.w(TAG, "Failed parsing config " + e);
1575        }
1576    }
1577
1578    void writeConfigFileLocked() {
1579        mHandler.removeMessages(MSG_WRITE_CONFIG);
1580        mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000);
1581    }
1582
1583    void handleWriteConfigFile() {
1584        final ByteArrayOutputStream memStream = new ByteArrayOutputStream();
1585
1586        try {
1587            synchronized (this) {
1588                XmlSerializer out = new FastXmlSerializer();
1589                out.setOutput(memStream, StandardCharsets.UTF_8.name());
1590                writeConfigFileLocked(out);
1591            }
1592        } catch (IOException e) {
1593        }
1594
1595        synchronized (mConfigFile) {
1596            FileOutputStream stream = null;
1597            try {
1598                stream = mConfigFile.startWrite();
1599                memStream.writeTo(stream);
1600                stream.flush();
1601                FileUtils.sync(stream);
1602                stream.close();
1603                mConfigFile.finishWrite(stream);
1604            } catch (IOException e) {
1605                Slog.w(TAG, "Error writing config file", e);
1606                mConfigFile.failWrite(stream);
1607            }
1608        }
1609    }
1610
1611    void writeConfigFileLocked(XmlSerializer out) throws IOException {
1612        out.startDocument(null, true);
1613        out.startTag(null, "config");
1614        for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) {
1615            String name = mPowerSaveWhitelistUserApps.keyAt(i);
1616            out.startTag(null, "wl");
1617            out.attribute(null, "n", name);
1618            out.endTag(null, "wl");
1619        }
1620        out.endTag(null, "config");
1621        out.endDocument();
1622    }
1623
1624    private void dumpHelp(PrintWriter pw) {
1625        pw.println("Device idle controller (deviceidle) dump options:");
1626        pw.println("  [-h] [CMD]");
1627        pw.println("  -h: print this help text.");
1628        pw.println("Commands:");
1629        pw.println("  step");
1630        pw.println("    Immediately step to next state, without waiting for alarm.");
1631        pw.println("  force-idle");
1632        pw.println("    Force directly into idle mode, regardless of other device state.");
1633        pw.println("    Use \"step\" to get out.");
1634        pw.println("  disable");
1635        pw.println("    Completely disable device idle mode.");
1636        pw.println("  enable");
1637        pw.println("    Re-enable device idle mode after it had previously been disabled.");
1638        pw.println("  enabled");
1639        pw.println("    Print 1 if device idle mode is currently enabled, else 0.");
1640        pw.println("  whitelist");
1641        pw.println("    Print currently whitelisted apps.");
1642        pw.println("  whitelist [package ...]");
1643        pw.println("    Add (prefix with +) or remove (prefix with -) packages.");
1644        pw.println("  tempwhitelist [package ..]");
1645        pw.println("    Temporarily place packages in whitelist for 10 seconds.");
1646    }
1647
1648    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1649        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
1650                != PackageManager.PERMISSION_GRANTED) {
1651            pw.println("Permission Denial: can't dump DeviceIdleController from from pid="
1652                    + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
1653                    + " without permission " + android.Manifest.permission.DUMP);
1654            return;
1655        }
1656
1657        if (args != null) {
1658            int userId = UserHandle.USER_OWNER;
1659            for (int i=0; i<args.length; i++) {
1660                String arg = args[i];
1661                if ("-h".equals(arg)) {
1662                    dumpHelp(pw);
1663                    return;
1664                } else if ("-u".equals(arg)) {
1665                    i++;
1666                    if (i < args.length) {
1667                        arg = args[i];
1668                        userId = Integer.parseInt(arg);
1669                    }
1670                } else if ("-a".equals(arg)) {
1671                    // Ignore, we always dump all.
1672                } else if ("step".equals(arg)) {
1673                    synchronized (this) {
1674                        long token = Binder.clearCallingIdentity();
1675                        try {
1676                            exitForceIdleLocked();
1677                            stepIdleStateLocked();
1678                            pw.print("Stepped to: "); pw.println(stateToString(mState));
1679                        } finally {
1680                            Binder.restoreCallingIdentity(token);
1681                        }
1682                    }
1683                    return;
1684                } else if ("force-idle".equals(arg)) {
1685                    synchronized (this) {
1686                        long token = Binder.clearCallingIdentity();
1687                        try {
1688                            if (!mEnabled) {
1689                                pw.println("Unable to go idle; not enabled");
1690                                return;
1691                            }
1692                            mForceIdle = true;
1693                            becomeInactiveIfAppropriateLocked();
1694                            int curState = mState;
1695                            while (curState != STATE_IDLE) {
1696                                stepIdleStateLocked();
1697                                if (curState == mState) {
1698                                    pw.print("Unable to go idle; stopped at ");
1699                                    pw.println(stateToString(mState));
1700                                    exitForceIdleLocked();
1701                                    return;
1702                                }
1703                                curState = mState;
1704                            }
1705                            pw.println("Now forced in to idle mode");
1706                        } finally {
1707                            Binder.restoreCallingIdentity(token);
1708                        }
1709                    }
1710                    return;
1711                } else if ("disable".equals(arg)) {
1712                    synchronized (this) {
1713                        long token = Binder.clearCallingIdentity();
1714                        try {
1715                            if (mEnabled) {
1716                                mEnabled = false;
1717                                becomeActiveLocked("disabled", Process.myUid());
1718                                pw.println("Idle mode disabled");
1719                            }
1720                        } finally {
1721                            Binder.restoreCallingIdentity(token);
1722                        }
1723                    }
1724                    return;
1725                } else if ("enable".equals(arg)) {
1726                    synchronized (this) {
1727                        long token = Binder.clearCallingIdentity();
1728                        try {
1729                            exitForceIdleLocked();
1730                            if (!mEnabled) {
1731                                mEnabled = true;
1732                                becomeInactiveIfAppropriateLocked();
1733                                pw.println("Idle mode enabled");
1734                            }
1735                        } finally {
1736                            Binder.restoreCallingIdentity(token);
1737                        }
1738                    }
1739                    return;
1740                } else if ("enabled".equals(arg)) {
1741                    synchronized (this) {
1742                        pw.println(mEnabled ? "1" : " 0");
1743                    }
1744                    return;
1745                } else if ("whitelist".equals(arg)) {
1746                    long token = Binder.clearCallingIdentity();
1747                    try {
1748                        i++;
1749                        if (i < args.length) {
1750                            while (i < args.length) {
1751                                arg = args[i];
1752                                i++;
1753                                if (arg.length() < 1 || (arg.charAt(0) != '-'
1754                                        && arg.charAt(0) != '+')) {
1755                                    pw.println("Package must be prefixed with + or -: " + arg);
1756                                    return;
1757                                }
1758                                char op = arg.charAt(0);
1759                                String pkg = arg.substring(1);
1760                                if (op == '+') {
1761                                    if (addPowerSaveWhitelistAppInternal(pkg)) {
1762                                        pw.println("Added: " + pkg);
1763                                    } else {
1764                                        pw.println("Unknown package: " + pkg);
1765                                    }
1766                                } else {
1767                                    if (removePowerSaveWhitelistAppInternal(pkg)) {
1768                                        pw.println("Removed: " + pkg);
1769                                    }
1770                                }
1771                            }
1772                        } else {
1773                            synchronized (this) {
1774                                for (int j=0; j<mPowerSaveWhitelistAppsExceptIdle.size(); j++) {
1775                                    pw.print("system-excidle,");
1776                                    pw.print(mPowerSaveWhitelistAppsExceptIdle.keyAt(j));
1777                                    pw.print(",");
1778                                    pw.println(mPowerSaveWhitelistAppsExceptIdle.valueAt(j));
1779                                }
1780                                for (int j=0; j<mPowerSaveWhitelistApps.size(); j++) {
1781                                    pw.print("system,");
1782                                    pw.print(mPowerSaveWhitelistApps.keyAt(j));
1783                                    pw.print(",");
1784                                    pw.println(mPowerSaveWhitelistApps.valueAt(j));
1785                                }
1786                                for (int j=0; j<mPowerSaveWhitelistUserApps.size(); j++) {
1787                                    pw.print("user,");
1788                                    pw.print(mPowerSaveWhitelistUserApps.keyAt(j));
1789                                    pw.print(",");
1790                                    pw.println(mPowerSaveWhitelistUserApps.valueAt(j));
1791                                }
1792                            }
1793                        }
1794                    } finally {
1795                        Binder.restoreCallingIdentity(token);
1796                    }
1797                    return;
1798                } else if ("tempwhitelist".equals(arg)) {
1799                    long token = Binder.clearCallingIdentity();
1800                    try {
1801                        i++;
1802                        if (i >= args.length) {
1803                            pw.println("At least one package name must be specified");
1804                            return;
1805                        }
1806                        while (i < args.length) {
1807                            arg = args[i];
1808                            i++;
1809                            addPowerSaveTempWhitelistAppInternal(0, arg, 10000L, userId, true,
1810                                    "shell");
1811                            pw.println("Added: " + arg);
1812                        }
1813                    } finally {
1814                        Binder.restoreCallingIdentity(token);
1815                    }
1816                    return;
1817                } else if (arg.length() > 0 && arg.charAt(0) == '-'){
1818                    pw.println("Unknown option: " + arg);
1819                    return;
1820                } else {
1821                    pw.println("Unknown command: " + arg);
1822                    return;
1823                }
1824            }
1825        }
1826
1827        synchronized (this) {
1828            mConstants.dump(pw);
1829
1830            int size = mPowerSaveWhitelistAppsExceptIdle.size();
1831            if (size > 0) {
1832                pw.println("  Whitelist (except idle) system apps:");
1833                for (int i = 0; i < size; i++) {
1834                    pw.print("    ");
1835                    pw.println(mPowerSaveWhitelistAppsExceptIdle.keyAt(i));
1836                }
1837            }
1838            size = mPowerSaveWhitelistApps.size();
1839            if (size > 0) {
1840                pw.println("  Whitelist system apps:");
1841                for (int i = 0; i < size; i++) {
1842                    pw.print("    ");
1843                    pw.println(mPowerSaveWhitelistApps.keyAt(i));
1844                }
1845            }
1846            size = mPowerSaveWhitelistUserApps.size();
1847            if (size > 0) {
1848                pw.println("  Whitelist user apps:");
1849                for (int i = 0; i < size; i++) {
1850                    pw.print("    ");
1851                    pw.println(mPowerSaveWhitelistUserApps.keyAt(i));
1852                }
1853            }
1854            size = mPowerSaveWhitelistExceptIdleAppIds.size();
1855            if (size > 0) {
1856                pw.println("  Whitelist (except idle) all app ids:");
1857                for (int i = 0; i < size; i++) {
1858                    pw.print("    ");
1859                    pw.print(mPowerSaveWhitelistExceptIdleAppIds.keyAt(i));
1860                    pw.println();
1861                }
1862            }
1863            size = mPowerSaveWhitelistAllAppIds.size();
1864            if (size > 0) {
1865                pw.println("  Whitelist all app ids:");
1866                for (int i = 0; i < size; i++) {
1867                    pw.print("    ");
1868                    pw.print(mPowerSaveWhitelistAllAppIds.keyAt(i));
1869                    pw.println();
1870                }
1871            }
1872            size = mTempWhitelistAppIdEndTimes.size();
1873            if (size > 0) {
1874                pw.println("  Temp whitelist schedule:");
1875                final long timeNow = SystemClock.elapsedRealtime();
1876                for (int i = 0; i < size; i++) {
1877                    pw.print("    UID=");
1878                    pw.print(mTempWhitelistAppIdEndTimes.keyAt(i));
1879                    pw.print(": ");
1880                    Pair<MutableLong, String> entry = mTempWhitelistAppIdEndTimes.valueAt(i);
1881                    TimeUtils.formatDuration(entry.first.value, timeNow, pw);
1882                    pw.print(" - ");
1883                    pw.println(entry.second);
1884                }
1885            }
1886            size = mTempWhitelistAppIdArray != null ? mTempWhitelistAppIdArray.length : 0;
1887            if (size > 0) {
1888                pw.println("  Temp whitelist app ids:");
1889                for (int i = 0; i < size; i++) {
1890                    pw.print("    ");
1891                    pw.print(mTempWhitelistAppIdArray[i]);
1892                    pw.println();
1893                }
1894            }
1895
1896            pw.print("  mEnabled="); pw.println(mEnabled);
1897            pw.print("  mForceIdle="); pw.println(mForceIdle);
1898            pw.print("  mSigMotionSensor="); pw.println(mSigMotionSensor);
1899            pw.print("  mCurDisplay="); pw.println(mCurDisplay);
1900            pw.print("  mScreenOn="); pw.println(mScreenOn);
1901            pw.print("  mCharging="); pw.println(mCharging);
1902            pw.print("  mSigMotionActive="); pw.println(mSigMotionActive);
1903            pw.print("  mSensing="); pw.print(mSensing); pw.print(" mNotMoving=");
1904                    pw.println(mNotMoving);
1905            pw.print("  mLocating="); pw.print(mLocating); pw.print(" mHaveGps=");
1906                    pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated);
1907            if (mLastGenericLocation != null) {
1908                pw.print("  mLastGenericLocation="); pw.println(mLastGenericLocation);
1909            }
1910            if (mLastGpsLocation != null) {
1911                pw.print("  mLastGpsLocation="); pw.println(mLastGpsLocation);
1912            }
1913            pw.print("  mState="); pw.println(stateToString(mState));
1914            pw.print("  mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
1915            pw.println();
1916            if (mNextAlarmTime != 0) {
1917                pw.print("  mNextAlarmTime=");
1918                TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
1919                pw.println();
1920            }
1921            if (mNextIdlePendingDelay != 0) {
1922                pw.print("  mNextIdlePendingDelay=");
1923                TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
1924                pw.println();
1925            }
1926            if (mNextIdleDelay != 0) {
1927                pw.print("  mNextIdleDelay=");
1928                TimeUtils.formatDuration(mNextIdleDelay, pw);
1929                pw.println();
1930            }
1931        }
1932    }
1933}
1934