Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 901ade86 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Prevent apps from setting negative estimated bytes."

parents 76e3b3cc 3d5d56f8
Loading
Loading
Loading
Loading
+27 −4
Original line number Diff line number Diff line
@@ -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;
@@ -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,
@@ -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) {
@@ -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;
        }

@@ -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;
+13 −16
Original line number Diff line number Diff line
@@ -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;
@@ -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));
    }

    /**
@@ -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;
+5 −2
Original line number Diff line number Diff line
@@ -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);
@@ -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
+2 −1
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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();