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