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

Commit e1d00c2d authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Make sure jobs started from TOP app don't consume credits."

parents 373c8a18 523a7fb6
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -1559,6 +1559,13 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    /** Return the current bias of the given UID. */
    public int getUidBias(int uid) {
        synchronized (mLock) {
            return mUidBiasOverride.get(uid, JobInfo.BIAS_DEFAULT);
        }
    }

    @Override
    public void onDeviceIdleStateChanged(boolean deviceIdle) {
        synchronized (mLock) {
+0 −25
Original line number Diff line number Diff line
@@ -366,9 +366,6 @@ public final class JobServiceContext implements ServiceConnection {
            } catch (RemoteException e) {
                // Whatever.
            }
            mEconomyManagerInternal.noteOngoingEventStarted(
                    job.getSourceUserId(), job.getSourcePackageName(),
                    getRunningActionId(job), String.valueOf(job.getJobId()));
            final String jobPackage = job.getSourcePackageName();
            final int jobUserId = job.getSourceUserId();
            UsageStatsManagerInternal usageStats =
@@ -401,25 +398,6 @@ public final class JobServiceContext implements ServiceConnection {
        }
    }

    @EconomicPolicy.AppAction
    private static int getRunningActionId(@NonNull JobStatus job) {
        switch (job.getEffectivePriority()) {
            case JobInfo.PRIORITY_MAX:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING;
            case JobInfo.PRIORITY_HIGH:
                return JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_RUNNING;
            case JobInfo.PRIORITY_LOW:
                return JobSchedulerEconomicPolicy.ACTION_JOB_LOW_RUNNING;
            case JobInfo.PRIORITY_MIN:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MIN_RUNNING;
            default:
                Slog.wtf(TAG, "Unknown priority: " + getPriorityString(job.getEffectivePriority()));
                // Intentional fallthrough
            case JobInfo.PRIORITY_DEFAULT:
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING;
        }
    }

    /**
     * Used externally to query the running job. Will return null if there is no job running.
     */
@@ -1043,9 +1021,6 @@ public final class JobServiceContext implements ServiceConnection {
        } catch (RemoteException e) {
            // Whatever.
        }
        mEconomyManagerInternal.noteOngoingEventStopped(
                mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(),
                getRunningActionId(mRunningJob), String.valueOf(mRunningJob.getJobId()));
        if (mParams.getStopReason() == JobParameters.STOP_REASON_TIMEOUT) {
            mEconomyManagerInternal.noteInstantaneousEvent(
                    mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(),
+89 −2
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.job.controllers;

import static android.app.job.JobInfo.getPriorityString;

import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;

import android.annotation.NonNull;
@@ -31,6 +33,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.tare.EconomicPolicy;
import com.android.server.tare.EconomyManagerInternal;
import com.android.server.tare.EconomyManagerInternal.ActionBill;
import com.android.server.tare.JobSchedulerEconomicPolicy;
@@ -285,6 +288,14 @@ public class TareController extends StateController {
                }
            };

    /**
     * List of jobs that started while the UID was in the TOP state. There will be no more than
     * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
     * fine.
     */
    @GuardedBy("mLock")
    private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>();

    @GuardedBy("mLock")
    private boolean mIsEnabled;

@@ -299,6 +310,7 @@ public class TareController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        final long nowElapsed = sElapsedRealtimeClock.millis();
        jobStatus.setTareWealthConstraintSatisfied(nowElapsed, hasEnoughWealthLocked(jobStatus));
@@ -312,6 +324,7 @@ public class TareController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void prepareForExecutionLocked(JobStatus jobStatus) {
        final int userId = jobStatus.getSourceUserId();
        final String pkgName = jobStatus.getSourcePackageName();
@@ -325,12 +338,29 @@ public class TareController extends StateController {
            }
        }
        addJobToBillList(jobStatus, getRunningBill(jobStatus));

        final int uid = jobStatus.getSourceUid();
        if (mService.getUidBias(uid) == JobInfo.BIAS_TOP_APP) {
            if (DEBUG) {
                Slog.d(TAG, jobStatus.toShortString() + " is top started job");
            }
            mTopStartedJobs.add(jobStatus);
            // Top jobs won't count towards quota so there's no need to involve the EconomyManager.
        } else {
            mEconomyManagerInternal.noteOngoingEventStarted(userId, pkgName,
                    getRunningActionId(jobStatus), String.valueOf(jobStatus.getJobId()));
        }
    }

    @Override
    @GuardedBy("mLock")
    public void unprepareFromExecutionLocked(JobStatus jobStatus) {
        final int userId = jobStatus.getSourceUserId();
        final String pkgName = jobStatus.getSourcePackageName();
        mEconomyManagerInternal.noteOngoingEventStopped(userId, pkgName,
                getRunningActionId(jobStatus), String.valueOf(jobStatus.getJobId()));
        mTopStartedJobs.remove(jobStatus);

        final ArraySet<ActionBill> bills = getPossibleStartBills(jobStatus);
        ArrayMap<ActionBill, ArraySet<JobStatus>> billToJobMap =
                mRegisteredBillsAndJobs.get(userId, pkgName);
@@ -347,10 +377,14 @@ public class TareController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
            boolean forUpdate) {
        final int userId = jobStatus.getSourceUserId();
        final String pkgName = jobStatus.getSourcePackageName();
        mEconomyManagerInternal.noteOngoingEventStopped(userId, pkgName,
                getRunningActionId(jobStatus), String.valueOf(jobStatus.getJobId()));
        mTopStartedJobs.remove(jobStatus);
        ArrayMap<ActionBill, ArraySet<JobStatus>> billToJobMap =
                mRegisteredBillsAndJobs.get(userId, pkgName);
        if (billToJobMap != null) {
@@ -391,8 +425,17 @@ public class TareController extends StateController {
        if (!mIsEnabled) {
            return true;
        }
        if (jobStatus.getEffectivePriority() == JobInfo.PRIORITY_MAX) {
            return canAffordBillLocked(jobStatus, BILL_JOB_START_MAX_EXPEDITED);
        }
        return canAffordBillLocked(jobStatus, BILL_JOB_START_HIGH_EXPEDITED);
    }

    /** @return true if the job was started while the app was in the TOP state. */
    @GuardedBy("mLock")
    private boolean isTopStartedJobLocked(@NonNull final JobStatus jobStatus) {
        return mTopStartedJobs.contains(jobStatus);
    }

    @GuardedBy("mLock")
    public long getMaxJobExecutionTimeMsLocked(@NonNull JobStatus jobStatus) {
@@ -459,6 +502,9 @@ public class TareController extends StateController {
            }
        }
        switch (jobStatus.getEffectivePriority()) {
            case JobInfo.PRIORITY_MAX:
                bills.add(BILL_JOB_START_MAX);
                break;
            case JobInfo.PRIORITY_HIGH:
                bills.add(BILL_JOB_START_HIGH);
                break;
@@ -471,6 +517,10 @@ public class TareController extends StateController {
            case JobInfo.PRIORITY_MIN:
                bills.add(BILL_JOB_START_MIN);
                break;
            default:
                Slog.wtf(TAG, "Unexpected priority: "
                        + JobInfo.getPriorityString(jobStatus.getEffectivePriority()));
                break;
        }
        return bills;
    }
@@ -502,11 +552,36 @@ public class TareController extends StateController {
        }
    }

    @EconomicPolicy.AppAction
    private static int getRunningActionId(@NonNull JobStatus job) {
        switch (job.getEffectivePriority()) {
            case JobInfo.PRIORITY_MAX:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING;
            case JobInfo.PRIORITY_HIGH:
                return JobSchedulerEconomicPolicy.ACTION_JOB_HIGH_RUNNING;
            case JobInfo.PRIORITY_LOW:
                return JobSchedulerEconomicPolicy.ACTION_JOB_LOW_RUNNING;
            case JobInfo.PRIORITY_MIN:
                return JobSchedulerEconomicPolicy.ACTION_JOB_MIN_RUNNING;
            default:
                Slog.wtf(TAG, "Unknown priority: " + getPriorityString(job.getEffectivePriority()));
                // Intentional fallthrough
            case JobInfo.PRIORITY_DEFAULT:
                return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING;
        }
    }

    @GuardedBy("mLock")
    private boolean canAffordBillLocked(@NonNull JobStatus jobStatus, @NonNull ActionBill bill) {
        if (!mIsEnabled) {
            return true;
        }
        if (mService.getUidBias(jobStatus.getSourceUid()) == JobInfo.BIAS_TOP_APP
                || isTopStartedJobLocked(jobStatus)) {
            // Jobs for the top app should always be allowed to run, and any jobs started while
            // the app is on top shouldn't consume any credits.
            return true;
        }
        final int userId = jobStatus.getSourceUserId();
        final String pkgName = jobStatus.getSourcePackageName();
        ArrayMap<ActionBill, Boolean> actionAffordability =
@@ -533,6 +608,12 @@ public class TareController extends StateController {
        if (!jobStatus.isRequestedExpeditedJob()) {
            return false;
        }
        if (mService.getUidBias(jobStatus.getSourceUid()) == JobInfo.BIAS_TOP_APP
                || isTopStartedJobLocked(jobStatus)) {
            // Jobs for the top app should always be allowed to run, and any jobs started while
            // the app is on top shouldn't consume any credits.
            return true;
        }
        if (mService.isCurrentlyRunningLocked(jobStatus)) {
            return canAffordBillLocked(jobStatus, getRunningBill(jobStatus));
        }
@@ -548,6 +629,12 @@ public class TareController extends StateController {
        if (!mIsEnabled) {
            return true;
        }
        if (mService.getUidBias(jobStatus.getSourceUid()) == JobInfo.BIAS_TOP_APP
                || isTopStartedJobLocked(jobStatus)) {
            // Jobs for the top app should always be allowed to run, and any jobs started while
            // the app is on top shouldn't consume any credits.
            return true;
        }
        if (mService.isCurrentlyRunningLocked(jobStatus)) {
            if (jobStatus.isRequestedExpeditedJob()) {
                return canAffordBillLocked(jobStatus, getRunningBill(jobStatus))