Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +27 −4 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; Loading Loading @@ -97,6 +98,15 @@ public class JobInfo implements Parcelable { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long THROW_ON_INVALID_PRIORITY_VALUE = 140852299L; /** * Require that estimated network bytes are nonnegative. * * @hide */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long REJECT_NEGATIVE_NETWORK_ESTIMATES = 253665015L; /** @hide */ @IntDef(prefix = { "NETWORK_TYPE_" }, value = { NETWORK_TYPE_NONE, Loading Loading @@ -1890,11 +1900,13 @@ 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)); return build(Compatibility.isChangeEnabled(DISALLOW_DEADLINES_FOR_PREFETCH_JOBS), Compatibility.isChangeEnabled(REJECT_NEGATIVE_NETWORK_ESTIMATES)); } /** @hide */ public JobInfo build(boolean disallowPrefetchDeadlines) { public JobInfo build(boolean disallowPrefetchDeadlines, boolean rejectNegativeNetworkEstimates) { // 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 @@ -1903,7 +1915,7 @@ public class JobInfo implements Parcelable { " setRequiresDeviceIdle is an error."); } JobInfo jobInfo = new JobInfo(this); jobInfo.enforceValidity(disallowPrefetchDeadlines); jobInfo.enforceValidity(disallowPrefetchDeadlines, rejectNegativeNetworkEstimates); return jobInfo; } Loading @@ -1921,13 +1933,24 @@ public class JobInfo implements Parcelable { /** * @hide */ public final void enforceValidity(boolean disallowPrefetchDeadlines) { public final void enforceValidity(boolean disallowPrefetchDeadlines, boolean rejectNegativeNetworkEstimates) { // Check that network estimates require network type and are reasonable values. if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0) && networkRequest == null) { throw new IllegalArgumentException( "Can't provide estimated network usage without requiring a network"); } if (networkRequest != null && rejectNegativeNetworkEstimates) { if (networkUploadBytes != NETWORK_BYTES_UNKNOWN && networkUploadBytes < 0) { throw new IllegalArgumentException( "Invalid network upload bytes: " + networkUploadBytes); } if (networkDownloadBytes != NETWORK_BYTES_UNKNOWN && networkDownloadBytes < 0) { throw new IllegalArgumentException( "Invalid network download bytes: " + networkDownloadBytes); } } final long estimatedTransfer; if (networkUploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = networkDownloadBytes; Loading apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java +13 −16 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN; import android.annotation.BytesLong; import android.annotation.Nullable; import android.compat.Compatibility; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; import android.os.Build; Loading Loading @@ -88,25 +89,11 @@ final public class JobWorkItem implements Parcelable { */ public JobWorkItem(@Nullable Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes, @BytesLong long minimumChunkBytes) { if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && minimumChunkBytes <= 0) { throw new IllegalArgumentException("Minimum chunk size must be positive"); } final long estimatedTransfer; if (uploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = downloadBytes; } else { estimatedTransfer = uploadBytes + (downloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : downloadBytes); } if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && estimatedTransfer != NETWORK_BYTES_UNKNOWN && minimumChunkBytes > estimatedTransfer) { throw new IllegalArgumentException( "Minimum chunk size can't be greater than estimated network usage"); } mIntent = intent; mNetworkDownloadBytes = downloadBytes; mNetworkUploadBytes = uploadBytes; mMinimumChunkBytes = minimumChunkBytes; enforceValidity(Compatibility.isChangeEnabled(JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES)); } /** Loading Loading @@ -222,7 +209,17 @@ final public class JobWorkItem implements Parcelable { /** * @hide */ public void enforceValidity() { public void enforceValidity(boolean rejectNegativeNetworkEstimates) { if (rejectNegativeNetworkEstimates) { if (mNetworkUploadBytes != NETWORK_BYTES_UNKNOWN && mNetworkUploadBytes < 0) { throw new IllegalArgumentException( "Invalid network upload bytes: " + mNetworkUploadBytes); } if (mNetworkDownloadBytes != NETWORK_BYTES_UNKNOWN && mNetworkDownloadBytes < 0) { throw new IllegalArgumentException( "Invalid network download bytes: " + mNetworkDownloadBytes); } } final long estimatedTransfer; if (mNetworkUploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = mNetworkDownloadBytes; Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +5 −2 Original line number Diff line number Diff line Loading @@ -3163,9 +3163,12 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJob(JobInfo job, int callingUid, @Nullable JobWorkItem jobWorkItem) { final boolean rejectNegativeNetworkEstimates = CompatChanges.isChangeEnabled( JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES, callingUid); job.enforceValidity( CompatChanges.isChangeEnabled( JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid)); JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid), rejectNegativeNetworkEstimates); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading @@ -3180,7 +3183,7 @@ public class JobSchedulerService extends com.android.server.SystemService } } if (jobWorkItem != null) { jobWorkItem.enforceValidity(); jobWorkItem.enforceValidity(rejectNegativeNetworkEstimates); if (jobWorkItem.getEstimatedNetworkDownloadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN || jobWorkItem.getEstimatedNetworkUploadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN Loading apex/jobscheduler/service/java/com/android/server/job/JobStore.java +2 −1 Original line number Diff line number Diff line Loading @@ -1024,7 +1024,8 @@ public final class JobStore { // 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); // The same logic applies for other target SDK-based validation checks. builtJob = jobBuilder.build(false, false); } catch (Exception e) { Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize(), e); return null; Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +2 −2 Original line number Diff line number Diff line Loading @@ -612,9 +612,9 @@ public final class JobStatus { requestBuilder.setUids( Collections.singleton(new Range<Integer>(this.sourceUid, this.sourceUid))); builder.setRequiredNetwork(requestBuilder.build()); // Don't perform prefetch-deadline check at this point. We've already passed the // Don't perform validation checks at this point since we've already passed the // initial validation check. job = builder.build(false); job = builder.build(false, false); } updateMediaBackupExemptionStatus(); Loading Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +27 −4 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ClipData; Loading Loading @@ -97,6 +98,15 @@ public class JobInfo implements Parcelable { @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long THROW_ON_INVALID_PRIORITY_VALUE = 140852299L; /** * Require that estimated network bytes are nonnegative. * * @hide */ @ChangeId @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) public static final long REJECT_NEGATIVE_NETWORK_ESTIMATES = 253665015L; /** @hide */ @IntDef(prefix = { "NETWORK_TYPE_" }, value = { NETWORK_TYPE_NONE, Loading Loading @@ -1890,11 +1900,13 @@ 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)); return build(Compatibility.isChangeEnabled(DISALLOW_DEADLINES_FOR_PREFETCH_JOBS), Compatibility.isChangeEnabled(REJECT_NEGATIVE_NETWORK_ESTIMATES)); } /** @hide */ public JobInfo build(boolean disallowPrefetchDeadlines) { public JobInfo build(boolean disallowPrefetchDeadlines, boolean rejectNegativeNetworkEstimates) { // 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 @@ -1903,7 +1915,7 @@ public class JobInfo implements Parcelable { " setRequiresDeviceIdle is an error."); } JobInfo jobInfo = new JobInfo(this); jobInfo.enforceValidity(disallowPrefetchDeadlines); jobInfo.enforceValidity(disallowPrefetchDeadlines, rejectNegativeNetworkEstimates); return jobInfo; } Loading @@ -1921,13 +1933,24 @@ public class JobInfo implements Parcelable { /** * @hide */ public final void enforceValidity(boolean disallowPrefetchDeadlines) { public final void enforceValidity(boolean disallowPrefetchDeadlines, boolean rejectNegativeNetworkEstimates) { // Check that network estimates require network type and are reasonable values. if ((networkDownloadBytes > 0 || networkUploadBytes > 0 || minimumNetworkChunkBytes > 0) && networkRequest == null) { throw new IllegalArgumentException( "Can't provide estimated network usage without requiring a network"); } if (networkRequest != null && rejectNegativeNetworkEstimates) { if (networkUploadBytes != NETWORK_BYTES_UNKNOWN && networkUploadBytes < 0) { throw new IllegalArgumentException( "Invalid network upload bytes: " + networkUploadBytes); } if (networkDownloadBytes != NETWORK_BYTES_UNKNOWN && networkDownloadBytes < 0) { throw new IllegalArgumentException( "Invalid network download bytes: " + networkDownloadBytes); } } final long estimatedTransfer; if (networkUploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = networkDownloadBytes; Loading
apex/jobscheduler/framework/java/android/app/job/JobWorkItem.java +13 −16 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN; import android.annotation.BytesLong; import android.annotation.Nullable; import android.compat.Compatibility; import android.compat.annotation.UnsupportedAppUsage; import android.content.Intent; import android.os.Build; Loading Loading @@ -88,25 +89,11 @@ final public class JobWorkItem implements Parcelable { */ public JobWorkItem(@Nullable Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes, @BytesLong long minimumChunkBytes) { if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && minimumChunkBytes <= 0) { throw new IllegalArgumentException("Minimum chunk size must be positive"); } final long estimatedTransfer; if (uploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = downloadBytes; } else { estimatedTransfer = uploadBytes + (downloadBytes == NETWORK_BYTES_UNKNOWN ? 0 : downloadBytes); } if (minimumChunkBytes != NETWORK_BYTES_UNKNOWN && estimatedTransfer != NETWORK_BYTES_UNKNOWN && minimumChunkBytes > estimatedTransfer) { throw new IllegalArgumentException( "Minimum chunk size can't be greater than estimated network usage"); } mIntent = intent; mNetworkDownloadBytes = downloadBytes; mNetworkUploadBytes = uploadBytes; mMinimumChunkBytes = minimumChunkBytes; enforceValidity(Compatibility.isChangeEnabled(JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES)); } /** Loading Loading @@ -222,7 +209,17 @@ final public class JobWorkItem implements Parcelable { /** * @hide */ public void enforceValidity() { public void enforceValidity(boolean rejectNegativeNetworkEstimates) { if (rejectNegativeNetworkEstimates) { if (mNetworkUploadBytes != NETWORK_BYTES_UNKNOWN && mNetworkUploadBytes < 0) { throw new IllegalArgumentException( "Invalid network upload bytes: " + mNetworkUploadBytes); } if (mNetworkDownloadBytes != NETWORK_BYTES_UNKNOWN && mNetworkDownloadBytes < 0) { throw new IllegalArgumentException( "Invalid network download bytes: " + mNetworkDownloadBytes); } } final long estimatedTransfer; if (mNetworkUploadBytes == NETWORK_BYTES_UNKNOWN) { estimatedTransfer = mNetworkDownloadBytes; Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +5 −2 Original line number Diff line number Diff line Loading @@ -3163,9 +3163,12 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJob(JobInfo job, int callingUid, @Nullable JobWorkItem jobWorkItem) { final boolean rejectNegativeNetworkEstimates = CompatChanges.isChangeEnabled( JobInfo.REJECT_NEGATIVE_NETWORK_ESTIMATES, callingUid); job.enforceValidity( CompatChanges.isChangeEnabled( JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid)); JobInfo.DISALLOW_DEADLINES_FOR_PREFETCH_JOBS, callingUid), rejectNegativeNetworkEstimates); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading @@ -3180,7 +3183,7 @@ public class JobSchedulerService extends com.android.server.SystemService } } if (jobWorkItem != null) { jobWorkItem.enforceValidity(); jobWorkItem.enforceValidity(rejectNegativeNetworkEstimates); if (jobWorkItem.getEstimatedNetworkDownloadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN || jobWorkItem.getEstimatedNetworkUploadBytes() != JobInfo.NETWORK_BYTES_UNKNOWN Loading
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +2 −1 Original line number Diff line number Diff line Loading @@ -1024,7 +1024,8 @@ public final class JobStore { // 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); // The same logic applies for other target SDK-based validation checks. builtJob = jobBuilder.build(false, false); } catch (Exception e) { Slog.w(TAG, "Unable to build job from XML, ignoring: " + jobBuilder.summarize(), e); return null; Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +2 −2 Original line number Diff line number Diff line Loading @@ -612,9 +612,9 @@ public final class JobStatus { requestBuilder.setUids( Collections.singleton(new Range<Integer>(this.sourceUid, this.sourceUid))); builder.setRequiredNetwork(requestBuilder.build()); // Don't perform prefetch-deadline check at this point. We've already passed the // Don't perform validation checks at this point since we've already passed the // initial validation check. job = builder.build(false); job = builder.build(false, false); } updateMediaBackupExemptionStatus(); Loading