Loading apex/jobscheduler/framework/java/android/app/job/JobInfo.java +76 −1 Original line number Diff line number Diff line Loading @@ -274,12 +274,19 @@ public class JobInfo implements Parcelable { /** * This job needs to be exempted from the app standby throttling. Only the system (UID 1000) * can set it. Jobs with a time constrant must not have it. * can set it. Jobs with a time constraint must not have it. * * @hide */ public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3; /** * Whether it's a so-called "HPJ" or not. * * @hide */ public static final int FLAG_FOREGROUND_JOB = 1 << 4; /** * @hide */ Loading Loading @@ -571,12 +578,20 @@ public class JobInfo implements Parcelable { /** * Return the backoff policy of this job. * * @see JobInfo.Builder#setBackoffCriteria(long, int) */ public @BackoffPolicy int getBackoffPolicy() { return backoffPolicy; } /** * @see JobInfo.Builder#setForeground(boolean) */ public boolean isForegroundJob() { return (flags & FLAG_FOREGROUND_JOB) != 0; } /** * @see JobInfo.Builder#setImportantWhileForeground(boolean) */ Loading Loading @@ -1441,6 +1456,41 @@ public class JobInfo implements Parcelable { return this; } /** * Setting this to true indicates that this job is important and needs to run as soon as * possible with stronger guarantees than regular jobs. These "foreground" jobs will: * <ol> * <li>Run as soon as possible</li> * <li>Be exempted from Doze and battery saver restrictions</li> * <li>Have network access</li> * </ol> * * Since these jobs have stronger guarantees than regular jobs, they will be subject to * stricter quotas. As long as an app has available foreground quota, jobs scheduled with * this set to true will run with these guarantees. If an app has run out of available * foreground quota, any pending foreground jobs will run as regular jobs. * {@link JobParameters#isForegroundJob()} can be used to know whether the executing job * has foreground guarantees or not. In addition, {@link JobScheduler#schedule(JobInfo)} * will immediately return {@link JobScheduler#RESULT_FAILURE} if the app does not have * available quota (and the job will not be successfully scheduled). * * Foreground jobs may only set network constraints. No other constraints are allowed. * * Note: Even though foreground jobs are meant to run as soon as possible, they may be * deferred if the system is under heavy load or the network constraint is satisfied * * @see JobInfo#isForegroundJob() */ @NonNull public Builder setForeground(boolean foreground) { if (foreground) { mFlags |= FLAG_FOREGROUND_JOB; } else { mFlags &= (~FLAG_FOREGROUND_JOB); } 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 @@ -1456,7 +1506,9 @@ public class JobInfo implements Parcelable { * @param importantWhileForeground whether to relax doze restrictions for this job when the * app is in the foreground. False by default. * @see JobInfo#isImportantWhileForeground() * @deprecated Use {@link #setForeground(boolean)} instead. */ @Deprecated public Builder setImportantWhileForeground(boolean importantWhileForeground) { if (importantWhileForeground) { mFlags |= FLAG_IMPORTANT_WHILE_FOREGROUND; Loading Loading @@ -1580,6 +1632,29 @@ public class JobInfo implements Parcelable { throw new IllegalArgumentException( "An important while foreground job cannot have a time delay"); } if ((flags & FLAG_FOREGROUND_JOB) != 0) { if (hasEarlyConstraint) { throw new IllegalArgumentException("A foreground job cannot have a time delay"); } if (hasLateConstraint) { throw new IllegalArgumentException("A foreground job cannot have a deadline"); } if (isPeriodic) { throw new IllegalArgumentException("A foreground job cannot be periodic"); } if (isPersisted) { throw new IllegalArgumentException("A foreground job cannot be persisted"); } if (constraintFlags != 0 || (flags & ~FLAG_FOREGROUND_JOB) != 0) { throw new IllegalArgumentException( "A foreground job can only have network constraints"); } if (triggerContentUris != null && triggerContentUris.length > 0) { throw new IllegalArgumentException( "Can't call addTriggerContentUri() on a foreground job"); } } } /** Loading apex/jobscheduler/framework/java/android/app/job/JobParameters.java +18 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ public class JobParameters implements Parcelable { @UnsupportedAppUsage private final IBinder callback; private final boolean overrideDeadlineExpired; // HPJs = foreground jobs. // TODO(171305774): clean up naming private final boolean mIsHpj; private final Uri[] mTriggeredContentUris; private final String[] mTriggeredContentAuthorities; private final Network network; Loading @@ -121,7 +124,7 @@ public class JobParameters implements Parcelable { /** @hide */ public JobParameters(IBinder callback, int jobId, PersistableBundle extras, Bundle transientExtras, ClipData clipData, int clipGrantFlags, boolean overrideDeadlineExpired, Uri[] triggeredContentUris, boolean overrideDeadlineExpired, boolean isHpj, Uri[] triggeredContentUris, String[] triggeredContentAuthorities, Network network) { this.jobId = jobId; this.extras = extras; Loading @@ -130,6 +133,7 @@ public class JobParameters implements Parcelable { this.clipGrantFlags = clipGrantFlags; this.callback = callback; this.overrideDeadlineExpired = overrideDeadlineExpired; this.mIsHpj = isHpj; this.mTriggeredContentUris = triggeredContentUris; this.mTriggeredContentAuthorities = triggeredContentAuthorities; this.network = network; Loading Loading @@ -194,6 +198,17 @@ public class JobParameters implements Parcelable { return clipGrantFlags; } /** * @return Whether this job is running as a foreground job or not. A job is guaranteed to have * all foreground job guarantees for the duration of the job execution if this returns * {@code true}. This will return {@code false} if the job that wasn't requested to run as a * foreground job, or if it was requested to run as a foreground job but the app didn't have * any remaining foreground job quota at the time of execution. */ public boolean isForegroundJob() { return mIsHpj; } /** * For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this * provides an easy way to tell whether the job is being executed due to the deadline Loading Loading @@ -337,6 +352,7 @@ public class JobParameters implements Parcelable { } callback = in.readStrongBinder(); overrideDeadlineExpired = in.readInt() == 1; mIsHpj = in.readBoolean(); mTriggeredContentUris = in.createTypedArray(Uri.CREATOR); mTriggeredContentAuthorities = in.createStringArray(); if (in.readInt() != 0) { Loading Loading @@ -373,6 +389,7 @@ public class JobParameters implements Parcelable { } dest.writeStrongBinder(callback); dest.writeInt(overrideDeadlineExpired ? 1 : 0); dest.writeBoolean(mIsHpj); dest.writeTypedArray(mTriggeredContentUris, flags); dest.writeStringArray(mTriggeredContentAuthorities); if (network != null) { Loading apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +5 −1 Original line number Diff line number Diff line Loading @@ -205,7 +205,9 @@ class JobConcurrencyManager { } private boolean isFgJob(JobStatus job) { return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP; // (It's super confusing PRIORITY_BOUND_FOREGROUND_SERVICE isn't FG here) return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP || job.shouldTreatAsForegroundJob(); } @GuardedBy("mLock") Loading Loading @@ -336,6 +338,8 @@ class JobConcurrencyManager { continue; } // TODO(171305774): make sure HPJs aren't pre-empted and add dedicated contexts for them final boolean isPendingFg = isFgJob(nextPending); // Find an available slot for nextPending. The context should be available OR Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +22 −5 Original line number Diff line number Diff line Loading @@ -834,6 +834,13 @@ public class JobSchedulerService extends com.android.server.SystemService // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT) return o2.overrideState - o1.overrideState; } if (o1.getSourceUid() == o2.getSourceUid()) { final boolean o1FGJ = o1.isRequestedForegroundJob(); if (o1FGJ != o2.isRequestedForegroundJob()) { // Attempt to run requested HPJs ahead of regular jobs, regardless of HPJ quota. return o1FGJ ? -1 : 1; } } if (o1.enqueueTime < o2.enqueueTime) { return -1; } Loading Loading @@ -1136,6 +1143,12 @@ public class JobSchedulerService extends com.android.server.SystemService JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag); // Return failure early if HPJ quota used up. if (jobStatus.isRequestedForegroundJob() && !mQuotaController.isWithinHpjQuotaLocked(jobStatus)) { return JobScheduler.RESULT_FAILURE; } // Give exemption if the source is in the foreground just now. // Note if it's a sync job, this method is called on the handler so it's not exactly // the state when requestSync() was called, but that should be fine because of the Loading Loading @@ -1791,9 +1804,9 @@ public class JobSchedulerService extends com.android.server.SystemService * time of the job to be the time of completion (i.e. the time at which this function is * called). * <p>This could be inaccurate b/c the job can run for as long as * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead * to underscheduling at least, rather than if we had taken the last execution time to be the * start of the execution. * {@link com.android.server.job.JobServiceContext#DEFAULT_EXECUTING_TIMESLICE_MILLIS}, but * will lead to underscheduling at least, rather than if we had taken the last execution time * to be the start of the execution. * * @return A new job representing the execution criteria for this instantiation of the * recurring job. Loading Loading @@ -1884,6 +1897,10 @@ public class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule); } // Intentionally not checking HPJ quota here. An app can't find out if it's run out of quota // when it asks JS to reschedule an HPJ. Instead, the rescheduled HPJ will just be demoted // to a regular job if the app has no HPJ quota left. // If the job wants to be rescheduled, we first need to make the next upcoming // job so we can transfer any appropriate state over from the previous job when // we stop it. Loading Loading @@ -2382,7 +2399,7 @@ public class JobSchedulerService extends com.android.server.SystemService public long getMaxJobExecutionTimeMs(JobStatus job) { synchronized (mLock) { return Math.min(mQuotaController.getMaxJobExecutionTimeMsLocked(job), JobServiceContext.EXECUTING_TIMESLICE_MILLIS); JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS); } } Loading Loading @@ -2600,7 +2617,6 @@ public class JobSchedulerService extends com.android.server.SystemService // job that runs one of the app's services, as well as verifying that the // named service properly requires the BIND_JOB_SERVICE permission private void enforceValidJobRequest(int uid, JobInfo job) { job.enforceValidity(); final PackageManager pm = getContext() .createContextAsUser(UserHandle.getUserHandleForUid(uid), 0) .getPackageManager(); Loading Loading @@ -2649,6 +2665,7 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJobFlags(JobInfo job, int callingUid) { job.enforceValidity(); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +26 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job; import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; import android.app.job.IJobCallback; Loading Loading @@ -73,7 +74,13 @@ public final class JobServiceContext implements ServiceConnection { private static final String TAG = "JobServiceContext"; /** Amount of time a job is allowed to execute for before being considered timed-out. */ public static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. public static final long DEFAULT_EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. /** * Amount of time a RESTRICTED HPJ is allowed to execute for before being considered * timed-out. */ public static final long DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS = DEFAULT_EXECUTING_TIMESLICE_MILLIS / 2; /** Amount of time the JobScheduler waits for the initial service launch+bind. */ private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000; /** Amount of time the JobScheduler will wait for a response from an app for a message. */ Loading Loading @@ -224,7 +231,8 @@ public final class JobServiceContext implements ServiceConnection { final JobInfo ji = job.getJob(); mParams = new JobParameters(mRunningCallback, job.getJobId(), ji.getExtras(), ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(), isDeadlineExpired, triggeredUris, triggeredAuthorities, job.network); isDeadlineExpired, job.shouldTreatAsForegroundJob(), triggeredUris, triggeredAuthorities, job.network); mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis(); final long whenDeferred = job.getWhenStandbyDeferred(); Loading @@ -250,9 +258,18 @@ public final class JobServiceContext implements ServiceConnection { final Intent intent = new Intent().setComponent(job.getServiceComponent()); boolean binding = false; try { binding = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_PERCEPTIBLE, final int bindFlags; if (job.shouldTreatAsForegroundJob()) { // Add BIND_FOREGROUND_SERVICE to make it BFGS. Without it, it'll be // PROCESS_STATE_IMPORTANT_FOREGROUND. Unclear which is better here. // TODO(171305774): The job should run on the little cores. We'll probably need // another binding flag for that. bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; } else { bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_PERCEPTIBLE; } binding = mContext.bindServiceAsUser(intent, this, bindFlags, UserHandle.of(job.getUserId())); } catch (SecurityException e) { // Some permission policy, for example INTERACT_ACROSS_USERS and Loading Loading @@ -848,7 +865,10 @@ public final class JobServiceContext implements ServiceConnection { final long timeoutMillis; switch (mVerb) { case VERB_EXECUTING: timeoutMillis = EXECUTING_TIMESLICE_MILLIS; timeoutMillis = mRunningJob.shouldTreatAsForegroundJob() && mRunningJob.getStandbyBucket() == RESTRICTED_INDEX ? DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS : DEFAULT_EXECUTING_TIMESLICE_MILLIS; break; case VERB_BINDING: Loading Loading
apex/jobscheduler/framework/java/android/app/job/JobInfo.java +76 −1 Original line number Diff line number Diff line Loading @@ -274,12 +274,19 @@ public class JobInfo implements Parcelable { /** * This job needs to be exempted from the app standby throttling. Only the system (UID 1000) * can set it. Jobs with a time constrant must not have it. * can set it. Jobs with a time constraint must not have it. * * @hide */ public static final int FLAG_EXEMPT_FROM_APP_STANDBY = 1 << 3; /** * Whether it's a so-called "HPJ" or not. * * @hide */ public static final int FLAG_FOREGROUND_JOB = 1 << 4; /** * @hide */ Loading Loading @@ -571,12 +578,20 @@ public class JobInfo implements Parcelable { /** * Return the backoff policy of this job. * * @see JobInfo.Builder#setBackoffCriteria(long, int) */ public @BackoffPolicy int getBackoffPolicy() { return backoffPolicy; } /** * @see JobInfo.Builder#setForeground(boolean) */ public boolean isForegroundJob() { return (flags & FLAG_FOREGROUND_JOB) != 0; } /** * @see JobInfo.Builder#setImportantWhileForeground(boolean) */ Loading Loading @@ -1441,6 +1456,41 @@ public class JobInfo implements Parcelable { return this; } /** * Setting this to true indicates that this job is important and needs to run as soon as * possible with stronger guarantees than regular jobs. These "foreground" jobs will: * <ol> * <li>Run as soon as possible</li> * <li>Be exempted from Doze and battery saver restrictions</li> * <li>Have network access</li> * </ol> * * Since these jobs have stronger guarantees than regular jobs, they will be subject to * stricter quotas. As long as an app has available foreground quota, jobs scheduled with * this set to true will run with these guarantees. If an app has run out of available * foreground quota, any pending foreground jobs will run as regular jobs. * {@link JobParameters#isForegroundJob()} can be used to know whether the executing job * has foreground guarantees or not. In addition, {@link JobScheduler#schedule(JobInfo)} * will immediately return {@link JobScheduler#RESULT_FAILURE} if the app does not have * available quota (and the job will not be successfully scheduled). * * Foreground jobs may only set network constraints. No other constraints are allowed. * * Note: Even though foreground jobs are meant to run as soon as possible, they may be * deferred if the system is under heavy load or the network constraint is satisfied * * @see JobInfo#isForegroundJob() */ @NonNull public Builder setForeground(boolean foreground) { if (foreground) { mFlags |= FLAG_FOREGROUND_JOB; } else { mFlags &= (~FLAG_FOREGROUND_JOB); } 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 @@ -1456,7 +1506,9 @@ public class JobInfo implements Parcelable { * @param importantWhileForeground whether to relax doze restrictions for this job when the * app is in the foreground. False by default. * @see JobInfo#isImportantWhileForeground() * @deprecated Use {@link #setForeground(boolean)} instead. */ @Deprecated public Builder setImportantWhileForeground(boolean importantWhileForeground) { if (importantWhileForeground) { mFlags |= FLAG_IMPORTANT_WHILE_FOREGROUND; Loading Loading @@ -1580,6 +1632,29 @@ public class JobInfo implements Parcelable { throw new IllegalArgumentException( "An important while foreground job cannot have a time delay"); } if ((flags & FLAG_FOREGROUND_JOB) != 0) { if (hasEarlyConstraint) { throw new IllegalArgumentException("A foreground job cannot have a time delay"); } if (hasLateConstraint) { throw new IllegalArgumentException("A foreground job cannot have a deadline"); } if (isPeriodic) { throw new IllegalArgumentException("A foreground job cannot be periodic"); } if (isPersisted) { throw new IllegalArgumentException("A foreground job cannot be persisted"); } if (constraintFlags != 0 || (flags & ~FLAG_FOREGROUND_JOB) != 0) { throw new IllegalArgumentException( "A foreground job can only have network constraints"); } if (triggerContentUris != null && triggerContentUris.length > 0) { throw new IllegalArgumentException( "Can't call addTriggerContentUri() on a foreground job"); } } } /** Loading
apex/jobscheduler/framework/java/android/app/job/JobParameters.java +18 −1 Original line number Diff line number Diff line Loading @@ -111,6 +111,9 @@ public class JobParameters implements Parcelable { @UnsupportedAppUsage private final IBinder callback; private final boolean overrideDeadlineExpired; // HPJs = foreground jobs. // TODO(171305774): clean up naming private final boolean mIsHpj; private final Uri[] mTriggeredContentUris; private final String[] mTriggeredContentAuthorities; private final Network network; Loading @@ -121,7 +124,7 @@ public class JobParameters implements Parcelable { /** @hide */ public JobParameters(IBinder callback, int jobId, PersistableBundle extras, Bundle transientExtras, ClipData clipData, int clipGrantFlags, boolean overrideDeadlineExpired, Uri[] triggeredContentUris, boolean overrideDeadlineExpired, boolean isHpj, Uri[] triggeredContentUris, String[] triggeredContentAuthorities, Network network) { this.jobId = jobId; this.extras = extras; Loading @@ -130,6 +133,7 @@ public class JobParameters implements Parcelable { this.clipGrantFlags = clipGrantFlags; this.callback = callback; this.overrideDeadlineExpired = overrideDeadlineExpired; this.mIsHpj = isHpj; this.mTriggeredContentUris = triggeredContentUris; this.mTriggeredContentAuthorities = triggeredContentAuthorities; this.network = network; Loading Loading @@ -194,6 +198,17 @@ public class JobParameters implements Parcelable { return clipGrantFlags; } /** * @return Whether this job is running as a foreground job or not. A job is guaranteed to have * all foreground job guarantees for the duration of the job execution if this returns * {@code true}. This will return {@code false} if the job that wasn't requested to run as a * foreground job, or if it was requested to run as a foreground job but the app didn't have * any remaining foreground job quota at the time of execution. */ public boolean isForegroundJob() { return mIsHpj; } /** * For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this * provides an easy way to tell whether the job is being executed due to the deadline Loading Loading @@ -337,6 +352,7 @@ public class JobParameters implements Parcelable { } callback = in.readStrongBinder(); overrideDeadlineExpired = in.readInt() == 1; mIsHpj = in.readBoolean(); mTriggeredContentUris = in.createTypedArray(Uri.CREATOR); mTriggeredContentAuthorities = in.createStringArray(); if (in.readInt() != 0) { Loading Loading @@ -373,6 +389,7 @@ public class JobParameters implements Parcelable { } dest.writeStrongBinder(callback); dest.writeInt(overrideDeadlineExpired ? 1 : 0); dest.writeBoolean(mIsHpj); dest.writeTypedArray(mTriggeredContentUris, flags); dest.writeStringArray(mTriggeredContentAuthorities); if (network != null) { Loading
apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +5 −1 Original line number Diff line number Diff line Loading @@ -205,7 +205,9 @@ class JobConcurrencyManager { } private boolean isFgJob(JobStatus job) { return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP; // (It's super confusing PRIORITY_BOUND_FOREGROUND_SERVICE isn't FG here) return job.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP || job.shouldTreatAsForegroundJob(); } @GuardedBy("mLock") Loading Loading @@ -336,6 +338,8 @@ class JobConcurrencyManager { continue; } // TODO(171305774): make sure HPJs aren't pre-empted and add dedicated contexts for them final boolean isPendingFg = isFgJob(nextPending); // Find an available slot for nextPending. The context should be available OR Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +22 −5 Original line number Diff line number Diff line Loading @@ -834,6 +834,13 @@ public class JobSchedulerService extends com.android.server.SystemService // Higher override state (OVERRIDE_FULL) should be before lower state (OVERRIDE_SOFT) return o2.overrideState - o1.overrideState; } if (o1.getSourceUid() == o2.getSourceUid()) { final boolean o1FGJ = o1.isRequestedForegroundJob(); if (o1FGJ != o2.isRequestedForegroundJob()) { // Attempt to run requested HPJs ahead of regular jobs, regardless of HPJ quota. return o1FGJ ? -1 : 1; } } if (o1.enqueueTime < o2.enqueueTime) { return -1; } Loading Loading @@ -1136,6 +1143,12 @@ public class JobSchedulerService extends com.android.server.SystemService JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag); // Return failure early if HPJ quota used up. if (jobStatus.isRequestedForegroundJob() && !mQuotaController.isWithinHpjQuotaLocked(jobStatus)) { return JobScheduler.RESULT_FAILURE; } // Give exemption if the source is in the foreground just now. // Note if it's a sync job, this method is called on the handler so it's not exactly // the state when requestSync() was called, but that should be fine because of the Loading Loading @@ -1791,9 +1804,9 @@ public class JobSchedulerService extends com.android.server.SystemService * time of the job to be the time of completion (i.e. the time at which this function is * called). * <p>This could be inaccurate b/c the job can run for as long as * {@link com.android.server.job.JobServiceContext#EXECUTING_TIMESLICE_MILLIS}, but will lead * to underscheduling at least, rather than if we had taken the last execution time to be the * start of the execution. * {@link com.android.server.job.JobServiceContext#DEFAULT_EXECUTING_TIMESLICE_MILLIS}, but * will lead to underscheduling at least, rather than if we had taken the last execution time * to be the start of the execution. * * @return A new job representing the execution criteria for this instantiation of the * recurring job. Loading Loading @@ -1884,6 +1897,10 @@ public class JobSchedulerService extends com.android.server.SystemService Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule); } // Intentionally not checking HPJ quota here. An app can't find out if it's run out of quota // when it asks JS to reschedule an HPJ. Instead, the rescheduled HPJ will just be demoted // to a regular job if the app has no HPJ quota left. // If the job wants to be rescheduled, we first need to make the next upcoming // job so we can transfer any appropriate state over from the previous job when // we stop it. Loading Loading @@ -2382,7 +2399,7 @@ public class JobSchedulerService extends com.android.server.SystemService public long getMaxJobExecutionTimeMs(JobStatus job) { synchronized (mLock) { return Math.min(mQuotaController.getMaxJobExecutionTimeMsLocked(job), JobServiceContext.EXECUTING_TIMESLICE_MILLIS); JobServiceContext.DEFAULT_EXECUTING_TIMESLICE_MILLIS); } } Loading Loading @@ -2600,7 +2617,6 @@ public class JobSchedulerService extends com.android.server.SystemService // job that runs one of the app's services, as well as verifying that the // named service properly requires the BIND_JOB_SERVICE permission private void enforceValidJobRequest(int uid, JobInfo job) { job.enforceValidity(); final PackageManager pm = getContext() .createContextAsUser(UserHandle.getUserHandleForUid(uid), 0) .getPackageManager(); Loading Loading @@ -2649,6 +2665,7 @@ public class JobSchedulerService extends com.android.server.SystemService } private void validateJobFlags(JobInfo job, int callingUid) { job.enforceValidity(); if ((job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0) { getContext().enforceCallingOrSelfPermission( android.Manifest.permission.CONNECTIVITY_INTERNAL, TAG); Loading
apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +26 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job; import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; import android.app.job.IJobCallback; Loading Loading @@ -73,7 +74,13 @@ public final class JobServiceContext implements ServiceConnection { private static final String TAG = "JobServiceContext"; /** Amount of time a job is allowed to execute for before being considered timed-out. */ public static final long EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. public static final long DEFAULT_EXECUTING_TIMESLICE_MILLIS = 10 * 60 * 1000; // 10mins. /** * Amount of time a RESTRICTED HPJ is allowed to execute for before being considered * timed-out. */ public static final long DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS = DEFAULT_EXECUTING_TIMESLICE_MILLIS / 2; /** Amount of time the JobScheduler waits for the initial service launch+bind. */ private static final long OP_BIND_TIMEOUT_MILLIS = 18 * 1000; /** Amount of time the JobScheduler will wait for a response from an app for a message. */ Loading Loading @@ -224,7 +231,8 @@ public final class JobServiceContext implements ServiceConnection { final JobInfo ji = job.getJob(); mParams = new JobParameters(mRunningCallback, job.getJobId(), ji.getExtras(), ji.getTransientExtras(), ji.getClipData(), ji.getClipGrantFlags(), isDeadlineExpired, triggeredUris, triggeredAuthorities, job.network); isDeadlineExpired, job.shouldTreatAsForegroundJob(), triggeredUris, triggeredAuthorities, job.network); mExecutionStartTimeElapsed = sElapsedRealtimeClock.millis(); final long whenDeferred = job.getWhenStandbyDeferred(); Loading @@ -250,9 +258,18 @@ public final class JobServiceContext implements ServiceConnection { final Intent intent = new Intent().setComponent(job.getServiceComponent()); boolean binding = false; try { binding = mContext.bindServiceAsUser(intent, this, Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_PERCEPTIBLE, final int bindFlags; if (job.shouldTreatAsForegroundJob()) { // Add BIND_FOREGROUND_SERVICE to make it BFGS. Without it, it'll be // PROCESS_STATE_IMPORTANT_FOREGROUND. Unclear which is better here. // TODO(171305774): The job should run on the little cores. We'll probably need // another binding flag for that. bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE; } else { bindFlags = Context.BIND_AUTO_CREATE | Context.BIND_NOT_FOREGROUND | Context.BIND_NOT_PERCEPTIBLE; } binding = mContext.bindServiceAsUser(intent, this, bindFlags, UserHandle.of(job.getUserId())); } catch (SecurityException e) { // Some permission policy, for example INTERACT_ACROSS_USERS and Loading Loading @@ -848,7 +865,10 @@ public final class JobServiceContext implements ServiceConnection { final long timeoutMillis; switch (mVerb) { case VERB_EXECUTING: timeoutMillis = EXECUTING_TIMESLICE_MILLIS; timeoutMillis = mRunningJob.shouldTreatAsForegroundJob() && mRunningJob.getStandbyBucket() == RESTRICTED_INDEX ? DEFAULT_RESTRICTED_HPJ_EXECUTING_TIMESLICE_MILLIS : DEFAULT_EXECUTING_TIMESLICE_MILLIS; break; case VERB_BINDING: Loading