Handle charging state separately from temporary parole

Don't use the parole state to deal with the plugged-in trigger.
Otherwise standby apps will only be paroled for a few minutes
after plugging in to charge and not the entire duration.

Use a different intent for charging state, since the CHARGING
intent takes several seconds to be received.

A refactor some time ago changed the charging state behavior
that caused this regression.

Bug: 31399882
Change-Id: Ic036de5e136b3151b225473d0c3f440adb3b48e7
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 8284773..04104b5 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -94,7 +94,7 @@
 
     static final String TAG = "UsageStatsService";
 
-    static final boolean DEBUG = false;
+    static final boolean DEBUG = false; // Never submit with true
     static final boolean COMPRESS_TIME = false;
 
     private static final long TEN_SECONDS = 10 * 1000;
@@ -139,8 +139,8 @@
     long mSystemTimeSnapshot;
 
     boolean mAppIdleEnabled;
-    boolean mAppIdleParoled;
-    private boolean mScreenOn;
+    boolean mAppIdleTempParoled;
+    boolean mCharging;
     private long mLastAppIdleParoledTime;
 
     private volatile boolean mPendingOneTimeCheckIdleStates;
@@ -191,7 +191,7 @@
         mAppIdleEnabled = getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_enableAutoPowerModes);
         if (mAppIdleEnabled) {
-            IntentFilter deviceStates = new IntentFilter(BatteryManager.ACTION_CHARGING);
+            IntentFilter deviceStates = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
             deviceStates.addAction(BatteryManager.ACTION_DISCHARGING);
             deviceStates.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
             getContext().registerReceiver(new DeviceStateReceiver(), deviceStates);
@@ -237,7 +237,7 @@
 
             mSystemServicesReady = true;
         } else if (phase == PHASE_BOOT_COMPLETED) {
-            setAppIdleParoled(getContext().getSystemService(BatteryManager.class).isCharging());
+            setChargingState(getContext().getSystemService(BatteryManager.class).isCharging());
         }
     }
 
@@ -284,9 +284,8 @@
         @Override
         public void onReceive(Context context, Intent intent) {
             final String action = intent.getAction();
-            if (BatteryManager.ACTION_CHARGING.equals(action)
-                    || BatteryManager.ACTION_DISCHARGING.equals(action)) {
-                setAppIdleParoled(BatteryManager.ACTION_CHARGING.equals(action));
+            if (Intent.ACTION_BATTERY_CHANGED.equals(action)) {
+                setChargingState(intent.getIntExtra("plugged", 0) != 0);
             } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
                 onDeviceIdleModeChanged();
             }
@@ -376,12 +375,21 @@
         }
     }
 
+    void setChargingState(boolean charging) {
+        synchronized (mLock) {
+            if (mCharging != charging) {
+                mCharging = charging;
+                postParoleStateChanged();
+            }
+        }
+    }
+
     /** Paroled here means temporary pardon from being inactive */
     void setAppIdleParoled(boolean paroled) {
         synchronized (mLock) {
-            if (mAppIdleParoled != paroled) {
-                mAppIdleParoled = paroled;
-                if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleParoled);
+            if (mAppIdleTempParoled != paroled) {
+                mAppIdleTempParoled = paroled;
+                if (DEBUG) Slog.d(TAG, "Changing paroled to " + mAppIdleTempParoled);
                 if (paroled) {
                     postParoleEndTimeout();
                 } else {
@@ -393,6 +401,12 @@
         }
     }
 
+    boolean isParoledOrCharging() {
+        synchronized (mLock) {
+            return mAppIdleTempParoled || mCharging;
+        }
+    }
+
     private void postNextParoleTimeout() {
         if (DEBUG) Slog.d(TAG, "Posting MSG_CHECK_PAROLE_TIMEOUT");
         mHandler.removeMessages(MSG_CHECK_PAROLE_TIMEOUT);
@@ -495,7 +509,7 @@
     /** Check if it's been a while since last parole and let idle apps do some work */
     void checkParoleTimeout() {
         synchronized (mLock) {
-            if (!mAppIdleParoled) {
+            if (!mAppIdleTempParoled) {
                 final long timeSinceLastParole = checkAndGetTimeLocked() - mLastAppIdleParoledTime;
                 if (timeSinceLastParole > mAppIdleParoleIntervalMillis) {
                     if (DEBUG) Slog.d(TAG, "Crossed default parole interval");
@@ -786,7 +800,7 @@
     }
 
     boolean isAppIdleFilteredOrParoled(String packageName, int userId, long elapsedRealtime) {
-        if (mAppIdleParoled) {
+        if (isParoledOrCharging()) {
             return false;
         }
         return isAppIdleFiltered(packageName, getAppId(packageName), userId, elapsedRealtime);
@@ -989,8 +1003,9 @@
     }
 
     void informParoleStateChanged() {
+        final boolean paroled = isParoledOrCharging();
         for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
-            listener.onParoleStateChanged(mAppIdleParoled);
+            listener.onParoleStateChanged(paroled);
         }
     }
 
@@ -1072,9 +1087,9 @@
 
             pw.println();
             pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
-            pw.print(" mAppIdleParoled="); pw.print(mAppIdleParoled);
-            pw.print(" mScreenOn="); pw.println(mScreenOn);
-            pw.print("mLastAppIdleParoledTime=");
+            pw.print(" mAppIdleTempParoled="); pw.print(mAppIdleTempParoled);
+            pw.print(" mCharging="); pw.print(mCharging);
+            pw.print(" mLastAppIdleParoledTime=");
             TimeUtils.formatDuration(mLastAppIdleParoledTime, pw);
             pw.println();
         }
@@ -1139,7 +1154,8 @@
                     break;
 
                 case MSG_PAROLE_STATE_CHANGED:
-                    if (DEBUG) Slog.d(TAG, "Parole state changed: " + mAppIdleParoled);
+                    if (DEBUG) Slog.d(TAG, "Parole state: " + mAppIdleTempParoled
+                            + ", Charging state:" + mCharging);
                     informParoleStateChanged();
                     break;
 
@@ -1466,7 +1482,7 @@
 
         @Override
         public boolean isAppIdleParoleOn() {
-            return mAppIdleParoled;
+            return isParoledOrCharging();
         }
 
         @Override