Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +5 −160 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) */ Loading Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -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); } Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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"); Loading @@ -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"); } Loading apex/jobscheduler/service/java/com/android/server/job/JobStore.java +0 −16 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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)); } /** Loading apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +3 −2 Original line number Diff line number Diff line Loading @@ -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)); } Loading apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +3 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +15 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1393,10 +1394,6 @@ public final class JobStatus { mInternalFlags = mInternalFlags & ~flags; } int getPreferredConstraintFlags() { return mPreferredConstraints; } public int getSatisfiedConstraintFlags() { return satisfiedConstraints; } Loading Loading @@ -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 Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +5 −160 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) */ Loading Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -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); } Loading Loading @@ -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(); Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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(); Loading Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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"); Loading @@ -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"); } Loading
apex/jobscheduler/service/java/com/android/server/job/JobStore.java +0 −16 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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)); } /** Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +3 −2 Original line number Diff line number Diff line Loading @@ -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)); } Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java +3 −3 Original line number Diff line number Diff line Loading @@ -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); } Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +15 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -1393,10 +1394,6 @@ public final class JobStatus { mInternalFlags = mInternalFlags & ~flags; } int getPreferredConstraintFlags() { return mPreferredConstraints; } public int getSatisfiedConstraintFlags() { return satisfiedConstraints; } Loading Loading @@ -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