Merge "Reserve execution slots for FGS jobs." into sc-dev
This commit is contained in:
@@ -73,20 +73,48 @@ class JobConcurrencyManager {
|
||||
CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms";
|
||||
private static final long DEFAULT_SCREEN_OFF_ADJUSTMENT_DELAY_MS = 30_000;
|
||||
|
||||
// Try to give higher priority types lower values.
|
||||
/**
|
||||
* Set of possible execution types that a job can have. The actual type(s) of a job are based
|
||||
* on the {@link JobStatus#lastEvaluatedPriority}, which is typically evaluated right before
|
||||
* execution (when we're trying to determine which jobs to run next) and won't change after the
|
||||
* job has started executing.
|
||||
*
|
||||
* Try to give higher priority types lower values.
|
||||
*
|
||||
* @see #getJobWorkTypes(JobStatus)
|
||||
*/
|
||||
|
||||
/** Job shouldn't run or qualify as any other work type. */
|
||||
static final int WORK_TYPE_NONE = 0;
|
||||
/** The job is for an app in the TOP state for a currently active user. */
|
||||
static final int WORK_TYPE_TOP = 1 << 0;
|
||||
static final int WORK_TYPE_EJ = 1 << 1;
|
||||
static final int WORK_TYPE_BG = 1 << 2;
|
||||
static final int WORK_TYPE_BGUSER = 1 << 3;
|
||||
/**
|
||||
* The job is for an app in a {@link ActivityManager#PROCESS_STATE_FOREGROUND_SERVICE} or higher
|
||||
* state (excluding {@link ActivityManager#PROCESS_STATE_TOP} for a currently active user.
|
||||
*/
|
||||
static final int WORK_TYPE_FGS = 1 << 1;
|
||||
/** The job is allowed to run as an expedited job for a currently active user. */
|
||||
static final int WORK_TYPE_EJ = 1 << 2;
|
||||
/**
|
||||
* The job does not satisfy any of the conditions for {@link #WORK_TYPE_TOP},
|
||||
* {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a currently active user, so
|
||||
* can run as a background job.
|
||||
*/
|
||||
static final int WORK_TYPE_BG = 1 << 3;
|
||||
/**
|
||||
* The job does not satisfy any of the conditions for {@link #WORK_TYPE_TOP},
|
||||
* {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a completely background user,
|
||||
* so can run as a background user job.
|
||||
*/
|
||||
static final int WORK_TYPE_BGUSER = 1 << 4;
|
||||
@VisibleForTesting
|
||||
static final int NUM_WORK_TYPES = 4;
|
||||
private static final int ALL_WORK_TYPES =
|
||||
WORK_TYPE_TOP | WORK_TYPE_EJ | WORK_TYPE_BG | WORK_TYPE_BGUSER;
|
||||
static final int NUM_WORK_TYPES = 5;
|
||||
private static final int ALL_WORK_TYPES = (1 << NUM_WORK_TYPES) - 1;
|
||||
|
||||
@IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = {
|
||||
WORK_TYPE_NONE,
|
||||
WORK_TYPE_TOP,
|
||||
WORK_TYPE_FGS,
|
||||
WORK_TYPE_EJ,
|
||||
WORK_TYPE_BG,
|
||||
WORK_TYPE_BGUSER
|
||||
@@ -95,12 +123,15 @@ class JobConcurrencyManager {
|
||||
public @interface WorkType {
|
||||
}
|
||||
|
||||
private static String workTypeToString(@WorkType int workType) {
|
||||
@VisibleForTesting
|
||||
static String workTypeToString(@WorkType int workType) {
|
||||
switch (workType) {
|
||||
case WORK_TYPE_NONE:
|
||||
return "NONE";
|
||||
case WORK_TYPE_TOP:
|
||||
return "TOP";
|
||||
case WORK_TYPE_FGS:
|
||||
return "FGS";
|
||||
case WORK_TYPE_EJ:
|
||||
return "EJ";
|
||||
case WORK_TYPE_BG:
|
||||
@@ -131,58 +162,60 @@ class JobConcurrencyManager {
|
||||
new WorkConfigLimitsPerMemoryTrimLevel(
|
||||
new WorkTypeConfig("screen_on_normal", 11,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_EJ, 3),
|
||||
Pair.create(WORK_TYPE_BG, 2)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_FGS, 1),
|
||||
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", 9,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 2),
|
||||
Pair.create(WORK_TYPE_BG, 2)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
|
||||
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", 6,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1),
|
||||
Pair.create(WORK_TYPE_BG, 1)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
|
||||
Pair.create(WORK_TYPE_EJ, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
),
|
||||
new WorkTypeConfig("screen_on_critical", 5,
|
||||
new WorkTypeConfig("screen_on_critical", 6,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
|
||||
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", 13,
|
||||
new WorkTypeConfig("screen_off_normal", 15,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 3),
|
||||
Pair.create(WORK_TYPE_BG, 2)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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_off_moderate", 13,
|
||||
new WorkTypeConfig("screen_off_moderate", 15,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_EJ, 3),
|
||||
Pair.create(WORK_TYPE_BG, 2)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_FGS, 2),
|
||||
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", 7,
|
||||
new WorkTypeConfig("screen_off_low", 9,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 2),
|
||||
Pair.create(WORK_TYPE_BG, 1)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
|
||||
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,
|
||||
new WorkTypeConfig("screen_off_critical", 6,
|
||||
// defaultMin
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_EJ, 1)),
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1),
|
||||
Pair.create(WORK_TYPE_EJ, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
)
|
||||
@@ -977,10 +1010,11 @@ class JobConcurrencyManager {
|
||||
|
||||
int getJobWorkTypes(@NonNull JobStatus js) {
|
||||
int classification = 0;
|
||||
// TODO: create dedicated work type for FGS
|
||||
if (shouldRunAsFgUserJob(js)) {
|
||||
if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
|
||||
classification |= WORK_TYPE_TOP;
|
||||
} else if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE) {
|
||||
classification |= WORK_TYPE_FGS;
|
||||
} else {
|
||||
classification |= WORK_TYPE_BG;
|
||||
}
|
||||
@@ -1001,11 +1035,13 @@ 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_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "max_fgs_";
|
||||
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_FGS = CONFIG_KEY_PREFIX_CONCURRENCY + "min_fgs_";
|
||||
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 =
|
||||
@@ -1053,6 +1089,10 @@ class JobConcurrencyManager {
|
||||
properties.getInt(KEY_PREFIX_MAX_TOP + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_TOP, mMaxTotal))));
|
||||
mMaxAllowedSlots.put(WORK_TYPE_TOP, maxTop);
|
||||
final int maxFgs = Math.max(1, Math.min(mMaxTotal,
|
||||
properties.getInt(KEY_PREFIX_MAX_FGS + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_FGS, mMaxTotal))));
|
||||
mMaxAllowedSlots.put(WORK_TYPE_FGS, maxFgs);
|
||||
final int maxEj = Math.max(1, Math.min(mMaxTotal,
|
||||
properties.getInt(KEY_PREFIX_MAX_EJ + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_EJ, mMaxTotal))));
|
||||
@@ -1074,6 +1114,12 @@ class JobConcurrencyManager {
|
||||
mDefaultMinReservedSlots.get(WORK_TYPE_TOP))));
|
||||
mMinReservedSlots.put(WORK_TYPE_TOP, minTop);
|
||||
remaining -= minTop;
|
||||
// Ensure fgs is in the range [0, min(maxFgs, remaining)]
|
||||
final int minFgs = Math.max(0, Math.min(Math.min(maxFgs, remaining),
|
||||
properties.getInt(KEY_PREFIX_MIN_FGS + mConfigIdentifier,
|
||||
mDefaultMinReservedSlots.get(WORK_TYPE_FGS))));
|
||||
mMinReservedSlots.put(WORK_TYPE_FGS, minFgs);
|
||||
remaining -= minFgs;
|
||||
// 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,
|
||||
@@ -1111,6 +1157,10 @@ class JobConcurrencyManager {
|
||||
.println();
|
||||
pw.print(KEY_PREFIX_MAX_TOP + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_TOP))
|
||||
.println();
|
||||
pw.print(KEY_PREFIX_MIN_FGS + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_FGS))
|
||||
.println();
|
||||
pw.print(KEY_PREFIX_MAX_FGS + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_FGS))
|
||||
.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))
|
||||
@@ -1205,6 +1255,7 @@ class JobConcurrencyManager {
|
||||
private int mConfigMaxTotal;
|
||||
private final SparseIntArray mConfigNumReservedSlots = new SparseIntArray(NUM_WORK_TYPES);
|
||||
private final SparseIntArray mConfigAbsoluteMaxSlots = new SparseIntArray(NUM_WORK_TYPES);
|
||||
private final SparseIntArray mRecycledReserved = new SparseIntArray(NUM_WORK_TYPES);
|
||||
|
||||
/**
|
||||
* Numbers may be lower in this than in {@link #mConfigNumReservedSlots} if there aren't
|
||||
@@ -1220,11 +1271,14 @@ class JobConcurrencyManager {
|
||||
mConfigMaxTotal = workTypeConfig.getMaxTotal();
|
||||
mConfigNumReservedSlots.put(WORK_TYPE_TOP,
|
||||
workTypeConfig.getMinReserved(WORK_TYPE_TOP));
|
||||
mConfigNumReservedSlots.put(WORK_TYPE_FGS,
|
||||
workTypeConfig.getMinReserved(WORK_TYPE_FGS));
|
||||
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_FGS, workTypeConfig.getMax(WORK_TYPE_FGS));
|
||||
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));
|
||||
@@ -1260,15 +1314,10 @@ class JobConcurrencyManager {
|
||||
// We don't need to adjust reservations if only one work type was modified
|
||||
// because that work type is the one we're using.
|
||||
|
||||
// 0 is WORK_TYPE_NONE.
|
||||
int workType = 1;
|
||||
int rem = workTypes;
|
||||
while (rem > 0) {
|
||||
if ((rem & 1) != 0) {
|
||||
for (int workType = 1; workType <= workTypes; workType <<= 1) {
|
||||
if ((workType & workTypes) == workType) {
|
||||
maybeAdjustReservations(workType);
|
||||
}
|
||||
rem = rem >>> 1;
|
||||
workType = workType << 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1280,21 +1329,11 @@ class JobConcurrencyManager {
|
||||
int numAdj = 0;
|
||||
// We don't know which type we'll classify the job as when we run it yet, so make sure
|
||||
// we have space in all applicable slots.
|
||||
if ((workTypes & WORK_TYPE_TOP) == WORK_TYPE_TOP) {
|
||||
mNumPendingJobs.put(WORK_TYPE_TOP, mNumPendingJobs.get(WORK_TYPE_TOP) + adj);
|
||||
numAdj++;
|
||||
}
|
||||
if ((workTypes & WORK_TYPE_EJ) == WORK_TYPE_EJ) {
|
||||
mNumPendingJobs.put(WORK_TYPE_EJ, mNumPendingJobs.get(WORK_TYPE_EJ) + adj);
|
||||
numAdj++;
|
||||
}
|
||||
if ((workTypes & WORK_TYPE_BG) == WORK_TYPE_BG) {
|
||||
mNumPendingJobs.put(WORK_TYPE_BG, mNumPendingJobs.get(WORK_TYPE_BG) + adj);
|
||||
numAdj++;
|
||||
}
|
||||
if ((workTypes & WORK_TYPE_BGUSER) == WORK_TYPE_BGUSER) {
|
||||
mNumPendingJobs.put(WORK_TYPE_BGUSER, mNumPendingJobs.get(WORK_TYPE_BGUSER) + adj);
|
||||
numAdj++;
|
||||
for (int workType = 1; workType <= workTypes; workType <<= 1) {
|
||||
if ((workTypes & workType) == workType) {
|
||||
mNumPendingJobs.put(workType, mNumPendingJobs.get(workType) + adj);
|
||||
numAdj++;
|
||||
}
|
||||
}
|
||||
|
||||
return numAdj;
|
||||
@@ -1388,105 +1427,45 @@ class JobConcurrencyManager {
|
||||
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;
|
||||
for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) {
|
||||
int run = mNumRunningJobs.get(workType);
|
||||
mRecycledReserved.put(workType, run);
|
||||
mNumUnspecializedRemaining -= run;
|
||||
}
|
||||
|
||||
// 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;
|
||||
for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) {
|
||||
int num = mNumRunningJobs.get(workType) + mNumPendingJobs.get(workType);
|
||||
int res = mRecycledReserved.get(workType);
|
||||
int fillUp = Math.max(0, Math.min(mNumUnspecializedRemaining,
|
||||
Math.min(num, mConfigNumReservedSlots.get(workType) - res)));
|
||||
res += fillUp;
|
||||
mRecycledReserved.put(workType, res);
|
||||
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)
|
||||
- resBgUser));
|
||||
mNumActuallyReservedSlots.put(WORK_TYPE_BGUSER, resBgUser + unspecializedAssigned);
|
||||
mNumUnspecializedRemaining -= unspecializedAssigned;
|
||||
for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) {
|
||||
int num = mNumRunningJobs.get(workType) + mNumPendingJobs.get(workType);
|
||||
int res = mRecycledReserved.get(workType);
|
||||
int unspecializedAssigned = Math.max(0,
|
||||
Math.min(mNumUnspecializedRemaining,
|
||||
Math.min(mConfigAbsoluteMaxSlots.get(workType), num) - res));
|
||||
mNumActuallyReservedSlots.put(workType, res + unspecializedAssigned);
|
||||
mNumUnspecializedRemaining -= unspecializedAssigned;
|
||||
}
|
||||
}
|
||||
|
||||
int canJobStart(int workTypes) {
|
||||
if ((workTypes & WORK_TYPE_TOP) == WORK_TYPE_TOP) {
|
||||
final int maxAllowed = Math.min(
|
||||
mConfigAbsoluteMaxSlots.get(WORK_TYPE_TOP),
|
||||
mNumActuallyReservedSlots.get(WORK_TYPE_TOP) + mNumUnspecializedRemaining);
|
||||
if (mNumRunningJobs.get(WORK_TYPE_TOP) + mNumStartingJobs.get(WORK_TYPE_TOP)
|
||||
< maxAllowed) {
|
||||
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),
|
||||
mNumActuallyReservedSlots.get(WORK_TYPE_BG) + mNumUnspecializedRemaining);
|
||||
if (mNumRunningJobs.get(WORK_TYPE_BG) + mNumStartingJobs.get(WORK_TYPE_BG)
|
||||
< maxAllowed) {
|
||||
return WORK_TYPE_BG;
|
||||
}
|
||||
}
|
||||
if ((workTypes & WORK_TYPE_BGUSER) == WORK_TYPE_BGUSER) {
|
||||
final int maxAllowed = Math.min(
|
||||
mConfigAbsoluteMaxSlots.get(WORK_TYPE_BGUSER),
|
||||
mNumActuallyReservedSlots.get(WORK_TYPE_BGUSER)
|
||||
+ mNumUnspecializedRemaining);
|
||||
if (mNumRunningJobs.get(WORK_TYPE_BGUSER) + mNumStartingJobs.get(WORK_TYPE_BGUSER)
|
||||
< maxAllowed) {
|
||||
return WORK_TYPE_BGUSER;
|
||||
for (int workType = 1; workType <= workTypes; workType <<= 1) {
|
||||
if ((workTypes & workType) == workType) {
|
||||
final int maxAllowed = Math.min(
|
||||
mConfigAbsoluteMaxSlots.get(workType),
|
||||
mNumActuallyReservedSlots.get(workType) + mNumUnspecializedRemaining);
|
||||
if (mNumRunningJobs.get(workType) + mNumStartingJobs.get(workType)
|
||||
< maxAllowed) {
|
||||
return workType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return WORK_TYPE_NONE;
|
||||
|
||||
@@ -20,8 +20,10 @@ 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_FGS;
|
||||
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
|
||||
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
|
||||
import static com.android.server.job.JobConcurrencyManager.workTypeToString;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
@@ -54,7 +56,7 @@ public class WorkCountTrackerTest {
|
||||
|
||||
private static final double[] EQUAL_PROBABILITY_CDF =
|
||||
buildWorkTypeCdf(1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES, 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;
|
||||
@@ -66,8 +68,9 @@ public class WorkCountTrackerTest {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static double[] buildWorkTypeCdf(double pTop, double pEj, double pBg, double pBgUser) {
|
||||
return buildCdf(pTop, pEj, pBg, pBgUser);
|
||||
private static double[] buildWorkTypeCdf(
|
||||
double pTop, double pFgs, double pEj, double pBg, double pBgUser) {
|
||||
return buildCdf(pTop, pFgs, pEj, pBg, pBgUser);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -102,10 +105,12 @@ public class WorkCountTrackerTest {
|
||||
case 0:
|
||||
return WORK_TYPE_TOP;
|
||||
case 1:
|
||||
return WORK_TYPE_EJ;
|
||||
return WORK_TYPE_FGS;
|
||||
case 2:
|
||||
return WORK_TYPE_BG;
|
||||
return WORK_TYPE_EJ;
|
||||
case 3:
|
||||
return WORK_TYPE_BG;
|
||||
case 4:
|
||||
return WORK_TYPE_BGUSER;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown work type");
|
||||
@@ -224,12 +229,15 @@ public class WorkCountTrackerTest {
|
||||
|
||||
private void startPendingJobs(Jobs jobs) {
|
||||
while (hasStartablePendingJob(jobs)) {
|
||||
final int startingWorkType =
|
||||
getRandomWorkType(EQUAL_PROBABILITY_CDF, mRandom.nextDouble());
|
||||
final int workType = getRandomWorkType(EQUAL_PROBABILITY_CDF, mRandom.nextDouble());
|
||||
|
||||
if (jobs.pending.get(workType) > 0) {
|
||||
final int pendingMultiType = getPendingMultiType(jobs, workType);
|
||||
final int startingWorkType = mWorkCountTracker.canJobStart(pendingMultiType);
|
||||
if (startingWorkType == WORK_TYPE_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (jobs.pending.get(startingWorkType) > 0
|
||||
&& mWorkCountTracker.canJobStart(startingWorkType) != WORK_TYPE_NONE) {
|
||||
final int pendingMultiType = getPendingMultiType(jobs, startingWorkType);
|
||||
jobs.removePending(pendingMultiType);
|
||||
jobs.running.put(startingWorkType, jobs.running.get(startingWorkType) + 1);
|
||||
mWorkCountTracker.stageJob(startingWorkType, pendingMultiType);
|
||||
@@ -304,7 +312,7 @@ public class WorkCountTrackerTest {
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final List<Pair<Integer, Integer>> minLimits = List.of();
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0.5, 0);
|
||||
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -322,7 +330,7 @@ public class WorkCountTrackerTest {
|
||||
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 probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] numTypesCdf = buildCdf(.75, .2, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -340,7 +348,7 @@ public class WorkCountTrackerTest {
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final List<Pair<Integer, Integer>> minLimits = List.of();
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] numTypesCdf = buildCdf(.05, .95);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -358,7 +366,7 @@ 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));
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0.8, .1);
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.8, .1);
|
||||
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -376,7 +384,7 @@ 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));
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0.9, 0, 0.1, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.85, 0.05, 0, 0.1, 0);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -394,7 +402,7 @@ 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));
|
||||
final double probStop = 0.4;
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0.1, .8);
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.1, .8);
|
||||
final double[] numTypesCdf = buildCdf(0.5, 0.5);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -413,7 +421,7 @@ public class WorkCountTrackerTest {
|
||||
final List<Pair<Integer, Integer>> minLimits =
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final double probStop = 0.4;
|
||||
final double[] cdf = buildWorkTypeCdf(0.9, 0, 0.05, 0.05);
|
||||
final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0.05, 0.05);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -432,7 +440,7 @@ public class WorkCountTrackerTest {
|
||||
final List<Pair<Integer, Integer>> minLimits =
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0.5, 0.5);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.5, 0.5);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -451,7 +459,7 @@ public class WorkCountTrackerTest {
|
||||
final List<Pair<Integer, Integer>> minLimits =
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0.1, 0.9);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.1, 0.9);
|
||||
final double[] numTypesCdf = buildCdf(0.9, 0.1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -470,7 +478,7 @@ public class WorkCountTrackerTest {
|
||||
final List<Pair<Integer, Integer>> minLimits =
|
||||
List.of(Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER, 1));
|
||||
final double probStop = 0.5;
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0.9, 0.1);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.9, 0.1);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -488,7 +496,7 @@ public class WorkCountTrackerTest {
|
||||
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 = buildWorkTypeCdf(0.5, 0.5, 0, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0, 0);
|
||||
final double[] numTypesCdf = buildCdf(0.1, 0.7, 0.2);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -511,7 +519,7 @@ public class WorkCountTrackerTest {
|
||||
final List<Pair<Integer, Integer>> minLimits =
|
||||
List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1));
|
||||
final double probStop = 0.13;
|
||||
final double[] numTypesCdf = buildCdf(0, 0.05, 0.1, 0.85);
|
||||
final double[] numTypesCdf = buildCdf(0, 0.05, 0.1, 0.8, 0.05);
|
||||
final double probStart = 0.87;
|
||||
|
||||
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
|
||||
@@ -528,7 +536,7 @@ public class WorkCountTrackerTest {
|
||||
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 = buildWorkTypeCdf(.1, 0.5, 0.35, 0.05);
|
||||
final double[] cdf = buildWorkTypeCdf(.1, 0, 0.5, 0.35, 0.05);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -548,7 +556,7 @@ public class WorkCountTrackerTest {
|
||||
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 = buildWorkTypeCdf(0.01, 0.49, 0.1, 0.4);
|
||||
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.4, 0.1, 0.4);
|
||||
final double[] numTypesCdf = buildCdf(0.7, 0.3);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -576,11 +584,13 @@ public class WorkCountTrackerTest {
|
||||
startPendingJobs(jobs);
|
||||
|
||||
for (Pair<Integer, Integer> run : resultRunning) {
|
||||
assertWithMessage("Incorrect running result for work type " + run.first)
|
||||
assertWithMessage(
|
||||
"Incorrect running result for work type " + workTypeToString(run.first))
|
||||
.that(jobs.running.get(run.first)).isEqualTo(run.second);
|
||||
}
|
||||
for (Pair<Integer, Integer> pend : resultPending) {
|
||||
assertWithMessage("Incorrect pending result for work type " + pend.first)
|
||||
assertWithMessage(
|
||||
"Incorrect pending result for work type " + workTypeToString(pend.first))
|
||||
.that(jobs.pending.get(pend.first)).isEqualTo(pend.second);
|
||||
}
|
||||
}
|
||||
@@ -938,10 +948,15 @@ public class WorkCountTrackerTest {
|
||||
assertThat(jobs.running.get(WORK_TYPE_TOP)).isEqualTo(6);
|
||||
assertThat(jobs.running.get(WORK_TYPE_EJ)).isEqualTo(1);
|
||||
assertThat(jobs.running.get(WORK_TYPE_BG)).isEqualTo(1);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(4);
|
||||
// If run the TOP jobs as TOP first, and a TOP|EJ job as EJ, then we'll have 4 TOP jobs
|
||||
// remaining.
|
||||
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isAtLeast(4);
|
||||
// If we end up running the TOP|EJ jobs as TOP first, then we'll have 5 TOP jobs remaining.
|
||||
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isAtMost(5);
|
||||
// Can't equate pending EJ since some could be running as TOP and BG
|
||||
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isAtLeast(2);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_BG)).isEqualTo(9);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_BG)).isAtLeast(8);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_BG)).isAtMost(9);
|
||||
|
||||
// Stop all jobs
|
||||
jobs.maybeFinishJobs(1);
|
||||
@@ -975,7 +990,7 @@ public class WorkCountTrackerTest {
|
||||
assertThat(jobs.running.get(WORK_TYPE_EJ)).isAtLeast(1);
|
||||
assertThat(jobs.running.get(WORK_TYPE_BG)).isEqualTo(1);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_TOP)).isEqualTo(0);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isAtLeast(2);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_EJ)).isAtLeast(1);
|
||||
assertThat(jobs.pending.get(WORK_TYPE_BG)).isEqualTo(4);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ 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_FGS;
|
||||
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_TOP;
|
||||
import static com.android.server.job.JobConcurrencyManager.workTypeToString;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
@@ -44,10 +46,12 @@ 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_FGS = "concurrency_max_fgs_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_FGS = "concurrency_min_fgs_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,15 +63,17 @@ public class WorkTypeConfigTest {
|
||||
|
||||
private void resetConfig() {
|
||||
// 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);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_TOTAL, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_TOP, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_FGS, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_EJ, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_BG, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_BGUSER, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_TOP, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_FGS, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_EJ, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BG, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BGUSER, null, false);
|
||||
}
|
||||
|
||||
private void check(@Nullable DeviceConfig.Properties config,
|
||||
@@ -103,10 +109,12 @@ public class WorkTypeConfigTest {
|
||||
|
||||
assertEquals(expectedTotal, counts.getMaxTotal());
|
||||
for (Pair<Integer, Integer> min : expectedMinLimits) {
|
||||
assertEquals((int) min.second, counts.getMinReserved(min.first));
|
||||
assertEquals("Incorrect min value for " + workTypeToString(min.first),
|
||||
(int) min.second, counts.getMinReserved(min.first));
|
||||
}
|
||||
for (Pair<Integer, Integer> max : expectedMaxLimits) {
|
||||
assertEquals((int) max.second, counts.getMax(max.first));
|
||||
assertEquals("Incorrect max value for " + workTypeToString(max.first),
|
||||
(int) max.second, counts.getMax(max.first));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,6 +201,14 @@ public class WorkTypeConfigTest {
|
||||
/* 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*/ 10,
|
||||
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
|
||||
Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
|
||||
/* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)),
|
||||
/*expected*/ true, 10,
|
||||
/* min */ List.of(Pair.create(WORK_TYPE_TOP, 3), Pair.create(WORK_TYPE_FGS, 2),
|
||||
Pair.create(WORK_TYPE_EJ, 1), Pair.create(WORK_TYPE_BG, 1)),
|
||||
/* max */ List.of(Pair.create(WORK_TYPE_FGS, 3)));
|
||||
check(null, /*default*/ 15,
|
||||
/* min */ List.of(Pair.create(WORK_TYPE_BG, 15)),
|
||||
/* max */ List.of(Pair.create(WORK_TYPE_BG, 15)),
|
||||
@@ -289,5 +305,30 @@ public class WorkTypeConfigTest {
|
||||
/*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)));
|
||||
|
||||
check(new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER)
|
||||
.setInt(KEY_MAX_TOTAL, 16)
|
||||
.setInt(KEY_MAX_TOP, 16)
|
||||
.setInt(KEY_MIN_TOP, 1)
|
||||
.setInt(KEY_MAX_FGS, 15)
|
||||
.setInt(KEY_MIN_FGS, 2)
|
||||
.setInt(KEY_MAX_EJ, 14)
|
||||
.setInt(KEY_MIN_EJ, 3)
|
||||
.setInt(KEY_MAX_BG, 13)
|
||||
.setInt(KEY_MIN_BG, 4)
|
||||
.setInt(KEY_MAX_BGUSER, 12)
|
||||
.setInt(KEY_MIN_BGUSER, 5)
|
||||
.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_FGS, 2),
|
||||
Pair.create(WORK_TYPE_EJ, 3),
|
||||
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 5)),
|
||||
/* max */
|
||||
List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15),
|
||||
Pair.create(WORK_TYPE_EJ, 14),
|
||||
Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 12)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user