Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +102 −14 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.Notification; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; Loading Loading @@ -402,6 +403,13 @@ public class JobInfo implements Parcelable { */ public static final int FLAG_DATA_TRANSFER = 1 << 5; /** * Whether it's a user initiated job or not. * * @hide */ public static final int FLAG_USER_INITIATED = 1 << 6; /** * @hide */ Loading Loading @@ -737,6 +745,14 @@ public class JobInfo implements Parcelable { return (flags & FLAG_DATA_TRANSFER) != 0; } /** * @see JobInfo.Builder#setUserInitiated(boolean) * @hide */ public boolean isUserInitiated() { return (flags & FLAG_USER_INITIATED) != 0; } /** * @see JobInfo.Builder#setImportantWhileForeground(boolean) */ Loading Loading @@ -1849,15 +1865,8 @@ public class JobInfo implements Parcelable { * * <p> * For user-initiated transfers that must be started immediately, call * {@link #setExpedited(boolean) setExpedited(true)}. Otherwise, the system may defer the * job to a more opportune time. Using {@link #setExpedited(boolean) setExpedited(true)} * with this API will only be allowed for foreground apps and when the user has clearly * interacted with the app. {@link #setExpedited(boolean) setExpedited(true)} will return * {@link JobScheduler#RESULT_FAILURE} for a data transfer job if the app is in the * background. Apps that successfully schedule data transfer jobs with * {@link #setExpedited(boolean) setExpedited(true)} will not have quotas applied to them, * though they may still be stopped for system health or constraint reasons. The system will * also give a user the ability to stop a data transfer job via the Task Manager. * {@link #setUserInitiated(boolean) setUserInitiated(true)}. Otherwise, the system may * defer the job to a more opportune time. * * <p> * If you want to perform more than one data transfer job, consider enqueuing multiple Loading @@ -1876,6 +1885,50 @@ public class JobInfo implements Parcelable { return this; } /** * Indicates that this job is being scheduled to fulfill an explicit user request. * As such, user-initiated jobs can only be scheduled when the app is in the foreground * or in a state where launching an activity is allowed, as defined * <a href= * "https://developer.android.com/guide/components/activities/background-starts#exceptions"> * here</a>. Attempting to schedule one outside of these conditions will throw a * {@link SecurityException}. * * <p> * This should <b>NOT</b> be used for automatic features. * * <p> * All user-initiated jobs must have an associated notification, set via * {@link JobService#setNotification(JobParameters, int, Notification, int)}, and will be * shown in the Task Manager when running. * * <p> * These jobs will not be subject to quotas and will be started immediately once scheduled * if all constraints are met and the device system health allows for additional tasks. * * @see JobInfo#isUserInitiated() * @hide */ @NonNull public Builder setUserInitiated(boolean userInitiated) { if (userInitiated) { mFlags |= FLAG_USER_INITIATED; if (mPriority == PRIORITY_DEFAULT) { // The default priority for UIJs is MAX, but only change this if .setPriority() // hasn't been called yet. mPriority = PRIORITY_MAX; } } else { if (mPriority == PRIORITY_MAX && (mFlags & FLAG_USER_INITIATED) != 0) { // Reset the priority for the job, but only change this if .setPriority() // hasn't been called yet. mPriority = PRIORITY_DEFAULT; } mFlags &= (~FLAG_USER_INITIATED); } return this; } /** * Setting this to true indicates that this job is important while the scheduling app * is in the foreground or on the temporary whitelist for background restrictions. Loading Loading @@ -2086,10 +2139,12 @@ public class JobInfo implements Parcelable { } final boolean isExpedited = (flags & FLAG_EXPEDITED) != 0; final boolean isUserInitiated = (flags & FLAG_USER_INITIATED) != 0; switch (mPriority) { case PRIORITY_MAX: if (!isExpedited) { throw new IllegalArgumentException("Only expedited jobs can have max priority"); if (!(isExpedited || isUserInitiated)) { throw new IllegalArgumentException( "Only expedited or user-initiated jobs can have max priority"); } break; case PRIORITY_HIGH: Loading Loading @@ -2118,14 +2173,20 @@ public class JobInfo implements Parcelable { if (isPeriodic) { throw new IllegalArgumentException("An expedited job cannot be periodic"); } if ((flags & FLAG_DATA_TRANSFER) != 0) { throw new IllegalArgumentException( "An expedited job cannot also be a data transfer job"); } if (isUserInitiated) { throw new IllegalArgumentException("An expedited job cannot be user-initiated"); } 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 || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY | FLAG_DATA_TRANSFER)) != 0)) { if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0 || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY)) != 0) { throw new IllegalArgumentException( "An expedited job can only have network and storage-not-low constraints"); } Loading @@ -2152,6 +2213,33 @@ public class JobInfo implements Parcelable { "A data transfer job must specify a valid network type"); } } if (isUserInitiated) { if (hasEarlyConstraint) { throw new IllegalArgumentException("A user-initiated job cannot have a time delay"); } if (hasLateConstraint) { throw new IllegalArgumentException("A user-initiated job cannot have a deadline"); } if (isPeriodic) { throw new IllegalArgumentException("A user-initiated job cannot be periodic"); } if ((flags & FLAG_PREFETCH) != 0) { throw new IllegalArgumentException( "A user-initiated job cannot also be a prefetch job"); } if (mPriority != PRIORITY_MAX) { throw new IllegalArgumentException("A user-initiated job must be max priority."); } if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) { throw new IllegalArgumentException( "A user-initiated job cannot have a device-idle constraint"); } if (triggerContentUris != null && triggerContentUris.length > 0) { throw new IllegalArgumentException( "Can't call addTriggerContentUri() on a user-initiated job"); } } } /** Loading Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +102 −14 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.app.Notification; import android.compat.Compatibility; import android.compat.annotation.ChangeId; import android.compat.annotation.EnabledAfter; Loading Loading @@ -402,6 +403,13 @@ public class JobInfo implements Parcelable { */ public static final int FLAG_DATA_TRANSFER = 1 << 5; /** * Whether it's a user initiated job or not. * * @hide */ public static final int FLAG_USER_INITIATED = 1 << 6; /** * @hide */ Loading Loading @@ -737,6 +745,14 @@ public class JobInfo implements Parcelable { return (flags & FLAG_DATA_TRANSFER) != 0; } /** * @see JobInfo.Builder#setUserInitiated(boolean) * @hide */ public boolean isUserInitiated() { return (flags & FLAG_USER_INITIATED) != 0; } /** * @see JobInfo.Builder#setImportantWhileForeground(boolean) */ Loading Loading @@ -1849,15 +1865,8 @@ public class JobInfo implements Parcelable { * * <p> * For user-initiated transfers that must be started immediately, call * {@link #setExpedited(boolean) setExpedited(true)}. Otherwise, the system may defer the * job to a more opportune time. Using {@link #setExpedited(boolean) setExpedited(true)} * with this API will only be allowed for foreground apps and when the user has clearly * interacted with the app. {@link #setExpedited(boolean) setExpedited(true)} will return * {@link JobScheduler#RESULT_FAILURE} for a data transfer job if the app is in the * background. Apps that successfully schedule data transfer jobs with * {@link #setExpedited(boolean) setExpedited(true)} will not have quotas applied to them, * though they may still be stopped for system health or constraint reasons. The system will * also give a user the ability to stop a data transfer job via the Task Manager. * {@link #setUserInitiated(boolean) setUserInitiated(true)}. Otherwise, the system may * defer the job to a more opportune time. * * <p> * If you want to perform more than one data transfer job, consider enqueuing multiple Loading @@ -1876,6 +1885,50 @@ public class JobInfo implements Parcelable { return this; } /** * Indicates that this job is being scheduled to fulfill an explicit user request. * As such, user-initiated jobs can only be scheduled when the app is in the foreground * or in a state where launching an activity is allowed, as defined * <a href= * "https://developer.android.com/guide/components/activities/background-starts#exceptions"> * here</a>. Attempting to schedule one outside of these conditions will throw a * {@link SecurityException}. * * <p> * This should <b>NOT</b> be used for automatic features. * * <p> * All user-initiated jobs must have an associated notification, set via * {@link JobService#setNotification(JobParameters, int, Notification, int)}, and will be * shown in the Task Manager when running. * * <p> * These jobs will not be subject to quotas and will be started immediately once scheduled * if all constraints are met and the device system health allows for additional tasks. * * @see JobInfo#isUserInitiated() * @hide */ @NonNull public Builder setUserInitiated(boolean userInitiated) { if (userInitiated) { mFlags |= FLAG_USER_INITIATED; if (mPriority == PRIORITY_DEFAULT) { // The default priority for UIJs is MAX, but only change this if .setPriority() // hasn't been called yet. mPriority = PRIORITY_MAX; } } else { if (mPriority == PRIORITY_MAX && (mFlags & FLAG_USER_INITIATED) != 0) { // Reset the priority for the job, but only change this if .setPriority() // hasn't been called yet. mPriority = PRIORITY_DEFAULT; } mFlags &= (~FLAG_USER_INITIATED); } return this; } /** * Setting this to true indicates that this job is important while the scheduling app * is in the foreground or on the temporary whitelist for background restrictions. Loading Loading @@ -2086,10 +2139,12 @@ public class JobInfo implements Parcelable { } final boolean isExpedited = (flags & FLAG_EXPEDITED) != 0; final boolean isUserInitiated = (flags & FLAG_USER_INITIATED) != 0; switch (mPriority) { case PRIORITY_MAX: if (!isExpedited) { throw new IllegalArgumentException("Only expedited jobs can have max priority"); if (!(isExpedited || isUserInitiated)) { throw new IllegalArgumentException( "Only expedited or user-initiated jobs can have max priority"); } break; case PRIORITY_HIGH: Loading Loading @@ -2118,14 +2173,20 @@ public class JobInfo implements Parcelable { if (isPeriodic) { throw new IllegalArgumentException("An expedited job cannot be periodic"); } if ((flags & FLAG_DATA_TRANSFER) != 0) { throw new IllegalArgumentException( "An expedited job cannot also be a data transfer job"); } if (isUserInitiated) { throw new IllegalArgumentException("An expedited job cannot be user-initiated"); } 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 || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY | FLAG_DATA_TRANSFER)) != 0)) { if ((constraintFlags & ~CONSTRAINT_FLAG_STORAGE_NOT_LOW) != 0 || (flags & ~(FLAG_EXPEDITED | FLAG_EXEMPT_FROM_APP_STANDBY)) != 0) { throw new IllegalArgumentException( "An expedited job can only have network and storage-not-low constraints"); } Loading @@ -2152,6 +2213,33 @@ public class JobInfo implements Parcelable { "A data transfer job must specify a valid network type"); } } if (isUserInitiated) { if (hasEarlyConstraint) { throw new IllegalArgumentException("A user-initiated job cannot have a time delay"); } if (hasLateConstraint) { throw new IllegalArgumentException("A user-initiated job cannot have a deadline"); } if (isPeriodic) { throw new IllegalArgumentException("A user-initiated job cannot be periodic"); } if ((flags & FLAG_PREFETCH) != 0) { throw new IllegalArgumentException( "A user-initiated job cannot also be a prefetch job"); } if (mPriority != PRIORITY_MAX) { throw new IllegalArgumentException("A user-initiated job must be max priority."); } if ((constraintFlags & CONSTRAINT_FLAG_DEVICE_IDLE) != 0) { throw new IllegalArgumentException( "A user-initiated job cannot have a device-idle constraint"); } if (triggerContentUris != null && triggerContentUris.length > 0) { throw new IllegalArgumentException( "Can't call addTriggerContentUri() on a user-initiated job"); } } } /** Loading