[3rd try] JobScheduler to use UID active state for job exemption

JobScheduler used to use procstate foreground state to decide whether
to exempt jobs, but it should use UID's active state instead, so that
if apps in the temp-whitelist schedule jobs, they run immediately.

Test: Boot
Test: atest CtsAlarmManagerTestCases
Test: atest CtsJobSchedulerTestCases
Test: atest CtsBatterySavingTestCases
Test: atest $ANDROID_BUILD_TOP/frameworks/base/services/tests/servicestests/src/com/android/server/AppStateTrackerTest.java

Bug: 72125364
Change-Id: I7a5628e76121199f3a5299e2a5576e1481574a6e
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 401c05e..47a4fb2 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -40,7 +40,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.Intent.UriFlags;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -79,7 +78,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.server.DeviceIdleController;
 import com.android.server.FgThread;
-import com.android.server.ForceAppStandbyTracker;
+import com.android.server.AppStateTracker;
 import com.android.server.LocalServices;
 import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
 import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
@@ -184,7 +183,7 @@
     ActivityManagerInternal mActivityManagerInternal;
     IBatteryStats mBatteryStats;
     DeviceIdleController.LocalService mLocalDeviceIdleController;
-    final ForceAppStandbyTracker mForceAppStandbyTracker;
+    AppStateTracker mAppStateTracker;
 
     /**
      * Set to true once we are allowed to run third party apps.
@@ -787,20 +786,13 @@
     }
 
     /**
-     * Return whether an UID is in the foreground or not.
+     * Return whether an UID is active or idle.
      */
-    private boolean isUidInForeground(int uid) {
-        synchronized (mLock) {
-            if (mUidPriorityOverride.get(uid, 0) > 0) {
-                return true;
-            }
-        }
-        // Note UID observer may not be called in time, so we always check with the AM.
-        return mActivityManagerInternal.getUidProcessState(uid)
-                <= ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+    private boolean isUidActive(int uid) {
+        return mAppStateTracker.isUidActiveSynced(uid);
     }
 
-    private final Predicate<Integer> mIsUidInForegroundPredicate = this::isUidInForeground;
+    private final Predicate<Integer> mIsUidActivePredicate = this::isUidActive;
 
     public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
             int userId, String tag) {
@@ -826,7 +818,7 @@
 
                     // If any of work item is enqueued when the source is in the foreground,
                     // exempt the entire job.
-                    toCancel.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+                    toCancel.maybeAddForegroundExemption(mIsUidActivePredicate);
 
                     return JobScheduler.RESULT_SUCCESS;
                 }
@@ -838,7 +830,7 @@
             // Note if it's a sync job, this method is called on the handler so it's not exactly
             // the state when requestSync() was called, but that should be fine because of the
             // 1 minute foreground grace period.
-            jobStatus.maybeAddForegroundExemption(mIsUidInForegroundPredicate);
+            jobStatus.maybeAddForegroundExemption(mIsUidActivePredicate);
 
             if (DEBUG) Slog.d(TAG, "SCHEDULE: " + jobStatus.toShortString());
             // Jobs on behalf of others don't apply to the per-app job cap
@@ -1123,8 +1115,6 @@
         mDeviceIdleJobsController = DeviceIdleJobsController.get(this);
         mControllers.add(mDeviceIdleJobsController);
 
-        mForceAppStandbyTracker = ForceAppStandbyTracker.getInstance(context);
-
         // If the job store determined that it can't yet reschedule persisted jobs,
         // we need to start watching the clock.
         if (!mJobs.jobTimesInflatedValid()) {
@@ -1185,7 +1175,8 @@
         if (PHASE_SYSTEM_SERVICES_READY == phase) {
             mConstants.start(getContext().getContentResolver());
 
-            mForceAppStandbyTracker.start();
+            mAppStateTracker = Preconditions.checkNotNull(
+                    LocalServices.getService(AppStateTracker.class));
 
             // Register br for package removals and user removals.
             final IntentFilter filter = new IntentFilter();