Merge "Promote apps in the NEVER bucket on sync scheduled"
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 9c6bd92..d34e6d3 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -195,6 +195,8 @@
     /** @hide */
     public static final int REASON_SUB_USAGE_EXEMPTED_SYNC_START = 0x000D;
     /** @hide */
+    public static final int REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED = 0x000E;
+    /** @hide */
     public static final int REASON_SUB_PREDICTED_RESTORED       = 0x0001;
 
 
@@ -972,6 +974,9 @@
                     case REASON_SUB_USAGE_EXEMPTED_SYNC_START:
                         sb.append("-es");
                         break;
+                    case REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED:
+                        sb.append("-uss");
+                        break;
                 }
                 break;
         }
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 43ce521..bbec6b3 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -257,12 +257,14 @@
             int numDeferredJobs, long timeSinceLastJobRun);
 
     /**
-     * Report a sync is scheduled by a foreground app.
+     * Report a sync that was scheduled.
      *
      * @param packageName name of the package that owns the sync adapter.
      * @param userId which user the app is associated with
+     * @param exempted is sync app standby exempted
      */
-    public abstract void reportExemptedSyncScheduled(String packageName, @UserIdInt int userId);
+    public abstract void reportSyncScheduled(String packageName, @UserIdInt int userId,
+                                             boolean exempted);
 
     /**
      * Report a sync that was scheduled by a foreground app is about to be executed.
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 8a208a5..9f80a83 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1639,13 +1639,12 @@
             }
         }
 
-        if (syncOperation.isAppStandbyExempted()) {
-            final UsageStatsManagerInternal usmi = LocalServices.getService(
-                    UsageStatsManagerInternal.class);
-            if (usmi != null) {
-                usmi.reportExemptedSyncScheduled(syncOperation.owningPackage,
-                        UserHandle.getUserId(syncOperation.owningUid));
-            }
+        final UsageStatsManagerInternal usmi =
+                LocalServices.getService(UsageStatsManagerInternal.class);
+        if (usmi != null) {
+            usmi.reportSyncScheduled(syncOperation.owningPackage,
+                    UserHandle.getUserId(syncOperation.owningUid),
+                    syncOperation.isAppStandbyExempted());
         }
 
         getJobScheduler().scheduleAsPackage(b.build(), syncOperation.owningPackage,
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 65ed85d..ffafb6d 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -35,6 +35,7 @@
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYNC_ADAPTER;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_INTERACTION;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_SYSTEM_UPDATE;
+import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED;
 import static android.app.usage.UsageStatsManager.REASON_SUB_USAGE_USER_INTERACTION;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
 import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_EXEMPTED;
@@ -197,7 +198,7 @@
     static final int MSG_ONE_TIME_CHECK_IDLE_STATES = 10;
     /** Check the state of one app: arg1 = userId, arg2 = uid, obj = (String) packageName */
     static final int MSG_CHECK_PACKAGE_IDLE_STATE = 11;
-    static final int MSG_REPORT_EXEMPTED_SYNC_SCHEDULED = 12;
+    static final int MSG_REPORT_SYNC_SCHEDULED = 12;
     static final int MSG_REPORT_EXEMPTED_SYNC_START = 13;
     static final int MSG_UPDATE_STABLE_CHARGING= 14;
 
@@ -231,6 +232,10 @@
      * Maximum time an exempted sync should keep the buckets elevated, when sync is started.
      */
     long mExemptedSyncStartTimeoutMillis;
+    /**
+     * Maximum time an unexempted sync should keep the buckets elevated, when sync is scheduled
+     */
+    long mUnexemptedSyncScheduledTimeoutMillis;
     /** Maximum time a system interaction should keep the buckets elevated. */
     long mSystemInteractionTimeoutMillis;
     /** The length of time phone must be charging before considered stable enough to run jobs  */
@@ -447,6 +452,25 @@
         }
     }
 
+    void reportUnexemptedSyncScheduled(String packageName, int userId) {
+        if (!mAppIdleEnabled) return;
+
+        final long elapsedRealtime = mInjector.elapsedRealtime();
+        synchronized (mAppIdleLock) {
+            final int currentBucket =
+                    mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime);
+            if (currentBucket == STANDBY_BUCKET_NEVER) {
+                // Bring the app out of the never bucket
+                AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId,
+                        STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED,
+                        0,
+                        elapsedRealtime + mUnexemptedSyncScheduledTimeoutMillis);
+                maybeInformListeners(packageName, userId, elapsedRealtime,
+                        appUsage.currentBucket, appUsage.bucketingReason, false);
+            }
+        }
+    }
+
     void reportExemptedSyncStart(String packageName, int userId) {
         if (!mAppIdleEnabled) return;
 
@@ -1423,8 +1447,8 @@
                 .sendToTarget();
     }
 
