Merge "Make applied flex constraints configurable." into main
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index e06006f..f405083 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -1769,7 +1769,8 @@
@VisibleForTesting
class CcConfig {
- private boolean mFlexIsEnabled = FlexibilityController.FcConfig.DEFAULT_FLEXIBILITY_ENABLED;
+ private boolean mFlexIsEnabled =
+ FlexibilityController.FcConfig.DEFAULT_APPLIED_CONSTRAINTS != 0;
private boolean mShouldReprocessNetworkCapabilities = false;
/**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
index 13a474cc..0e67b9a 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java
@@ -24,7 +24,6 @@
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONNECTIVITY;
-import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE;
import android.annotation.ElapsedRealtimeLong;
@@ -74,17 +73,10 @@
private static final int JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS = CONSTRAINT_CONNECTIVITY;
/** List of all flexible constraints. */
- private static final int FLEXIBLE_CONSTRAINTS =
+ @VisibleForTesting
+ static final int FLEXIBLE_CONSTRAINTS =
JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS | SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
- private static final int NUM_JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS =
- Integer.bitCount(JOB_SPECIFIC_FLEXIBLE_CONSTRAINTS);
-
- static final int NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS =
- Integer.bitCount(SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS);
-
- static final int NUM_FLEXIBLE_CONSTRAINTS = Integer.bitCount(FLEXIBLE_CONSTRAINTS);
-
private static final long NO_LIFECYCLE_END = Long.MAX_VALUE;
/**
@@ -100,9 +92,15 @@
private long mUnseenConstraintGracePeriodMs =
FcConfig.DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS;
- @VisibleForTesting
+ /** Set of constraints supported on this device for flex scheduling. */
+ private final int mSupportedFlexConstraints;
+
@GuardedBy("mLock")
- boolean mFlexibilityEnabled = FcConfig.DEFAULT_FLEXIBILITY_ENABLED;
+ private boolean mFlexibilityEnabled;
+
+ /** Set of constraints that will be used in the flex policy. */
+ @GuardedBy("mLock")
+ private int mAppliedConstraints = FcConfig.DEFAULT_APPLIED_CONSTRAINTS;
private long mMinTimeBetweenFlexibilityAlarmsMs =
FcConfig.DEFAULT_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS;
@@ -118,9 +116,6 @@
*/
private int[] mPercentToDropConstraints;
- @VisibleForTesting
- boolean mDeviceSupportsFlexConstraints;
-
/**
* Keeps track of what flexible constraints are satisfied at the moment.
* Is updated by the other controllers.
@@ -178,7 +173,7 @@
if (!js.hasFlexibilityConstraint()) {
continue;
}
- mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
}
}
@@ -186,15 +181,23 @@
};
private static final int MSG_UPDATE_JOBS = 0;
+ private static final int MSG_UPDATE_JOB = 1;
public FlexibilityController(
JobSchedulerService service, PrefetchController prefetchController) {
super(service);
mHandler = new FcHandler(AppSchedulingModuleThread.get().getLooper());
- mDeviceSupportsFlexConstraints = !mContext.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE);
- mFlexibilityEnabled &= mDeviceSupportsFlexConstraints;
- mFlexibilityTracker = new FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS);
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
+ || mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED)) {
+ // Embedded devices have no user-installable apps. Assume all jobs are critical
+ // and can't be flexed.
+ mSupportedFlexConstraints = 0;
+ } else {
+ // TODO(236261941): handle devices without a battery
+ mSupportedFlexConstraints = FLEXIBLE_CONSTRAINTS;
+ }
+ mFlexibilityEnabled = (mAppliedConstraints & mSupportedFlexConstraints) != 0;
+ mFlexibilityTracker = new FlexibilityTracker(Integer.bitCount(mSupportedFlexConstraints));
mFcConfig = new FcConfig();
mFlexibilityAlarmQueue = new FlexibilityAlarmQueue(
mContext, AppSchedulingModuleThread.get().getLooper());
@@ -218,10 +221,12 @@
public void maybeStartTrackingJobLocked(JobStatus js, JobStatus lastJob) {
if (js.hasFlexibilityConstraint()) {
final long nowElapsed = sElapsedRealtimeClock.millis();
- if (!mDeviceSupportsFlexConstraints) {
+ if (mSupportedFlexConstraints == 0) {
js.setFlexibilityConstraintSatisfied(nowElapsed, true);
return;
}
+ js.setNumAppliedFlexibleConstraints(
+ Integer.bitCount(getRelevantAppliedConstraintsLocked(js)));
js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
mFlexibilityTracker.add(js);
js.setTrackingController(JobStatus.TRACKING_FLEXIBILITY);
@@ -266,6 +271,14 @@
|| mService.isCurrentlyRunningLocked(js);
}
+ @VisibleForTesting
+ @GuardedBy("mLock")
+ int getRelevantAppliedConstraintsLocked(@NonNull JobStatus js) {
+ final int relevantConstraints = SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
+ | (js.canApplyTransportAffinities() ? CONSTRAINT_CONNECTIVITY : 0);
+ return mAppliedConstraints & relevantConstraints;
+ }
+
/**
* Returns whether there are enough constraints satisfied to allow running the job from flex's
* perspective. This takes into account unseen constraint combinations and expectations around
@@ -274,7 +287,7 @@
@VisibleForTesting
@GuardedBy("mLock")
boolean hasEnoughSatisfiedConstraintsLocked(@NonNull JobStatus js) {
- final int satisfiedConstraints = mSatisfiedFlexibleConstraints
+ final int satisfiedConstraints = mSatisfiedFlexibleConstraints & mAppliedConstraints
& (SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
| (js.areTransportAffinitiesSatisfied() ? CONSTRAINT_CONNECTIVITY : 0));
final int numSatisfied = Integer.bitCount(satisfiedConstraints);
@@ -296,8 +309,7 @@
// count have not been seen recently enough, then assume they won't be seen anytime soon,
// so don't force the job to wait longer. If any combinations with a higher count have been
// seen recently, then the job can potentially wait for those combinations.
- final int irrelevantConstraints = ~(SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
- | (js.canApplyTransportAffinities() ? CONSTRAINT_CONNECTIVITY : 0));
+ final int irrelevantConstraints = ~getRelevantAppliedConstraintsLocked(js);
for (int i = mLastSeenConstraintTimesElapsed.size() - 1; i >= 0; --i) {
final int constraints = mLastSeenConstraintTimesElapsed.keyAt(i);
if ((constraints & irrelevantConstraints) != 0) {
@@ -515,9 +527,9 @@
for (int j = 0; j < mFlexibilityTracker.size(); j++) {
final ArraySet<JobStatus> jobs = mFlexibilityTracker
.getJobsByNumRequiredConstraints(j);
- for (int i = 0; i < jobs.size(); i++) {
+ for (int i = jobs.size() - 1; i >= 0; --i) {
JobStatus js = jobs.valueAt(i);
- mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityTracker.updateFlexibleConstraints(js, nowElapsed);
mFlexibilityAlarmQueue.scheduleDropNumConstraintsAlarm(js, nowElapsed);
if (js.setFlexibilityConstraintSatisfied(
nowElapsed, isFlexibilitySatisfiedLocked(js))) {
@@ -579,18 +591,46 @@
mTrackedJobs.get(js.getNumRequiredFlexibleConstraints()).remove(js);
}
- public void resetJobNumDroppedConstraints(JobStatus js, long nowElapsed) {
+ /**
+ * Updates applied and dropped constraints for the job.
+ */
+ public void updateFlexibleConstraints(JobStatus js, long nowElapsed) {
+ final int prevNumRequired = js.getNumRequiredFlexibleConstraints();
+
+ final int numAppliedConstraints =
+ Integer.bitCount(getRelevantAppliedConstraintsLocked(js));
+ js.setNumAppliedFlexibleConstraints(numAppliedConstraints);
+
final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
int toDrop = 0;
- final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
- + (js.canApplyTransportAffinities() ? 1 : 0);
+ for (int i = 0; i < numAppliedConstraints; i++) {
+ if (curPercent >= mPercentToDropConstraints[i]) {
+ toDrop++;
+ }
+ }
+ js.setNumDroppedFlexibleConstraints(toDrop);
+
+ if (prevNumRequired == js.getNumRequiredFlexibleConstraints()) {
+ return;
+ }
+ mTrackedJobs.get(prevNumRequired).remove(js);
+ add(js);
+ }
+
+ /**
+ * Calculates the number of constraints that should be dropped for the job, based on how
+ * far along the job is into its lifecycle.
+ */
+ public void calculateNumDroppedConstraints(JobStatus js, long nowElapsed) {
+ final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
+ int toDrop = 0;
+ final int jsMaxFlexibleConstraints = js.getNumAppliedFlexibleConstraints();
for (int i = 0; i < jsMaxFlexibleConstraints; i++) {
if (curPercent >= mPercentToDropConstraints[i]) {
toDrop++;
}
}
- adjustJobsRequiredConstraints(
- js, js.getNumDroppedFlexibleConstraints() - toDrop, nowElapsed);
+ setNumDroppedFlexibleConstraints(js, toDrop);
}
/** Returns all tracked jobs. */
@@ -599,17 +639,14 @@
}
/**
- * Adjusts number of required flexible constraints and sorts it into the tracker.
- * Returns false if the job status's number of flexible constraints is now 0.
+ * Updates the number of dropped flexible constraints and sorts it into the tracker.
*/
- public boolean adjustJobsRequiredConstraints(JobStatus js, int adjustBy, long nowElapsed) {
- if (adjustBy != 0) {
+ public void setNumDroppedFlexibleConstraints(JobStatus js, int numDropped) {
+ if (numDropped != js.getNumDroppedFlexibleConstraints()) {
remove(js);
- js.adjustNumRequiredFlexibleConstraints(adjustBy);
- js.setFlexibilityConstraintSatisfied(nowElapsed, isFlexibilitySatisfiedLocked(js));
+ js.setNumDroppedFlexibleConstraints(numDropped);
add(js);
}
- return js.getNumRequiredFlexibleConstraints() > 0;
}
public int size() {
@@ -658,8 +695,10 @@
if (DEBUG) {
Slog.d(TAG, "scheduleDropNumConstraintsAlarm: "
+ js.getSourcePackageName() + " " + js.getSourceUserId()
+ + " numApplied: " + js.getNumAppliedFlexibleConstraints()
+ " numRequired: " + js.getNumRequiredFlexibleConstraints()
- + " numSatisfied: " + Integer.bitCount(mSatisfiedFlexibleConstraints)
+ + " numSatisfied: " + Integer.bitCount(
+ mSatisfiedFlexibleConstraints & getRelevantAppliedConstraintsLocked(js))
+ " curTime: " + nowElapsed
+ " earliest: " + earliest
+ " latest: " + latest
@@ -669,8 +708,9 @@
if (DEBUG) {
Slog.d(TAG, "deadline proximity met: " + js);
}
- mFlexibilityTracker.adjustJobsRequiredConstraints(js,
- -js.getNumRequiredFlexibleConstraints(), nowElapsed);
+ mFlexibilityTracker.setNumDroppedFlexibleConstraints(js,
+ js.getNumAppliedFlexibleConstraints());
+ mHandler.obtainMessage(MSG_UPDATE_JOB, js).sendToTarget();
return;
}
if (nextTimeElapsed == NO_LIFECYCLE_END) {
@@ -696,12 +736,15 @@
final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = 0; i < expired.size(); i++) {
JobStatus js = expired.valueAt(i);
- boolean wasFlexibilitySatisfied = js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE);
-
- if (mFlexibilityTracker.adjustJobsRequiredConstraints(js, -1, nowElapsed)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Alarm fired for " + js.toShortString());
+ }
+ mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
+ if (js.getNumRequiredFlexibleConstraints() > 0) {
scheduleDropNumConstraintsAlarm(js, nowElapsed);
}
- if (wasFlexibilitySatisfied != js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE)) {
+ if (js.setFlexibilityConstraintSatisfied(nowElapsed,
+ isFlexibilitySatisfiedLocked(js))) {
changedJobs.add(js);
}
}
@@ -725,7 +768,9 @@
final long nowElapsed = sElapsedRealtimeClock.millis();
final ArraySet<JobStatus> changedJobs = new ArraySet<>();
- for (int o = 0; o <= NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS; ++o) {
+ final int numAppliedSystemWideConstraints = Integer.bitCount(
+ mAppliedConstraints & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS);
+ for (int o = 0; o <= numAppliedSystemWideConstraints; ++o) {
final ArraySet<JobStatus> jobsByNumConstraints = mFlexibilityTracker
.getJobsByNumRequiredConstraints(o);
@@ -744,6 +789,23 @@
}
}
break;
+
+ case MSG_UPDATE_JOB:
+ synchronized (mLock) {
+ final JobStatus js = (JobStatus) msg.obj;
+ if (DEBUG) {
+ Slog.d("blah", "Checking on " + js.toShortString());
+ }
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ if (js.setFlexibilityConstraintSatisfied(
+ nowElapsed, isFlexibilitySatisfiedLocked(js))) {
+ // TODO(141645789): add method that will take a single job
+ ArraySet<JobStatus> changedJob = new ArraySet<>();
+ changedJob.add(js);
+ mStateChangedListener.onControllerStateChanged(changedJob);
+ }
+ }
+ break;
}
}
}
@@ -754,7 +816,8 @@
/** Prefix to use with all constant keys in order to "sub-namespace" the keys. */
private static final String FC_CONFIG_PREFIX = "fc_";
- static final String KEY_FLEXIBILITY_ENABLED = FC_CONFIG_PREFIX + "enable_flexibility";
+ @VisibleForTesting
+ static final String KEY_APPLIED_CONSTRAINTS = FC_CONFIG_PREFIX + "applied_constraints";
static final String KEY_DEADLINE_PROXIMITY_LIMIT =
FC_CONFIG_PREFIX + "flexibility_deadline_proximity_limit_ms";
static final String KEY_FALLBACK_FLEXIBILITY_DEADLINE =
@@ -770,7 +833,7 @@
static final String KEY_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS =
FC_CONFIG_PREFIX + "unseen_constraint_grace_period_ms";
- static final boolean DEFAULT_FLEXIBILITY_ENABLED = false;
+ static final int DEFAULT_APPLIED_CONSTRAINTS = 0;
@VisibleForTesting
static final long DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS;
@VisibleForTesting
@@ -783,11 +846,8 @@
@VisibleForTesting
static final long DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS = 3 * DAY_IN_MILLIS;
- /**
- * If false the controller will not track new jobs
- * and the flexibility constraint will always be satisfied.
- */
- public boolean FLEXIBILITY_ENABLED = DEFAULT_FLEXIBILITY_ENABLED;
+ /** Which constraints to apply/consider in flex policy. */
+ public int APPLIED_CONSTRAINTS = DEFAULT_APPLIED_CONSTRAINTS;
/** How close to a jobs' deadline all flexible constraints will be dropped. */
public long DEADLINE_PROXIMITY_LIMIT_MS = DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS;
/** For jobs that lack a deadline, the time that will be used to drop all constraints by. */
@@ -811,16 +871,19 @@
public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
@NonNull String key) {
switch (key) {
- case KEY_FLEXIBILITY_ENABLED:
- FLEXIBILITY_ENABLED = properties.getBoolean(key, DEFAULT_FLEXIBILITY_ENABLED)
- && mDeviceSupportsFlexConstraints;
- if (mFlexibilityEnabled != FLEXIBILITY_ENABLED) {
- mFlexibilityEnabled = FLEXIBILITY_ENABLED;
+ case KEY_APPLIED_CONSTRAINTS:
+ APPLIED_CONSTRAINTS =
+ properties.getInt(key, DEFAULT_APPLIED_CONSTRAINTS)
+ & mSupportedFlexConstraints;
+ if (mAppliedConstraints != APPLIED_CONSTRAINTS) {
+ mAppliedConstraints = APPLIED_CONSTRAINTS;
mShouldReevaluateConstraints = true;
- if (mFlexibilityEnabled) {
+ if (mAppliedConstraints != 0) {
+ mFlexibilityEnabled = true;
mPrefetchController
.registerPrefetchChangedListener(mPrefetchChangedListener);
} else {
+ mFlexibilityEnabled = false;
mPrefetchController
.unRegisterPrefetchChangedListener(mPrefetchChangedListener);
}
@@ -893,7 +956,7 @@
private int[] parsePercentToDropString(String s) {
String[] dropPercentString = s.split(",");
- int[] dropPercentInt = new int[NUM_FLEXIBLE_CONSTRAINTS];
+ int[] dropPercentInt = new int[Integer.bitCount(FLEXIBLE_CONSTRAINTS)];
if (dropPercentInt.length != dropPercentString.length) {
return DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS;
}
@@ -922,7 +985,7 @@
pw.println(":");
pw.increaseIndent();
- pw.print(KEY_FLEXIBILITY_ENABLED, FLEXIBILITY_ENABLED).println();
+ pw.print(KEY_APPLIED_CONSTRAINTS, APPLIED_CONSTRAINTS).println();
pw.print(KEY_DEADLINE_PROXIMITY_LIMIT, DEADLINE_PROXIMITY_LIMIT_MS).println();
pw.print(KEY_FALLBACK_FLEXIBILITY_DEADLINE, FALLBACK_FLEXIBILITY_DEADLINE_MS).println();
pw.print(KEY_MIN_TIME_BETWEEN_FLEXIBILITY_ALARMS_MS,
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index d1f575e..0d5d11e 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -24,7 +24,6 @@
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
-import static com.android.server.job.controllers.FlexibilityController.NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
import android.annotation.ElapsedRealtimeLong;
@@ -155,7 +154,7 @@
/**
* Keeps track of how many flexible constraints must be satisfied for the job to execute.
*/
- private final int mNumRequiredFlexibleConstraints;
+ private int mNumAppliedFlexibleConstraints;
/**
* Number of required flexible constraints that have been dropped.
@@ -697,11 +696,7 @@
&& satisfiesMinWindowException
&& (numFailures + numSystemStops) != 1
&& lacksSomeFlexibleConstraints) {
- mNumRequiredFlexibleConstraints =
- NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mCanApplyTransportAffinities ? 1 : 0);
requiredConstraints |= CONSTRAINT_FLEXIBLE;
- } else {
- mNumRequiredFlexibleConstraints = 0;
}
this.requiredConstraints = requiredConstraints;
@@ -1527,9 +1522,14 @@
return (requiredConstraints & CONSTRAINT_FLEXIBLE) != 0;
}
+ /** Returns the number of flexible job constraints being applied to the job. */
+ public int getNumAppliedFlexibleConstraints() {
+ return mNumAppliedFlexibleConstraints;
+ }
+
/** Returns the number of flexible job constraints required to be satisfied to execute */
public int getNumRequiredFlexibleConstraints() {
- return mNumRequiredFlexibleConstraints - mNumDroppedFlexibleConstraints;
+ return mNumAppliedFlexibleConstraints - mNumDroppedFlexibleConstraints;
}
/**
@@ -2112,9 +2112,14 @@
}
/** Adjusts the number of required flexible constraints by the given number */
- public void adjustNumRequiredFlexibleConstraints(int adjustment) {
- mNumDroppedFlexibleConstraints = Math.max(0, Math.min(mNumRequiredFlexibleConstraints,
- mNumDroppedFlexibleConstraints - adjustment));
+ public void setNumAppliedFlexibleConstraints(int count) {
+ mNumAppliedFlexibleConstraints = count;
+ }
+
+ /** Sets the number of dropped flexible constraints to the given number */
+ public void setNumDroppedFlexibleConstraints(int count) {
+ mNumDroppedFlexibleConstraints = Math.max(0,
+ Math.min(mNumAppliedFlexibleConstraints, count));
}
/**
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
index 4fb9472..650c473 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java
@@ -30,15 +30,16 @@
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_FALLBACK_FLEXIBILITY_DEADLINE_MS;
import static com.android.server.job.controllers.FlexibilityController.FcConfig.DEFAULT_UNSEEN_CONSTRAINT_GRACE_PERIOD_MS;
+import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_APPLIED_CONSTRAINTS;
import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_DEADLINE_PROXIMITY_LIMIT;
import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FALLBACK_FLEXIBILITY_DEADLINE;
-import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_FLEXIBILITY_ENABLED;
import static com.android.server.job.controllers.FlexibilityController.FcConfig.KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS;
-import static com.android.server.job.controllers.FlexibilityController.NUM_FLEXIBLE_CONSTRAINTS;
+import static com.android.server.job.controllers.FlexibilityController.FLEXIBLE_CONSTRAINTS;
import static com.android.server.job.controllers.FlexibilityController.SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONNECTIVITY;
+import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CONTENT_TRIGGER;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_FLEXIBLE;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_IDLE;
import static com.android.server.job.controllers.JobStatus.MIN_WINDOW_FOR_FLEXIBILITY_MS;
@@ -66,6 +67,7 @@
import android.provider.DeviceConfig;
import android.util.ArraySet;
+import com.android.server.AppSchedulingModuleThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.JobStore;
@@ -129,6 +131,7 @@
when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mPackageManager.hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(false);
+ when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_EMBEDDED)).thenReturn(false);
// Used in FlexibilityController.FcConstants.
doAnswer((Answer<Void>) invocationOnMock -> null)
.when(() -> DeviceConfig.addOnPropertiesChangedListener(
@@ -161,7 +164,8 @@
setDeviceConfigString(KEY_PERCENTS_TO_DROP_NUM_FLEXIBLE_CONSTRAINTS, "50,60,70,80");
setDeviceConfigLong(KEY_DEADLINE_PROXIMITY_LIMIT, 0L);
- setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+ waitForQuietModuleThread();
}
@After
@@ -171,17 +175,22 @@
}
}
- private void setDeviceConfigBoolean(String key, boolean val) {
- mDeviceConfigPropertiesBuilder.setBoolean(key, val);
- synchronized (mFlexibilityController.mLock) {
- mFlexibilityController.prepareForUpdatedConstantsLocked();
- mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
- mFlexibilityController.onConstantsUpdatedLocked();
- }
+ private void setDeviceConfigInt(String key, int val) {
+ mDeviceConfigPropertiesBuilder.setInt(key, val);
+ updateDeviceConfig(key);
}
private void setDeviceConfigLong(String key, Long val) {
mDeviceConfigPropertiesBuilder.setLong(key, val);
+ updateDeviceConfig(key);
+ }
+
+ private void setDeviceConfigString(String key, String val) {
+ mDeviceConfigPropertiesBuilder.setString(key, val);
+ updateDeviceConfig(key);
+ }
+
+ private void updateDeviceConfig(String key) {
synchronized (mFlexibilityController.mLock) {
mFlexibilityController.prepareForUpdatedConstantsLocked();
mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
@@ -189,13 +198,9 @@
}
}
- private void setDeviceConfigString(String key, String val) {
- mDeviceConfigPropertiesBuilder.setString(key, val);
- synchronized (mFlexibilityController.mLock) {
- mFlexibilityController.prepareForUpdatedConstantsLocked();
- mFcConfig.processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
- mFlexibilityController.onConstantsUpdatedLocked();
- }
+ private void waitForQuietModuleThread() {
+ assertTrue("Failed to wait for quiet module thread",
+ AppSchedulingModuleThread.getHandler().runWithScissors(() -> {}, 10_000L));
}
private static JobInfo.Builder createJob(int id) {
@@ -207,6 +212,10 @@
JobStatus js = JobStatus.createFromJobInfo(
jobInfo, 1000, SOURCE_PACKAGE, SOURCE_USER_ID, "FCTest", testTag);
js.enqueueTime = FROZEN_TIME;
+ if (js.hasFlexibilityConstraint()) {
+ js.setNumAppliedFlexibleConstraints(Integer.bitCount(
+ mFlexibilityController.getRelevantAppliedConstraintsLocked(js)));
+ }
return js;
}
@@ -215,18 +224,120 @@
*/
@Test
public void testDefaultVariableValues() {
- assertEquals(NUM_FLEXIBLE_CONSTRAINTS,
+ assertEquals(Integer.bitCount(FLEXIBLE_CONSTRAINTS),
mFlexibilityController.mFcConfig.DEFAULT_PERCENT_TO_DROP_FLEXIBLE_CONSTRAINTS.length
);
}
@Test
- public void testOnConstantsUpdated_DefaultFlexibility() {
+ public void testAppliedConstraints() {
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+
+ // Add connectivity to require 4 constraints
+ JobStatus connJs = createJobStatus("testAppliedConstraints",
+ createJob(0).setRequiredNetworkType(NETWORK_TYPE_ANY));
+ JobStatus nonConnJs = createJobStatus("testAppliedConstraints",
+ createJob(1).setRequiredNetworkType(NETWORK_TYPE_NONE));
+
+ mFlexibilityController.maybeStartTrackingJobLocked(connJs, null);
+ mFlexibilityController.maybeStartTrackingJobLocked(nonConnJs, null);
+
+ assertEquals(4, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(3, nonConnJs.getNumAppliedFlexibleConstraints());
+
+ mFlexibilityController.setConstraintSatisfied(
+ CONSTRAINT_BATTERY_NOT_LOW, true,
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+ mFlexibilityController.setConstraintSatisfied(
+ CONSTRAINT_CHARGING, false,
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+ mFlexibilityController.setConstraintSatisfied(
+ CONSTRAINT_IDLE, false,
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+ mFlexibilityController.setConstraintSatisfied(
+ CONSTRAINT_CONNECTIVITY, true,
+ JobSchedulerService.sElapsedRealtimeClock.millis() - HOUR_IN_MILLIS);
+ connJs.setTransportAffinitiesSatisfied(true);
+
+ synchronized (mFlexibilityController.mLock) {
+ assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS,
+ CONSTRAINT_BATTERY_NOT_LOW | CONSTRAINT_CONNECTIVITY);
+ waitForQuietModuleThread();
+
+ // Only battery-not-low (which is satisfied) applies to the non-connectivity job, so it
+ // should be able to run.
+ assertEquals(2, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_BATTERY_NOT_LOW);
+ waitForQuietModuleThread();
+
+ assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CONNECTIVITY);
+ waitForQuietModuleThread();
+
+ // No constraints apply to the non-connectivity job, so it should be able to run.
+ assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CHARGING);
+ waitForQuietModuleThread();
+
+ assertEquals(1, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(1, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertFalse(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, 0);
+ waitForQuietModuleThread();
+
+ // No constraints apply, so they should be able to run.
+ assertEquals(0, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+
+ // Invalid constraint to apply.
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, CONSTRAINT_CONTENT_TRIGGER);
+ waitForQuietModuleThread();
+
+ // No constraints apply, so they should be able to run.
+ assertEquals(0, connJs.getNumAppliedFlexibleConstraints());
+ assertEquals(0, nonConnJs.getNumAppliedFlexibleConstraints());
+ synchronized (mFlexibilityController.mLock) {
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(connJs));
+ assertTrue(mFlexibilityController.hasEnoughSatisfiedConstraintsLocked(nonConnJs));
+ }
+ }
+
+ @Test
+ public void testOnConstantsUpdated_AppliedConstraints() {
JobStatus js = createJobStatus("testDefaultFlexibilityConfig", createJob(0));
- assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
- setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, false);
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, 0);
assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
- setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
assertFalse(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
}
@@ -261,10 +372,10 @@
new int[] {10, 20, 30, 40});
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(1);
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 2,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(2);
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 3,
mFlexibilityController.getNextConstraintDropTimeElapsedLocked(js));
}
@@ -303,12 +414,12 @@
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(FROZEN_TIME + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
@@ -321,11 +432,11 @@
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(130400100, nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(156320100L, nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(182240100L, nextTimeToDropNumConstraints);
@@ -337,11 +448,11 @@
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(129600100, nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(155520100L, nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(181440100L, nextTimeToDropNumConstraints);
@@ -357,12 +468,12 @@
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 5,
nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(1);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 6,
nextTimeToDropNumConstraints);
- js.adjustNumRequiredFlexibleConstraints(-1);
+ js.setNumDroppedFlexibleConstraints(2);
nextTimeToDropNumConstraints = mFlexibilityController
.getNextConstraintDropTimeElapsedLocked(js);
assertEquals(windowStart + MIN_WINDOW_FOR_FLEXIBILITY_MS / 10 * 7,
@@ -580,10 +691,10 @@
}
@Test
- public void testWontStopJobFromRunning() {
- JobStatus js = createJobStatus("testWontStopJobFromRunning", createJob(101));
+ public void testWontStopAlreadyRunningJob() {
+ JobStatus js = createJobStatus("testWontStopAlreadyRunningJob", createJob(101));
// Stop satisfied constraints from causing a false positive.
- js.adjustNumRequiredFlexibleConstraints(100);
+ js.setNumAppliedFlexibleConstraints(100);
synchronized (mFlexibilityController.mLock) {
when(mJobSchedulerService.isCurrentlyRunningLocked(js)).thenReturn(true);
assertTrue(mFlexibilityController.isFlexibilitySatisfiedLocked(js));
@@ -593,10 +704,9 @@
@Test
public void testFlexibilityTracker() {
FlexibilityController.FlexibilityTracker flexTracker =
- mFlexibilityController.new
- FlexibilityTracker(NUM_FLEXIBLE_CONSTRAINTS);
+ mFlexibilityController.new FlexibilityTracker(4);
// Plus one for jobs with 0 required constraint.
- assertEquals(NUM_FLEXIBLE_CONSTRAINTS + 1, flexTracker.size());
+ assertEquals(4 + 1, flexTracker.size());
JobStatus[] jobs = new JobStatus[4];
JobInfo.Builder jb;
for (int i = 0; i < jobs.length; i++) {
@@ -622,21 +732,21 @@
assertEquals(3, trackedJobs.get(3).size());
assertEquals(0, trackedJobs.get(4).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+ flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 1);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(1, trackedJobs.get(2).size());
assertEquals(2, trackedJobs.get(3).size());
assertEquals(0, trackedJobs.get(4).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+ flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 2);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(1, trackedJobs.get(1).size());
assertEquals(0, trackedJobs.get(2).size());
assertEquals(2, trackedJobs.get(3).size());
assertEquals(0, trackedJobs.get(4).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -1, FROZEN_TIME);
+ flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 3);
assertEquals(2, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(0, trackedJobs.get(2).size());
@@ -650,14 +760,14 @@
assertEquals(1, trackedJobs.get(3).size());
assertEquals(0, trackedJobs.get(4).size());
- flexTracker.resetJobNumDroppedConstraints(jobs[0], FROZEN_TIME);
+ flexTracker.calculateNumDroppedConstraints(jobs[0], FROZEN_TIME);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(0, trackedJobs.get(2).size());
assertEquals(2, trackedJobs.get(3).size());
assertEquals(0, trackedJobs.get(4).size());
- flexTracker.adjustJobsRequiredConstraints(jobs[0], -2, FROZEN_TIME);
+ flexTracker.setNumDroppedFlexibleConstraints(jobs[0], 2);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(1, trackedJobs.get(1).size());
assertEquals(0, trackedJobs.get(2).size());
@@ -669,7 +779,7 @@
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- flexTracker.resetJobNumDroppedConstraints(jobs[0], nowElapsed);
+ flexTracker.calculateNumDroppedConstraints(jobs[0], nowElapsed);
assertEquals(1, trackedJobs.get(0).size());
assertEquals(0, trackedJobs.get(1).size());
assertEquals(1, trackedJobs.get(2).size());
@@ -779,9 +889,9 @@
mFlexibilityController.setConstraintSatisfied(
SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS, false, FROZEN_TIME);
// Require only a single constraint
- jsAny.adjustNumRequiredFlexibleConstraints(-3);
- jsCell.adjustNumRequiredFlexibleConstraints(-2);
- jsWifi.adjustNumRequiredFlexibleConstraints(-2);
+ jsAny.setNumAppliedFlexibleConstraints(1);
+ jsCell.setNumAppliedFlexibleConstraints(1);
+ jsWifi.setNumAppliedFlexibleConstraints(1);
synchronized (mFlexibilityController.mLock) {
jsAny.setTransportAffinitiesSatisfied(false);
jsCell.setTransportAffinitiesSatisfied(false);
@@ -1008,9 +1118,9 @@
}
@Test
- public void testResetJobNumDroppedConstraints() {
+ public void testCalculateNumDroppedConstraints() {
JobInfo.Builder jb = createJob(22);
- JobStatus js = createJobStatus("testResetJobNumDroppedConstraints", jb);
+ JobStatus js = createJobStatus("testCalculateNumDroppedConstraints", jb);
long nowElapsed = FROZEN_TIME;
mFlexibilityController.mFlexibilityTracker.add(js);
@@ -1025,14 +1135,14 @@
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
mFlexibilityController.mFlexibilityTracker
- .adjustJobsRequiredConstraints(js, -1, nowElapsed);
+ .setNumDroppedFlexibleConstraints(js, 1);
assertEquals(2, js.getNumRequiredFlexibleConstraints());
assertEquals(1, js.getNumDroppedFlexibleConstraints());
assertEquals(1, mFlexibilityController
.mFlexibilityTracker.getJobsByNumRequiredConstraints(2).size());
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
assertEquals(2, js.getNumRequiredFlexibleConstraints());
assertEquals(1, js.getNumDroppedFlexibleConstraints());
@@ -1043,7 +1153,7 @@
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
assertEquals(3, js.getNumRequiredFlexibleConstraints());
assertEquals(0, js.getNumDroppedFlexibleConstraints());
@@ -1054,7 +1164,7 @@
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
assertEquals(0, js.getNumRequiredFlexibleConstraints());
assertEquals(3, js.getNumDroppedFlexibleConstraints());
@@ -1063,7 +1173,7 @@
JobSchedulerService.sElapsedRealtimeClock =
Clock.fixed(Instant.ofEpochMilli(nowElapsed), ZoneOffset.UTC);
- mFlexibilityController.mFlexibilityTracker.resetJobNumDroppedConstraints(js, nowElapsed);
+ mFlexibilityController.mFlexibilityTracker.calculateNumDroppedConstraints(js, nowElapsed);
assertEquals(1, js.getNumRequiredFlexibleConstraints());
assertEquals(2, js.getNumDroppedFlexibleConstraints());
@@ -1139,20 +1249,28 @@
}
@Test
- public void testDeviceDisabledFlexibility_Auto() {
- when(mPackageManager.hasSystemFeature(
- PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(true);
+ public void testUnsupportedDevice_Auto() {
+ runTestUnsupportedDevice(PackageManager.FEATURE_AUTOMOTIVE);
+ }
+
+ @Test
+ public void testUnsupportedDevice_Embedded() {
+ runTestUnsupportedDevice(PackageManager.FEATURE_EMBEDDED);
+ }
+
+ private void runTestUnsupportedDevice(String feature) {
+ when(mPackageManager.hasSystemFeature(feature)).thenReturn(true);
mFlexibilityController =
new FlexibilityController(mJobSchedulerService, mPrefetchController);
- assertFalse(mFlexibilityController.mFlexibilityEnabled);
+ assertFalse(mFlexibilityController.isEnabled());
- JobStatus js = createJobStatus("testIsAuto", createJob(0));
+ JobStatus js = createJobStatus("testUnsupportedDevice", createJob(0));
mFlexibilityController.maybeStartTrackingJobLocked(js, null);
assertTrue(js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE));
- setDeviceConfigBoolean(KEY_FLEXIBILITY_ENABLED, true);
- assertFalse(mFlexibilityController.mFlexibilityEnabled);
+ setDeviceConfigInt(KEY_APPLIED_CONSTRAINTS, FLEXIBLE_CONSTRAINTS);
+ assertFalse(mFlexibilityController.isEnabled());
ArrayList<ArraySet<JobStatus>> jobs =
mFlexibilityController.mFlexibilityTracker.getArrayList();
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 8397b877..293391f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -232,6 +232,19 @@
}
@Test
+ public void testFlexibleConstraintCounts() {
+ JobStatus js = createJobStatus(new JobInfo.Builder(101, new ComponentName("foo", "bar"))
+ .setUserInitiated(false)
+ .build());
+
+ js.setNumAppliedFlexibleConstraints(3);
+ js.setNumDroppedFlexibleConstraints(2);
+ assertEquals(3, js.getNumAppliedFlexibleConstraints());
+ assertEquals(2, js.getNumDroppedFlexibleConstraints());
+ assertEquals(1, js.getNumRequiredFlexibleConstraints());
+ }
+
+ @Test
public void testIsUserVisibleJob() {
JobInfo jobInfo = new JobInfo.Builder(101, new ComponentName("foo", "bar"))
.setUserInitiated(false)