Loading apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,12 @@ public interface JobSchedulerInternal { boolean isNotificationChannelAssociatedWithAnyUserInitiatedJobs( @NonNull String notificationChannel, int userId, @NonNull String packageName); /** * @return {@code true} if the given package holds the * {@link android.Manifest.permission.RUN_BACKUP_JOBS} permission. */ boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid); /** * Report a snapshot of sync-related jobs back to the sync manager */ Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -4196,6 +4196,11 @@ public class JobSchedulerService extends com.android.server.SystemService notificationChannel, userId, packageName); } @Override public boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) { return JobSchedulerService.this.hasRunBackupJobsPermission(packageName, packageUid); } @Override public JobStorePersistStats getPersistStats() { synchronized (mLock) { Loading Loading @@ -4358,6 +4363,22 @@ public class JobSchedulerService extends com.android.server.SystemService } } /** * Returns whether the app holds the {@link Manifest.permission.RUN_BACKUP_JOBS} permission. */ private boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) { if (packageName == null) { Slog.wtfStack(TAG, "Expected a non-null package name when calling hasRunBackupJobsPermission"); return false; } return PermissionChecker.checkPermissionForPreflight(getTestableContext(), android.Manifest.permission.RUN_BACKUP_JOBS, PermissionChecker.PID_UNKNOWN, packageUid, packageName) == PermissionChecker.PERMISSION_GRANTED; } /** * Binder stub trampoline implementation */ Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +11 −7 Original line number Diff line number Diff line Loading @@ -1222,21 +1222,25 @@ public final class JobStatus { return ACTIVE_INDEX; } final int bucketWithMediaExemption; if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX && mHasMediaBackupExemption) { final boolean isEligibleAsBackupJob = job.getTriggerContentUris() != null && job.getRequiredNetwork() != null && !job.hasLateConstraint() && mJobSchedulerInternal.hasRunBackupJobsPermission(sourcePackageName, sourceUid); final boolean isBackupExempt = mHasMediaBackupExemption || isEligibleAsBackupJob; final int bucketWithBackupExemption; if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX && isBackupExempt) { // Treat it as if it's at most WORKING_INDEX (lower index grants higher quota) since // media backup jobs are important to the user, and the source package may not have // been used directly in a while. bucketWithMediaExemption = Math.min(WORKING_INDEX, actualBucket); bucketWithBackupExemption = Math.min(WORKING_INDEX, actualBucket); } else { bucketWithMediaExemption = actualBucket; bucketWithBackupExemption = actualBucket; } // If the app is considered buggy, but hasn't yet been put in the RESTRICTED bucket // (potentially because it's used frequently by the user), limit its effective bucket // so that it doesn't get to run as much as a normal ACTIVE app. if (isBuggy && bucketWithMediaExemption < WORKING_INDEX) { if (isBuggy && bucketWithBackupExemption < WORKING_INDEX) { if (!mIsDowngradedDueToBuggyApp) { // Safety check to avoid logging multiple times for the same job. Counter.logIncrementWithUid( Loading @@ -1246,7 +1250,7 @@ public final class JobStatus { } return WORKING_INDEX; } return bucketWithMediaExemption; return bucketWithBackupExemption; } /** Returns the real standby bucket of the job. */ Loading Loading
apex/jobscheduler/framework/java/com/android/server/job/JobSchedulerInternal.java +6 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,12 @@ public interface JobSchedulerInternal { boolean isNotificationChannelAssociatedWithAnyUserInitiatedJobs( @NonNull String notificationChannel, int userId, @NonNull String packageName); /** * @return {@code true} if the given package holds the * {@link android.Manifest.permission.RUN_BACKUP_JOBS} permission. */ boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid); /** * Report a snapshot of sync-related jobs back to the sync manager */ Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +21 −0 Original line number Diff line number Diff line Loading @@ -4196,6 +4196,11 @@ public class JobSchedulerService extends com.android.server.SystemService notificationChannel, userId, packageName); } @Override public boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) { return JobSchedulerService.this.hasRunBackupJobsPermission(packageName, packageUid); } @Override public JobStorePersistStats getPersistStats() { synchronized (mLock) { Loading Loading @@ -4358,6 +4363,22 @@ public class JobSchedulerService extends com.android.server.SystemService } } /** * Returns whether the app holds the {@link Manifest.permission.RUN_BACKUP_JOBS} permission. */ private boolean hasRunBackupJobsPermission(@NonNull String packageName, int packageUid) { if (packageName == null) { Slog.wtfStack(TAG, "Expected a non-null package name when calling hasRunBackupJobsPermission"); return false; } return PermissionChecker.checkPermissionForPreflight(getTestableContext(), android.Manifest.permission.RUN_BACKUP_JOBS, PermissionChecker.PID_UNKNOWN, packageUid, packageName) == PermissionChecker.PERMISSION_GRANTED; } /** * Binder stub trampoline implementation */ Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +11 −7 Original line number Diff line number Diff line Loading @@ -1222,21 +1222,25 @@ public final class JobStatus { return ACTIVE_INDEX; } final int bucketWithMediaExemption; if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX && mHasMediaBackupExemption) { final boolean isEligibleAsBackupJob = job.getTriggerContentUris() != null && job.getRequiredNetwork() != null && !job.hasLateConstraint() && mJobSchedulerInternal.hasRunBackupJobsPermission(sourcePackageName, sourceUid); final boolean isBackupExempt = mHasMediaBackupExemption || isEligibleAsBackupJob; final int bucketWithBackupExemption; if (actualBucket != RESTRICTED_INDEX && actualBucket != NEVER_INDEX && isBackupExempt) { // Treat it as if it's at most WORKING_INDEX (lower index grants higher quota) since // media backup jobs are important to the user, and the source package may not have // been used directly in a while. bucketWithMediaExemption = Math.min(WORKING_INDEX, actualBucket); bucketWithBackupExemption = Math.min(WORKING_INDEX, actualBucket); } else { bucketWithMediaExemption = actualBucket; bucketWithBackupExemption = actualBucket; } // If the app is considered buggy, but hasn't yet been put in the RESTRICTED bucket // (potentially because it's used frequently by the user), limit its effective bucket // so that it doesn't get to run as much as a normal ACTIVE app. if (isBuggy && bucketWithMediaExemption < WORKING_INDEX) { if (isBuggy && bucketWithBackupExemption < WORKING_INDEX) { if (!mIsDowngradedDueToBuggyApp) { // Safety check to avoid logging multiple times for the same job. Counter.logIncrementWithUid( Loading @@ -1246,7 +1250,7 @@ public final class JobStatus { } return WORKING_INDEX; } return bucketWithMediaExemption; return bucketWithBackupExemption; } /** Returns the real standby bucket of the job. */ Loading