Merge "Reserve execution slot for important bg user jobs." into sc-dev am: 1d8242ec01
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/13759743 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: I8521c13847f5dcef7c25425e96889e4963d75f6d
This commit is contained in:
@@ -102,14 +102,19 @@ class JobConcurrencyManager {
|
||||
* can run as a background job.
|
||||
*/
|
||||
static final int WORK_TYPE_BG = 1 << 3;
|
||||
/**
|
||||
* The job is for an app in a {@link ActivityManager#PROCESS_STATE_FOREGROUND_SERVICE} or higher
|
||||
* state, or is allowed to run as an expedited job, but is for a completely background user.
|
||||
*/
|
||||
static final int WORK_TYPE_BGUSER_IMPORTANT = 1 << 4;
|
||||
/**
|
||||
* 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;
|
||||
static final int WORK_TYPE_BGUSER = 1 << 5;
|
||||
@VisibleForTesting
|
||||
static final int NUM_WORK_TYPES = 5;
|
||||
static final int NUM_WORK_TYPES = 6;
|
||||
private static final int ALL_WORK_TYPES = (1 << NUM_WORK_TYPES) - 1;
|
||||
|
||||
@IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = {
|
||||
@@ -118,6 +123,7 @@ class JobConcurrencyManager {
|
||||
WORK_TYPE_FGS,
|
||||
WORK_TYPE_EJ,
|
||||
WORK_TYPE_BG,
|
||||
WORK_TYPE_BGUSER_IMPORTANT,
|
||||
WORK_TYPE_BGUSER
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -139,6 +145,8 @@ class JobConcurrencyManager {
|
||||
return "BG";
|
||||
case WORK_TYPE_BGUSER:
|
||||
return "BGUSER";
|
||||
case WORK_TYPE_BGUSER_IMPORTANT:
|
||||
return "BGUSER_IMPORTANT";
|
||||
default:
|
||||
return "WORK(" + workType + ")";
|
||||
}
|
||||
@@ -164,30 +172,40 @@ class JobConcurrencyManager {
|
||||
new WorkTypeConfig("screen_on_normal", 11,
|
||||
// defaultMin
|
||||
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)),
|
||||
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 4))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 6),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
|
||||
Pair.create(WORK_TYPE_BGUSER, 3))
|
||||
),
|
||||
new WorkTypeConfig("screen_on_moderate", 9,
|
||||
// defaultMin
|
||||
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)),
|
||||
Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 4),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
),
|
||||
new WorkTypeConfig("screen_on_low", 6,
|
||||
// defaultMin
|
||||
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))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
),
|
||||
new WorkTypeConfig("screen_on_critical", 6,
|
||||
// defaultMin
|
||||
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))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
)
|
||||
);
|
||||
private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF =
|
||||
@@ -195,30 +213,40 @@ class JobConcurrencyManager {
|
||||
new WorkTypeConfig("screen_off_normal", 15,
|
||||
// defaultMin
|
||||
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)),
|
||||
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 6), Pair.create(WORK_TYPE_BGUSER, 4))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 6),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 2),
|
||||
Pair.create(WORK_TYPE_BGUSER, 3))
|
||||
),
|
||||
new WorkTypeConfig("screen_off_moderate", 15,
|
||||
// defaultMin
|
||||
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)),
|
||||
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)),
|
||||
// defaultMax
|
||||
List.of(Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 2))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 4),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
),
|
||||
new WorkTypeConfig("screen_off_low", 9,
|
||||
// defaultMin
|
||||
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))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
),
|
||||
new WorkTypeConfig("screen_off_critical", 6,
|
||||
// defaultMin
|
||||
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))
|
||||
List.of(Pair.create(WORK_TYPE_BG, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1),
|
||||
Pair.create(WORK_TYPE_BGUSER, 1))
|
||||
)
|
||||
);
|
||||
|
||||
@@ -823,17 +851,22 @@ class JobConcurrencyManager {
|
||||
// Only expedited jobs can replace expedited jobs.
|
||||
if (js.shouldTreatAsExpeditedJob()) {
|
||||
// Keep fg/bg user distinction.
|
||||
if (workType == WORK_TYPE_BGUSER) {
|
||||
// For now, let any bg user job replace a bg user expedited job.
|
||||
// TODO: limit to ej once we have dedicated bg user ej slots.
|
||||
if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_BGUSER) > 0) {
|
||||
return "blocking " + workTypeToString(workType) + " queue";
|
||||
if (workType == WORK_TYPE_BGUSER_IMPORTANT || workType == WORK_TYPE_BGUSER) {
|
||||
// Let any important bg user job replace a bg user expedited job.
|
||||
if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_BGUSER_IMPORTANT) > 0) {
|
||||
return "blocking " + workTypeToString(WORK_TYPE_BGUSER_IMPORTANT) + " queue";
|
||||
}
|
||||
} else {
|
||||
if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) {
|
||||
return "blocking " + workTypeToString(workType) + " queue";
|
||||
// Let a fg user EJ preempt a bg user EJ (if able), but not the other way around.
|
||||
if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0
|
||||
&& mWorkCountTracker.canJobStart(WORK_TYPE_EJ, workType)
|
||||
!= WORK_TYPE_NONE) {
|
||||
return "blocking " + workTypeToString(WORK_TYPE_EJ) + " queue";
|
||||
}
|
||||
} else if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) {
|
||||
return "blocking " + workTypeToString(WORK_TYPE_EJ) + " queue";
|
||||
}
|
||||
// No other pending EJs. Return null so we don't let regular jobs preempt an EJ.
|
||||
return null;
|
||||
}
|
||||
|
||||
// Easy check. If there are pending jobs of the same work type, then we know that
|
||||
@@ -1017,6 +1050,7 @@ class JobConcurrencyManager {
|
||||
|
||||
int getJobWorkTypes(@NonNull JobStatus js) {
|
||||
int classification = 0;
|
||||
|
||||
if (shouldRunAsFgUserJob(js)) {
|
||||
if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) {
|
||||
classification |= WORK_TYPE_TOP;
|
||||
@@ -1030,7 +1064,11 @@ class JobConcurrencyManager {
|
||||
classification |= WORK_TYPE_EJ;
|
||||
}
|
||||
} else {
|
||||
// TODO(171305774): create dedicated slots for EJs of bg user
|
||||
if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_FOREGROUND_SERVICE
|
||||
|| js.shouldTreatAsExpeditedJob()) {
|
||||
classification |= WORK_TYPE_BGUSER_IMPORTANT;
|
||||
}
|
||||
// BGUSER_IMPORTANT jobs can also run as BGUSER jobs, so not an 'else' here.
|
||||
classification |= WORK_TYPE_BGUSER;
|
||||
}
|
||||
|
||||
@@ -1047,12 +1085,16 @@ class JobConcurrencyManager {
|
||||
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_MAX_BGUSER_IMPORTANT =
|
||||
CONFIG_KEY_PREFIX_CONCURRENCY + "max_bguser_important_";
|
||||
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 =
|
||||
CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_";
|
||||
private static final String KEY_PREFIX_MIN_BGUSER_IMPORTANT =
|
||||
CONFIG_KEY_PREFIX_CONCURRENCY + "min_bguser_important_";
|
||||
private final String mConfigIdentifier;
|
||||
|
||||
private int mMaxTotal;
|
||||
@@ -1108,6 +1150,10 @@ class JobConcurrencyManager {
|
||||
properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal))));
|
||||
mMaxAllowedSlots.put(WORK_TYPE_BG, maxBg);
|
||||
final int maxBgUserImp = Math.max(1, Math.min(mMaxTotal,
|
||||
properties.getInt(KEY_PREFIX_MAX_BGUSER_IMPORTANT + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, mMaxTotal))));
|
||||
mMaxAllowedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, maxBgUserImp);
|
||||
final int maxBgUser = Math.max(1, Math.min(mMaxTotal,
|
||||
properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
|
||||
mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal))));
|
||||
@@ -1139,6 +1185,11 @@ class JobConcurrencyManager {
|
||||
mDefaultMinReservedSlots.get(WORK_TYPE_BG))));
|
||||
mMinReservedSlots.put(WORK_TYPE_BG, minBg);
|
||||
remaining -= minBg;
|
||||
// Ensure bg user imp is in the range [0, min(maxBgUserImp, remaining)]
|
||||
final int minBgUserImp = Math.max(0, Math.min(Math.min(maxBgUserImp, remaining),
|
||||
properties.getInt(KEY_PREFIX_MIN_BGUSER_IMPORTANT + mConfigIdentifier,
|
||||
mDefaultMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT, 0))));
|
||||
mMinReservedSlots.put(WORK_TYPE_BGUSER_IMPORTANT, minBgUserImp);
|
||||
// Ensure bg user is in the range [0, min(maxBgUser, remaining)]
|
||||
final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining),
|
||||
properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
|
||||
@@ -1176,6 +1227,10 @@ class JobConcurrencyManager {
|
||||
.println();
|
||||
pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG))
|
||||
.println();
|
||||
pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
|
||||
mMinReservedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
|
||||
pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
|
||||
mMaxAllowedSlots.get(WORK_TYPE_BGUSER_IMPORTANT)).println();
|
||||
pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier,
|
||||
mMinReservedSlots.get(WORK_TYPE_BGUSER)).println();
|
||||
pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier,
|
||||
@@ -1276,19 +1331,10 @@ class JobConcurrencyManager {
|
||||
|
||||
void setConfig(@NonNull WorkTypeConfig workTypeConfig) {
|
||||
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));
|
||||
for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) {
|
||||
mConfigNumReservedSlots.put(workType, workTypeConfig.getMinReserved(workType));
|
||||
mConfigAbsoluteMaxSlots.put(workType, workTypeConfig.getMax(workType));
|
||||
}
|
||||
|
||||
mNumUnspecializedRemaining = mConfigMaxTotal;
|
||||
for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) {
|
||||
|
||||
@@ -19,6 +19,7 @@ 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_BGUSER_IMPORTANT;
|
||||
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;
|
||||
@@ -29,6 +30,7 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static com.google.common.truth.Truth.assertWithMessage;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.SparseIntArray;
|
||||
|
||||
@@ -52,11 +54,11 @@ import java.util.Random;
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
public class WorkCountTrackerTest {
|
||||
private static final String TAG = "WorkerCountTrackerTest";
|
||||
private static final String TAG = "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, 1.0 / NUM_WORK_TYPES, 1.0 / NUM_WORK_TYPES);
|
||||
|
||||
private Random mRandom;
|
||||
private WorkCountTracker mWorkCountTracker;
|
||||
@@ -69,12 +71,15 @@ public class WorkCountTrackerTest {
|
||||
|
||||
@NonNull
|
||||
private static double[] buildWorkTypeCdf(
|
||||
double pTop, double pFgs, double pEj, double pBg, double pBgUser) {
|
||||
return buildCdf(pTop, pFgs, pEj, pBg, pBgUser);
|
||||
double pTop, double pFgs, double pEj, double pBg, double pBgUserImp, double pBgUser) {
|
||||
return buildCdf(pTop, pFgs, pEj, pBg, pBgUserImp, pBgUser);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static double[] buildCdf(double... probs) {
|
||||
if (probs.length == 0) {
|
||||
throw new IllegalArgumentException("Must supply at least one probability");
|
||||
}
|
||||
double[] cdf = new double[probs.length];
|
||||
double sum = 0;
|
||||
|
||||
@@ -84,7 +89,9 @@ public class WorkCountTrackerTest {
|
||||
}
|
||||
|
||||
if (Double.compare(1, sum) != 0) {
|
||||
throw new IllegalArgumentException("probabilities don't sum to one: " + sum);
|
||||
Log.e(TAG, "probabilities don't sum to one: " + sum);
|
||||
// 1.0/6 doesn't work well in code :/
|
||||
cdf[cdf.length - 1] = 1;
|
||||
}
|
||||
return cdf;
|
||||
}
|
||||
@@ -111,6 +118,8 @@ public class WorkCountTrackerTest {
|
||||
case 3:
|
||||
return WORK_TYPE_BG;
|
||||
case 4:
|
||||
return WORK_TYPE_BGUSER_IMPORTANT;
|
||||
case 5:
|
||||
return WORK_TYPE_BGUSER;
|
||||
default:
|
||||
throw new IllegalStateException("Unknown work type");
|
||||
@@ -312,7 +321,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, 0.5, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0, 0.5, 0, 0);
|
||||
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -330,7 +339,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, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
|
||||
final double[] numTypesCdf = buildCdf(.75, .2, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -348,7 +357,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, 0, 1.0 / 3, 1.0 / 3);
|
||||
final double[] cdf = buildWorkTypeCdf(1.0 / 3, 0, 0, 1.0 / 3, 0, 1.0 / 3);
|
||||
final double[] numTypesCdf = buildCdf(.05, .95);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -366,7 +375,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, 0.8, .1);
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.8, 0.02, .08);
|
||||
final double[] numTypesCdf = buildCdf(.5, .3, .15, .05);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -384,7 +393,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.85, 0.05, 0, 0.1, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.85, 0.05, 0, 0.1, 0, 0);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -402,7 +411,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, 0.1, .8);
|
||||
final double[] cdf = buildWorkTypeCdf(0.1, 0, 0, 0.1, 0.05, .75);
|
||||
final double[] numTypesCdf = buildCdf(0.5, 0.5);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -421,7 +430,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.8, 0.1, 0, 0.05, 0.05);
|
||||
final double[] cdf = buildWorkTypeCdf(0.8, 0.1, 0, 0.05, 0, 0.05);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -440,7 +449,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, 0.5, 0.5);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.5, 0, 0.5);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -459,7 +468,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, 0.1, 0.9);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.1, 0, 0.9);
|
||||
final double[] numTypesCdf = buildCdf(0.9, 0.1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -478,7 +487,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, 0.9, 0.1);
|
||||
final double[] cdf = buildWorkTypeCdf(0, 0, 0, 0.9, 0, 0.1);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -496,7 +505,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, 0.5, 0, 0);
|
||||
final double[] cdf = buildWorkTypeCdf(0.5, 0, 0.5, 0, 0, 0);
|
||||
final double[] numTypesCdf = buildCdf(0.1, 0.7, 0.2);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -519,7 +528,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.8, 0.05);
|
||||
final double[] numTypesCdf = buildCdf(0, 0.05, 0.1, 0.7, 0.1, 0.05);
|
||||
final double probStart = 0.87;
|
||||
|
||||
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
|
||||
@@ -536,7 +545,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, 0.5, 0.35, 0.05);
|
||||
final double[] cdf = buildWorkTypeCdf(.1, 0, 0.5, 0.35, 0, 0.05);
|
||||
final double[] numTypesCdf = buildCdf(1);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -556,7 +565,28 @@ 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.09, 0.4, 0.1, 0.4);
|
||||
final double[] cdf = buildWorkTypeCdf(0.01, 0.09, 0.4, 0.1, 0, 0.4);
|
||||
final double[] numTypesCdf = buildCdf(0.7, 0.3);
|
||||
final double probStart = 0.5;
|
||||
|
||||
checkRandom(jobs, numTests, totalMax, minLimits, maxLimits, probStart,
|
||||
cdf, numTypesCdf, probStop);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRandom16() {
|
||||
final Jobs jobs = new Jobs();
|
||||
|
||||
final int numTests = 5000;
|
||||
final int totalMax = 7;
|
||||
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_IMPORTANT, 1),
|
||||
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 = buildWorkTypeCdf(0.01, 0.09, 0.25, 0.05, 0.3, 0.3);
|
||||
final double[] numTypesCdf = buildCdf(0.7, 0.3);
|
||||
final double probStart = 0.5;
|
||||
|
||||
@@ -748,6 +778,7 @@ public class WorkCountTrackerTest {
|
||||
/* resPen */ List.of(
|
||||
Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER, 2)));
|
||||
|
||||
Log.d(TAG, "START***#*#*#*#*#*#**#*");
|
||||
// Test multi-types
|
||||
checkSimple(6,
|
||||
/* min */ List.of(Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
|
||||
@@ -764,7 +795,10 @@ public class WorkCountTrackerTest {
|
||||
/* resRun */ List.of(Pair.create(WORK_TYPE_TOP, 2),
|
||||
Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 2)),
|
||||
/* resPen */ List.of(
|
||||
Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 1)));
|
||||
// Not checking BG count because the test starts jobs in random order
|
||||
// and if it tries to start 4 BG jobs (2 will run as EJ from EJ|BG), but
|
||||
// the resulting pending will be 3 BG instead of 4 BG.
|
||||
Pair.create(WORK_TYPE_BGUSER, 1)));
|
||||
}
|
||||
|
||||
/** Tests that the counter updates properly when jobs are stopped. */
|
||||
|
||||
@@ -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_BGUSER_IMPORTANT;
|
||||
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;
|
||||
@@ -49,11 +50,13 @@ public class WorkTypeConfigTest {
|
||||
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_IMPORTANT = "concurrency_max_bguser_important_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_IMPORTANT = "concurrency_min_bguser_important_test";
|
||||
private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test";
|
||||
|
||||
@After
|
||||
@@ -68,11 +71,15 @@ public class WorkTypeConfigTest {
|
||||
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_IMPORTANT, 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_IMPORTANT, null, false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BGUSER, null, false);
|
||||
}
|
||||
|
||||
@@ -316,19 +323,23 @@ public class WorkTypeConfigTest {
|
||||
.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)
|
||||
.setInt(KEY_MAX_BGUSER_IMPORTANT, 12)
|
||||
.setInt(KEY_MIN_BGUSER_IMPORTANT, 5)
|
||||
.setInt(KEY_MAX_BGUSER, 11)
|
||||
.setInt(KEY_MIN_BGUSER, 6)
|
||||
.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)),
|
||||
Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 4),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 5),
|
||||
Pair.create(WORK_TYPE_BGUSER, 6)),
|
||||
/* 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)));
|
||||
Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13),
|
||||
Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 12),
|
||||
Pair.create(WORK_TYPE_BGUSER, 11)));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user