Loading apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +82 −36 Original line number Original line Diff line number Diff line Loading @@ -102,14 +102,19 @@ class JobConcurrencyManager { * can run as a background job. * can run as a background job. */ */ static final int WORK_TYPE_BG = 1 << 3; 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}, * 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, * {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a completely background user, * so can run as a background user job. * 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 @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; private static final int ALL_WORK_TYPES = (1 << NUM_WORK_TYPES) - 1; @IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = { @IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = { Loading @@ -118,6 +123,7 @@ class JobConcurrencyManager { WORK_TYPE_FGS, WORK_TYPE_FGS, WORK_TYPE_EJ, WORK_TYPE_EJ, WORK_TYPE_BG, WORK_TYPE_BG, WORK_TYPE_BGUSER_IMPORTANT, WORK_TYPE_BGUSER WORK_TYPE_BGUSER }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) Loading @@ -139,6 +145,8 @@ class JobConcurrencyManager { return "BG"; return "BG"; case WORK_TYPE_BGUSER: case WORK_TYPE_BGUSER: return "BGUSER"; return "BGUSER"; case WORK_TYPE_BGUSER_IMPORTANT: return "BGUSER_IMPORTANT"; default: default: return "WORK(" + workType + ")"; return "WORK(" + workType + ")"; } } Loading @@ -164,30 +172,40 @@ class JobConcurrencyManager { new WorkTypeConfig("screen_on_normal", 11, new WorkTypeConfig("screen_on_normal", 11, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_FGS, 1), 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 // 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, new WorkTypeConfig("screen_on_moderate", 9, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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, 2)), Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_on_low", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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, new WorkTypeConfig("screen_on_critical", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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 = private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF = Loading @@ -195,30 +213,40 @@ class JobConcurrencyManager { new WorkTypeConfig("screen_off_normal", 15, new WorkTypeConfig("screen_off_normal", 15, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_moderate", 15, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_low", 9, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_critical", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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)) ) ) ); ); Loading Loading @@ -823,17 +851,22 @@ class JobConcurrencyManager { // Only expedited jobs can replace expedited jobs. // Only expedited jobs can replace expedited jobs. if (js.shouldTreatAsExpeditedJob()) { if (js.shouldTreatAsExpeditedJob()) { // Keep fg/bg user distinction. // Keep fg/bg user distinction. if (workType == WORK_TYPE_BGUSER) { if (workType == WORK_TYPE_BGUSER_IMPORTANT || workType == WORK_TYPE_BGUSER) { // For now, let any bg user job replace a bg user expedited job. // Let any important 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_IMPORTANT) > 0) { if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_BGUSER) > 0) { return "blocking " + workTypeToString(WORK_TYPE_BGUSER_IMPORTANT) + " queue"; return "blocking " + workTypeToString(workType) + " queue"; } } } else { // 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) { if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0 return "blocking " + workTypeToString(workType) + " queue"; && 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 // Easy check. If there are pending jobs of the same work type, then we know that Loading Loading @@ -1017,6 +1050,7 @@ class JobConcurrencyManager { int getJobWorkTypes(@NonNull JobStatus js) { int getJobWorkTypes(@NonNull JobStatus js) { int classification = 0; int classification = 0; if (shouldRunAsFgUserJob(js)) { if (shouldRunAsFgUserJob(js)) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { classification |= WORK_TYPE_TOP; classification |= WORK_TYPE_TOP; Loading @@ -1030,7 +1064,11 @@ class JobConcurrencyManager { classification |= WORK_TYPE_EJ; classification |= WORK_TYPE_EJ; } } } else { } 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; classification |= WORK_TYPE_BGUSER; } } Loading @@ -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_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "max_bg_"; private static final String KEY_PREFIX_MAX_BGUSER = private static final String KEY_PREFIX_MAX_BGUSER = CONFIG_KEY_PREFIX_CONCURRENCY + "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_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_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_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_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "min_bg_"; private static final String KEY_PREFIX_MIN_BGUSER = private static final String KEY_PREFIX_MIN_BGUSER = CONFIG_KEY_PREFIX_CONCURRENCY + "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 final String mConfigIdentifier; private int mMaxTotal; private int mMaxTotal; Loading Loading @@ -1108,6 +1150,10 @@ class JobConcurrencyManager { properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier, properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier, mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal)))); mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal)))); mMaxAllowedSlots.put(WORK_TYPE_BG, maxBg); 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, final int maxBgUser = Math.max(1, Math.min(mMaxTotal, properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal)))); mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal)))); Loading Loading @@ -1139,6 +1185,11 @@ class JobConcurrencyManager { mDefaultMinReservedSlots.get(WORK_TYPE_BG)))); mDefaultMinReservedSlots.get(WORK_TYPE_BG)))); mMinReservedSlots.put(WORK_TYPE_BG, minBg); mMinReservedSlots.put(WORK_TYPE_BG, minBg); remaining -= 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)] // Ensure bg user is in the range [0, min(maxBgUser, remaining)] final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining), final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining), properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, Loading Loading @@ -1176,6 +1227,10 @@ class JobConcurrencyManager { .println(); .println(); pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG)) pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG)) .println(); .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, pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_BGUSER)).println(); mMinReservedSlots.get(WORK_TYPE_BGUSER)).println(); pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, Loading Loading @@ -1276,19 +1331,10 @@ class JobConcurrencyManager { void setConfig(@NonNull WorkTypeConfig workTypeConfig) { void setConfig(@NonNull WorkTypeConfig workTypeConfig) { mConfigMaxTotal = workTypeConfig.getMaxTotal(); mConfigMaxTotal = workTypeConfig.getMaxTotal(); mConfigNumReservedSlots.put(WORK_TYPE_TOP, for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) { workTypeConfig.getMinReserved(WORK_TYPE_TOP)); mConfigNumReservedSlots.put(workType, workTypeConfig.getMinReserved(workType)); mConfigNumReservedSlots.put(WORK_TYPE_FGS, mConfigAbsoluteMaxSlots.put(workType, workTypeConfig.getMax(workType)); 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)); mNumUnspecializedRemaining = mConfigMaxTotal; mNumUnspecializedRemaining = mConfigMaxTotal; for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) { for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) { Loading services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java +54 −20 File changed.Preview size limit exceeded, changes collapsed. Show changes services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java +17 −6 Original line number Original line Diff line number Diff line Loading @@ -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_BG; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER; 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_EJ; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_FGS; 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.WORK_TYPE_TOP; Loading Loading @@ -49,11 +50,13 @@ public class WorkTypeConfigTest { private static final String KEY_MAX_FGS = "concurrency_max_fgs_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_EJ = "concurrency_max_ej_test"; private static final String KEY_MAX_BG = "concurrency_max_bg_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_MAX_BGUSER = "concurrency_max_bguser_test"; private static final String KEY_MIN_TOP = "concurrency_min_top_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_FGS = "concurrency_min_fgs_test"; private static final String KEY_MIN_EJ = "concurrency_min_ej_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_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"; private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test"; @After @After Loading @@ -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_FGS, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_EJ, 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_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_MAX_BGUSER, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_TOP, 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_FGS, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_EJ, 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_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); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BGUSER, null, false); } } Loading Loading @@ -316,19 +323,23 @@ public class WorkTypeConfigTest { .setInt(KEY_MIN_EJ, 3) .setInt(KEY_MIN_EJ, 3) .setInt(KEY_MAX_BG, 13) .setInt(KEY_MAX_BG, 13) .setInt(KEY_MIN_BG, 4) .setInt(KEY_MIN_BG, 4) .setInt(KEY_MAX_BGUSER, 12) .setInt(KEY_MAX_BGUSER_IMPORTANT, 12) .setInt(KEY_MIN_BGUSER, 5) .setInt(KEY_MIN_BGUSER_IMPORTANT, 5) .setInt(KEY_MAX_BGUSER, 11) .setInt(KEY_MIN_BGUSER, 6) .build(), .build(), /*default*/ 9, /*default*/ 9, /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)), /*expected*/ true, 16, /*expected*/ true, 16, /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_FGS, 2), /* 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_EJ, 3), Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 5)), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 5), Pair.create(WORK_TYPE_BGUSER, 6)), /* max */ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15), List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15), Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 12))); Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 12), Pair.create(WORK_TYPE_BGUSER, 11))); } } } } Loading
apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +82 −36 Original line number Original line Diff line number Diff line Loading @@ -102,14 +102,19 @@ class JobConcurrencyManager { * can run as a background job. * can run as a background job. */ */ static final int WORK_TYPE_BG = 1 << 3; 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}, * 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, * {@link #WORK_TYPE_FGS}, or {@link #WORK_TYPE_EJ}, but is for a completely background user, * so can run as a background user job. * 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 @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; private static final int ALL_WORK_TYPES = (1 << NUM_WORK_TYPES) - 1; @IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = { @IntDef(prefix = {"WORK_TYPE_"}, flag = true, value = { Loading @@ -118,6 +123,7 @@ class JobConcurrencyManager { WORK_TYPE_FGS, WORK_TYPE_FGS, WORK_TYPE_EJ, WORK_TYPE_EJ, WORK_TYPE_BG, WORK_TYPE_BG, WORK_TYPE_BGUSER_IMPORTANT, WORK_TYPE_BGUSER WORK_TYPE_BGUSER }) }) @Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE) Loading @@ -139,6 +145,8 @@ class JobConcurrencyManager { return "BG"; return "BG"; case WORK_TYPE_BGUSER: case WORK_TYPE_BGUSER: return "BGUSER"; return "BGUSER"; case WORK_TYPE_BGUSER_IMPORTANT: return "BGUSER_IMPORTANT"; default: default: return "WORK(" + workType + ")"; return "WORK(" + workType + ")"; } } Loading @@ -164,30 +172,40 @@ class JobConcurrencyManager { new WorkTypeConfig("screen_on_normal", 11, new WorkTypeConfig("screen_on_normal", 11, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 2), Pair.create(WORK_TYPE_FGS, 1), 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 // 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, new WorkTypeConfig("screen_on_moderate", 9, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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, 2)), Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_on_low", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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, new WorkTypeConfig("screen_on_critical", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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 = private static final WorkConfigLimitsPerMemoryTrimLevel CONFIG_LIMITS_SCREEN_OFF = Loading @@ -195,30 +213,40 @@ class JobConcurrencyManager { new WorkTypeConfig("screen_off_normal", 15, new WorkTypeConfig("screen_off_normal", 15, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_moderate", 15, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 6), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 3), Pair.create(WORK_TYPE_BG, 2), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_low", 9, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 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)), Pair.create(WORK_TYPE_EJ, 2), Pair.create(WORK_TYPE_BG, 1)), // defaultMax // 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, new WorkTypeConfig("screen_off_critical", 6, // defaultMin // defaultMin List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), List.of(Pair.create(WORK_TYPE_TOP, 4), Pair.create(WORK_TYPE_FGS, 1), Pair.create(WORK_TYPE_EJ, 1)), Pair.create(WORK_TYPE_EJ, 1)), // defaultMax // 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)) ) ) ); ); Loading Loading @@ -823,17 +851,22 @@ class JobConcurrencyManager { // Only expedited jobs can replace expedited jobs. // Only expedited jobs can replace expedited jobs. if (js.shouldTreatAsExpeditedJob()) { if (js.shouldTreatAsExpeditedJob()) { // Keep fg/bg user distinction. // Keep fg/bg user distinction. if (workType == WORK_TYPE_BGUSER) { if (workType == WORK_TYPE_BGUSER_IMPORTANT || workType == WORK_TYPE_BGUSER) { // For now, let any bg user job replace a bg user expedited job. // Let any important 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_IMPORTANT) > 0) { if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_BGUSER) > 0) { return "blocking " + workTypeToString(WORK_TYPE_BGUSER_IMPORTANT) + " queue"; return "blocking " + workTypeToString(workType) + " queue"; } } } else { // 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) { if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0 return "blocking " + workTypeToString(workType) + " queue"; && 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 // Easy check. If there are pending jobs of the same work type, then we know that Loading Loading @@ -1017,6 +1050,7 @@ class JobConcurrencyManager { int getJobWorkTypes(@NonNull JobStatus js) { int getJobWorkTypes(@NonNull JobStatus js) { int classification = 0; int classification = 0; if (shouldRunAsFgUserJob(js)) { if (shouldRunAsFgUserJob(js)) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { if (js.lastEvaluatedPriority >= JobInfo.PRIORITY_TOP_APP) { classification |= WORK_TYPE_TOP; classification |= WORK_TYPE_TOP; Loading @@ -1030,7 +1064,11 @@ class JobConcurrencyManager { classification |= WORK_TYPE_EJ; classification |= WORK_TYPE_EJ; } } } else { } 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; classification |= WORK_TYPE_BGUSER; } } Loading @@ -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_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "max_bg_"; private static final String KEY_PREFIX_MAX_BGUSER = private static final String KEY_PREFIX_MAX_BGUSER = CONFIG_KEY_PREFIX_CONCURRENCY + "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_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_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_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_BG = CONFIG_KEY_PREFIX_CONCURRENCY + "min_bg_"; private static final String KEY_PREFIX_MIN_BGUSER = private static final String KEY_PREFIX_MIN_BGUSER = CONFIG_KEY_PREFIX_CONCURRENCY + "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 final String mConfigIdentifier; private int mMaxTotal; private int mMaxTotal; Loading Loading @@ -1108,6 +1150,10 @@ class JobConcurrencyManager { properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier, properties.getInt(KEY_PREFIX_MAX_BG + mConfigIdentifier, mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal)))); mDefaultMaxAllowedSlots.get(WORK_TYPE_BG, mMaxTotal)))); mMaxAllowedSlots.put(WORK_TYPE_BG, maxBg); 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, final int maxBgUser = Math.max(1, Math.min(mMaxTotal, properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, properties.getInt(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal)))); mDefaultMaxAllowedSlots.get(WORK_TYPE_BGUSER, mMaxTotal)))); Loading Loading @@ -1139,6 +1185,11 @@ class JobConcurrencyManager { mDefaultMinReservedSlots.get(WORK_TYPE_BG)))); mDefaultMinReservedSlots.get(WORK_TYPE_BG)))); mMinReservedSlots.put(WORK_TYPE_BG, minBg); mMinReservedSlots.put(WORK_TYPE_BG, minBg); remaining -= 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)] // Ensure bg user is in the range [0, min(maxBgUser, remaining)] final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining), final int minBgUser = Math.max(0, Math.min(Math.min(maxBgUser, remaining), properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, properties.getInt(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, Loading Loading @@ -1176,6 +1227,10 @@ class JobConcurrencyManager { .println(); .println(); pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG)) pw.print(KEY_PREFIX_MAX_BG + mConfigIdentifier, mMaxAllowedSlots.get(WORK_TYPE_BG)) .println(); .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, pw.print(KEY_PREFIX_MIN_BGUSER + mConfigIdentifier, mMinReservedSlots.get(WORK_TYPE_BGUSER)).println(); mMinReservedSlots.get(WORK_TYPE_BGUSER)).println(); pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, pw.print(KEY_PREFIX_MAX_BGUSER + mConfigIdentifier, Loading Loading @@ -1276,19 +1331,10 @@ class JobConcurrencyManager { void setConfig(@NonNull WorkTypeConfig workTypeConfig) { void setConfig(@NonNull WorkTypeConfig workTypeConfig) { mConfigMaxTotal = workTypeConfig.getMaxTotal(); mConfigMaxTotal = workTypeConfig.getMaxTotal(); mConfigNumReservedSlots.put(WORK_TYPE_TOP, for (int workType = 1; workType < ALL_WORK_TYPES; workType <<= 1) { workTypeConfig.getMinReserved(WORK_TYPE_TOP)); mConfigNumReservedSlots.put(workType, workTypeConfig.getMinReserved(workType)); mConfigNumReservedSlots.put(WORK_TYPE_FGS, mConfigAbsoluteMaxSlots.put(workType, workTypeConfig.getMax(workType)); 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)); mNumUnspecializedRemaining = mConfigMaxTotal; mNumUnspecializedRemaining = mConfigMaxTotal; for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) { for (int i = mNumRunningJobs.size() - 1; i >= 0; --i) { Loading
services/tests/servicestests/src/com/android/server/job/WorkCountTrackerTest.java +54 −20 File changed.Preview size limit exceeded, changes collapsed. Show changes
services/tests/servicestests/src/com/android/server/job/WorkTypeConfigTest.java +17 −6 Original line number Original line Diff line number Diff line Loading @@ -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_BG; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_BGUSER; 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_EJ; import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_FGS; 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.WORK_TYPE_TOP; Loading Loading @@ -49,11 +50,13 @@ public class WorkTypeConfigTest { private static final String KEY_MAX_FGS = "concurrency_max_fgs_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_EJ = "concurrency_max_ej_test"; private static final String KEY_MAX_BG = "concurrency_max_bg_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_MAX_BGUSER = "concurrency_max_bguser_test"; private static final String KEY_MIN_TOP = "concurrency_min_top_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_FGS = "concurrency_min_fgs_test"; private static final String KEY_MIN_EJ = "concurrency_min_ej_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_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"; private static final String KEY_MIN_BGUSER = "concurrency_min_bguser_test"; @After @After Loading @@ -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_FGS, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MAX_EJ, 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_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_MAX_BGUSER, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_TOP, 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_FGS, null, false); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_EJ, 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_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); DeviceConfig.setProperty(DeviceConfig.NAMESPACE_JOB_SCHEDULER, KEY_MIN_BGUSER, null, false); } } Loading Loading @@ -316,19 +323,23 @@ public class WorkTypeConfigTest { .setInt(KEY_MIN_EJ, 3) .setInt(KEY_MIN_EJ, 3) .setInt(KEY_MAX_BG, 13) .setInt(KEY_MAX_BG, 13) .setInt(KEY_MIN_BG, 4) .setInt(KEY_MIN_BG, 4) .setInt(KEY_MAX_BGUSER, 12) .setInt(KEY_MAX_BGUSER_IMPORTANT, 12) .setInt(KEY_MIN_BGUSER, 5) .setInt(KEY_MIN_BGUSER_IMPORTANT, 5) .setInt(KEY_MAX_BGUSER, 11) .setInt(KEY_MIN_BGUSER, 6) .build(), .build(), /*default*/ 9, /*default*/ 9, /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* min */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)), /* max */ List.of(Pair.create(WORK_TYPE_BG, 9)), /*expected*/ true, 16, /*expected*/ true, 16, /* min */ List.of(Pair.create(WORK_TYPE_TOP, 1), Pair.create(WORK_TYPE_FGS, 2), /* 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_EJ, 3), Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BG, 4), Pair.create(WORK_TYPE_BGUSER, 5)), Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 5), Pair.create(WORK_TYPE_BGUSER, 6)), /* max */ /* max */ List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15), List.of(Pair.create(WORK_TYPE_TOP, 16), Pair.create(WORK_TYPE_FGS, 15), Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_EJ, 14), Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BG, 13), Pair.create(WORK_TYPE_BGUSER, 12))); Pair.create(WORK_TYPE_BGUSER_IMPORTANT, 12), Pair.create(WORK_TYPE_BGUSER, 11))); } } } }