-    void postReportExemptedSyncScheduled(String packageName, int userId) {
-        mHandler.obtainMessage(MSG_REPORT_EXEMPTED_SYNC_SCHEDULED, userId, 0, packageName)
+    void postReportSyncScheduled(String packageName, int userId, boolean exempted) {
+        mHandler.obtainMessage(MSG_REPORT_SYNC_SCHEDULED, userId, exempted ? 1 : 0, packageName)
                 .sendToTarget();
     }
 
@@ -1492,6 +1516,9 @@
         pw.print("  mExemptedSyncStartTimeoutMillis=");
         TimeUtils.formatDuration(mExemptedSyncStartTimeoutMillis, pw);
         pw.println();
+        pw.print("  mUnexemptedSyncScheduledTimeoutMillis=");
+        TimeUtils.formatDuration(mUnexemptedSyncScheduledTimeoutMillis, pw);
+        pw.println();
 
         pw.print("  mSystemUpdateUsageTimeoutMillis=");
         TimeUtils.formatDuration(mSystemUpdateUsageTimeoutMillis, pw);
@@ -1706,8 +1733,13 @@
                             mInjector.elapsedRealtime());
                     break;
 
-                case MSG_REPORT_EXEMPTED_SYNC_SCHEDULED:
-                    reportExemptedSyncScheduled((String) msg.obj, msg.arg1);
+                case MSG_REPORT_SYNC_SCHEDULED:
+                    final boolean exempted = msg.arg1 > 0 ? true : false;
+                    if (exempted) {
+                        reportExemptedSyncScheduled((String) msg.obj, msg.arg1);
+                    } else {
+                        reportUnexemptedSyncScheduled((String) msg.obj, msg.arg1);
+                    }
                     break;
 
                 case MSG_REPORT_EXEMPTED_SYNC_START:
@@ -1799,12 +1831,14 @@
                 "system_update_usage_duration";
         private static final String KEY_PREDICTION_TIMEOUT = "prediction_timeout";
         private static final String KEY_SYNC_ADAPTER_HOLD_DURATION = "sync_adapter_duration";
-        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION
-                = "exempted_sync_scheduled_nd_duration";
-        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION
-                = "exempted_sync_scheduled_d_duration";
-        private static final String KEY_EXEMPTED_SYNC_START_HOLD_DURATION
-                = "exempted_sync_start_duration";
+        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION =
+                "exempted_sync_scheduled_nd_duration";
+        private static final String KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION =
+                "exempted_sync_scheduled_d_duration";
+        private static final String KEY_EXEMPTED_SYNC_START_HOLD_DURATION =
+                "exempted_sync_start_duration";
+        private static final String KEY_UNEXEMPTED_SYNC_SCHEDULED_HOLD_DURATION =
+                "unexempted_sync_scheduled_duration";
         private static final String KEY_SYSTEM_INTERACTION_HOLD_DURATION =
                 "system_interaction_duration";
         private static final String KEY_STABLE_CHARGING_THRESHOLD = "stable_charging_threshold";
@@ -1816,6 +1850,7 @@
         public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT = 4 * ONE_HOUR;
         public static final long DEFAULT_EXEMPTED_SYNC_START_TIMEOUT = 10 * ONE_MINUTE;
+        public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_STABLE_CHARGING_THRESHOLD = 10 * ONE_MINUTE;
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -1883,42 +1918,47 @@
                         ELAPSED_TIME_THRESHOLDS);
                 mCheckIdleIntervalMillis = Math.min(mAppStandbyElapsedThresholds[1] / 4,
                         COMPRESS_TIME ? ONE_MINUTE : 4 * 60 * ONE_MINUTE); // 4 hours
