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:
Kweku Adams
2021-03-07 04:17:35 +00:00
committed by Automerger Merge Worker
3 changed files with 153 additions and 62 deletions

View File

@@ -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) {

View File

@@ -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. */

View File

@@ -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)));
}
}