summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kweku Adams <kwekua@google.com> 2021-02-01 11:09:25 -0800
committer Kweku Adams <kwekua@google.com> 2021-02-08 19:18:40 -0800
commit20b0eee64fc47d16769939d8c2263b95101bd760 (patch)
tree0a793c3f1ff338c8b8a0bb6ad3eef0a7454dab2a
parent076669f905517c3637066dfa3caf6821e400358c (diff)
Reserve execution slots for expedited jobs.
Make sure we reserve at least 3 slots for expedited jobs (in the ideal case) so we can get them to run as quickly as possible. Also fix how we assign slots when there are already running jobs. Bug: 171305774 Test: atest CtsJobSchedulerTestCases Test: atest FrameworksMockingServicesTests:JobSchedulerServiceTest Test: atest FrameworksServicesTests:PrioritySchedulingTest Test: atest FrameworksServicesTests:WorkCountTrackerTest Test: atest FrameworksServicesTests:WorkTypeConfigTest Change-Id: Ic08bc9d665c4c016f01ddce8f952710e72bd27f9
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java196
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java397
-rw-r--r--services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java249
4 files changed, 515 insertions, 331 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 edf2ce3c92cb..82e967ae1a0b 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -75,13 +75,16 @@ class JobConcurrencyManager {
// Try to give higher priority types lower values.
static final int WORK_TYPE_NONE = 0;
static final int WORK_TYPE_TOP = 1 << 0;
- static final int WORK_TYPE_BG = 1 << 1;
- static final int WORK_TYPE_BGUSER = 1 << 2;
- private static final int NUM_WORK_TYPES = 3;
+ static final int WORK_TYPE_EJ = 1 << 1;
+ static final int WORK_TYPE_BG = 1 << 2;
+ static final int WORK_TYPE_BGUSER = 1 << 3;
+ @VisibleForTesting
+ static final int NUM_WORK_TYPES = 4;
@IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = {
WORK_TYPE_NONE,
WORK_TYPE_TOP,
+ WORK_TYPE_EJ,
WORK_TYPE_BG,
WORK_TYPE_BGUSER
})
@@ -106,54 +109,60 @@ class JobConcurrencyManager {
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_ON =
new WorkConfigLimitsPerMemoryTrimLevel(
- new WorkTypeConfig("screen_on_normal", 8,
+ new WorkTypeConfig("screen_on_normal", 11,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_BG, 2)),
+ List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_EJ, 3),
+ Pair.create(WORK_TYPE_BG, 2)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 4))
),
- new WorkTypeConfig("screen_on_moderate", 8,
+ new WorkTypeConfig("screen_on_moderate", 9,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 2)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 2),
+ Pair.create(WORK_TYPE_BG, 2)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2))
),
- new WorkTypeConfig("screen_on_low", 5,
+ new WorkTypeConfig("screen_on_low", 6,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1),
+ Pair.create(WORK_TYPE_BG, 1)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
),
new WorkTypeConfig("screen_on_critical", 5,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
)
);
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF =
new WorkConfigLimitsPerMemoryTrimLevel(
- new WorkTypeConfig("screen_off_normal", 10,
+ new WorkTypeConfig("screen_off_normal", 13,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 2)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
+ Pair.create(WORK_TYPE_BG, 2)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 4))
),
- new WorkTypeConfig("screen_off_moderate", 10,
+ new WorkTypeConfig("screen_off_moderate", 13,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_BG, 2)),
+ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_EJ, 3),
+ Pair.create(WORK_TYPE_BG, 2)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2))
),
- new WorkTypeConfig("screen_off_low", 5,
+ new WorkTypeConfig("screen_off_low", 7,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 2),
+ Pair.create(WORK_TYPE_BG, 1)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
),
new WorkTypeConfig("screen_off_critical", 5,
// defaultMin
- List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1)),
// defaultMax
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
)
@@ -818,15 +827,22 @@ class JobConcurrencyManager {
int getJobWorkTypes(@NonNull JobStatus js) {
int classification = 0;
- // TODO(171305774): create dedicated work type for EJ and FGS
- if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP
- || js.shouldTreatAsExpeditedJob()) {
- classification |= WORK_TYPE_TOP;
- } else if (shouldRunAsFgUserJob(js)) {
- classification |= WORK_TYPE_BG;
+ // TODO: create dedicated work type for FGS
+ if (shouldRunAsFgUserJob(js)) {
+ if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
+ classification |= WORK_TYPE_TOP;
+ } else {
+ classification |= WORK_TYPE_BG;
+ }
+
+ if (js.shouldTreatAsExpeditedJob()) {
+ classification |= WORK_TYPE_EJ;
+ }
} else {
+ // TODO(171305774): create dedicated slots for EJs of bg user
classification |= WORK_TYPE_BGUSER;
}
+
return classification;
}
@@ -835,10 +851,12 @@ class JobConcurrencyManager {
private static final String KEY_PREFIX_MAX_TOTAL =
CONFIG_KEY_PREFIX_CONCURRENCY + "max_total_";
private static final String KEY_PREFIX_MAX_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "max_top_";
+ private static final String KEY_PREFIX_MAX_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "max_ej_";
private static final String KEY_PREFIX_MAX_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "max_bg_";
private static final String KEY_PREFIX_MAX_BGUSER =
CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_";
private static final String KEY_PREFIX_MIN_TOP = CONFIG_KEY_PREFIX_CONCURRENCY + "min_top_";
+ private static final String KEY_PREFIX_MIN_EJ = CONFIG_KEY_PREFIX_CONCURRENCY + "min_ej_";
private static final String KEY_PREFIX_MIN_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "min_bg_";
private static final String KEY_PREFIX_MIN_BGUSER =
CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_";
@@ -885,6 +903,10 @@ class JobConcurrencyManager {
properties.getInt(KEY_PREFIX_MAX_TOP + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_TOP, mMaxTotal))));
mMaxAllowedSlots.put(WORK_TYPE_TOP, maxTop);
+ final int maxEj = Math.max(1, Math.min(mMaxTotal,
+ properties.getInt(KEY_PREFIX_MAX_EJ + mConfigIdentifier,
+ mDefaultMaxAllowedSlots.get(WORK_TYPE_EJ, mMaxTotal))));
+ mMaxAllowedSlots.put(WORK_TYPE_EJ, maxEj);
final int maxBg = Math.max(1, Math.min(mMaxTotal,
properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier,
mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal))));
@@ -902,6 +924,12 @@ class JobConcurrencyManager {
mDefaultMinReservedSlots.get(WORK_TYPE_TOP))));
mMinReservedSlots.put(WORK_TYPE_TOP, minTop);
remaining -= minTop;
+ // Ensure ej is in the range [0, min(maxEj, remaining)]
+ final int minEj = Math.max(0, Math.min(Math.min(maxEj, remaining),
+ properties.getInt(KEY_PREFIX_MIN_EJ + mConfigIdentifier,
+ mDefaultMinReservedSlots.get(WORK_TYPE_EJ))));
+ mMinReservedSlots.put(WORK_TYPE_EJ, minEj);
+ remaining -= minEj;
// Ensure bg is in the range [0, min(maxBg, remaining)]
final int minBg = Math.max(0, Math.min(Math.min(maxBg, remaining),
properties.getInt(KEY_PREFIX_MIN_BG + mConfigIdentifier,
@@ -933,6 +961,10 @@ class JobConcurrencyManager {
.println();
pw.print(KEY_PREFIX_MAX_TOP + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_TOP))
.println();
+ pw.print(KEY_PREFIX_MIN_EJ + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_EJ))
+ .println();
+ pw.print(KEY_PREFIX_MAX_EJ + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_EJ))
+ .println();
pw.print(KEY_PREFIX_MIN_BG + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_BG))
.println();
pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG))
@@ -1032,24 +1064,21 @@ class JobConcurrencyManager {
private final SparseIntArray mNumPendingJobs = new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mNumRunningJobs = new SparseIntArray(NUM_WORK_TYPES);
private final SparseIntArray mNumStartingJobs = new SparseIntArray(NUM_WORK_TYPES);
- private int mNumUnspecialized = 0;
private int mNumUnspecializedRemaining = 0;
void setConfig(@NonNull WorkTypeConfig workTypeConfig) {
mConfigMaxTotal = workTypeConfig.getMaxTotal();
mConfigNumReservedSlots.put(WORK_TYPE_TOP,
workTypeConfig.getMinReserved(WORK_TYPE_TOP));
+ mConfigNumReservedSlots.put(WORK_TYPE_EJ, workTypeConfig.getMinReserved(WORK_TYPE_EJ));
mConfigNumReservedSlots.put(WORK_TYPE_BG, workTypeConfig.getMinReserved(WORK_TYPE_BG));
mConfigNumReservedSlots.put(WORK_TYPE_BGUSER,
workTypeConfig.getMinReserved(WORK_TYPE_BGUSER));
mConfigAbsoluteMaxSlots.put(WORK_TYPE_TOP, workTypeConfig.getMax(WORK_TYPE_TOP));
+ mConfigAbsoluteMaxSlots.put(WORK_TYPE_EJ, workTypeConfig.getMax(WORK_TYPE_EJ));
mConfigAbsoluteMaxSlots.put(WORK_TYPE_BG, workTypeConfig.getMax(WORK_TYPE_BG));
mConfigAbsoluteMaxSlots.put(WORK_TYPE_BGUSER, workTypeConfig.getMax(WORK_TYPE_BGUSER));
- mNumUnspecialized = mConfigMaxTotal;
- mNumUnspecialized -= mConfigNumReservedSlots.get(WORK_TYPE_TOP);
- mNumUnspecialized -= mConfigNumReservedSlots.get(WORK_TYPE_BG);
- mNumUnspecialized -= mConfigNumReservedSlots.get(WORK_TYPE_BGUSER);
mNumUnspecializedRemaining = mConfigMaxTotal;
for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) {
mNumUnspecializedRemaining -= Math.max(mNumRunningJobs.valueAt(i),
@@ -1078,6 +1107,9 @@ class JobConcurrencyManager {
if ((workTypes & WORK_TYPE_TOP) == WORK_TYPE_TOP) {
mNumPendingJobs.put(WORK_TYPE_TOP, mNumPendingJobs.get(WORK_TYPE_TOP) + 1);
}
+ if ((workTypes & WORK_TYPE_EJ) == WORK_TYPE_EJ) {
+ mNumPendingJobs.put(WORK_TYPE_EJ, mNumPendingJobs.get(WORK_TYPE_EJ) + 1);
+ }
if ((workTypes & WORK_TYPE_BG) == WORK_TYPE_BG) {
mNumPendingJobs.put(WORK_TYPE_BG, mNumPendingJobs.get(WORK_TYPE_BG) + 1);
}
@@ -1165,61 +1197,70 @@ class JobConcurrencyManager {
void onCountDone() {
// Calculate how many slots to reserve for each work type. "Unspecialized" slots will
- // be reserved for higher importance types first (ie. top before bg).
- mNumUnspecialized = mConfigMaxTotal;
- final int numTop = mNumRunningJobs.get(WORK_TYPE_TOP)
- + mNumPendingJobs.get(WORK_TYPE_TOP);
- int resTop = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_TOP), numTop);
- mNumActuallyReservedSlots.put(WORK_TYPE_TOP, resTop);
- mNumUnspecialized -= resTop;
- final int numBg = mNumRunningJobs.get(WORK_TYPE_BG) + mNumPendingJobs.get(WORK_TYPE_BG);
- int resBg = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_BG), numBg);
- mNumActuallyReservedSlots.put(WORK_TYPE_BG, resBg);
- mNumUnspecialized -= resBg;
- final int numBgUser = mNumRunningJobs.get(WORK_TYPE_BGUSER)
- + mNumPendingJobs.get(WORK_TYPE_BGUSER);
- int resBgUser = Math.min(mConfigNumReservedSlots.get(WORK_TYPE_BGUSER), numBgUser);
- mNumActuallyReservedSlots.put(WORK_TYPE_BGUSER, resBgUser);
- mNumUnspecialized -= resBgUser;
-
- mNumUnspecializedRemaining = mNumUnspecialized;
- // Account for already running jobs after we've assigned the minimum number of slots.
- int unspecializedAssigned;
- int extraRunning = (mNumRunningJobs.get(WORK_TYPE_TOP) - resTop);
- if (extraRunning > 0) {
- unspecializedAssigned = Math.max(0,
- Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP) - resTop,
- extraRunning));
- resTop += unspecializedAssigned;
- mNumUnspecializedRemaining -= extraRunning;
- }
- extraRunning = (mNumRunningJobs.get(WORK_TYPE_BG) - resBg);
- if (extraRunning > 0) {
- unspecializedAssigned = Math.max(0,
- Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG) - resBg, extraRunning));
- resBg += unspecializedAssigned;
- mNumUnspecializedRemaining -= extraRunning;
- }
- extraRunning = (mNumRunningJobs.get(WORK_TYPE_BGUSER) - resBgUser);
- if (extraRunning > 0) {
- unspecializedAssigned = Math.max(0,
- Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BGUSER) - resBgUser,
- extraRunning));
- resBgUser += unspecializedAssigned;
- mNumUnspecializedRemaining -= extraRunning;
- }
+ // be reserved for higher importance types first (ie. top before ej before bg).
+ // Steps:
+ // 1. Account for slots for already running jobs
+ // 2. Use remaining unaccounted slots to try and ensure minimum reserved slots
+ // 3. Allocate remaining up to max, based on importance
- // Assign remaining unspecialized based on ranking.
- unspecializedAssigned = Math.max(0,
+ mNumUnspecializedRemaining = mConfigMaxTotal;
+
+ // Step 1
+ int runTop = mNumRunningJobs.get(WORK_TYPE_TOP);
+ int resTop = runTop;
+ mNumUnspecializedRemaining -= resTop;
+ int runEj = mNumRunningJobs.get(WORK_TYPE_EJ);
+ int resEj = runEj;
+ mNumUnspecializedRemaining -= resEj;
+ int runBg = mNumRunningJobs.get(WORK_TYPE_BG);
+ int resBg = runBg;
+ mNumUnspecializedRemaining -= resBg;
+ int runBgUser = mNumRunningJobs.get(WORK_TYPE_BGUSER);
+ int resBgUser = runBgUser;
+ mNumUnspecializedRemaining -= resBgUser;
+
+ // Step 2
+ final int numTop = runTop + mNumPendingJobs.get(WORK_TYPE_TOP);
+ int fillUp = Math.max(0, Math.min(mNumUnspecializedRemaining,
+ Math.min(numTop, mConfigNumReservedSlots.get(WORK_TYPE_TOP) - resTop)));
+ resTop += fillUp;
+ mNumUnspecializedRemaining -= fillUp;
+ final int numEj = runEj + mNumPendingJobs.get(WORK_TYPE_EJ);
+ fillUp = Math.max(0, Math.min(mNumUnspecializedRemaining,
+ Math.min(numEj, mConfigNumReservedSlots.get(WORK_TYPE_EJ) - resEj)));
+ resEj += fillUp;
+ mNumUnspecializedRemaining -= fillUp;
+ final int numBg = runBg + mNumPendingJobs.get(WORK_TYPE_BG);
+ fillUp = Math.max(0, Math.min(mNumUnspecializedRemaining,
+ Math.min(numBg, mConfigNumReservedSlots.get(WORK_TYPE_BG) - resBg)));
+ resBg += fillUp;
+ mNumUnspecializedRemaining -= fillUp;
+ final int numBgUser = runBgUser + mNumPendingJobs.get(WORK_TYPE_BGUSER);
+ fillUp = Math.max(0, Math.min(mNumUnspecializedRemaining,
+ Math.min(numBgUser,
+ mConfigNumReservedSlots.get(WORK_TYPE_BGUSER) - resBgUser)));
+ resBgUser += fillUp;
+ mNumUnspecializedRemaining -= fillUp;
+
+ // Step 3
+ int unspecializedAssigned = Math.max(0,
Math.min(mNumUnspecializedRemaining,
Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP), numTop) - resTop));
mNumActuallyReservedSlots.put(WORK_TYPE_TOP, resTop + unspecializedAssigned);
mNumUnspecializedRemaining -= unspecializedAssigned;
+
+ unspecializedAssigned = Math.max(0,
+ Math.min(mNumUnspecializedRemaining,
+ Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_EJ), numEj) - resEj));
+ mNumActuallyReservedSlots.put(WORK_TYPE_EJ, resEj + unspecializedAssigned);
+ mNumUnspecializedRemaining -= unspecializedAssigned;
+
unspecializedAssigned = Math.max(0,
Math.min(mNumUnspecializedRemaining,
Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG), numBg) - resBg));
mNumActuallyReservedSlots.put(WORK_TYPE_BG, resBg + unspecializedAssigned);
mNumUnspecializedRemaining -= unspecializedAssigned;
+
unspecializedAssigned = Math.max(0,
Math.min(mNumUnspecializedRemaining,
Math.min(mConfigAbsoluteMaxSlots.get(WORK_TYPE_BGUSER), numBgUser)
@@ -1238,6 +1279,15 @@ class JobConcurrencyManager {
return WORK_TYPE_TOP;
}
}
+ if ((workTypes & WORK_TYPE_EJ) == WORK_TYPE_EJ) {
+ final int maxAllowed = Math.min(
+ mConfigAbsoluteMaxSlots.get(WORK_TYPE_EJ),
+ mNumActuallyReservedSlots.get(WORK_TYPE_EJ) + mNumUnspecializedRemaining);
+ if (mNumRunningJobs.get(WORK_TYPE_EJ) + mNumStartingJobs.get(WORK_TYPE_EJ)
+ < maxAllowed) {
+ return WORK_TYPE_EJ;
+ }
+ }
if ((workTypes & WORK_TYPE_BG) == WORK_TYPE_BG) {
final int maxAllowed = Math.min(
mConfigAbsoluteMaxSlots.get(WORK_TYPE_BG),
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index 4effa4d445bb..f2bb47bfb8ad 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -62,6 +62,7 @@ import com.android.server.LocalServices;
import com.android.server.PowerAllowlistInternal;
import com.android.server.SystemServiceManager;
import com.android.server.job.controllers.JobStatus;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.usage.AppStandbyInternal;
import org.junit.After;
@@ -128,6 +129,9 @@ public class JobSchedulerServiceTest {
// Called in DeviceIdleJobsController constructor.
doReturn(mock(DeviceIdleInternal.class))
.when(() -> LocalServices.getService(DeviceIdleInternal.class));
+ // Used in JobConcurrencyManager.
+ doReturn(mock(UserManagerInternal.class))
+ .when(() -> LocalServices.getService(UserManagerInternal.class));
// Used in JobStatus.
doReturn(mock(PackageManagerInternal.class))
.when(() -> LocalServices.getService(PackageManagerInternal.class));
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
index 9c781922bf2e..353ac4bd2129 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java
@@ -16,8 +16,10 @@
package com.android.server.job;
+import static com.android.server.job.JobConcurrencyManager.NUM_WORK_TYPES;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BG;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER;
+import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_EJ;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
@@ -48,6 +50,10 @@ import java.util.Random;
public class WorkCountTrackerTest {
private static final String TAG = "WorkerCountTrackerTest";
+ private static final double[] EQUAL_PROBABILITY_CDF =
+ buildCdf(1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES,
+ 1.0 / NUM_WORK_TYPES);
+
private Random mRandom;
private WorkCountTracker mWorkCountTracker;
@@ -57,6 +63,47 @@ public class WorkCountTrackerTest {
mWorkCountTracker = new WorkCountTracker();
}
+ @NonNull
+ private static double[] buildCdf(double pTop, double pEj, double pBg, double pBgUser) {
+ double[] cdf = new double[JobConcurrencyManager.NUM_WORK_TYPES];
+ double sum = 0;
+
+ sum += pTop;
+ cdf[0] = sum;
+ sum += pEj;
+ cdf[1] = sum;
+ sum += pBg;
+ cdf[2] = sum;
+ sum += pBgUser;
+ cdf[3] = sum;
+
+ if (Double.compare(1, sum) != 0) {
+ throw new IllegalArgumentException("probabilities don't sum to one: " + sum);
+ }
+ return cdf;
+ }
+
+ @JobConcurrencyManager.WorkType
+ static int getRandomWorkType(double[] cdf, double rand) {
+ for (int i = cdf.length - 1; i >= 0; --i) {
+ if (rand < cdf[i] && (i == 0 || rand > cdf[i - 1])) {
+ switch (i) {
+ case 0:
+ return WORK_TYPE_TOP;
+ case 1:
+ return WORK_TYPE_EJ;
+ case 2:
+ return WORK_TYPE_BG;
+ case 3:
+ return WORK_TYPE_BGUSER;
+ default:
+ throw new IllegalStateException("Unknown work type");
+ }
+ }
+ }
+ throw new IllegalStateException("Couldn't pick random work type");
+ }
+
/**
* Represents running and pending jobs.
*/
@@ -64,35 +111,22 @@ public class WorkCountTrackerTest {
public final SparseIntArray running = new SparseIntArray();
public final SparseIntArray pending = new SparseIntArray();
- public void maybeEnqueueJobs(double startRatio, double fgJobRatio, double fgUserJobRatio) {
- // fgUserJobRatio should always be at least fgJobRatio, otherwise no WORK_TYPE_BG will
- // be enqueued.
- while (mRandom.nextDouble() < startRatio) {
- final double random = mRandom.nextDouble();
- if (random < fgJobRatio) {
- pending.put(WORK_TYPE_TOP, pending.get(WORK_TYPE_TOP) + 1);
- } else if (random < fgUserJobRatio) {
- pending.put(WORK_TYPE_BG, pending.get(WORK_TYPE_BG) + 1);
- } else {
- pending.put(WORK_TYPE_BGUSER, pending.get(WORK_TYPE_BGUSER) + 1);
- }
+ public void maybeEnqueueJobs(double probStart, double[] typeCdf) {
+ while (mRandom.nextDouble() < probStart) {
+ final int workType = getRandomWorkType(typeCdf, mRandom.nextDouble());
+ pending.put(workType, pending.get(workType) + 1);
}
}
- public void maybeFinishJobs(double stopRatio) {
- for (int i = running.get(WORK_TYPE_BGUSER); i > 0; i--) {
- if (mRandom.nextDouble() < stopRatio) {
- running.put(WORK_TYPE_BGUSER, running.get(WORK_TYPE_BGUSER) - 1);
- }
- }
+ public void maybeFinishJobs(double probStop) {
for (int i = running.get(WORK_TYPE_BG); i > 0; i--) {
- if (mRandom.nextDouble() < stopRatio) {
+ if (mRandom.nextDouble() < probStop) {
running.put(WORK_TYPE_BG, running.get(WORK_TYPE_BG) - 1);
mWorkCountTracker.onJobFinished(WORK_TYPE_BG);
}
}
for (int i = running.get(WORK_TYPE_TOP); i > 0; i--) {
- if (mRandom.nextDouble() < stopRatio) {
+ if (mRandom.nextDouble() < probStop) {
running.put(WORK_TYPE_TOP, running.get(WORK_TYPE_TOP) - 1);
mWorkCountTracker.onJobFinished(WORK_TYPE_TOP);
}
@@ -127,40 +161,27 @@ public class WorkCountTrackerTest {
mWorkCountTracker.onCountDone();
}
+ private boolean hasStartablePendingJob(Jobs jobs) {
+ for (int i = 0; i < jobs.pending.size(); ++i) {
+ if (jobs.pending.valueAt(i) > 0
+ && mWorkCountTracker.canJobStart(jobs.pending.keyAt(i)) != WORK_TYPE_NONE) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void startPendingJobs(Jobs jobs) {
- while ((jobs.pending.get(WORK_TYPE_TOP) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_TOP) != WORK_TYPE_NONE)
- || (jobs.pending.get(WORK_TYPE_BG) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_BG) != WORK_TYPE_NONE)
- || (jobs.pending.get(WORK_TYPE_BGUSER) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_BGUSER) != WORK_TYPE_NONE)) {
- final boolean isStartingFg = mRandom.nextBoolean();
- final boolean isStartingFgUser = mRandom.nextBoolean();
-
- if (isStartingFg) {
- if (jobs.pending.get(WORK_TYPE_TOP) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_TOP) != WORK_TYPE_NONE) {
- jobs.pending.put(WORK_TYPE_TOP, jobs.pending.get(WORK_TYPE_TOP) - 1);
- jobs.running.put(WORK_TYPE_TOP, jobs.running.get(WORK_TYPE_TOP) + 1);
- mWorkCountTracker.stageJob(WORK_TYPE_TOP);
- mWorkCountTracker.onJobStarted(WORK_TYPE_TOP);
- }
- } else if (isStartingFgUser) {
- if (jobs.pending.get(WORK_TYPE_BG) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_BG) != WORK_TYPE_NONE) {
- jobs.pending.put(WORK_TYPE_BG, jobs.pending.get(WORK_TYPE_BG) - 1);
- jobs.running.put(WORK_TYPE_BG, jobs.running.get(WORK_TYPE_BG) + 1);
- mWorkCountTracker.stageJob(WORK_TYPE_BG);
- mWorkCountTracker.onJobStarted(WORK_TYPE_BG);
- }
- } else {
- if (jobs.pending.get(WORK_TYPE_BGUSER) > 0
- && mWorkCountTracker.canJobStart(WORK_TYPE_BGUSER) != WORK_TYPE_NONE) {
- jobs.pending.put(WORK_TYPE_BGUSER, jobs.pending.get(WORK_TYPE_BGUSER) - 1);
- jobs.running.put(WORK_TYPE_BGUSER, jobs.running.get(WORK_TYPE_BGUSER) + 1);
- mWorkCountTracker.stageJob(WORK_TYPE_BGUSER);
- mWorkCountTracker.onJobStarted(WORK_TYPE_BGUSER);
- }
+ while (hasStartablePendingJob(jobs)) {
+ final int startingWorkType =
+ getRandomWorkType(EQUAL_PROBABILITY_CDF, mRandom.nextDouble());
+
+ if (jobs.pending.get(startingWorkType) > 0
+ && mWorkCountTracker.canJobStart(startingWorkType) != WORK_TYPE_NONE) {
+ jobs.pending.put(startingWorkType, jobs.pending.get(startingWorkType) - 1);
+ jobs.running.put(startingWorkType, jobs.running.get(startingWorkType) + 1);
+ mWorkCountTracker.stageJob(startingWorkType);
+ mWorkCountTracker.onJobStarted(startingWorkType);
}
}
}
@@ -171,10 +192,10 @@ public class WorkCountTrackerTest {
private void checkRandom(Jobs jobs, int numTests, int totalMax,
@NonNull List<Pair<Integer, Integer>> minLimits,
@NonNull List<Pair<Integer, Integer>> maxLimits,
- double startRatio, double fgJobRatio, double fgUserJobRatio, double stopRatio) {
+ double probStart, double[] typeCdf, double probStop) {
for (int i = 0; i < numTests; i++) {
- jobs.maybeFinishJobs(stopRatio);
- jobs.maybeEnqueueJobs(startRatio, fgJobRatio, fgUserJobRatio);
+ jobs.maybeFinishJobs(probStop);
+ jobs.maybeEnqueueJobs(probStart, typeCdf);
recount(jobs, totalMax, minLimits, maxLimits);
startPendingJobs(jobs);
@@ -200,25 +221,19 @@ public class WorkCountTrackerTest {
*/
@Test
public void testRandom1() {
+ assertThat(EQUAL_PROBABILITY_CDF.length).isEqualTo(NUM_WORK_TYPES);
+
final Jobs jobs = new Jobs();
final int numTests = 5000;
final int totalMax = 6;
- final List<Pair<Integer, Integer>> maxLimits =
- List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
- final List<Pair<Integer, Integer>> minLimits =
- List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final double stopRatio = 0.1;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 50%
- // WORK_TYPE_BG -- 50%
- // WORK_TYPE_BGUSER -- 0%
- final double fgJobRatio = 0.5;
- final double fgUserJobRatio = 1;
- final double startRatio = 0.1;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
+ final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final double probStop = 0.1;
+ final double probStart = 0.1;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ EQUAL_PROBABILITY_CDF, probStop);
}
@Test
@@ -230,17 +245,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of();
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 50%
- // WORK_TYPE_BG -- 50%
- // WORK_TYPE_BGUSER -- 0%
- final double fgJobRatio = 0.5;
- final double fgUserJobRatio = 1;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0.5, 0, 0.5, 0);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -252,17 +261,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 33%
- // WORK_TYPE_BG -- 33%
- // WORK_TYPE_BGUSER -- 33%
- final double fgJobRatio = 1 / 3.0;
- final double fgUserJobRatio = 2 / 3.0;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(1.0 / 3, 0, 1.0 / 3, 1.0 / 3);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -274,17 +277,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
final List<Pair<Integer, Integer>> minLimits = List.of();
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 33%
- // WORK_TYPE_BG -- 33%
- // WORK_TYPE_BGUSER -- 33%
- final double fgJobRatio = 1 / 3.0;
- final double fgUserJobRatio = 2 / 3.0;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(1.0 / 3, 0, 1.0 / 3, 1.0 / 3);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -296,17 +293,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 10%
- // WORK_TYPE_BG -- 80%
- // WORK_TYPE_BGUSER -- 10%
- final double fgJobRatio = 0.1;
- final double fgUserJobRatio = 0.9;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0.1, 0, 0.8, .1);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -318,17 +309,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 90%
- // WORK_TYPE_BG -- 10%
- // WORK_TYPE_BGUSER -- 0%
- final double fgJobRatio = 0.9;
- final double fgUserJobRatio = 1;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0.9, 0, 0.1, 0);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -340,17 +325,11 @@ public class WorkCountTrackerTest {
final List<Pair<Integer, Integer>> maxLimits =
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
- final double stopRatio = 0.4;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 10%
- // WORK_TYPE_BG -- 10%
- // WORK_TYPE_BGUSER -- 80%
- final double fgJobRatio = 0.1;
- final double fgUserJobRatio = 0.2;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.4;
+ final double[] cdf = buildCdf(0.1, 0, 0.1, .8);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -363,17 +342,11 @@ public class WorkCountTrackerTest {
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final double stopRatio = 0.4;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 90%
- // WORK_TYPE_BG -- 5%
- // WORK_TYPE_BGUSER -- 5%
- final double fgJobRatio = 0.9;
- final double fgUserJobRatio = 0.95;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.4;
+ final double[] cdf = buildCdf(0.9, 0, 0.05, 0.05);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -386,17 +359,11 @@ public class WorkCountTrackerTest {
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 0%
- // WORK_TYPE_BG -- 50%
- // WORK_TYPE_BGUSER -- 50%
- final double fgJobRatio = 0;
- final double fgUserJobRatio = 0.5;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0, 0, 0.5, 0.5);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -409,17 +376,11 @@ public class WorkCountTrackerTest {
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 0%
- // WORK_TYPE_BG -- 10%
- // WORK_TYPE_BGUSER -- 90%
- final double fgJobRatio = 0;
- final double fgUserJobRatio = 0.1;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0, 0, 0.1, 0.9);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
@Test
@@ -432,17 +393,81 @@ public class WorkCountTrackerTest {
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2));
final List<Pair<Integer, Integer>> minLimits =
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
- final double stopRatio = 0.5;
- // WorkType probabilities:
- // WORK_TYPE_TOP -- 0%
- // WORK_TYPE_BG -- 90%
- // WORK_TYPE_BGUSER -- 10%
- final double fgJobRatio = 0;
- final double fgUserJobRatio = 0.9;
- final double startRatio = 0.5;
-
- checkRandom(jobs, numTests, totalMax, minLimits, maxLimits,
- startRatio, fgJobRatio, fgUserJobRatio, stopRatio);
+ final double probStop = 0.5;
+ final double[] cdf = buildCdf(0, 0, 0.9, 0.1);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
+ }
+
+ @Test
+ public void testRandom12() {
+ final Jobs jobs = new Jobs();
+
+ final int numTests = 5000;
+ final int totalMax = 6;
+ final List<Pair<Integer, Integer>> maxLimits = List.of(Pair.create(WORK_TYPE_BG, 4));
+ final List<Pair<Integer, Integer>> minLimits =
+ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2));
+ final double probStop = 0.4;
+ final double[] cdf = buildCdf(0.5, 0.5, 0, 0);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
+ }
+
+ @Test
+ public void testRandom13() {
+ assertThat(EQUAL_PROBABILITY_CDF.length).isEqualTo(NUM_WORK_TYPES);
+
+ final Jobs jobs = new Jobs();
+
+ final int numTests = 5000;
+ final int totalMax = 13;
+ final List<Pair<Integer, Integer>> maxLimits = List.of(
+ Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
+ Pair.create(WORK_TYPE_BGUSER, 3));
+ final List<Pair<Integer, Integer>> minLimits =
+ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1));
+ final double probStop = 0.01;
+ final double probStart = 0.99;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
+ EQUAL_PROBABILITY_CDF, probStop);
+ }
+
+ @Test
+ public void testRandom14() {
+ final Jobs jobs = new Jobs();
+
+ final int numTests = 5000;
+ final int totalMax = 6;
+ final List<Pair<Integer, Integer>> maxLimits =
+ List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4));
+ final List<Pair<Integer, Integer>> minLimits = List.of(Pair.create(WORK_TYPE_BG, 2));
+ final double probStop = 0.4;
+ final double[] cdf = buildCdf(.1, 0.5, 0.35, 0.05);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
+ }
+
+ @Test
+ public void testRandom15() {
+ final Jobs jobs = new Jobs();
+
+ final int numTests = 5000;
+ final int totalMax = 6;
+ final List<Pair<Integer, Integer>> maxLimits =
+ List.of(Pair.create(WORK_TYPE_EJ, 5), Pair.create(WORK_TYPE_BG, 4),
+ Pair.create(WORK_TYPE_BGUSER, 1));
+ final List<Pair<Integer, Integer>> minLimits =
+ List.of(Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2));
+ final double probStop = 0.4;
+ final double[] cdf = buildCdf(0.01, 0.49, 0.1, 0.4);
+ final double probStart = 0.5;
+
+ checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart, cdf, probStop);
}
/** Used by the following tests */
@@ -574,6 +599,16 @@ public class WorkCountTrackerTest {
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
/* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3)));
+ checkSimple(8,
+ /* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 4)),
+ /* run */ List.of(Pair.create(WORK_TYPE_TOP, 6)),
+ /* pen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_EJ, 5),
+ Pair.create(WORK_TYPE_BG, 3)),
+ /* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_EJ, 2)),
+ /* resPen */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 3),
+ Pair.create(WORK_TYPE_BG, 3)));
+
// This could happen if we lower the effective config due to higher memory pressure after
// we've already started running jobs. We shouldn't stop already running jobs, but also
// shouldn't start new ones.
diff --git a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
index bbc1f1d26282..2288a8925561 100644
--- a/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java
@@ -17,6 +17,7 @@ package com.android.server.job;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BG;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER;
+import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_EJ;
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
import static org.junit.Assert.assertEquals;
@@ -36,7 +37,6 @@ import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.ArrayList;
import java.util.List;
@RunWith(AndroidJUnit4.class)
@@ -44,9 +44,11 @@ import java.util.List;
public class WorkTypeConfigTest {
private static final String KEY_MAX_TOTAL = "concurrency_max_total_test";
private static final String KEY_MAX_TOP = "concurrency_max_top_test";
+ private static final String KEY_MAX_EJ = "concurrency_max_ej_test";
private static final String KEY_MAX_BG = "concurrency_max_bg_test";
private static final String KEY_MAX_BGUSER = "concurrency_max_bguser_test";
private static final String KEY_MIN_TOP = "concurrency_min_top_test";
+ private static final String KEY_MIN_EJ = "concurrency_min_ej_test";
private static final String KEY_MIN_BG = "concurrency_min_bg_test";
private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test";
@@ -59,55 +61,27 @@ public class WorkTypeConfigTest {
// DeviceConfig.resetToDefaults() doesn't work here. Need to reset constants manually.
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_TOTAL, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_TOP, "", false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_EJ, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_BG, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_BGUSER, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_TOP, "", false);
+ DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_EJ, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BG, "", false);
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BGUSER, "", false);
}
private void check(@Nullable DeviceConfig.Properties config,
int defaultTotal,
- @Nullable Pair<Integer, Integer> defaultTopLimits,
- @Nullable Pair<Integer, Integer> defaultBgLimits,
- @Nullable Pair<Integer, Integer> defaultBgUserLimits,
+ @NonNull List<Pair<Integer, Integer>> defaultMin,
+ @NonNull List<Pair<Integer, Integer>> defaultMax,
boolean expectedValid, int expectedTotal,
- @NonNull Pair<Integer, Integer> expectedTopLimits,
- @NonNull Pair<Integer, Integer> expectedBgLimits,
- @NonNull Pair<Integer, Integer> expectedBgUserLimits) throws Exception {
+ @NonNull List<Pair<Integer, Integer>> expectedMinLimits,
+ @NonNull List<Pair<Integer, Integer>> expectedMaxLimits) throws Exception {
resetConfig();
if (config != null) {
DeviceConfig.setProperties(config);
}
- List<Pair<Integer, Integer>> defaultMin = new ArrayList<>();
- List<Pair<Integer, Integer>> defaultMax = new ArrayList<>();
- Integer val;
- if (defaultTopLimits != null) {
- if ((val = defaultTopLimits.first) != null) {
- defaultMin.add(Pair.create(WORK_TYPE_TOP, val));
- }
- if ((val = defaultTopLimits.second) != null) {
- defaultMax.add(Pair.create(WORK_TYPE_TOP, val));
- }
- }
- if (defaultBgLimits != null) {
- if ((val = defaultBgLimits.first) != null) {
- defaultMin.add(Pair.create(WORK_TYPE_BG, val));
- }
- if ((val = defaultBgLimits.second) != null) {
- defaultMax.add(Pair.create(WORK_TYPE_BG, val));
- }
- }
- if (defaultBgUserLimits != null) {
- if ((val = defaultBgUserLimits.first) != null) {
- defaultMin.add(Pair.create(WORK_TYPE_BGUSER, val));
- }
- if ((val = defaultBgUserLimits.second) != null) {
- defaultMax.add(Pair.create(WORK_TYPE_BGUSER, val));
- }
- }
-
final WorkTypeConfig counts;
try {
counts = new WorkTypeConfig("test",
@@ -128,44 +102,125 @@ public class WorkTypeConfigTest {
counts.update(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER));
assertEquals(expectedTotal, counts.getMaxTotal());
- assertEquals((int) expectedTopLimits.first, counts.getMinReserved(WORK_TYPE_TOP));
- assertEquals((int) expectedTopLimits.second, counts.getMax(WORK_TYPE_TOP));
- assertEquals((int) expectedBgLimits.first, counts.getMinReserved(WORK_TYPE_BG));
- assertEquals((int) expectedBgLimits.second, counts.getMax(WORK_TYPE_BG));
- assertEquals((int) expectedBgUserLimits.first, counts.getMinReserved(WORK_TYPE_BGUSER));
- assertEquals((int) expectedBgUserLimits.second, counts.getMax(WORK_TYPE_BGUSER));
+ for (Pair<Integer, Integer> min : expectedMinLimits) {
+ assertEquals((int) min.second, counts.getMinReserved(min.first));
+ }
+ for (Pair<Integer, Integer> max : expectedMaxLimits) {
+ assertEquals((int) max.second, counts.getMax(max.first));
+ }
}
@Test
public void test() throws Exception {
// Tests with various combinations.
- check(null, /*default*/ 5, Pair.create(4, null), Pair.create(0, 1), Pair.create(0, 1),
- /*expected*/ true, 5, Pair.create(4, 5), Pair.create(0, 1), Pair.create(0, 1));
- check(null, /*default*/ 5, Pair.create(5, null), Pair.create(0, 0), Pair.create(0, 0),
- /*expected*/ true, 5, Pair.create(5, 5), Pair.create(0, 1), Pair.create(0, 1));
- check(null, /*default*/ 0, Pair.create(5, null), Pair.create(0, 0), Pair.create(0, 0),
- /*expected*/ false, 1, Pair.create(1, 1), Pair.create(0, 1), Pair.create(0, 1));
- check(null, /*default*/ -1, null, Pair.create(-1, -1), Pair.create(-1, -1),
- /*expected*/ false, 1, Pair.create(1, 1), Pair.create(0, 1), Pair.create(0, 1));
- check(null, /*default*/ 5, null, Pair.create(5, 5), Pair.create(0, 5),
- /*expected*/ true, 5, Pair.create(1, 5), Pair.create(4, 5), Pair.create(0, 5));
- check(null, /*default*/ 6, Pair.create(1, null), Pair.create(6, 5), Pair.create(2, 1),
- /*expected*/ false, 6, Pair.create(1, 6), Pair.create(5, 5), Pair.create(0, 1));
- check(null, /*default*/ 4, null, Pair.create(6, 5), Pair.create(6, 5),
- /*expected*/ false, 4, Pair.create(1, 4), Pair.create(3, 4), Pair.create(0, 4));
- check(null, /*default*/ 5, Pair.create(4, null), Pair.create(1, 1), Pair.create(0, 5),
- /*expected*/ true, 5, Pair.create(4, 5), Pair.create(1, 1), Pair.create(0, 5));
- check(null, /*default*/ 5, Pair.create(4, null), Pair.create(0, 1), Pair.create(1, 5),
- /*expected*/ true, 5, Pair.create(4, 5), Pair.create(0, 1), Pair.create(1, 5));
- check(null, /*default*/ 15, null, Pair.create(15, 15), Pair.create(0, 15),
- /*expected*/ true, 15, Pair.create(1, 15), Pair.create(14, 15), Pair.create(0, 15));
- check(null, /*default*/ 16, null, Pair.create(16, 16), Pair.create(0, 16),
- /*expected*/ true, 16, Pair.create(1, 16), Pair.create(15, 16), Pair.create(0, 16));
- check(null, /*default*/ 20, null, Pair.create(20, 20), Pair.create(10, 20),
+ check(null, /*default*/ 13,
+ /* min */ List.of(),
+ /* max */ List.of(),
+ /*expected*/ true, 13,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 0),
+ Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 13), Pair.create(WORK_TYPE_EJ, 13),
+ Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 13)));
+ check(null, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 1)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 0), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1)));
+ check(null, /*default*/ 0,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 0)),
+ /*expected*/ false, 1,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /*default*/ -1,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, -1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, -1)),
+ /*expected*/ false, 1,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /*default*/ 5,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)));
+ check(null, /*default*/ 6,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)),
+ /*expected*/ false, 6,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 6),
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 1)));
+ check(null, /*default*/ 4,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 6)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 5), Pair.create(WORK_TYPE_BGUSER, 5)),
+ /*expected*/ false, 4,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 3), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 4),
+ Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 4)));
+ check(null, /*default*/ 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_BG, 1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /*default*/ 10,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
+ Pair.create(WORK_TYPE_BG, 1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 1)),
+ /*expected*/ true, 10,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
+ Pair.create(WORK_TYPE_BG, 1)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 10), Pair.create(WORK_TYPE_BG, 1)));
+ check(null, /*default*/ 15,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 15)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 15)),
+ /*expected*/ true, 15,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 14)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 15), Pair.create(WORK_TYPE_BG, 15)));
+ check(null, /*default*/ 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ /*expected*/ true, 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
+ check(null, /*default*/ 20,
+ /* min */ List.of(
+ Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 10)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 20), Pair.create(WORK_TYPE_BGUSER, 20)),
/*expected*/ false, 16,
- Pair.create(1, 16), Pair.create(15, 16), Pair.create(0, 16));
- check(null, /*default*/ 20, null, Pair.create(16, 16), Pair.create(0, 16),
- /*expected*/ true, 16, Pair.create(1, 16), Pair.create(15, 16), Pair.create(0, 16));
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1),
+ Pair.create(WORK_TYPE_BG, 15), Pair.create(WORK_TYPE_BGUSER, 0)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16),
+ Pair.create(WORK_TYPE_BG, 16), Pair.create(WORK_TYPE_BGUSER, 16)));
+ check(null, /*default*/ 20,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 16)),
+ /*expected*/ true, 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 15)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
// Test for overriding with a setting string.
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
@@ -173,26 +228,66 @@ public class WorkTypeConfigTest {
.setInt(KEY_MAX_BG, 4)
.setInt(KEY_MIN_BG, 3)
.build(),
- /*default*/ 9, null, Pair.create(9, 9), Pair.create(0, 2),
- /*expected*/ true, 5, Pair.create(1, 5), Pair.create(3, 4), Pair.create(0, 2));
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(
+ Pair.create(WORK_TYPE_BG, 9), Pair.create(WORK_TYPE_BGUSER, 2)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5),
+ Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 5).build(),
- /*default*/ 9, null, Pair.create(9, 9), Pair.create(0, 0),
- /*expected*/ true, 5, Pair.create(1, 5), Pair.create(4, 5), Pair.create(0, 1));
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /*expected*/ true, 5,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 5), Pair.create(WORK_TYPE_BG, 5)));
+
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_BG, 4).build(),
- /*default*/ 9, null, Pair.create(9, 9), Pair.create(0, 9),
- /*expected*/ true, 9, Pair.create(1, 9), Pair.create(4, 4), Pair.create(0, 9));
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /*expected*/ true, 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 4)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 4)));
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MIN_BG, 3).build(),
- /*default*/ 9, null, Pair.create(9, 9), Pair.create(0, 6),
- /*expected*/ true, 9, Pair.create(1, 9), Pair.create(3, 9), Pair.create(0, 6));
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /*expected*/ true, 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 3)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 9), Pair.create(WORK_TYPE_BG, 9)));
+ check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
+ .setInt(KEY_MAX_TOTAL, 20)
+ .setInt(KEY_MAX_EJ, 5)
+ .setInt(KEY_MIN_EJ, 2)
+ .setInt(KEY_MAX_BG, 16)
+ .setInt(KEY_MIN_BG, 8)
+ .build(),
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /*expected*/ true, 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_EJ, 2),
+ Pair.create(WORK_TYPE_BG, 8)),
+ /* max */
+ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_EJ, 5),
+ Pair.create(WORK_TYPE_BG, 16)));
+
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
.setInt(KEY_MAX_TOTAL, 20)
.setInt(KEY_MAX_BG, 20)
.setInt(KEY_MIN_BG, 8)
.build(),
- /*default*/ 9, null, Pair.create(9, 9), Pair.create(0, 8),
- /*expected*/ true, 16, Pair.create(1, 16), Pair.create(8, 16), Pair.create(0, 8));
+ /*default*/ 9,
+ /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)),
+ /*expected*/ true, 16,
+ /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_BG, 8)),
+ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_BG, 16)));
}
}