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