Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +43 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; import android.content.ComponentName; Loading Loading @@ -63,6 +66,25 @@ import java.util.Objects; public class JobInfo implements Parcelable { private static String TAG = "JobInfo"; /** * Disallow setting a deadline (via {@link Builder#setOverrideDeadline(long)}) for prefetch * jobs ({@link Builder#setPrefetch(boolean)}. Prefetch jobs are meant to run close to the next * app launch, so there's no good reason to allow them to have deadlines. * * We don't drop or cancel any previously scheduled prefetch jobs with a deadline. * There's no way for an app to keep a perpetually scheduled prefetch job with a deadline. * Prefetch jobs with a deadline will run and apps under this restriction won't be able to * schedule new prefetch jobs with a deadline. If a job is rescheduled (by providing * {@code true} via {@link JobService#jobFinished(JobParameters, boolean)} or * {@link JobService#onStopJob(JobParameters)}'s return value),the deadline is dropped. * Periodic jobs require all constraints to be met, so there's no issue with their deadlines. * * @hide */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long DISALLOW_DEADLINES_FOR_PREFETCH_JOBS = 194532703L; /** @hide */ @IntDef(prefix = { "NETWORK_TYPE_" }, value = { NETWORK_TYPE_NONE, Loading Loading @@ -1445,7 +1467,9 @@ public class JobInfo implements Parcelable { /** * Specify that this job should recur with the provided interval, not more than once per * period. You have no control over when within this interval this job will be executed, * only the guarantee that it will be executed at most once within this interval. * only the guarantee that it will be executed at most once within this interval, as long * as the constraints are satisfied. If the constraints are not satisfied within this * interval, the job will wait until the constraints are satisfied. * Setting this function on the builder with {@link #setMinimumLatency(long)} or * {@link #setOverrideDeadline(long)} will result in an error. * @param intervalMillis Millisecond interval for which this job will repeat. Loading Loading @@ -1641,6 +1665,9 @@ public class JobInfo implements Parcelable { * the specific user of this device. For example, fetching top headlines * of interest to the current user. * <p> * Starting with Android version {@link Build.VERSION_CODES#TIRAMISU}, prefetch jobs are * not allowed to have deadlines (set via {@link #setOverrideDeadline(long)}. * <p> * The system may use this signal to relax the network constraints you * originally requested, such as allowing a * {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over a metered Loading Loading @@ -1675,6 +1702,11 @@ public class JobInfo implements Parcelable { * @return The job object to hand to the JobScheduler. This object is immutable. */ public JobInfo build() { return build(Compatibility.isChangeEnabled(DISALLOW_DEADLINES_FOR_PREFETCH_JOBS)); } /** @hide */ public JobInfo build(boolean disallowPrefetchDeadlines) { // This check doesn't need to be inside enforceValidity. It's an unnecessary legacy // check that would ideally be phased out instead. if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) { Loading @@ -1683,7 +1715,7 @@ public class JobInfo implements Parcelable { " setRequiresDeviceIdle is an error."); } JobInfo jobInfo = new JobInfo(this); jobInfo.enforceValidity(); jobInfo.enforceValidity(disallowPrefetchDeadlines); return jobInfo; } Loading @@ -1701,7 +1733,7 @@ public class JobInfo implements Parcelable { /** * @hide */ public final void enforceValidity() { public final void enforceValidity(boolean disallowPrefetchDeadlines) { // Check that network estimates require network type and are reasonable values. if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0) && networkRequest == null) { Loading @@ -1725,9 +1757,10 @@ public class JobInfo implements Parcelable { throw new IllegalArgumentException("Minimum chunk size must be positive"); } final boolean hasDeadline = maxExecutionDelayMillis != 0L; // Check that a deadline was not set on a periodic job. if (isPeriodic) { if (maxExecutionDelayMillis != 0L) { if (hasDeadline) { throw new IllegalArgumentException( "Can't call setOverrideDeadline() on a periodic job."); } Loading @@ -1741,6 +1774,12 @@ public class JobInfo implements Parcelable { } } // Prefetch jobs should not have deadlines if (disallowPrefetchDeadlines && hasDeadline && (flags & FLAG_PREFETCH) != 0) { throw new IllegalArgumentException( "Can't call setOverrideDeadline() on a prefetch job."); } if (isPersisted) { // We can't serialize network specifiers if (networkRequest != null Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.IUidObserver; import android.app.compat.CompatChanges; import android.app.job.IJobScheduler; import android.app.job.JobInfo; import android.app.job.JobParameters; Loading Loading @@ -2932,7 +2933,9 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJobFlags(JobInfo job, int callingUid) { job.enforceValidity(); job.enforceValidity( CompatChanges.isChangeEnabled( JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid)); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading apex/jobscheduler/service/java/com/android/server/job/JobStore.java +11 −6 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.server.IoThread; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerInternal.JobStorePersistStats; import com.android.server.job.controllers.JobStatus; Loading Loading @@ -978,10 +977,17 @@ public final class JobStore { final JobInfo builtJob; try { builtJob = jobBuilder.build(); // Don't perform prefetch-deadline check here. Apps targeting S- shouldn't have // any prefetch-with-deadline jobs accidentally dropped. It's not worth doing // target SDK version checks here for apps targeting T+. There's no way for an // app to keep a perpetually scheduled prefetch job with a deadline. Prefetch jobs // with a deadline would run and then any newly scheduled prefetch jobs wouldn't // have a deadline. If a job is rescheduled (via jobFinished(true) or onStopJob()'s // return value), the deadline is dropped. Periodic jobs require all constraints // to be met, so there's no issue with their deadlines. builtJob = jobBuilder.build(false); } catch (Exception e) { Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize()); Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize(), e); return null; } Loading @@ -997,11 +1003,10 @@ public final class JobStore { } // And now we're done JobSchedulerInternal service = LocalServices.getService(JobSchedulerInternal.class); final int appBucket = JobSchedulerService.standbyBucketForPackage(sourcePackageName, sourceUserId, elapsedNow); JobStatus js = new JobStatus( jobBuilder.build(), uid, sourcePackageName, sourceUserId, builtJob, uid, sourcePackageName, sourceUserId, appBucket, sourceTag, elapsedRuntimes.first, elapsedRuntimes.second, lastSuccessfulRunTime, lastFailedRunTime, Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +3 −1 Original line number Diff line number Diff line Loading @@ -555,7 +555,9 @@ public final class JobStatus { requestBuilder.setUids( Collections.singleton(new Range<Integer>(this.sourceUid, this.sourceUid))); builder.setRequiredNetwork(requestBuilder.build()); job = builder.build(); // Don't perform prefetch-deadline check at this point. We've already passed the // initial validation check. job = builder.build(false); } final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class); Loading Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +43 −4 Original line number Diff line number Diff line Loading @@ -29,6 +29,9 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; import android.content.ComponentName; Loading Loading @@ -63,6 +66,25 @@ import java.util.Objects; public class JobInfo implements Parcelable { private static String TAG = "JobInfo"; /** * Disallow setting a deadline (via {@link Builder#setOverrideDeadline(long)}) for prefetch * jobs ({@link Builder#setPrefetch(boolean)}. Prefetch jobs are meant to run close to the next * app launch, so there's no good reason to allow them to have deadlines. * * We don't drop or cancel any previously scheduled prefetch jobs with a deadline. * There's no way for an app to keep a perpetually scheduled prefetch job with a deadline. * Prefetch jobs with a deadline will run and apps under this restriction won't be able to * schedule new prefetch jobs with a deadline. If a job is rescheduled (by providing * {@code true} via {@link JobService#jobFinished(JobParameters, boolean)} or * {@link JobService#onStopJob(JobParameters)}'s return value),the deadline is dropped. * Periodic jobs require all constraints to be met, so there's no issue with their deadlines. * * @hide */ @ChangeId @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long DISALLOW_DEADLINES_FOR_PREFETCH_JOBS = 194532703L; /** @hide */ @IntDef(prefix = { "NETWORK_TYPE_" }, value = { NETWORK_TYPE_NONE, Loading Loading @@ -1445,7 +1467,9 @@ public class JobInfo implements Parcelable { /** * Specify that this job should recur with the provided interval, not more than once per * period. You have no control over when within this interval this job will be executed, * only the guarantee that it will be executed at most once within this interval. * only the guarantee that it will be executed at most once within this interval, as long * as the constraints are satisfied. If the constraints are not satisfied within this * interval, the job will wait until the constraints are satisfied. * Setting this function on the builder with {@link #setMinimumLatency(long)} or * {@link #setOverrideDeadline(long)} will result in an error. * @param intervalMillis Millisecond interval for which this job will repeat. Loading Loading @@ -1641,6 +1665,9 @@ public class JobInfo implements Parcelable { * the specific user of this device. For example, fetching top headlines * of interest to the current user. * <p> * Starting with Android version {@link Build.VERSION_CODES#TIRAMISU}, prefetch jobs are * not allowed to have deadlines (set via {@link #setOverrideDeadline(long)}. * <p> * The system may use this signal to relax the network constraints you * originally requested, such as allowing a * {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over a metered Loading Loading @@ -1675,6 +1702,11 @@ public class JobInfo implements Parcelable { * @return The job object to hand to the JobScheduler. This object is immutable. */ public JobInfo build() { return build(Compatibility.isChangeEnabled(DISALLOW_DEADLINES_FOR_PREFETCH_JOBS)); } /** @hide */ public JobInfo build(boolean disallowPrefetchDeadlines) { // This check doesn't need to be inside enforceValidity. It's an unnecessary legacy // check that would ideally be phased out instead. if (mBackoffPolicySet && (mConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) { Loading @@ -1683,7 +1715,7 @@ public class JobInfo implements Parcelable { " setRequiresDeviceIdle is an error."); } JobInfo jobInfo = new JobInfo(this); jobInfo.enforceValidity(); jobInfo.enforceValidity(disallowPrefetchDeadlines); return jobInfo; } Loading @@ -1701,7 +1733,7 @@ public class JobInfo implements Parcelable { /** * @hide */ public final void enforceValidity() { public final void enforceValidity(boolean disallowPrefetchDeadlines) { // Check that network estimates require network type and are reasonable values. if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0) && networkRequest == null) { Loading @@ -1725,9 +1757,10 @@ public class JobInfo implements Parcelable { throw new IllegalArgumentException("Minimum chunk size must be positive"); } final boolean hasDeadline = maxExecutionDelayMillis != 0L; // Check that a deadline was not set on a periodic job. if (isPeriodic) { if (maxExecutionDelayMillis != 0L) { if (hasDeadline) { throw new IllegalArgumentException( "Can't call setOverrideDeadline() on a periodic job."); } Loading @@ -1741,6 +1774,12 @@ public class JobInfo implements Parcelable { } } // Prefetch jobs should not have deadlines if (disallowPrefetchDeadlines && hasDeadline && (flags & FLAG_PREFETCH) != 0) { throw new IllegalArgumentException( "Can't call setOverrideDeadline() on a prefetch job."); } if (isPersisted) { // We can't serialize network specifiers if (networkRequest != null Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +4 −1 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.app.ActivityManager; import android.app.ActivityManagerInternal; import android.app.AppGlobals; import android.app.IUidObserver; import android.app.compat.CompatChanges; import android.app.job.IJobScheduler; import android.app.job.JobInfo; import android.app.job.JobParameters; Loading Loading @@ -2932,7 +2933,9 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJobFlags(JobInfo job, int callingUid) { job.enforceValidity(); job.enforceValidity( CompatChanges.isChangeEnabled( JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid)); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +11 −6 Original line number Diff line number Diff line Loading @@ -49,7 +49,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.BitUtils; import com.android.server.IoThread; import com.android.server.LocalServices; import com.android.server.job.JobSchedulerInternal.JobStorePersistStats; import com.android.server.job.controllers.JobStatus; Loading Loading @@ -978,10 +977,17 @@ public final class JobStore { final JobInfo builtJob; try { builtJob = jobBuilder.build(); // Don't perform prefetch-deadline check here. Apps targeting S- shouldn't have // any prefetch-with-deadline jobs accidentally dropped. It's not worth doing // target SDK version checks here for apps targeting T+. There's no way for an // app to keep a perpetually scheduled prefetch job with a deadline. Prefetch jobs // with a deadline would run and then any newly scheduled prefetch jobs wouldn't // have a deadline. If a job is rescheduled (via jobFinished(true) or onStopJob()'s // return value), the deadline is dropped. Periodic jobs require all constraints // to be met, so there's no issue with their deadlines. builtJob = jobBuilder.build(false); } catch (Exception e) { Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize()); Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize(), e); return null; } Loading @@ -997,11 +1003,10 @@ public final class JobStore { } // And now we're done JobSchedulerInternal service = LocalServices.getService(JobSchedulerInternal.class); final int appBucket = JobSchedulerService.standbyBucketForPackage(sourcePackageName, sourceUserId, elapsedNow); JobStatus js = new JobStatus( jobBuilder.build(), uid, sourcePackageName, sourceUserId, builtJob, uid, sourcePackageName, sourceUserId, appBucket, sourceTag, elapsedRuntimes.first, elapsedRuntimes.second, lastSuccessfulRunTime, lastFailedRunTime, Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +3 −1 Original line number Diff line number Diff line Loading @@ -555,7 +555,9 @@ public final class JobStatus { requestBuilder.setUids( Collections.singleton(new Range<Integer>(this.sourceUid, this.sourceUid))); builder.setRequiredNetwork(requestBuilder.build()); job = builder.build(); // Don't perform prefetch-deadline check at this point. We've already passed the // initial validation check. job = builder.build(false); } final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class); Loading