Loading apex/jobscheduler/service/aconfig/job.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -127,3 +127,13 @@ flag { } } flag { name: "fix_deadline_delay_job_stall" namespace: "backstage_power" description: "Fix deadline and delay job stall due to a incorrect time check in TimeController" bug: "400440145" metadata { purpose: PURPOSE_BUGFIX } } apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java +45 −5 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.server.AppSchedulingModuleThread; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateControllerProto; Loading Loading @@ -143,6 +144,26 @@ public final class TimeController extends StateController { } } /** * Check if the delay alarm has been delayed past the next scheduled time. * This can happen since we use a in-exact alarm for the delay. * Checking here avoids unnecessary delays in starting the job. */ private boolean isDelayAlarmDelayed() { return Flags.fixDeadlineDelayJobStall() && sElapsedRealtimeClock.millis() >= mNextDelayExpiredElapsedMillis; } /** * Check if the deadline alarm has been delayed past the next scheduled time. * This can happen since we use a in-exact alarm for the deadline. * Checking here avoids unnecessary delays in starting the job. */ private boolean isDeadlineAlarmDelayed() { return Flags.fixDeadlineDelayJobStall() && sElapsedRealtimeClock.millis() >= mNextJobExpiredElapsedMillis; } @Override public void evaluateStateLocked(JobStatus job) { final long nowElapsedMillis = sElapsedRealtimeClock.millis(); Loading @@ -151,7 +172,8 @@ public final class TimeController extends StateController { // unnecessary processing of the timing delay. if (job.hasDeadlineConstraint() && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE) && job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis) { && (job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis || isDeadlineAlarmDelayed())) { if (evaluateDeadlineConstraint(job, nowElapsedMillis)) { if (job.isReady()) { // If the job still isn't ready, there's no point trying to rush the Loading @@ -169,7 +191,8 @@ public final class TimeController extends StateController { } if (job.hasTimingDelayConstraint() && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY) && job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis) { && (job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis || isDelayAlarmDelayed())) { // Since this is just the delay, we don't need to rush the Scheduler to run the job // immediately if the constraint is satisfied here. if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) { Loading Loading @@ -401,8 +424,16 @@ public final class TimeController extends StateController { if (DEBUG) { Slog.d(TAG, "Deadline-expired alarm fired"); } if (Flags.fixDeadlineDelayJobStall()) { synchronized (mLock) { mNextJobExpiredElapsedMillis = Long.MAX_VALUE; checkExpiredDeadlinesAndResetAlarm(); } } else { checkExpiredDeadlinesAndResetAlarm(); } } }; private final OnAlarmListener mNextDelayExpiredListener = new OnAlarmListener() { Loading @@ -411,9 +442,18 @@ public final class TimeController extends StateController { if (DEBUG) { Slog.d(TAG, "Delay-expired alarm fired"); } if (Flags.fixDeadlineDelayJobStall()) { synchronized (mLock) { mLastFiredDelayExpiredElapsedMillis = sElapsedRealtimeClock.millis(); mNextDelayExpiredElapsedMillis = Long.MAX_VALUE; checkExpiredDelaysAndResetAlarm(); } } else { mLastFiredDelayExpiredElapsedMillis = sElapsedRealtimeClock.millis(); checkExpiredDelaysAndResetAlarm(); } } }; @Override Loading Loading
apex/jobscheduler/service/aconfig/job.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -127,3 +127,13 @@ flag { } } flag { name: "fix_deadline_delay_job_stall" namespace: "backstage_power" description: "Fix deadline and delay job stall due to a incorrect time check in TimeController" bug: "400440145" metadata { purpose: PURPOSE_BUGFIX } }
apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java +45 −5 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.server.AppSchedulingModuleThread; import com.android.server.job.Flags; import com.android.server.job.JobSchedulerService; import com.android.server.job.StateControllerProto; Loading Loading @@ -143,6 +144,26 @@ public final class TimeController extends StateController { } } /** * Check if the delay alarm has been delayed past the next scheduled time. * This can happen since we use a in-exact alarm for the delay. * Checking here avoids unnecessary delays in starting the job. */ private boolean isDelayAlarmDelayed() { return Flags.fixDeadlineDelayJobStall() && sElapsedRealtimeClock.millis() >= mNextDelayExpiredElapsedMillis; } /** * Check if the deadline alarm has been delayed past the next scheduled time. * This can happen since we use a in-exact alarm for the deadline. * Checking here avoids unnecessary delays in starting the job. */ private boolean isDeadlineAlarmDelayed() { return Flags.fixDeadlineDelayJobStall() && sElapsedRealtimeClock.millis() >= mNextJobExpiredElapsedMillis; } @Override public void evaluateStateLocked(JobStatus job) { final long nowElapsedMillis = sElapsedRealtimeClock.millis(); Loading @@ -151,7 +172,8 @@ public final class TimeController extends StateController { // unnecessary processing of the timing delay. if (job.hasDeadlineConstraint() && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_DEADLINE) && job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis) { && (job.getLatestRunTimeElapsed() <= mNextJobExpiredElapsedMillis || isDeadlineAlarmDelayed())) { if (evaluateDeadlineConstraint(job, nowElapsedMillis)) { if (job.isReady()) { // If the job still isn't ready, there's no point trying to rush the Loading @@ -169,7 +191,8 @@ public final class TimeController extends StateController { } if (job.hasTimingDelayConstraint() && !job.isConstraintSatisfied(JobStatus.CONSTRAINT_TIMING_DELAY) && job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis) { && (job.getEarliestRunTime() <= mNextDelayExpiredElapsedMillis || isDelayAlarmDelayed())) { // Since this is just the delay, we don't need to rush the Scheduler to run the job // immediately if the constraint is satisfied here. if (evaluateTimingDelayConstraint(job, nowElapsedMillis)) { Loading Loading @@ -401,8 +424,16 @@ public final class TimeController extends StateController { if (DEBUG) { Slog.d(TAG, "Deadline-expired alarm fired"); } if (Flags.fixDeadlineDelayJobStall()) { synchronized (mLock) { mNextJobExpiredElapsedMillis = Long.MAX_VALUE; checkExpiredDeadlinesAndResetAlarm(); } } else { checkExpiredDeadlinesAndResetAlarm(); } } }; private final OnAlarmListener mNextDelayExpiredListener = new OnAlarmListener() { Loading @@ -411,9 +442,18 @@ public final class TimeController extends StateController { if (DEBUG) { Slog.d(TAG, "Delay-expired alarm fired"); } if (Flags.fixDeadlineDelayJobStall()) { synchronized (mLock) { mLastFiredDelayExpiredElapsedMillis = sElapsedRealtimeClock.millis(); mNextDelayExpiredElapsedMillis = Long.MAX_VALUE; checkExpiredDelaysAndResetAlarm(); } } else { mLastFiredDelayExpiredElapsedMillis = sElapsedRealtimeClock.millis(); checkExpiredDelaysAndResetAlarm(); } } }; @Override Loading