From d4dae380e3cfde7484408d41b2555ed8b7859ded Mon Sep 17 00:00:00 2001
From: Xin Guan <guanxin@google.com>
Date: Wed, 1 May 2024 14:21:28 +0000
Subject: [PATCH] Avoid app idle check on boot.

- Avoid app idle check during the boot up
- Avoid duplicate STANDBY_BUCKET_CHANGE usage event
  reporting during the boot up.
- Logging fix.

Bug: 337864590
Test: atest CtsUsageStatsTestCases:UsageStatsTest
Test: atest FrameworksServicesTests:AppIdleHistoryTests
Test: atest FrameworksServicesTests:AppStandbyControllerTests
Change-Id: Iee31b50be48dc38c25dd6c885535ab9426edff4a
---
 apex/jobscheduler/service/Android.bp          |  1 +
 apex/jobscheduler/service/aconfig/Android.bp  | 13 ++++++++++
 .../service/aconfig/app_idle.aconfig          | 14 +++++++++++
 .../android/server/usage/AppIdleHistory.java  |  8 ++++++-
 .../server/usage/AppStandbyController.java    | 24 ++++++++++++++-----
 .../server/usage/AppIdleHistoryTests.java     |  6 +++--
 6 files changed, 57 insertions(+), 9 deletions(-)
 create mode 100644 apex/jobscheduler/service/aconfig/app_idle.aconfig

diff --git a/apex/jobscheduler/service/Android.bp b/apex/jobscheduler/service/Android.bp
index 06c7d64d1708..559490cec04f 100644
--- a/apex/jobscheduler/service/Android.bp
+++ b/apex/jobscheduler/service/Android.bp
@@ -33,6 +33,7 @@ java_library {
         "modules-utils-fastxmlserializer",
         "service-jobscheduler-alarm.flags-aconfig-java",
         "service-jobscheduler-job.flags-aconfig-java",
+        "service-jobscheduler-appidle.flags-aconfig-java",
     ],
 
     // Rename classes shared with the framework
diff --git a/apex/jobscheduler/service/aconfig/Android.bp b/apex/jobscheduler/service/aconfig/Android.bp
index 859c67ad8910..7b2525c67916 100644
--- a/apex/jobscheduler/service/aconfig/Android.bp
+++ b/apex/jobscheduler/service/aconfig/Android.bp
@@ -42,3 +42,16 @@ java_aconfig_library {
     name: "service-jobscheduler-alarm.flags-aconfig-java",
     aconfig_declarations: "alarm_flags",
 }