-                mStrongUsageTimeoutMillis = mParser.getDurationMillis
-                        (KEY_STRONG_USAGE_HOLD_DURATION,
+                mStrongUsageTimeoutMillis = mParser.getDurationMillis(
+                        KEY_STRONG_USAGE_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STRONG_USAGE_TIMEOUT);
-                mNotificationSeenTimeoutMillis = mParser.getDurationMillis
-                        (KEY_NOTIFICATION_SEEN_HOLD_DURATION,
+                mNotificationSeenTimeoutMillis = mParser.getDurationMillis(
+                        KEY_NOTIFICATION_SEEN_HOLD_DURATION,
                                 COMPRESS_TIME ? 12 * ONE_MINUTE : DEFAULT_NOTIFICATION_TIMEOUT);
-                mSystemUpdateUsageTimeoutMillis = mParser.getDurationMillis
-                        (KEY_SYSTEM_UPDATE_HOLD_DURATION,
+                mSystemUpdateUsageTimeoutMillis = mParser.getDurationMillis(
+                        KEY_SYSTEM_UPDATE_HOLD_DURATION,
                                 COMPRESS_TIME ? 2 * ONE_MINUTE : DEFAULT_SYSTEM_UPDATE_TIMEOUT);
-                mPredictionTimeoutMillis = mParser.getDurationMillis
-                        (KEY_PREDICTION_TIMEOUT,
+                mPredictionTimeoutMillis = mParser.getDurationMillis(
+                        KEY_PREDICTION_TIMEOUT,
                                 COMPRESS_TIME ? 10 * ONE_MINUTE : DEFAULT_PREDICTION_TIMEOUT);
-                mSyncAdapterTimeoutMillis = mParser.getDurationMillis
-                        (KEY_SYNC_ADAPTER_HOLD_DURATION,
+                mSyncAdapterTimeoutMillis = mParser.getDurationMillis(
+                        KEY_SYNC_ADAPTER_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYNC_ADAPTER_TIMEOUT);
 
-                mExemptedSyncScheduledNonDozeTimeoutMillis = mParser.getDurationMillis
-                        (KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION,
+                mExemptedSyncScheduledNonDozeTimeoutMillis = mParser.getDurationMillis(
+                        KEY_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_HOLD_DURATION,
                                 COMPRESS_TIME ? (ONE_MINUTE / 2)
                                         : DEFAULT_EXEMPTED_SYNC_SCHEDULED_NON_DOZE_TIMEOUT);
 
-                mExemptedSyncScheduledDozeTimeoutMillis = mParser.getDurationMillis
-                        (KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
+                mExemptedSyncScheduledDozeTimeoutMillis = mParser.getDurationMillis(
+                        KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE
                                         : DEFAULT_EXEMPTED_SYNC_SCHEDULED_DOZE_TIMEOUT);
 
-                mExemptedSyncStartTimeoutMillis = mParser.getDurationMillis
-                        (KEY_EXEMPTED_SYNC_START_HOLD_DURATION,
+                mExemptedSyncStartTimeoutMillis = mParser.getDurationMillis(
+                        KEY_EXEMPTED_SYNC_START_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE
                                         : DEFAULT_EXEMPTED_SYNC_START_TIMEOUT);
 
-                mSystemInteractionTimeoutMillis = mParser.getDurationMillis
-                        (KEY_SYSTEM_INTERACTION_HOLD_DURATION,
+                mUnexemptedSyncScheduledTimeoutMillis = mParser.getDurationMillis(
+                        KEY_EXEMPTED_SYNC_SCHEDULED_DOZE_HOLD_DURATION,
+                                COMPRESS_TIME ? ONE_MINUTE
+                                        : DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT); // TODO
+
+                mSystemInteractionTimeoutMillis = mParser.getDurationMillis(
+                        KEY_SYSTEM_INTERACTION_HOLD_DURATION,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_SYSTEM_INTERACTION_TIMEOUT);
-                mStableChargingThresholdMillis = mParser.getDurationMillis
-                        (KEY_STABLE_CHARGING_THRESHOLD,
+                mStableChargingThresholdMillis = mParser.getDurationMillis(
+                        KEY_STABLE_CHARGING_THRESHOLD,
                                 COMPRESS_TIME ? ONE_MINUTE : DEFAULT_STABLE_CHARGING_THRESHOLD);
             }
 
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index ebb0210..b14d722 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -1751,8 +1751,8 @@
         }
 
         @Override
-        public void reportExemptedSyncScheduled(String packageName, int userId) {
-            mAppStandby.postReportExemptedSyncScheduled(packageName, userId);
+        public void reportSyncScheduled(String packageName, int userId, boolean exempted) {
+            mAppStandby.postReportSyncScheduled(packageName, userId, exempted);
         }
 
         @Override