From 69d4668ea7fd5bcffb3928431098338ce398b885 Mon Sep 17 00:00:00 2001 From: Kweku Adams Date: Fri, 25 Mar 2022 18:49:17 +0000 Subject: [PATCH] Let EJs for TOP app run immediately and without limit. We're encouraging developers to switch from FGS to EJs. However, there were some aspects of EJs that made developers hesitant to switch over. This addresses one of the concerns by allowing EJs for the TOP app to start immediately. "Immediate" here means we start the JobService (call Context.bindService()) before the call to JobScheduler.schedule() returns (assuming all of the constraints are met). In order to guarantee "immediate," we needed to remove the concurrency limit on top-started EJs. This means there's a chance the TOP app could run more than our intended limit of 16 apps, so we create new JobServiceContexts for TOP EJs if need be, and if we ever have more than 16 total jobs running, we don't start any new jobs (except TOP EJ) until we fall back below the 16 limit. If we ever get above the intended limit, TOP EJs will be forced to stop at the earlier timeout (default 3 minutes) instead of being allowed to run for the full 30 minutes. Bug: 223437753 Test: atest CtsJobSchedulerTestCases Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/job Change-Id: I97d19f47533690196619a080087bf0a56a21e8f2 --- .../server/job/JobConcurrencyManager.java | 160 +++++++++++++++--- .../server/job/JobSchedulerService.java | 3 +- .../android/server/job/JobServiceContext.java | 3 +- .../job/controllers/QuotaController.java | 6 +- .../job/controllers/TareController.java | 6 +- .../server/job/JobConcurrencyManagerTest.java | 8 +- .../server/job/BiasSchedulingTest.java | 8 +- 7 files changed, 152 insertions(+), 42 deletions(-) diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java index 549badd5ba826..b4238c975d985 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java @@ -16,7 +16,6 @@ package com.android.server.job; -import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX; import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock; @@ -82,6 +81,11 @@ class JobConcurrencyManager { private static final String TAG = JobSchedulerService.TAG + ".Concurrency"; private static final boolean DEBUG = JobSchedulerService.DEBUG; + /** The maximum number of concurrent jobs we'll aim to run at one time. */ + public static final int STANDARD_CONCURRENCY_LIMIT = 16; + /** The maximum number of objects we should retain in memory when not in use. */ + private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * STANDARD_CONCURRENCY_LIMIT); + static final String CONFIG_KEY_PREFIX_CONCURRENCY = "concurrency_"; private static final String KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS = CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms"; @@ -93,7 +97,7 @@ class JobConcurrencyManager { @VisibleForTesting static final String KEY_PKG_CONCURRENCY_LIMIT_REGULAR = CONFIG_KEY_PREFIX_CONCURRENCY + "pkg_concurrency_limit_regular"; - private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = MAX_JOB_CONTEXTS_COUNT / 2; + private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = STANDARD_CONCURRENCY_LIMIT / 2; /** * Set of possible execution types that a job can have. The actual type(s) of a job are based @@ -309,7 +313,7 @@ class JobConcurrencyManager { private final ArrayList mRecycledStoppable = new ArrayList<>(); private final Pools.Pool mContextAssignmentPool = - new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT); + new Pools.SimplePool<>(MAX_RETAINED_OBJECTS); /** * Set of JobServiceContexts that are actively running jobs. @@ -317,14 +321,16 @@ class JobConcurrencyManager { final List mActiveServices = new ArrayList<>(); /** Set of JobServiceContexts that aren't currently running any jobs. */ - final ArraySet mIdleContexts = new ArraySet<>(); + private final ArraySet mIdleContexts = new ArraySet<>(); + + private int mNumDroppedContexts = 0; private final ArraySet mRunningJobs = new ArraySet<>(); private final WorkCountTracker mWorkCountTracker = new WorkCountTracker(); private final Pools.Pool mPkgStatsPool = - new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT); + new Pools.SimplePool<>(MAX_RETAINED_OBJECTS); private final SparseArrayMap mActivePkgStats = new SparseArrayMap<>(); @@ -406,7 +412,7 @@ class JobConcurrencyManager { void onThirdPartyAppsCanStart() { final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); - for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) { + for (int i = 0; i < STANDARD_CONCURRENCY_LIMIT; i++) { mIdleContexts.add( new JobServiceContext(mService, this, batteryStats, mService.mJobPackageTracker, mContext.getMainLooper())); @@ -655,13 +661,13 @@ class JobConcurrencyManager { } preferredUidOnly.sort(sDeterminationComparator); stoppable.sort(sDeterminationComparator); - for (int i = numRunningJobs; i < MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = numRunningJobs; i < STANDARD_CONCURRENCY_LIMIT; ++i) { final JobServiceContext jsc; final int numIdleContexts = mIdleContexts.size(); if (numIdleContexts > 0) { jsc = mIdleContexts.removeAt(numIdleContexts - 1); } else { - Slog.wtf(TAG, "Had fewer than " + MAX_JOB_CONTEXTS_COUNT + " in existence"); + Slog.wtf(TAG, "Had fewer than " + STANDARD_CONCURRENCY_LIMIT + " in existence"); jsc = createNewJobServiceContext(); } @@ -681,6 +687,7 @@ class JobConcurrencyManager { JobStatus nextPending; pendingJobQueue.resetIterator(); + int projectedRunningCount = numRunningJobs; while ((nextPending = pendingJobQueue.next()) != null) { if (mRunningJobs.contains(nextPending)) { continue; @@ -694,6 +701,9 @@ class JobConcurrencyManager { ContextAssignment selectedContext = null; final int allWorkTypes = getJobWorkTypes(nextPending); final boolean pkgConcurrencyOkay = !isPkgConcurrencyLimitedLocked(nextPending); + final boolean isTopEj = nextPending.shouldTreatAsExpeditedJob() + && nextPending.lastEvaluatedBias == JobInfo.BIAS_TOP_APP; + final boolean isInOverage = projectedRunningCount > STANDARD_CONCURRENCY_LIMIT; boolean startingJob = false; if (idle.size() > 0) { final int idx = idle.size() - 1; @@ -711,14 +721,36 @@ class JobConcurrencyManager { assignment.newWorkType = workType; } } - if (selectedContext == null) { + if (selectedContext == null && stoppable.size() > 0) { + int topEjCount = 0; + for (int r = mRunningJobs.size() - 1; r >= 0; --r) { + JobStatus js = mRunningJobs.valueAt(r); + if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + topEjCount++; + } + } for (int s = stoppable.size() - 1; s >= 0; --s) { final ContextAssignment assignment = stoppable.get(s); final JobStatus runningJob = assignment.context.getRunningJobLocked(); - // Maybe stop the job if it has had its day in the sun. Don't let a different - // app preempt jobs started for TOP apps though. - if (runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP - && assignment.shouldStopJobReason != null) { + // Maybe stop the job if it has had its day in the sun. Only allow replacing + // for one of the following conditions: + // 1. We're putting in the current TOP app's EJ + // 2. There aren't too many jobs running AND the current job started when the + // app was in the background + // 3. There aren't too many jobs running AND the current job started when the + // app was on TOP, but the app has since left TOP + // 4. There aren't too many jobs running AND the current job started when the + // app was on TOP, the app is still TOP, but there are too many TOP+EJs + // running (because we don't want them to starve out other apps and the + // current job has already run for the minimum guaranteed time). + boolean canReplace = isTopEj; // Case 1 + if (!canReplace && !isInOverage) { + final int currentJobBias = mService.evaluateJobBiasLocked(runningJob); + canReplace = runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP // Case 2 + || currentJobBias < JobInfo.BIAS_TOP_APP // Case 3 + || topEjCount > .5 * mWorkTypeConfig.getMaxTotal(); // Case 4 + } + if (canReplace) { int replaceWorkType = mWorkCountTracker.canJobStart(allWorkTypes, assignment.context.getRunningJobWorkType()); if (replaceWorkType != WORK_TYPE_NONE) { @@ -736,7 +768,7 @@ class JobConcurrencyManager { } } } - if (selectedContext == null) { + if (selectedContext == null && (!isInOverage || isTopEj)) { int lowestBiasSeen = Integer.MAX_VALUE; for (int p = preferredUidOnly.size() - 1; p >= 0; --p) { final ContextAssignment assignment = preferredUidOnly.get(p); @@ -765,10 +797,43 @@ class JobConcurrencyManager { preferredUidOnly.remove(selectedContext); } } + // Make sure to run EJs for the TOP app immediately. + if (isTopEj) { + if (selectedContext != null + && selectedContext.context.getRunningJobLocked() != null) { + // We're "replacing" a currently running job, but we want TOP EJs to start + // immediately, so we'll start the EJ on a fresh available context and + // stop this currently running job to replace in two steps. + changed.add(selectedContext); + projectedRunningCount--; + selectedContext.newJob = null; + selectedContext.newWorkType = WORK_TYPE_NONE; + selectedContext = null; + } + if (selectedContext == null) { + selectedContext = mContextAssignmentPool.acquire(); + if (selectedContext == null) { + selectedContext = new ContextAssignment(); + } + selectedContext.context = mIdleContexts.size() > 0 + ? mIdleContexts.removeAt(mIdleContexts.size() - 1) + : createNewJobServiceContext(); + selectedContext.newJob = nextPending; + final int workType = mWorkCountTracker.canJobStart(allWorkTypes); + selectedContext.newWorkType = + (workType != WORK_TYPE_NONE) ? workType : WORK_TYPE_TOP; + } + } final PackageStats packageStats = getPkgStatsLocked( nextPending.getSourceUserId(), nextPending.getSourcePackageName()); if (selectedContext != null) { changed.add(selectedContext); + if (selectedContext.context.getRunningJobLocked() != null) { + projectedRunningCount--; + } + if (selectedContext.newJob != null) { + projectedRunningCount++; + } packageStats.adjustStagedCount(true, nextPending.shouldTreatAsExpeditedJob()); } if (startingJob) { @@ -793,7 +858,7 @@ class JobConcurrencyManager { if (DEBUG) { Slog.d(TAG, "preempting job: " + js); } - // preferredUid will be set to uid of currently running job. + // preferredUid will be set to uid of currently running job, if appropriate. assignment.context.cancelExecutingJobLocked( assignment.preemptReasonCode, JobParameters.INTERNAL_STOP_REASON_PREEMPT, assignment.preemptReason); @@ -811,9 +876,6 @@ class JobConcurrencyManager { } for (int s = stoppable.size() - 1; s >= 0; --s) { final ContextAssignment assignment = stoppable.get(s); - // The preferred UID is set when we cancel with PREEMPT reason, but don't preserve the - // UID for any stoppable contexts since we want to open the context up to any/all apps. - assignment.context.clearPreferredUid(); assignment.clear(); mContextAssignmentPool.release(assignment); } @@ -837,6 +899,21 @@ class JobConcurrencyManager { noteConcurrency(); } + @GuardedBy("mLock") + void onUidBiasChangedLocked(int prevBias, int newBias) { + if (prevBias != JobInfo.BIAS_TOP_APP && newBias != JobInfo.BIAS_TOP_APP) { + // TOP app didn't change. Nothing to do. + return; + } + if (mService.getPendingJobQueue().size() == 0) { + // Nothing waiting for the top app to leave. Nothing to do. + return; + } + // Don't stop the TOP jobs directly. Instead, see if they would be replaced by some + // pending job (there may not always be something to replace them). + assignJobsToContextsLocked(); + } + @GuardedBy("mLock") boolean stopJobOnServiceContextLocked(JobStatus job, @JobParameters.StopReason int reason, int internalReasonCode, String debugReason) { @@ -1041,7 +1118,13 @@ class JobConcurrencyManager { mWorkCountTracker.onJobFinished(workType); mRunningJobs.remove(jobStatus); mActiveServices.remove(worker); - mIdleContexts.add(worker); + if (mIdleContexts.size() < MAX_RETAINED_OBJECTS) { + // Don't need to save all new contexts, but keep some extra around in case we need + // extras for another TOP+EJ overage. + mIdleContexts.add(worker); + } else { + mNumDroppedContexts++; + } final PackageStats packageStats = mActivePkgStats.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName()); if (packageStats == null) { @@ -1054,6 +1137,14 @@ class JobConcurrencyManager { } } + if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) { + worker.clearPreferredUid(); + // We're over the limit (because the TOP app scheduled a lot of EJs). Don't start + // running anything new until we get back below the limit. + noteConcurrency(); + return; + } + final PendingJobQueue pendingJobQueue = mService.getPendingJobQueue(); if (worker.getPreferredUid() != JobServiceContext.NO_PREFERRED_UID) { updateCounterConfigLocked(); @@ -1245,6 +1336,18 @@ class JobConcurrencyManager { } } else if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) { return "blocking " + workTypeToString(WORK_TYPE_EJ) + " queue"; + } else if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + // Try not to let TOP + EJ starve out other apps. + int topEjCount = 0; + for (int r = mRunningJobs.size() - 1; r >= 0; --r) { + JobStatus j = mRunningJobs.valueAt(r); + if (j.startedAsExpeditedJob && j.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) { + topEjCount++; + } + } + if (topEjCount > .5 * mWorkTypeConfig.getMaxTotal()) { + return "prevent top EJ dominance"; + } } // No other pending EJs. Return null so we don't let regular jobs preempt an EJ. return null; @@ -1361,10 +1464,10 @@ class JobConcurrencyManager { CONFIG_LIMITS_SCREEN_OFF.low.update(properties); CONFIG_LIMITS_SCREEN_OFF.critical.update(properties); - // Package concurrency limits must in the range [1, MAX_JOB_CONTEXTS_COUNT]. - mPkgConcurrencyLimitEj = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + // Package concurrency limits must in the range [1, STANDARD_CONCURRENCY_LIMIT]. + mPkgConcurrencyLimitEj = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt(KEY_PKG_CONCURRENCY_LIMIT_EJ, DEFAULT_PKG_CONCURRENCY_LIMIT_EJ))); - mPkgConcurrencyLimitRegular = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + mPkgConcurrencyLimitRegular = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt( KEY_PKG_CONCURRENCY_LIMIT_REGULAR, DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR))); } @@ -1492,6 +1595,13 @@ class JobConcurrencyManager { jsc.dumpLocked(pw, nowElapsed); } pw.decreaseIndent(); + + if (mNumDroppedContexts > 0) { + pw.println(); + pw.print("Dropped "); + pw.print(mNumDroppedContexts); + pw.println(" contexts"); + } } public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) { @@ -1600,7 +1710,7 @@ class JobConcurrencyManager { WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal, List> defaultMin, List> defaultMax) { mConfigIdentifier = configIdentifier; - mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, MAX_JOB_CONTEXTS_COUNT); + mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, STANDARD_CONCURRENCY_LIMIT); int numReserved = 0; for (int i = defaultMin.size() - 1; i >= 0; --i) { mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second); @@ -1621,8 +1731,8 @@ class JobConcurrencyManager { } void update(@NonNull DeviceConfig.Properties properties) { - // Ensure total in the range [1, MAX_JOB_CONTEXTS_COUNT]. - mMaxTotal = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT, + // Ensure total in the range [1, STANDARD_CONCURRENCY_LIMIT]. + mMaxTotal = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT, properties.getInt(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mDefaultMaxTotal))); mMaxAllowedSlots.clear(); 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 1f5c46d3aeb00..f8fe2ed9fda2d 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java @@ -159,8 +159,6 @@ public class JobSchedulerService extends com.android.server.SystemService public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); public static final boolean DEBUG_STANDBY = DEBUG || false; - /** The maximum number of concurrent jobs we run at one time. */ - static final int MAX_JOB_CONTEXTS_COUNT = 16; /** The maximum number of jobs that we allow an app to schedule */ private static final int MAX_JOBS_PER_APP = 150; /** The number of the most recently completed jobs to keep track of for debugging purposes. */ @@ -1420,6 +1418,7 @@ public class JobSchedulerService extends com.android.server.SystemService for (int c = 0; c < mControllers.size(); ++c) { mControllers.get(c).onUidBiasChangedLocked(uid, prevBias, newBias); } + mConcurrencyManager.onUidBiasChangedLocked(prevBias, newBias); } } } 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 54e0a4c6663ce..2a79ec4587fcb 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java @@ -751,7 +751,8 @@ public final class JobServiceContext implements ServiceConnection { } } mParams.setStopReason(stopReasonCode, internalStopReasonCode, debugReason); - if (internalStopReasonCode == JobParameters.INTERNAL_STOP_REASON_PREEMPT) { + if (stopReasonCode == JobParameters.STOP_REASON_PREEMPT) { + // Only preserve the UID when we're preempting the job for another one of the same UID. mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : NO_PREFERRED_UID; } handleCancelLocked(debugReason); diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java index ee0f9e8f9658d..aadeeaab543ca 100644 --- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java @@ -297,9 +297,9 @@ public final class QuotaController extends StateController { private final SparseBooleanArray mForegroundUids = new SparseBooleanArray(); /** - * 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. + * List of jobs that started while the UID was in the TOP state. There will usually be no more + * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an + * ArraySet is fine. */ private final ArraySet mTopStartedJobs = new ArraySet<>(); 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 fd6aa7a1d2824..223091a27ee10 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 @@ -289,9 +289,9 @@ 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. + * List of jobs that started while the UID was in the TOP state. There will usually be no more + * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an + * ArraySet is fine. */ @GuardedBy("mLock") private final ArraySet mTopStartedJobs = new ArraySet<>(); diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java index 04fe777cd909a..b354c7b3d1f3d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java @@ -116,14 +116,14 @@ public final class JobConcurrencyManagerTest { assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob)); // Pending jobs shouldn't affect TOP job's status. - for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i); mPendingJobQueue.add(job); } assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob)); // Already running jobs shouldn't affect TOP job's status. - for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE, i); mJobConcurrencyManager.addRunningJobForTesting(job); } @@ -183,9 +183,9 @@ public final class JobConcurrencyManagerTest { spyOn(testEj); doReturn(true).when(testEj).shouldTreatAsExpeditedJob(); - setConcurrencyConfig(JobSchedulerService.MAX_JOB_CONTEXTS_COUNT); + setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT); - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i, i + 1); mPendingJobQueue.add(job); } diff --git a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java index bda7cf66f685c..e886e7dc1d60e 100644 --- a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java +++ b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java @@ -57,14 +57,14 @@ public class BiasSchedulingTest extends AndroidTestCase { } public void testLowerBiasJobPreempted() throws Exception { - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) .setBias(LOW_BIAS) .setOverrideDeadline(0) .build(); mJobScheduler.schedule(job); } - final int higherBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; + final int higherBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent) .setBias(HIGH_BIAS) .setMinimumLatency(2000) @@ -88,14 +88,14 @@ public class BiasSchedulingTest extends AndroidTestCase { } public void testHigherBiasJobNotPreempted() throws Exception { - for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) { + for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) { JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent) .setBias(HIGH_BIAS) .setOverrideDeadline(0) .build(); mJobScheduler.schedule(job); } - final int lowerBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; + final int lowerBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent) .setBias(LOW_BIAS) .setMinimumLatency(2000)