Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bbb0459c authored by Kweku Adams's avatar Kweku Adams
Browse files

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
parent 01dee0df
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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)) {
+15 −0
Original line number Diff line number Diff line
@@ -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;
    }
+6 −19
Original line number Diff line number Diff line
@@ -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,