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