+
+// App Idle
+aconfig_declarations {
+    name: "app_idle_flags",
+    package: "com.android.server.usage",
+    container: "system",
+    srcs: ["app_idle.aconfig"],
+}
+
+java_aconfig_library {
+    name: "service-jobscheduler-appidle.flags-aconfig-java",
+    aconfig_declarations: "app_idle_flags",
+}
diff --git a/apex/jobscheduler/service/aconfig/app_idle.aconfig b/apex/jobscheduler/service/aconfig/app_idle.aconfig
new file mode 100644
index 000000000000..c8976ca8361e
--- /dev/null
+++ b/apex/jobscheduler/service/aconfig/app_idle.aconfig
@@ -0,0 +1,14 @@
+package: "com.android.server.usage"
+container: "system"
+
+flag {
+    name: "avoid_idle_check"
+    namespace: "backstage_power"
+    description: "Postpone app idle check after boot completed"
+    is_fixed_read_only: true
+    bug: "337864590"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 4d4e3407a3c3..6265d9bb815f 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -788,7 +788,13 @@ public class AppIdleHistory {
                         }
                         appUsageHistory.nextEstimatedLaunchTime = getLongValue(parser,
                                 ATTR_NEXT_ESTIMATED_APP_LAUNCH_TIME, 0);
-                        appUsageHistory.lastInformedBucket = -1;
+                        if (Flags.avoidIdleCheck()) {
+                            // Set lastInformedBucket to the same value with the currentBucket
+                            // it should have already been informed.
+                            appUsageHistory.lastInformedBucket = appUsageHistory.currentBucket;
+                        } else {
+                            appUsageHistory.lastInformedBucket = -1;
+                        }
                         userHistory.put(packageName, appUsageHistory);
 
                         if (version >= XML_VERSION_ADD_BUCKET_EXPIRY_TIMES) {
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 410074e6ec85..c3fe0314636e 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -707,7 +707,7 @@ public class AppStandbyController
                 initializeDefaultsForSystemApps(UserHandle.USER_SYSTEM);
             }
 
-            if (mPendingOneTimeCheckIdleStates) {
+            if (!Flags.avoidIdleCheck() && mPendingOneTimeCheckIdleStates) {
                 postOneTimeCheckIdleStates();
             }
 
@@ -1021,7 +1021,7 @@ public class AppStandbyController
                                         == REASON_SUB_DEFAULT_APP_RESTORED)) {
                             newBucket = getBucketForLocked(packageName, userId, elapsedRealtime);
                             if (DEBUG) {
-                                Slog.d(TAG, "Evaluated AOSP newBucket = "
+                                Slog.d(TAG, "Evaluated " + packageName + " newBucket = "
                                         + standbyBucketToString(newBucket));
                             }
                             reason = REASON_MAIN_TIMEOUT;
@@ -1990,7 +1990,9 @@ public class AppStandbyController
             }
         }
         if (android.app.admin.flags.Flags.disallowUserControlBgUsageFix()) {
-            postCheckIdleStates(userId);
+            if (!Flags.avoidIdleCheck()) {
+                postCheckIdleStates(userId);
+            }
         }
     }
 
@@ -2392,9 +2394,14 @@ public class AppStandbyController
             final boolean isHeadLess = !systemLauncherActivities.contains(pkg);
 
             if (updateHeadlessSystemAppCache(pkg, isHeadLess)) {
-                mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE,
-                        UserHandle.USER_SYSTEM, -1, pkg)
-                    .sendToTarget();
+                if (!Flags.avoidIdleCheck()) {
+                    // Checking idle state for the each individual headless system app
+                    // during the boot up is not necessary, a full idle check for all
+                    // usres will be scheduled after boot completed.
+                    mHandler.obtainMessage(MSG_CHECK_PACKAGE_IDLE_STATE,
+                                    UserHandle.USER_SYSTEM, -1, pkg)
+                            .sendToTarget();
+                }
             }
         }
         final long end = SystemClock.uptimeMillis();
@@ -2438,6 +2445,11 @@ public class AppStandbyController
 
     @Override
     public void dumpState(String[] args, PrintWriter pw) {
+        pw.println("Flags: ");
+        pw.println("    " + Flags.FLAG_AVOID_IDLE_CHECK
+                + ": " + Flags.avoidIdleCheck());
+        pw.println();
+
         synchronized (mCarrierPrivilegedLock) {
             pw.println("Carrier privileged apps (have=" + mHaveCarrierPrivilegedApps
                     + "): " + mCarrierPrivilegedApps);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 06726b031a36..55d93fb8d9dc 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -144,7 +144,9 @@ public class AppIdleHistoryTests extends AndroidTestCase {
         assertEquals(aih.getAppStandbyReason(PACKAGE_4, USER_ID, 3000),
                 REASON_MAIN_FORCED_BY_USER);
 
-        assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
+        if (!Flags.avoidIdleCheck()) {
+            assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
+        }
         assertFalse(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_RARE));
         assertTrue(aih.shouldInformListeners(PACKAGE_1, USER_ID, 5000, STANDBY_BUCKET_FREQUENT));
     }
@@ -243,4 +245,4 @@ public class AppIdleHistoryTests extends AndroidTestCase {
                     expectedExpiryTimeMs, actualExpiryTimeMs);
         }
     }
-}
\ No newline at end of file
+}
-- 
GitLab