Add a new intent to navigate to the long background tasks page.

Also add a new API in JobScheduler to check if apps hold the permission.

Bug: 255821578
Test: manually
Change-Id: I4beeb7eb40b5e19fc95784b4a54031467e9bc780
diff --git a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
index f59e7a4..c6d4a892 100644
--- a/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
+++ b/apex/jobscheduler/framework/java/android/app/JobSchedulerImpl.java
@@ -103,6 +103,15 @@
     }
 
     @Override
+    public boolean hasRunLongJobsPermission(String packageName, int userId) {
+        try {
+            return mBinder.hasRunLongJobsPermission(packageName, userId);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    @Override
     public List<JobInfo> getStartedJobs() {
         try {
             return mBinder.getStartedJobs();
diff --git a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
index 3006f50..452fb04 100644
--- a/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
+++ b/apex/jobscheduler/framework/java/android/app/job/IJobScheduler.aidl
@@ -33,6 +33,7 @@
     void cancelAll();
     ParceledListSlice getAllPendingJobs();
     JobInfo getPendingJob(int jobId);
+    boolean hasRunLongJobsPermission(String packageName, int userId);
     List<JobInfo> getStartedJobs();
     ParceledListSlice getAllJobSnapshots();
 }
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
index 7448686..807f32d 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobScheduler.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UserIdInt;
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.content.ClipData;
@@ -249,6 +250,15 @@
     public abstract @Nullable JobInfo getPendingJob(int jobId);
 
     /**
+     * Returns {@code true} if the app currently holds the
+     * {@link android.Manifest.permission#RUN_LONG_JOBS} permission, allowing it to run long jobs.
+     * @hide
+     */
+    public boolean hasRunLongJobsPermission(@NonNull String packageName, @UserIdInt int userId) {
+        return false;
+    }
+
+    /**
      * <b>For internal system callers only!</b>
      * Returns a list of all currently-executing jobs.
      * @hide
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index d9fe30d..56f318f6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -28,6 +28,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.AppGlobals;
+import android.app.AppOpsManager;
 import android.app.IUidObserver;
 import android.app.compat.CompatChanges;
 import android.app.job.IJobScheduler;
@@ -304,6 +305,7 @@
     final JobHandler mHandler;
     final JobSchedulerStub mJobSchedulerStub;
 
+    private AppOpsManager mAppOps;
     PackageManagerInternal mLocalPM;
     ActivityManagerInternal mActivityManagerInternal;
     DeviceIdleInternal mLocalDeviceIdleController;
@@ -1804,6 +1806,8 @@
                 controller.onSystemServicesReady();
             }
 
+            mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
+
             mAppStateTracker = (AppStateTrackerImpl) Objects.requireNonNull(
                     LocalServices.getService(AppStateTracker.class));
 
@@ -3409,6 +3413,21 @@
             }
         }
 
+        @Override
+        public boolean hasRunLongJobsPermission(@NonNull String packageName,
+                @UserIdInt int userId) {
+            final int uid = mLocalPM.getPackageUid(packageName, 0, userId);
+            final int callingUid = Binder.getCallingUid();
+            if (callingUid != uid && !UserHandle.isCore(callingUid)) {
+                throw new SecurityException("Uid " + callingUid
+                        + " cannot query canRunLongJobs for package " + packageName);
+            }
+
+            final int mode = mAppOps.checkOpNoThrow(AppOpsManager.OP_RUN_LONG_JOBS, uid,
+                    packageName);
+            return mode == AppOpsManager.MODE_ALLOWED || mode == AppOpsManager.MODE_DEFAULT;
+        }
+
         /**
          * "dumpsys" infrastructure
          */
diff --git a/core/api/current.txt b/core/api/current.txt
index a3738f7..75bea40 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -35818,6 +35818,7 @@
     field public static final String ACTION_MANAGE_ALL_SIM_PROFILES_SETTINGS = "android.settings.MANAGE_ALL_SIM_PROFILES_SETTINGS";
     field public static final String ACTION_MANAGE_APPLICATIONS_SETTINGS = "android.settings.MANAGE_APPLICATIONS_SETTINGS";
     field public static final String ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION = "android.settings.MANAGE_APP_ALL_FILES_ACCESS_PERMISSION";
+    field public static final String ACTION_MANAGE_APP_LONG_JOBS = "android.settings.MANAGE_APP_LONG_JOBS";
     field public static final String ACTION_MANAGE_DEFAULT_APPS_SETTINGS = "android.settings.MANAGE_DEFAULT_APPS_SETTINGS";
     field public static final String ACTION_MANAGE_OVERLAY_PERMISSION = "android.settings.action.MANAGE_OVERLAY_PERMISSION";
     field public static final String ACTION_MANAGE_SUPERVISOR_RESTRICTED_SETTING = "android.settings.MANAGE_SUPERVISOR_RESTRICTED_SETTING";
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 52b1adb..dfa41b3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -585,6 +585,22 @@
             "android.settings.REQUEST_MANAGE_MEDIA";
 
     /**
+     * Activity Action: Show settings to allow configuration of
+     * {@link Manifest.permission#RUN_LONG_JOBS} permission
+     *
+     * Input: Optionally, the Intent's data URI can specify the application package name to
+     * directly invoke the management GUI specific to the package name. For example
+     * "package:com.my.app".
+     * <p>
+     * Output: When a package data uri is passed as input, the activity result is set to
+     * {@link android.app.Activity#RESULT_OK} if the permission was granted to the app. Otherwise,
+     * the result is set to {@link android.app.Activity#RESULT_CANCELED}.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_MANAGE_APP_LONG_JOBS =
+            "android.settings.MANAGE_APP_LONG_JOBS";
+
+    /**
      * Activity Action: Show settings to allow configuration of cross-profile access for apps
      *
      * Input: Optionally, the Intent's data URI can specify the application package name to