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
This commit is contained in:
Kweku Adams
2019-08-05 15:17:23 -07:00
parent 01dee0df54
commit bbb0459c29
3 changed files with 22 additions and 20 deletions

View File

@@ -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)) {

View File

@@ -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;
}

View File

@@ -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,