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

Commit d6ff7d2a authored by Kweku Adams's avatar Kweku Adams
Browse files

Expose job priority API.

The API allows apps to indicate job execution preference.
Ordering is done between an app's own jobs.

* Expedited jobs can only be MAX or HIGH priority (with MAX as the
  default value). Regular jobs can only be HIGH, DEFAULT, LOW, or MIN
  priority (with DEFAULT as the default value). Periodic and prefetch
  jobs cannot be HIGH priority. EJs are always ordered ahead of regular
  jobs, even if both are HIGH priority.
* HIGH priority jobs have a standard timeout of at least 4 minutes (5 as
  default), while DEFAULT and below maintain their 10 minute timeout.
* To prevent certain starvation cases (where lower priority jobs
  continue to be deferred because higher priority jobs are retried and
  run ahead of the lower priority jobs), priorities will decay as a job
  is repeatedly retried.

Bug: 142272435
Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/job
Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job
Test: atest CtsJobSchedulerTestCases
Change-Id: I583d7436bea4975e2f0aecc4019712afdcd0ea77
parent ef2bb53c
Loading
Loading
Loading
Loading
+202 −9
Original line number Original line Diff line number Diff line
@@ -85,6 +85,17 @@ public class JobInfo implements Parcelable {
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    public static final long DISALLOW_DEADLINES_FOR_PREFETCH_JOBS = 194532703L;
    public static final long DISALLOW_DEADLINES_FOR_PREFETCH_JOBS = 194532703L;


    /**
     * Whether to throw an exception when an app provides an invalid priority value via
     * {@link Builder#setPriority(int)}. Legacy apps may be incorrectly using the API and
     * so the call will silently fail for them if they continue using the API.
     *
     * @hide
     */
    @ChangeId
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    public static final long THROW_ON_INVALID_PRIORITY_VALUE = 140852299L;

    /** @hide */
    /** @hide */
    @IntDef(prefix = { "NETWORK_TYPE_" }, value = {
    @IntDef(prefix = { "NETWORK_TYPE_" }, value = {
            NETWORK_TYPE_NONE,
            NETWORK_TYPE_NONE,
@@ -206,6 +217,67 @@ public class JobInfo implements Parcelable {
     */
     */
    public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;
    public static final int DEFAULT_BACKOFF_POLICY = BACKOFF_POLICY_EXPONENTIAL;


    /**
     * Job has minimal value to the user. The user has absolutely no expectation
     * or knowledge of this task and it has no bearing on the user's perception of
     * the app whatsoever. JobScheduler <i>may</i> decide to defer these tasks while
     * there are higher priority tasks in order to ensure there is sufficient quota
     * available for the higher priority tasks.
     * A sample task of min priority: uploading analytics
     */
    public static final int PRIORITY_MIN = 100;

    /**
     * Low priority. The task provides some benefit to users, but is not critical
     * and is more of a nice-to-have. This is more important than minimum priority
     * jobs and will be prioritized ahead of them, but may still be deferred in lieu
     * of higher priority jobs. JobScheduler <i>may</i> decide to defer these tasks
     * while there are higher priority tasks in order to ensure there is sufficient
     * quota available for the higher priority tasks.
     * A sample task of low priority: prefetching data the user hasn't requested
     */
    public static final int PRIORITY_LOW = 200;

    /**
     * Default value for all regular jobs. As noted in {@link JobScheduler},
     * these jobs have a general maximum execution time of 10 minutes.
     * Receives the standard job management policy.
     */
    public static final int PRIORITY_DEFAULT = 300;

    /**
     * This task should be ordered ahead of most other tasks. It may be
     * deferred a little, but if it doesn't run at some point, the user may think
     * something is wrong. Assuming all constraints remain satisfied
     * (including ideal system load conditions), these jobs will have a maximum
     * execution time of at least 4 minutes. Setting all of your jobs to high
     * priority will not be beneficial to your app and in fact may hurt its
     * performance in the long run.
     */
    public static final int PRIORITY_HIGH = 400;

    /**
     * This task should be run ahead of all other tasks. Only Expedited Jobs
     * {@link Builder#setExpedited(boolean)} can have this priority and as such,
     * are subject to the same maximum execution time details noted in
     * {@link Builder#setExpedited(boolean)}.
     * A sample task of max priority: receiving a text message and processing it to
     * show a notification
     */
    public static final int PRIORITY_MAX = 500;

    /** @hide */
    @IntDef(prefix = {"PRIORITY_"}, value = {
            PRIORITY_MIN,
            PRIORITY_LOW,
            PRIORITY_DEFAULT,
            PRIORITY_HIGH,
            PRIORITY_MAX,
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface Priority {
    }

    /**
    /**
     * Default of {@link #getBias}.
     * Default of {@link #getBias}.
     * @hide
     * @hide
@@ -359,6 +431,8 @@ public class JobInfo implements Parcelable {
    private final long initialBackoffMillis;
    private final long initialBackoffMillis;
    private final int backoffPolicy;
    private final int backoffPolicy;
    private final int mBias;
    private final int mBias;
    @Priority
    private final int mPriority;
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private final int flags;
    private final int flags;


@@ -410,6 +484,14 @@ public class JobInfo implements Parcelable {
        return mBias;
        return mBias;
    }
    }


    /**
     * @see JobInfo.Builder#setPriority(int)
     */
    @Priority
    public int getPriority() {
        return mPriority;
    }

    /** @hide */
    /** @hide */
    public int getFlags() {
    public int getFlags() {
        return flags;
        return flags;
@@ -746,6 +828,9 @@ public class JobInfo implements Parcelable {
        if (mBias != j.mBias) {
        if (mBias != j.mBias) {
            return false;
            return false;
        }
        }
        if (mPriority != j.mPriority) {
            return false;
        }
        if (flags != j.flags) {
        if (flags != j.flags) {
            return false;
            return false;
        }
        }
@@ -791,6 +876,7 @@ public class JobInfo implements Parcelable {
        hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis);
        hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis);
        hashCode = 31 * hashCode + backoffPolicy;
        hashCode = 31 * hashCode + backoffPolicy;
        hashCode = 31 * hashCode + mBias;
        hashCode = 31 * hashCode + mBias;
        hashCode = 31 * hashCode + mPriority;
        hashCode = 31 * hashCode + flags;
        hashCode = 31 * hashCode + flags;
        return hashCode;
        return hashCode;
    }
    }
@@ -830,6 +916,7 @@ public class JobInfo implements Parcelable {
        hasEarlyConstraint = in.readInt() == 1;
        hasEarlyConstraint = in.readInt() == 1;
        hasLateConstraint = in.readInt() == 1;
        hasLateConstraint = in.readInt() == 1;
        mBias = in.readInt();
        mBias = in.readInt();
        mPriority = in.readInt();
        flags = in.readInt();
        flags = in.readInt();
    }
    }


@@ -861,6 +948,7 @@ public class JobInfo implements Parcelable {
        hasEarlyConstraint = b.mHasEarlyConstraint;
        hasEarlyConstraint = b.mHasEarlyConstraint;
        hasLateConstraint = b.mHasLateConstraint;
        hasLateConstraint = b.mHasLateConstraint;
        mBias = b.mBias;
        mBias = b.mBias;
        mPriority = b.mPriority;
        flags = b.mFlags;
        flags = b.mFlags;
    }
    }


@@ -906,6 +994,7 @@ public class JobInfo implements Parcelable {
        out.writeInt(hasEarlyConstraint ? 1 : 0);
        out.writeInt(hasEarlyConstraint ? 1 : 0);
        out.writeInt(hasLateConstraint ? 1 : 0);
        out.writeInt(hasLateConstraint ? 1 : 0);
        out.writeInt(mBias);
        out.writeInt(mBias);
        out.writeInt(mPriority);
        out.writeInt(this.flags);
        out.writeInt(this.flags);
    }
    }


@@ -1024,6 +1113,8 @@ public class JobInfo implements Parcelable {
        private ClipData mClipData;
        private ClipData mClipData;
        private int mClipGrantFlags;
        private int mClipGrantFlags;
        private int mBias = BIAS_DEFAULT;
        private int mBias = BIAS_DEFAULT;
        @Priority
        private int mPriority = PRIORITY_DEFAULT;
        private int mFlags;
        private int mFlags;
        // Requirements.
        // Requirements.
        private int mConstraintFlags;
        private int mConstraintFlags;
@@ -1100,6 +1191,7 @@ public class JobInfo implements Parcelable {
            // mBackoffPolicySet isn't set but it's fine since this is copying from an already valid
            // mBackoffPolicySet isn't set but it's fine since this is copying from an already valid
            // job.
            // job.
            mBackoffPolicy = job.getBackoffPolicy();
            mBackoffPolicy = job.getBackoffPolicy();
            mPriority = job.getPriority();
        }
        }


        /** @hide */
        /** @hide */
@@ -1109,11 +1201,36 @@ public class JobInfo implements Parcelable {
            return this;
            return this;
        }
        }


        /** @hide */
        /**
        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
         * Indicate the priority for this job. The priority set here will be used to sort jobs
        public Builder setPriority(int priority) {
         * for a single app and apply slightly different policies based on the priority.
            // No-op for invalid calls. This wasn't a supported API before Tiramisu, so anyone
         * The priority will <b>NOT</b> be used as a global sorting value to sort between
            // calling this that isn't targeting T isn't guaranteed a behavior change.
         * different app's jobs. Use this to inform the system about which jobs it should try
         * to run before other jobs. Giving the same priority to all of your jobs will result
         * in them all being treated the same. The priorities each have slightly different
         * behaviors, as noted in their relevant javadoc.
         *
         * <b>NOTE:</b> Setting all of your jobs to high priority will not be
         * beneficial to your app and in fact may hurt its performance in the
         * long run.
         *
         * In order to prevent starvation, repeatedly retried jobs (because of failures) will slowly
         * have their priorities lowered.
         *
         * @see JobInfo#getPriority()
         */
        @NonNull
        public Builder setPriority(@Priority int priority) {
            if (priority > PRIORITY_MAX || priority < PRIORITY_MIN) {
                if (Compatibility.isChangeEnabled(THROW_ON_INVALID_PRIORITY_VALUE)) {
                    throw new IllegalArgumentException("Invalid priority value");
                }
                // No-op for invalid calls of apps that are targeting S-. This was an unsupported
                // API before Tiramisu, so anyone calling this that isn't targeting T isn't
                // guaranteed a behavior change.
                return this;
            }
            mPriority = priority;
            return this;
            return this;
        }
        }


@@ -1637,7 +1754,17 @@ public class JobInfo implements Parcelable {
        public Builder setExpedited(boolean expedited) {
        public Builder setExpedited(boolean expedited) {
            if (expedited) {
            if (expedited) {
                mFlags |= FLAG_EXPEDITED;
                mFlags |= FLAG_EXPEDITED;
                if (mPriority == PRIORITY_DEFAULT) {
                    // The default priority for EJs is MAX, but only change this if .setPriority()
                    // hasn't been called yet.
                    mPriority = PRIORITY_MAX;
                }
            } else {
            } else {
                if (mPriority == PRIORITY_MAX && (mFlags & FLAG_EXPEDITED) != 0) {
                    // Reset the priority for the job, but only change this if .setPriority()
                    // hasn't been called yet.
                    mPriority = PRIORITY_DEFAULT;
                }
                mFlags &= (~FLAG_EXPEDITED);
                mFlags &= (~FLAG_EXPEDITED);
            }
            }
            return this;
            return this;
@@ -1664,7 +1791,18 @@ public class JobInfo implements Parcelable {
        public Builder setImportantWhileForeground(boolean importantWhileForeground) {
        public Builder setImportantWhileForeground(boolean importantWhileForeground) {
            if (importantWhileForeground) {
            if (importantWhileForeground) {
                mFlags |= FLAG_IMPORTANT_WHILE_FOREGROUND;
                mFlags |= FLAG_IMPORTANT_WHILE_FOREGROUND;
                if (mPriority == PRIORITY_DEFAULT) {
                    // The default priority for important-while-foreground is HIGH, but only change
                    // this if .setPriority() hasn't been called yet.
                    mPriority = PRIORITY_HIGH;
                }
            } else {
            } else {
                if (mPriority == PRIORITY_HIGH
                        && (mFlags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
                    // Reset the priority for the job, but only change this if .setPriority()
                    // hasn't been called yet.
                    mPriority = PRIORITY_DEFAULT;
                }
                mFlags &= (~FLAG_IMPORTANT_WHILE_FOREGROUND);
                mFlags &= (~FLAG_IMPORTANT_WHILE_FOREGROUND);
            }
            }
            return this;
            return this;
@@ -1812,12 +1950,42 @@ public class JobInfo implements Parcelable {
            }
            }
        }
        }


        if ((flags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0 && hasEarlyConstraint) {
        if ((flags & FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
            if (hasEarlyConstraint) {
                throw new IllegalArgumentException(
                throw new IllegalArgumentException(
                        "An important while foreground job cannot have a time delay");
                        "An important while foreground job cannot have a time delay");
            }
            }
            if (mPriority != PRIORITY_HIGH && mPriority != PRIORITY_DEFAULT) {
                throw new IllegalArgumentException(
                        "An important while foreground job must be high or default priority."
                                + " Don't mark unimportant tasks as important while foreground.");
            }
        }

        final boolean isExpedited = (flags & FLAG_EXPEDITED) != 0;
        switch (mPriority) {
            case PRIORITY_MAX:
                if (!isExpedited) {
                    throw new IllegalArgumentException("Only expedited jobs can have max priority");
                }
                break;
            case PRIORITY_HIGH:
                if ((flags & FLAG_PREFETCH) != 0) {
                    throw new IllegalArgumentException("Prefetch jobs cannot be high priority");
                }
                if (isPeriodic) {
                    throw new IllegalArgumentException("Periodic jobs cannot be high priority");
                }
                break;
            case PRIORITY_DEFAULT:
            case PRIORITY_LOW:
            case PRIORITY_MIN:
                break;
            default:
                throw new IllegalArgumentException("Invalid priority level provided: " + mPriority);
        }


        if ((flags & FLAG_EXPEDITED) != 0) {
        if (isExpedited) {
            if (hasEarlyConstraint) {
            if (hasEarlyConstraint) {
                throw new IllegalArgumentException("An expedited job cannot have a time delay");
                throw new IllegalArgumentException("An expedited job cannot have a time delay");
            }
            }
@@ -1827,6 +1995,11 @@ public class JobInfo implements Parcelable {
            if (isPeriodic) {
            if (isPeriodic) {
                throw new IllegalArgumentException("An expedited job cannot be periodic");
                throw new IllegalArgumentException("An expedited job cannot be periodic");
            }
            }
            if (mPriority != PRIORITY_MAX && mPriority != PRIORITY_HIGH) {
                throw new IllegalArgumentException(
                        "An expedited job must be high or max priority. Don't use expedited jobs"
                                + " for unimportant tasks.");
            }
            if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0
            if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0
                    || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY)) != 0) {
                    || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY)) != 0) {
                throw new IllegalArgumentException(
                throw new IllegalArgumentException(
@@ -1863,4 +2036,24 @@ public class JobInfo implements Parcelable {
        }
        }
        return bias + " [UNKNOWN]";
        return bias + " [UNKNOWN]";
    }
    }

    /**
     * Convert a priority integer into a human readable string for debugging.
     * @hide
     */
    public static String getPriorityString(@Priority int priority) {
        switch (priority) {
            case PRIORITY_MIN:
                return priority + " [MIN]";
            case PRIORITY_LOW:
                return priority + " [LOW]";
            case PRIORITY_DEFAULT:
                return priority + " [DEFAULT]";
            case PRIORITY_HIGH:
                return priority + " [HIGH]";
            case PRIORITY_MAX:
                return priority + " [MAX]";
        }
        return priority + " [UNKNOWN]";
    }
}
}
+148 −36

File changed.

Preview size limit exceeded, changes collapsed.

+30 −6
Original line number Original line Diff line number Diff line
@@ -16,6 +16,8 @@


package com.android.server.job;
package com.android.server.job;


import static android.app.job.JobInfo.getPriorityString;

import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;


@@ -378,19 +380,41 @@ public final class JobServiceContext implements ServiceConnection {


    @EconomicPolicy.AppAction
    @EconomicPolicy.AppAction
    private static int getStartActionId(@NonNull JobStatus job) {
    private static int getStartActionId(@NonNull JobStatus job) {
        if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) {
        switch (job.getEffectivePriority()) {
            case JobInfo.PRIORITY_MAX:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START;
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START;
        }
            case JobInfo.PRIORITY_HIGH:
                return JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_START;
            case JobInfo.PRIORITY_LOW:
                return JobSchedulerEconomicPolicy.ACTION_JOB_LOW_START;
            case JobInfo.PRIORITY_MIN:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MIN_START;
            default:
                Slog.wtf(TAG, "Unknown priority: " + getPriorityString(job.getEffectivePriority()));
                // Intentional fallthrough
            case JobInfo.PRIORITY_DEFAULT:
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START;
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START;
        }
        }
    }


    @EconomicPolicy.AppAction
    @EconomicPolicy.AppAction
    private static int getRunningActionId(@NonNull JobStatus job) {
    private static int getRunningActionId(@NonNull JobStatus job) {
        if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) {
        switch (job.getEffectivePriority()) {
            case JobInfo.PRIORITY_MAX:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING;
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING;
        }
            case JobInfo.PRIORITY_HIGH:
                return JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_RUNNING;
            case JobInfo.PRIORITY_LOW:
                return JobSchedulerEconomicPolicy.ACTION_JOB_LOW_RUNNING;
            case JobInfo.PRIORITY_MIN:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MIN_RUNNING;
            default:
                Slog.wtf(TAG, "Unknown priority: " + getPriorityString(job.getEffectivePriority()));
                // Intentional fallthrough
            case JobInfo.PRIORITY_DEFAULT:
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING;
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING;
        }
        }
    }


    /**
    /**
     * Used externally to query the running job. Will return null if there is no job running.
     * Used externally to query the running job. Will return null if there is no job running.
+22 −11
Original line number Original line Diff line number Diff line
@@ -335,7 +335,7 @@ public final class JobStore {
    }
    }


    /** Version of the db schema. */
    /** Version of the db schema. */
    private static final int JOBS_FILE_VERSION = 0;
    private static final int JOBS_FILE_VERSION = 1;
    /** Tag corresponds to constraints this job needs. */
    /** Tag corresponds to constraints this job needs. */
    private static final String XML_TAG_PARAMS_CONSTRAINTS = "constraints";
    private static final String XML_TAG_PARAMS_CONSTRAINTS = "constraints";
    /** Tag corresponds to execution parameters. */
    /** Tag corresponds to execution parameters. */
@@ -548,6 +548,7 @@ public final class JobStore {
            out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
            out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId()));
            out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
            out.attribute(null, "uid", Integer.toString(jobStatus.getUid()));
            out.attribute(null, "bias", String.valueOf(jobStatus.getBias()));
            out.attribute(null, "bias", String.valueOf(jobStatus.getBias()));
            out.attribute(null, "priority", String.valueOf(jobStatus.getEffectivePriority()));
            out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
            out.attribute(null, "flags", String.valueOf(jobStatus.getFlags()));
            if (jobStatus.getInternalFlags() != 0) {
            if (jobStatus.getInternalFlags() != 0) {
                out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags()));
                out.attribute(null, "internalFlags", String.valueOf(jobStatus.getInternalFlags()));
@@ -771,10 +772,11 @@ public final class JobStore {
            String tagName = parser.getName();
            String tagName = parser.getName();
            if ("job-info".equals(tagName)) {
            if ("job-info".equals(tagName)) {
                final List<JobStatus> jobs = new ArrayList<JobStatus>();
                final List<JobStatus> jobs = new ArrayList<JobStatus>();
                final int version;
                // Read in version info.
                // Read in version info.
                try {
                try {
                    int version = Integer.parseInt(parser.getAttributeValue(null, "version"));
                    version = Integer.parseInt(parser.getAttributeValue(null, "version"));
                    if (version != JOBS_FILE_VERSION) {
                    if (version > JOBS_FILE_VERSION || version < 0) {
                        Slog.d(TAG, "Invalid version number, aborting jobs file read.");
                        Slog.d(TAG, "Invalid version number, aborting jobs file read.");
                        return null;
                        return null;
                    }
                    }
@@ -789,7 +791,7 @@ public final class JobStore {
                        tagName = parser.getName();
                        tagName = parser.getName();
                        // Start reading job.
                        // Start reading job.
                        if ("job".equals(tagName)) {
                        if ("job".equals(tagName)) {
                            JobStatus persistedJob = restoreJobFromXml(rtcIsGood, parser);
                            JobStatus persistedJob = restoreJobFromXml(rtcIsGood, parser, version);
                            if (persistedJob != null) {
                            if (persistedJob != null) {
                                if (DEBUG) {
                                if (DEBUG) {
                                    Slog.d(TAG, "Read out " + persistedJob);
                                    Slog.d(TAG, "Read out " + persistedJob);
@@ -812,8 +814,8 @@ public final class JobStore {
         *               will take the parser into the body of the job tag.
         *               will take the parser into the body of the job tag.
         * @return Newly instantiated job holding all the information we just read out of the xml tag.
         * @return Newly instantiated job holding all the information we just read out of the xml tag.
         */
         */
        private JobStatus restoreJobFromXml(boolean rtcIsGood, XmlPullParser parser)
        private JobStatus restoreJobFromXml(boolean rtcIsGood, XmlPullParser parser,
                throws XmlPullParserException, IOException {
                int schemaVersion) throws XmlPullParserException, IOException {
            JobInfo.Builder jobBuilder;
            JobInfo.Builder jobBuilder;
            int uid, sourceUserId;
            int uid, sourceUserId;
            long lastSuccessfulRunTime;
            long lastSuccessfulRunTime;
@@ -826,13 +828,22 @@ public final class JobStore {
                jobBuilder.setPersisted(true);
                jobBuilder.setPersisted(true);
                uid = Integer.parseInt(parser.getAttributeValue(null, "uid"));
                uid = Integer.parseInt(parser.getAttributeValue(null, "uid"));


                String val = parser.getAttributeValue(null, "bias");
                String val;
                if (val == null) {
                if (schemaVersion == 0) {
                    val = parser.getAttributeValue(null, "priority");
                    val = parser.getAttributeValue(null, "priority");
                    if (val != null) {
                        jobBuilder.setBias(Integer.parseInt(val));
                    }
                    }
                } else if (schemaVersion >= 1) {
                    val = parser.getAttributeValue(null, "bias");
                    if (val != null) {
                    if (val != null) {
                        jobBuilder.setBias(Integer.parseInt(val));
                        jobBuilder.setBias(Integer.parseInt(val));
                    }
                    }
                    val = parser.getAttributeValue(null, "priority");
                    if (val != null) {
                        jobBuilder.setPriority(Integer.parseInt(val));
                    }
                }
                val = parser.getAttributeValue(null, "flags");
                val = parser.getAttributeValue(null, "flags");
                if (val != null) {
                if (val != null) {
                    jobBuilder.setFlags(Integer.parseInt(val));
                    jobBuilder.setFlags(Integer.parseInt(val));
+3 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,7 @@
            "name": "CtsJobSchedulerTestCases",
            "name": "CtsJobSchedulerTestCases",
            "options": [
            "options": [
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.LargeTest"},
                {"exclude-annotation": "androidx.test.filters.FlakyTest"},
                {"exclude-annotation": "androidx.test.filters.FlakyTest"},
                {"exclude-annotation": "androidx.test.filters.LargeTest"}
                {"exclude-annotation": "androidx.test.filters.LargeTest"}
            ]
            ]
@@ -13,6 +14,7 @@
            "options": [
            "options": [
                {"include-filter": "com.android.server.job"},
                {"include-filter": "com.android.server.job"},
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.LargeTest"},
                {"exclude-annotation": "androidx.test.filters.FlakyTest"}
                {"exclude-annotation": "androidx.test.filters.FlakyTest"}
            ]
            ]
        },
        },
@@ -21,6 +23,7 @@
            "options": [
            "options": [
                {"include-filter": "com.android.server.job"},
                {"include-filter": "com.android.server.job"},
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
                {"exclude-annotation": "android.platform.test.annotations.LargeTest"},
                {"exclude-annotation": "androidx.test.filters.FlakyTest"}
                {"exclude-annotation": "androidx.test.filters.FlakyTest"}
            ]
            ]
        }
        }
Loading