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

Commit 26c647f5 authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Revert "Add methods to mark some constraints as optional."" into main

parents 30c1f002 6b5722c2
Loading
Loading
Loading
Loading
+5 −160
Original line number Diff line number Diff line
@@ -432,7 +432,6 @@ public class JobInfo implements Parcelable {
    @UnsupportedAppUsage
    private final ComponentName service;
    private final int constraintFlags;
    private final int mPreferredConstraintFlags;
    private final TriggerContentUri[] triggerContentUris;
    private final long triggerContentUpdateDelay;
    private final long triggerContentMaxDelay;
@@ -522,30 +521,6 @@ public class JobInfo implements Parcelable {
        return ((flags & FLAG_EXEMPT_FROM_APP_STANDBY) != 0) && !isPeriodic();
    }

    /**
     * @hide
     * @see JobInfo.Builder#setPrefersBatteryNotLow(boolean)
     */
    public boolean isPreferBatteryNotLow() {
        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0;
    }

    /**
     * @hide
     * @see JobInfo.Builder#setPrefersCharging(boolean)
     */
    public boolean isPreferCharging() {
        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_CHARGING) != 0;
    }

    /**
     * @hide
     * @see JobInfo.Builder#setPrefersDeviceIdle(boolean)
     */
    public boolean isPreferDeviceIdle() {
        return (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0;
    }

    /**
     * @see JobInfo.Builder#setRequiresCharging(boolean)
     */
@@ -581,13 +556,6 @@ public class JobInfo implements Parcelable {
        return constraintFlags;
    }

    /**
     * @hide
     */
    public int getPreferredConstraintFlags() {
        return mPreferredConstraintFlags;
    }

    /**
     * Which content: URIs must change for the job to be scheduled.  Returns null
     * if there are none required.
@@ -832,9 +800,6 @@ public class JobInfo implements Parcelable {
        if (constraintFlags != j.constraintFlags) {
            return false;
        }
        if (mPreferredConstraintFlags != j.mPreferredConstraintFlags) {
            return false;
        }
        if (!Arrays.equals(triggerContentUris, j.triggerContentUris)) {
            return false;
        }
@@ -915,7 +880,6 @@ public class JobInfo implements Parcelable {
            hashCode = 31 * hashCode + service.hashCode();
        }
        hashCode = 31 * hashCode + constraintFlags;
        hashCode = 31 * hashCode + mPreferredConstraintFlags;
        if (triggerContentUris != null) {
            hashCode = 31 * hashCode + Arrays.hashCode(triggerContentUris);
        }
@@ -958,7 +922,6 @@ public class JobInfo implements Parcelable {
        }
        service = in.readParcelable(null);
        constraintFlags = in.readInt();
        mPreferredConstraintFlags = in.readInt();
        triggerContentUris = in.createTypedArray(TriggerContentUri.CREATOR);
        triggerContentUpdateDelay = in.readLong();
        triggerContentMaxDelay = in.readLong();
@@ -993,7 +956,6 @@ public class JobInfo implements Parcelable {
        clipGrantFlags = b.mClipGrantFlags;
        service = b.mJobService;
        constraintFlags = b.mConstraintFlags;
        mPreferredConstraintFlags = b.mPreferredConstraintFlags;
        triggerContentUris = b.mTriggerContentUris != null
                ? b.mTriggerContentUris.toArray(new TriggerContentUri[b.mTriggerContentUris.size()])
                : null;
@@ -1037,7 +999,6 @@ public class JobInfo implements Parcelable {
        }
        out.writeParcelable(service, flags);
        out.writeInt(constraintFlags);
        out.writeInt(mPreferredConstraintFlags);
        out.writeTypedArray(triggerContentUris, flags);
        out.writeLong(triggerContentUpdateDelay);
        out.writeLong(triggerContentMaxDelay);
@@ -1185,7 +1146,6 @@ public class JobInfo implements Parcelable {
        private int mFlags;
        // Requirements.
        private int mConstraintFlags;
        private int mPreferredConstraintFlags;
        private NetworkRequest mNetworkRequest;
        private long mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
        private long mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
@@ -1239,7 +1199,6 @@ public class JobInfo implements Parcelable {
            mBias = job.getBias();
            mFlags = job.getFlags();
            mConstraintFlags = job.getConstraintFlags();
            mPreferredConstraintFlags = job.getPreferredConstraintFlags();
            mNetworkRequest = job.getRequiredNetwork();
            mNetworkDownloadBytes = job.getEstimatedNetworkDownloadBytes();
            mNetworkUploadBytes = job.getEstimatedNetworkUploadBytes();
@@ -1389,6 +1348,10 @@ public class JobInfo implements Parcelable {
         * {@link android.Manifest.permission#ACCESS_NETWORK_STATE} permission to
         * schedule a job that requires a network.
         *
         * <p> Starting in Android version {@link android.os.Build.VERSION_CODES#UPSIDE_DOWN_CAKE},
         * {@link JobScheduler} may try to shift the execution of jobs requiring
         * {@link #NETWORK_TYPE_ANY} to when there is access to an un-metered network.
         *
         * <p class="note">
         * When your job executes in
         * {@link JobService#onStartJob(JobParameters)}, be sure to use the
@@ -1554,100 +1517,6 @@ public class JobInfo implements Parcelable {
            return this;
        }

        /**
         * Specify that this job would prefer to be run when the device's battery is not low.
         * This defaults to {@code false}.
         *
         * <p>The system may attempt to delay this job until the device's battery is not low,
         * but may choose to run it even if the device's battery is low. JobScheduler will not stop
         * this job if this constraint is no longer satisfied after the job has started running.
         * If this job must only run when the device's battery is not low,
         * use {@link #setRequiresBatteryNotLow(boolean)} instead.
         *
         * <p>
         * Because it doesn't make sense for a constraint to be both preferred and required,
         * calling both this and {@link #setRequiresBatteryNotLow(boolean)} with {@code true}
         * will result in an {@link java.lang.IllegalArgumentException} when
         * {@link android.app.job.JobInfo.Builder#build()} is called.
         *
         * @param prefersBatteryNotLow Pass {@code true} to prefer that the device's battery level
         *                             not be low in order to run the job.
         * @return This object for method chaining
         * @see JobInfo#isPreferBatteryNotLow()
         * @hide
         */
        @NonNull
        public Builder setPrefersBatteryNotLow(boolean prefersBatteryNotLow) {
            mPreferredConstraintFlags =
                    (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_BATTERY_NOT_LOW)
                            | (prefersBatteryNotLow ? CONSTRAINT_FLAG_BATTERY_NOT_LOW : 0);
            return this;
        }

        /**
         * Specify that this job would prefer to be run when the device is charging (or be a
         * non-battery-powered device connected to permanent power, such as Android TV
         * devices). This defaults to {@code false}.
         *
         * <p>
         * The system may attempt to delay this job until the device is charging, but may
         * choose to run it even if the device is not charging. JobScheduler will not stop
         * this job if this constraint is no longer satisfied after the job has started running.
         * If this job must only run when the device is charging,
         * use {@link #setRequiresCharging(boolean)} instead.
         *
         * <p>
         * Because it doesn't make sense for a constraint to be both preferred and required,
         * calling both this and {@link #setRequiresCharging(boolean)} with {@code true}
         * will result in an {@link java.lang.IllegalArgumentException} when
         * {@link android.app.job.JobInfo.Builder#build()} is called.
         *
         * @param prefersCharging Pass {@code true} to prefer that the device be
         *                        charging in order to run the job.
         * @return This object for method chaining
         * @see JobInfo#isPreferCharging()
         * @hide
         */
        @NonNull
        public Builder setPrefersCharging(boolean prefersCharging) {
            mPreferredConstraintFlags = (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_CHARGING)
                    | (prefersCharging ? CONSTRAINT_FLAG_CHARGING : 0);
            return this;
        }

        /**
         * Specify that this job would prefer to be run when the device is not in active use.
         * This defaults to {@code false}.
         *
         * <p>The system may attempt to delay this job until the device is not in active use,
         * but may choose to run it even if the device is not idle. JobScheduler will not stop
         * this job if this constraint is no longer satisfied after the job has started running.
         * If this job must only run when the device is not in active use,
         * use {@link #setRequiresDeviceIdle(boolean)} instead.
         *
         * <p>
         * Because it doesn't make sense for a constraint to be both preferred and required,
         * calling both this and {@link #setRequiresDeviceIdle(boolean)} with {@code true}
         * will result in an {@link java.lang.IllegalArgumentException} when
         * {@link android.app.job.JobInfo.Builder#build()} is called.
         *
         * <p class="note">Despite the similar naming, this job constraint is <em>not</em>
         * related to the system's "device idle" or "doze" states.  This constraint only
         * determines whether a job is allowed to run while the device is directly in use.
         *
         * @param prefersDeviceIdle Pass {@code true} to prefer that the device not be in active
         *                          use when running this job.
         * @return This object for method chaining
         * @see JobInfo#isRequireDeviceIdle()
         * @hide
         */
        @NonNull
        public Builder setPrefersDeviceIdle(boolean prefersDeviceIdle) {
            mPreferredConstraintFlags = (mPreferredConstraintFlags & ~CONSTRAINT_FLAG_DEVICE_IDLE)
                    | (prefersDeviceIdle ? CONSTRAINT_FLAG_DEVICE_IDLE : 0);
            return this;
        }

        /**
         * Specify that to run this job, the device must be charging (or be a
         * non-battery-powered device connected to permanent power, such as Android TV
@@ -2306,29 +2175,6 @@ public class JobInfo implements Parcelable {
            }
        }

        if ((constraintFlags & mPreferredConstraintFlags) != 0) {
            // Something is marked as both preferred and required. Try to give a clear exception
            // reason.
            if ((constraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0
                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_BATTERY_NOT_LOW) != 0) {
                throw new IllegalArgumentException(
                        "battery-not-low constraint cannot be both preferred and required");
            }
            if ((constraintFlags & CONSTRAINT_FLAG_CHARGING) != 0
                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_CHARGING) != 0) {
                throw new IllegalArgumentException(
                        "charging constraint cannot be both preferred and required");
            }
            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0
                    && (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
                throw new IllegalArgumentException(
                        "device idle constraint cannot be both preferred and required");
            }
            // Couldn't figure out what the overlap was. Just use a generic message.
            throw new IllegalArgumentException(
                    "constraints cannot be both preferred and required");
        }

        if (isUserInitiated) {
            if (hasEarlyConstraint) {
                throw new IllegalArgumentException("A user-initiated job cannot have a time delay");
@@ -2346,8 +2192,7 @@ public class JobInfo implements Parcelable {
            if (mPriority != PRIORITY_MAX) {
                throw new IllegalArgumentException("A user-initiated job must be max priority.");
            }
            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0
                    || (mPreferredConstraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
            if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) {
                throw new IllegalArgumentException(
                        "A user-initiated job cannot have a device-idle constraint");
            }
+0 −16
Original line number Diff line number Diff line
@@ -938,15 +938,6 @@ public final class JobStore {
            if (job.isRequireStorageNotLow()) {
                out.attribute(null, "storage-not-low", Boolean.toString(true));
            }
            if (job.isPreferBatteryNotLow()) {
                out.attributeBoolean(null, "prefer-battery-not-low", true);
            }
            if (job.isPreferCharging()) {
                out.attributeBoolean(null, "prefer-charging", true);
            }
            if (job.isPreferDeviceIdle()) {
                out.attributeBoolean(null, "prefer-idle", true);
            }
            out.endTag(null, XML_TAG_PARAMS_CONSTRAINTS);
        }

@@ -1638,13 +1629,6 @@ public final class JobStore {
            if (val != null) {
                jobBuilder.setRequiresStorageNotLow(true);
            }

            jobBuilder.setPrefersBatteryNotLow(
                    parser.getAttributeBoolean(null, "prefer-battery-not-low", false));
            jobBuilder.setPrefersCharging(
                    parser.getAttributeBoolean(null, "prefer-charging", false));
            jobBuilder.setPrefersDeviceIdle(
                    parser.getAttributeBoolean(null, "prefer-idle", false));
        }

        /**
+3 −2
Original line number Diff line number Diff line
@@ -1263,9 +1263,10 @@ public final class ConnectivityController extends RestrictingController implemen

        final boolean changed = jobStatus.setConnectivityConstraintSatisfied(nowElapsed, satisfied);

        if (jobStatus.getPreferUnmetered()) {
            jobStatus.setHasAccessToUnmetered(satisfied && capabilities != null
                    && capabilities.hasCapability(NET_CAPABILITY_NOT_METERED));
        if (jobStatus.getPreferUnmetered()) {

            jobStatus.setFlexibilityConstraintSatisfied(nowElapsed,
                    mFlexibilityController.isFlexibilitySatisfiedLocked(jobStatus));
        }
+3 −3
Original line number Diff line number Diff line
@@ -252,15 +252,15 @@ public final class FlexibilityController extends StateController {
    boolean isFlexibilitySatisfiedLocked(JobStatus js) {
        return !mFlexibilityEnabled
                || mService.getUidBias(js.getSourceUid()) == JobInfo.BIAS_TOP_APP
                || getNumSatisfiedFlexibleConstraintsLocked(js)
                || getNumSatisfiedRequiredConstraintsLocked(js)
                        >= js.getNumRequiredFlexibleConstraints()
                || mService.isCurrentlyRunningLocked(js);
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    int getNumSatisfiedFlexibleConstraintsLocked(JobStatus js) {
        return Integer.bitCount(mSatisfiedFlexibleConstraints & js.getPreferredConstraintFlags())
    int getNumSatisfiedRequiredConstraintsLocked(JobStatus js) {
        return Integer.bitCount(mSatisfiedFlexibleConstraints)
                // Connectivity is job-specific, so must be handled separately.
                + (js.getHasAccessToUnmetered() ? 1 : 0);
    }
+15 −21
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.job.controllers;

import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;

import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
@@ -24,6 +25,8 @@ import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.controllers.FlexibilityController.NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;

import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
@@ -124,11 +127,12 @@ public final class JobStatus {
    static final int CONSTRAINT_WITHIN_QUOTA = 1 << 24;      // Implicit constraint
    static final int CONSTRAINT_PREFETCH = 1 << 23;
    static final int CONSTRAINT_BACKGROUND_NOT_RESTRICTED = 1 << 22; // Implicit constraint
    static final int CONSTRAINT_FLEXIBLE = 1 << 21;
    static final int CONSTRAINT_FLEXIBLE = 1 << 21; // Implicit constraint

    private static final int IMPLICIT_CONSTRAINTS = 0
            | CONSTRAINT_BACKGROUND_NOT_RESTRICTED
            | CONSTRAINT_DEVICE_NOT_DOZING
            | CONSTRAINT_FLEXIBLE
            | CONSTRAINT_TARE_WEALTH
            | CONSTRAINT_WITHIN_QUOTA;

@@ -323,7 +327,6 @@ public final class JobStatus {

    // Constraints.
    final int requiredConstraints;
    private final int mPreferredConstraints;
    private final int mRequiredConstraintsOfInterest;
    int satisfiedConstraints = 0;
    private int mSatisfiedConstraintsOfInterest = 0;
@@ -668,26 +671,24 @@ public final class JobStatus {
        }
        mHasExemptedMediaUrisOnly = exemptedMediaUrisOnly;

        mPreferredConstraints = job.getPreferredConstraintFlags();

        // Exposing a preferredNetworkRequest API requires that we make sure that the preferred
        // NetworkRequest is a subset of the required NetworkRequest. We currently don't have the
        // code to ensure that, so disable this part for now.
        // TODO(236261941): look into enabling flexible network constraint requests
        mPreferUnmetered = false;
                // && job.getRequiredNetwork() != null
                // && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED);
        mPreferUnmetered = job.getRequiredNetwork() != null
                && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED);

        final boolean lacksSomeFlexibleConstraints =
                ((~requiredConstraints) & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS) != 0
                        || mPreferUnmetered;
        final boolean satisfiesMinWindowException =
                (latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis)
                >= MIN_WINDOW_FOR_FLEXIBILITY_MS;

        // The first time a job is rescheduled it will not be subject to flexible constraints.
        // Otherwise, every consecutive reschedule increases a jobs' flexibility deadline.
        if (mPreferredConstraints != 0 && !isRequestedExpeditedJob() && !job.isUserInitiated()
        if (!isRequestedExpeditedJob() && !job.isUserInitiated()
                && satisfiesMinWindowException
                && (numFailures + numSystemStops) != 1) {
            mNumRequiredFlexibleConstraints = Integer.bitCount(mPreferredConstraints);
                && (numFailures + numSystemStops) != 1
                && lacksSomeFlexibleConstraints) {
            mNumRequiredFlexibleConstraints =
                    NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mPreferUnmetered ? 1 : 0);
            requiredConstraints |= CONSTRAINT_FLEXIBLE;
        } else {
            mNumRequiredFlexibleConstraints = 0;
@@ -1393,10 +1394,6 @@ public final class JobStatus {
        mInternalFlags = mInternalFlags & ~flags;
    }

    int getPreferredConstraintFlags() {
        return mPreferredConstraints;
    }

    public int getSatisfiedConstraintFlags() {
        return satisfiedConstraints;
    }
@@ -2778,9 +2775,6 @@ public final class JobStatus {
        pw.print("Required constraints:");
        dumpConstraints(pw, requiredConstraints);
        pw.println();
        pw.print("Preferred constraints:");
        dumpConstraints(pw, mPreferredConstraints);
        pw.println();
        pw.print("Dynamic constraints:");
        dumpConstraints(pw, mDynamicConstraints);
        pw.println();
Loading