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

Commit a071ad39 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Make sure RESTRICTED quota is properly counted." into sc-dev

parents 49a841c0 b76da7cb
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -621,6 +621,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        final long nowElapsed = sElapsedRealtimeClock.millis();
        final int userId = jobStatus.getSourceUserId();
@@ -648,6 +649,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void prepareForExecutionLocked(JobStatus jobStatus) {
        if (DEBUG) {
            Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
@@ -676,6 +678,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void unprepareFromExecutionLocked(JobStatus jobStatus) {
        Timer timer = mPkgTimers.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
        if (timer != null) {
@@ -691,6 +694,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
            boolean forUpdate) {
        if (jobStatus.clearTrackingController(JobStatus.TRACKING_QUOTA)) {
@@ -796,10 +800,12 @@ public final class QuotaController extends StateController {
    }

    /** Returns the maximum amount of time this job could run for. */
    @GuardedBy("mLock")
    public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
        if (!jobStatus.shouldTreatAsExpeditedJob()) {
            // If quota is currently "free", then the job can run for the full amount of time.
            if (mChargeTracker.isCharging()
            // If quota is currently "free", then the job can run for the full amount of time,
            // regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
            if (mChargeTracker.isChargingLocked()
                    || mTopAppCache.get(jobStatus.getSourceUid())
                    || isTopStartedJobLocked(jobStatus)
                    || isUidInForeground(jobStatus.getSourceUid())) {
@@ -810,7 +816,7 @@ public final class QuotaController extends StateController {
        }

        // Expedited job.
        if (mChargeTracker.isCharging()) {
        if (mChargeTracker.isChargingLocked()) {
            return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
        }
        if (mTopAppCache.get(jobStatus.getSourceUid()) || isTopStartedJobLocked(jobStatus)) {
@@ -828,8 +834,9 @@ public final class QuotaController extends StateController {
    }

    /** @return true if the job is within expedited job quota. */
    @GuardedBy("mLock")
    public boolean isWithinEJQuotaLocked(@NonNull final JobStatus jobStatus) {
        if (isQuotaFree(jobStatus.getEffectiveStandbyBucket())) {
        if (isQuotaFreeLocked(jobStatus.getEffectiveStandbyBucket())) {
            return true;
        }
        // A job is within quota if one of the following is true:
@@ -887,9 +894,10 @@ public final class QuotaController extends StateController {
                jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
    }

    private boolean isQuotaFree(final int standbyBucket) {
    @GuardedBy("mLock")
    private boolean isQuotaFreeLocked(final int standbyBucket) {
        // Quota constraint is not enforced while charging.
        if (mChargeTracker.isCharging()) {
        if (mChargeTracker.isChargingLocked()) {
            // Restricted jobs require additional constraints when charging, so don't immediately
            // mark quota as free when charging.
            return standbyBucket != RESTRICTED_INDEX;
@@ -898,11 +906,12 @@ public final class QuotaController extends StateController {
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName,
            final int standbyBucket) {
        if (standbyBucket == NEVER_INDEX) return false;

        if (isQuotaFree(standbyBucket)) return true;
        if (isQuotaFreeLocked(standbyBucket)) return true;

        ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
        return getRemainingExecutionTimeLocked(stats) > 0
@@ -1556,9 +1565,9 @@ public final class QuotaController extends StateController {

    private void handleNewChargingStateLocked() {
        mTimerChargingUpdateFunctor.setStatus(sElapsedRealtimeClock.millis(),
                mChargeTracker.isCharging());
                mChargeTracker.isChargingLocked());
        if (DEBUG) {
            Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isCharging());
            Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isChargingLocked());
        }
        // Deal with Timers first.
        mEJPkgTimers.forEach(mTimerChargingUpdateFunctor);
@@ -1827,6 +1836,7 @@ public final class QuotaController extends StateController {
         * Track whether we're charging. This has a slightly different definition than that of
         * BatteryController.
         */
        @GuardedBy("mLock")
        private boolean mCharging;

        ChargingTracker() {
@@ -1846,7 +1856,8 @@ public final class QuotaController extends StateController {
            mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
        }

        public boolean isCharging() {
        @GuardedBy("mLock")
        public boolean isChargingLocked() {
            return mCharging;
        }

@@ -2055,9 +2066,12 @@ public final class QuotaController extends StateController {
                    }
                    return;
                }
                if (mRunningBgJobs.remove(jobStatus)
                        && !mChargeTracker.isCharging() && mRunningBgJobs.size() == 0) {
                    emitSessionLocked(sElapsedRealtimeClock.millis());
                final long nowElapsed = sElapsedRealtimeClock.millis();
                final int standbyBucket = JobSchedulerService.standbyBucketForPackage(
                        mPkg.packageName, mPkg.userId, nowElapsed);
                if (mRunningBgJobs.remove(jobStatus) && mRunningBgJobs.size() == 0
                        && !isQuotaFreeLocked(standbyBucket)) {
                    emitSessionLocked(nowElapsed);
                    cancelCutoff();
                }
            }
@@ -2077,6 +2091,7 @@ public final class QuotaController extends StateController {
            cancelCutoff();
        }

        @GuardedBy("mLock")
        private void emitSessionLocked(long nowElapsed) {
            if (mBgJobCount <= 0) {
                // Nothing to emit.
@@ -2121,6 +2136,7 @@ public final class QuotaController extends StateController {
            }
        }

        @GuardedBy("mLock")
        private boolean shouldTrackLocked() {
            final long nowElapsed = sElapsedRealtimeClock.millis();
            final int standbyBucket = JobSchedulerService.standbyBucketForPackage(mPkg.packageName,
@@ -2132,7 +2148,7 @@ public final class QuotaController extends StateController {
            final long topAppGracePeriodEndElapsed = mTopAppGraceCache.get(mUid);
            final boolean hasTopAppExemption = !mRegularJobTimer
                    && (mTopAppCache.get(mUid) || nowElapsed < topAppGracePeriodEndElapsed);
            return (standbyBucket == RESTRICTED_INDEX || !mChargeTracker.isCharging())
            return !isQuotaFreeLocked(standbyBucket)
                    && !mForegroundUids.get(mUid) && !hasTempAllowlistExemption
                    && !hasTopAppExemption;
        }
@@ -4054,7 +4070,7 @@ public final class QuotaController extends StateController {
    @Override
    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
            final Predicate<JobStatus> predicate) {
        pw.println("Is charging: " + mChargeTracker.isCharging());
        pw.println("Is charging: " + mChargeTracker.isChargingLocked());
        pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
        pw.println();

@@ -4231,7 +4247,8 @@ public final class QuotaController extends StateController {
        final long token = proto.start(fieldId);
        final long mToken = proto.start(StateControllerProto.QUOTA);

        proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
        proto.write(StateControllerProto.QuotaController.IS_CHARGING,
                mChargeTracker.isChargingLocked());
        proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
                sElapsedRealtimeClock.millis());