summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java25
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java91
3 files changed, 96 insertions, 27 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 3da508d490f1..86d7a5a5a62e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -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) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 9cae864576ce..00d1bfffd9a6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -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(),
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
index bc7b49eff5d2..fd6aa7a1d282 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
@@ -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;
@@ -195,7 +198,7 @@ public class TareController extends StateController {
JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING, 0, 1_000L)
));
- /**
+ /**
* Bill to use while we're waiting to start a job. If a job isn't running yet, don't consider it
* eligible to run unless it can pay for a job start and at least some period of execution time.
*/
@@ -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,7 +425,16 @@ public class TareController extends StateController {
if (!mIsEnabled) {
return true;
}
- return canAffordBillLocked(jobStatus, BILL_JOB_START_MAX_EXPEDITED);
+ 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")
@@ -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))