From bbb0459c29532cfa24cd315bb245eabb4ffafadb Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Mon, 5 Aug 2019 15:17:23 -0700 Subject: [PATCH] Using effective standby bucket for job batching. The effective standby bucket takes uidActive and standby exemption into account, which makes it better for determining if a job should be force batched or not. Bug: 138806139 Test: atest com.android.server.job.controllers.JobStatusTest Test: atest com.android.server.job.controllers.QuotaControllerTest Test: atest com.android.server.job.JobSchedulerServiceTest Test: atest CtsJobSchedulerTestCases Change-Id: I7f46a5c26d36c6c6482931575b8d61b93960ff2c --- .../server/job/JobSchedulerService.java | 2 +- .../server/job/controllers/JobStatus.java | 15 +++++++++++ .../job/controllers/QuotaController.java | 25 +++++-------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java index 38bb75f33f024..b2f4eb7607473 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -1943,7 +1943,7 @@ public class JobSchedulerService extends com.android.server.SystemService } catch (RemoteException e) { } if (mConstants.MIN_READY_NON_ACTIVE_JOBS_COUNT > 1 - && job.getStandbyBucket() != ACTIVE_INDEX + && job.getEffectiveStandbyBucket() != ACTIVE_INDEX && (job.getFirstForceBatchedTimeElapsed() == 0 || sElapsedRealtimeClock.millis() - job.getFirstForceBatchedTimeElapsed() < mConstants.MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS)) { diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java index ae4abd65ab60f..3c50e3809e7ba 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java @@ -16,6 +16,7 @@ package com.android.server.job.controllers; +import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; import android.app.AppGlobals; @@ -698,6 +699,20 @@ public final class JobStatus { return UserHandle.getUserId(callingUid); } + /** + * Returns an appropriate standby bucket for the job, taking into account any standby + * exemptions. + */ + public int getEffectiveStandbyBucket() { + if (uidActive || getJob().isExemptedFromAppStandby()) { + // Treat these cases as if they're in the ACTIVE bucket so that they get throttled + // like other ACTIVE apps. + return ACTIVE_INDEX; + } + return getStandbyBucket(); + } + + /** Returns the real standby bucket of the job. */ public int getStandbyBucket() { return standbyBucket; } diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index 043cda469db27..38950d5a9d341 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -608,7 +608,7 @@ public final class QuotaController extends StateController { final boolean isWithinQuota = isWithinQuotaLocked(jobStatus); setConstraintSatisfied(jobStatus, isWithinQuota); if (!isWithinQuota) { - maybeScheduleStartAlarmLocked(userId, pkgName, getEffectiveStandbyBucket(jobStatus)); + maybeScheduleStartAlarmLocked(userId, pkgName, jobStatus.getEffectiveStandbyBucket()); } } @@ -719,22 +719,9 @@ public final class QuotaController extends StateController { return getRemainingExecutionTimeLocked(jobStatus); } - /** - * Returns an appropriate standby bucket for the job, taking into account any standby - * exemptions. - */ - private int getEffectiveStandbyBucket(@NonNull final JobStatus jobStatus) { - if (jobStatus.uidActive || jobStatus.getJob().isExemptedFromAppStandby()) { - // Treat these cases as if they're in the ACTIVE bucket so that they get throttled - // like other ACTIVE apps. - return ACTIVE_INDEX; - } - return jobStatus.getStandbyBucket(); - } - @VisibleForTesting boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) { - final int standbyBucket = getEffectiveStandbyBucket(jobStatus); + final int standbyBucket = jobStatus.getEffectiveStandbyBucket(); // A job is within quota if one of the following is true: // 1. it was started while the app was in the TOP state // 2. the app is currently in the foreground @@ -784,7 +771,7 @@ public final class QuotaController extends StateController { long getRemainingExecutionTimeLocked(@NonNull final JobStatus jobStatus) { return getRemainingExecutionTimeLocked(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), - getEffectiveStandbyBucket(jobStatus)); + jobStatus.getEffectiveStandbyBucket()); } @VisibleForTesting @@ -1258,7 +1245,7 @@ public final class QuotaController extends StateController { // finish. changed |= js.setQuotaConstraintSatisfied(true); } else if (realStandbyBucket != ACTIVE_INDEX - && realStandbyBucket == getEffectiveStandbyBucket(js)) { + && realStandbyBucket == js.getEffectiveStandbyBucket()) { // An app in the ACTIVE bucket may be out of quota while the job could be in quota // for some reason. Therefore, avoid setting the real value here and check each job // individually. @@ -2563,7 +2550,7 @@ public final class QuotaController extends StateController { pw.println(); pw.increaseIndent(); - pw.print(JobStatus.bucketName(getEffectiveStandbyBucket(js))); + pw.print(JobStatus.bucketName(js.getEffectiveStandbyBucket())); pw.print(", "); if (js.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) { pw.print("within quota"); @@ -2675,7 +2662,7 @@ public final class QuotaController extends StateController { js.getSourceUid()); proto.write( StateControllerProto.QuotaController.TrackedJob.EFFECTIVE_STANDBY_BUCKET, - getEffectiveStandbyBucket(js)); + js.getEffectiveStandbyBucket()); proto.write(StateControllerProto.QuotaController.TrackedJob.IS_TOP_STARTED_JOB, mTopStartedJobs.contains(js)); proto.write(StateControllerProto.QuotaController.TrackedJob.HAS_QUOTA,