summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2023-11-10 19:39:48 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-11-10 19:39:48 +0000
commit032cc572136987d025c8ffdff86956b0c7660f80 (patch)
tree922e68f2b6c5d7d0ba9dbacbb831ff2bde7af0ba
parentaa3e3af194316ca0559251c21581fd507587247e (diff)
parent366583d33138d8565e8fa774b3a8dbc05418de9a (diff)
Merge "Add transport affinities for flex scheduling." into main
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java1
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java255
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/FlexibilityController.java14
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java34
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java216
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/FlexibilityControllerTest.java14
6 files changed, 463 insertions, 71 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index bff43534ce05..07475b4f2136 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -998,6 +998,7 @@ public class JobSchedulerService extends com.android.server.SystemService
DEFAULT_SYSTEM_STOP_TO_FAILURE_RATIO);
}
+ // TODO(141645789): move into ConnectivityController.CcConfig
private void updateConnectivityConstantsLocked() {
CONN_CONGESTION_DELAY_FRAC = DeviceConfig.getFloat(DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_CONN_CONGESTION_DELAY_FRAC,
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 ae4e99cfeef3..0cf0cc5dcd22 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
@@ -19,6 +19,9 @@ package com.android.server.job.controllers;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
@@ -29,6 +32,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.job.JobInfo;
+import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
import android.net.INetworkPolicyListener;
@@ -40,6 +44,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.telephony.CellSignalStrength;
import android.telephony.SignalStrength;
import android.telephony.TelephonyCallback;
@@ -53,6 +58,7 @@ import android.util.Pools;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -117,6 +123,26 @@ public final class ConnectivityController extends RestrictingController implemen
| ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER
| ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED);
+ @VisibleForTesting
+ static final int TRANSPORT_AFFINITY_UNDEFINED = 0;
+ @VisibleForTesting
+ static final int TRANSPORT_AFFINITY_PREFER = 1;
+ @VisibleForTesting
+ static final int TRANSPORT_AFFINITY_AVOID = 2;
+ /**
+ * Set of affinities to different network transports. If a given network has multiple
+ * transports, the avoided ones take priority --- a network with an avoided transport
+ * should be avoided if possible, even if the network has preferred transports as well.
+ */
+ @VisibleForTesting
+ static final SparseIntArray sNetworkTransportAffinities = new SparseIntArray();
+ static {
+ sNetworkTransportAffinities.put(TRANSPORT_CELLULAR, TRANSPORT_AFFINITY_AVOID);
+ sNetworkTransportAffinities.put(TRANSPORT_WIFI, TRANSPORT_AFFINITY_PREFER);
+ sNetworkTransportAffinities.put(TRANSPORT_ETHERNET, TRANSPORT_AFFINITY_PREFER);
+ }
+
+ private final CcConfig mCcConfig;
private final ConnectivityManager mConnManager;
private final NetworkPolicyManager mNetPolicyManager;
private final NetworkPolicyManagerInternal mNetPolicyManagerInternal;
@@ -138,7 +164,7 @@ public final class ConnectivityController extends RestrictingController implemen
* latest capabilities to avoid unnecessary calls into ConnectivityManager.
*/
@GuardedBy("mLock")
- private final ArrayMap<Network, NetworkCapabilities> mAvailableNetworks = new ArrayMap<>();
+ private final ArrayMap<Network, CachedNetworkMetadata> mAvailableNetworks = new ArrayMap<>();
private final SparseArray<UidDefaultNetworkCallback> mCurrentDefaultNetworkCallbacks =
new SparseArray<>();
@@ -267,6 +293,7 @@ public final class ConnectivityController extends RestrictingController implemen
@NonNull FlexibilityController flexibilityController) {
super(service);
mHandler = new CcHandler(AppSchedulingModuleThread.get().getLooper());
+ mCcConfig = new CcConfig();
mConnManager = mContext.getSystemService(ConnectivityManager.class);
mNetPolicyManager = mContext.getSystemService(NetworkPolicyManager.class);
@@ -279,6 +306,11 @@ public final class ConnectivityController extends RestrictingController implemen
mConnManager.registerNetworkCallback(request, mNetworkCallback);
mNetPolicyManager.registerListener(mNetPolicyListener);
+
+ if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+ // For now, we don't have network affinities on watches.
+ sNetworkTransportAffinities.clear();
+ }
}
@GuardedBy("mLock")
@@ -386,7 +418,9 @@ public final class ConnectivityController extends RestrictingController implemen
synchronized (mLock) {
for (int i = 0; i < mAvailableNetworks.size(); ++i) {
final Network network = mAvailableNetworks.keyAt(i);
- final NetworkCapabilities capabilities = mAvailableNetworks.valueAt(i);
+ final CachedNetworkMetadata metadata = mAvailableNetworks.valueAt(i);
+ final NetworkCapabilities capabilities =
+ metadata == null ? null : metadata.networkCapabilities;
final boolean satisfied = isSatisfied(job, network, capabilities, mConstants);
if (DEBUG) {
Slog.v(TAG, "isNetworkAvailable(" + job + ") with network " + network
@@ -589,6 +623,43 @@ public final class ConnectivityController extends RestrictingController implemen
mHandler.sendEmptyMessage(MSG_UPDATE_ALL_TRACKED_JOBS);
}
+ @Override
+ public void prepareForUpdatedConstantsLocked() {
+ mCcConfig.mShouldReprocessNetworkCapabilities = false;
+ mCcConfig.mFlexIsEnabled = mFlexibilityController.isEnabled();
+ }
+
+ @Override
+ public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
+ @NonNull String key) {
+ mCcConfig.processConstantLocked(properties, key);
+ }
+
+ @Override
+ public void onConstantsUpdatedLocked() {
+ if (mCcConfig.mShouldReprocessNetworkCapabilities
+ || (mFlexibilityController.isEnabled() != mCcConfig.mFlexIsEnabled)) {
+ AppSchedulingModuleThread.getHandler().post(() -> {
+ boolean shouldUpdateJobs = false;
+ for (int i = 0; i < mAvailableNetworks.size(); ++i) {
+ CachedNetworkMetadata metadata = mAvailableNetworks.valueAt(i);
+ if (metadata == null || metadata.networkCapabilities == null) {
+ continue;
+ }
+ boolean satisfies = satisfiesTransportAffinities(metadata.networkCapabilities);
+ if (metadata.satisfiesTransportAffinities != satisfies) {
+ metadata.satisfiesTransportAffinities = satisfies;
+ // Something changed. Update jobs.
+ shouldUpdateJobs = true;
+ }
+ }
+ if (shouldUpdateJobs) {
+ updateAllTrackedJobsLocked(false);
+ }
+ });
+ }
+ }
+
private boolean isUsable(NetworkCapabilities capabilities) {
return capabilities != null
&& capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
@@ -831,7 +902,7 @@ public final class ConnectivityController extends RestrictingController implemen
if (!constants.CONN_USE_CELL_SIGNAL_STRENGTH) {
return true;
}
- if (!capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ if (!capabilities.hasTransport(TRANSPORT_CELLULAR)) {
return true;
}
if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN)) {
@@ -988,6 +1059,52 @@ public final class ConnectivityController extends RestrictingController implemen
return false;
}
+ private boolean satisfiesTransportAffinities(@Nullable NetworkCapabilities capabilities) {
+ if (!mFlexibilityController.isEnabled()) {
+ return true;
+ }
+ if (capabilities == null) {
+ Slog.wtf(TAG, "Network constraint satisfied with null capabilities");
+ return !mCcConfig.AVOID_UNDEFINED_TRANSPORT_AFFINITY;
+ }
+
+ if (sNetworkTransportAffinities.size() == 0) {
+ return !mCcConfig.AVOID_UNDEFINED_TRANSPORT_AFFINITY;
+ }
+
+ final int[] transports = capabilities.getTransportTypes();
+ if (transports.length == 0) {
+ return !mCcConfig.AVOID_UNDEFINED_TRANSPORT_AFFINITY;
+ }
+
+ for (int t : transports) {
+ int affinity = sNetworkTransportAffinities.get(t, TRANSPORT_AFFINITY_UNDEFINED);
+ if (DEBUG) {
+ Slog.d(TAG,
+ "satisfiesTransportAffinities transport=" + t + " aff=" + affinity);
+ }
+ switch (affinity) {
+ case TRANSPORT_AFFINITY_UNDEFINED:
+ if (mCcConfig.AVOID_UNDEFINED_TRANSPORT_AFFINITY) {
+ // Avoided transports take precedence.
+ // Return as soon as we encounter a transport to avoid.
+ return false;
+ }
+ break;
+ case TRANSPORT_AFFINITY_PREFER:
+ // Nothing to do here. We like this transport.
+ break;
+ case TRANSPORT_AFFINITY_AVOID:
+ // Avoided transports take precedence.
+ // Return as soon as we encounter a transport to avoid.
+ return false;
+ }
+ }
+
+ // Didn't see any transport to avoid.
+ return true;
+ }
+
@GuardedBy("mLock")
private void maybeRegisterDefaultNetworkCallbackLocked(JobStatus jobStatus) {
final int sourceUid = jobStatus.getSourceUid();
@@ -1172,6 +1289,12 @@ public final class ConnectivityController extends RestrictingController implemen
@Nullable
private NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
+ final CachedNetworkMetadata metadata = getNetworkMetadata(network);
+ return metadata == null ? null : metadata.networkCapabilities;
+ }
+
+ @Nullable
+ private CachedNetworkMetadata getNetworkMetadata(@Nullable Network network) {
if (network == null) {
return null;
}
@@ -1234,14 +1357,16 @@ public final class ConnectivityController extends RestrictingController implemen
return updateConstraintsSatisfied(jobStatus, nowElapsed, null, null);
}
final Network network = getNetworkLocked(jobStatus);
- final NetworkCapabilities capabilities = getNetworkCapabilities(network);
- return updateConstraintsSatisfied(jobStatus, nowElapsed, network, capabilities);
+ final CachedNetworkMetadata networkMetadata = getNetworkMetadata(network);
+ return updateConstraintsSatisfied(jobStatus, nowElapsed, network, networkMetadata);
}
private boolean updateConstraintsSatisfied(JobStatus jobStatus, final long nowElapsed,
- Network network, NetworkCapabilities capabilities) {
+ Network network, @Nullable CachedNetworkMetadata networkMetadata) {
// TODO: consider matching against non-default networks
+ final NetworkCapabilities capabilities =
+ networkMetadata == null ? null : networkMetadata.networkCapabilities;
final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
if (!satisfied && jobStatus.network != null
@@ -1263,10 +1388,10 @@ public final class ConnectivityController extends RestrictingController implemen
final boolean changed = jobStatus.setConnectivityConstraintSatisfied(nowElapsed, satisfied);
- if (jobStatus.getPreferUnmetered()) {
- jobStatus.setHasAccessToUnmetered(satisfied && capabilities != null
- && capabilities.hasCapability(NET_CAPABILITY_NOT_METERED));
-
+ jobStatus.setTransportAffinitiesSatisfied(satisfied && networkMetadata != null
+ && networkMetadata.satisfiesTransportAffinities);
+ if (jobStatus.canApplyTransportAffinities()) {
+ // Only modify the flex constraint if the job actually needs it.
jobStatus.setFlexibilityConstraintSatisfied(nowElapsed,
mFlexibilityController.isFlexibilitySatisfiedLocked(jobStatus));
}
@@ -1367,7 +1492,6 @@ public final class ConnectivityController extends RestrictingController implemen
final JobStatus js = jobs.valueAt(i);
final Network net = getNetworkLocked(js);
- final NetworkCapabilities netCap = getNetworkCapabilities(net);
final boolean match = (filterNetwork == null
|| Objects.equals(filterNetwork, net));
@@ -1375,7 +1499,7 @@ public final class ConnectivityController extends RestrictingController implemen
// job hasn't yet been evaluated against the currently
// active network; typically when we just lost a network.
if (match || !Objects.equals(js.network, net)) {
- changed |= updateConstraintsSatisfied(js, nowElapsed, net, netCap);
+ changed |= updateConstraintsSatisfied(js, nowElapsed, net, getNetworkMetadata(net));
}
}
return changed;
@@ -1417,10 +1541,18 @@ public final class ConnectivityController extends RestrictingController implemen
Slog.v(TAG, "onCapabilitiesChanged: " + network);
}
synchronized (mLock) {
- final NetworkCapabilities oldCaps = mAvailableNetworks.put(network, capabilities);
- if (oldCaps != null) {
- maybeUnregisterSignalStrengthCallbackLocked(oldCaps);
+ CachedNetworkMetadata cnm = mAvailableNetworks.get(network);
+ if (cnm == null) {
+ cnm = new CachedNetworkMetadata();
+ mAvailableNetworks.put(network, cnm);
+ } else {
+ final NetworkCapabilities oldCaps = cnm.networkCapabilities;
+ if (oldCaps != null) {
+ maybeUnregisterSignalStrengthCallbackLocked(oldCaps);
+ }
}
+ cnm.networkCapabilities = capabilities;
+ cnm.satisfiesTransportAffinities = satisfiesTransportAffinities(capabilities);
maybeRegisterSignalStrengthCallbackLocked(capabilities);
updateTrackedJobsLocked(-1, network);
postAdjustCallbacks();
@@ -1433,9 +1565,9 @@ public final class ConnectivityController extends RestrictingController implemen
Slog.v(TAG, "onLost: " + network);
}
synchronized (mLock) {
- final NetworkCapabilities capabilities = mAvailableNetworks.remove(network);
- if (capabilities != null) {
- maybeUnregisterSignalStrengthCallbackLocked(capabilities);
+ final CachedNetworkMetadata cnm = mAvailableNetworks.remove(network);
+ if (cnm != null && cnm.networkCapabilities != null) {
+ maybeUnregisterSignalStrengthCallbackLocked(cnm.networkCapabilities);
}
for (int u = 0; u < mCurrentDefaultNetworkCallbacks.size(); ++u) {
UidDefaultNetworkCallback callback = mCurrentDefaultNetworkCallbacks.valueAt(u);
@@ -1451,7 +1583,7 @@ public final class ConnectivityController extends RestrictingController implemen
@GuardedBy("mLock")
private void maybeRegisterSignalStrengthCallbackLocked(
@NonNull NetworkCapabilities capabilities) {
- if (!capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ if (!capabilities.hasTransport(TRANSPORT_CELLULAR)) {
return;
}
TelephonyManager telephonyManager = mContext.getSystemService(TelephonyManager.class);
@@ -1476,14 +1608,17 @@ public final class ConnectivityController extends RestrictingController implemen
@GuardedBy("mLock")
private void maybeUnregisterSignalStrengthCallbackLocked(
@NonNull NetworkCapabilities capabilities) {
- if (!capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
+ if (!capabilities.hasTransport(TRANSPORT_CELLULAR)) {
return;
}
ArraySet<Integer> activeIds = new ArraySet<>();
for (int i = 0, size = mAvailableNetworks.size(); i < size; ++i) {
- NetworkCapabilities nc = mAvailableNetworks.valueAt(i);
- if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
- activeIds.addAll(nc.getSubscriptionIds());
+ final CachedNetworkMetadata metadata = mAvailableNetworks.valueAt(i);
+ if (metadata == null || metadata.networkCapabilities == null) {
+ continue;
+ }
+ if (metadata.networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ activeIds.addAll(metadata.networkCapabilities.getSubscriptionIds());
}
}
if (DEBUG) {
@@ -1573,6 +1708,57 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
+ @VisibleForTesting
+ class CcConfig {
+ private boolean mFlexIsEnabled = FlexibilityController.FcConfig.DEFAULT_FLEXIBILITY_ENABLED;
+ private boolean mShouldReprocessNetworkCapabilities = false;
+
+ /**
+ * Prefix to use with all constant keys in order to "sub-namespace" the keys.
+ * "conn_" is used for legacy reasons.
+ */
+ private static final String CC_CONFIG_PREFIX = "conn_";
+
+ @VisibleForTesting
+ static final String KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY =
+ CC_CONFIG_PREFIX + "avoid_undefined_transport_affinity";
+
+ private static final boolean DEFAULT_AVOID_UNDEFINED_TRANSPORT_AFFINITY = false;
+
+ /**
+ * If true, will avoid network transports that don't have an explicitly defined affinity.
+ */
+ public boolean AVOID_UNDEFINED_TRANSPORT_AFFINITY =
+ DEFAULT_AVOID_UNDEFINED_TRANSPORT_AFFINITY;
+
+ @GuardedBy("mLock")
+ public void processConstantLocked(@NonNull DeviceConfig.Properties properties,
+ @NonNull String key) {
+ switch (key) {
+ case KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY:
+ final boolean avoid = properties.getBoolean(key,
+ DEFAULT_AVOID_UNDEFINED_TRANSPORT_AFFINITY);
+ if (AVOID_UNDEFINED_TRANSPORT_AFFINITY != avoid) {
+ AVOID_UNDEFINED_TRANSPORT_AFFINITY = avoid;
+ mShouldReprocessNetworkCapabilities = true;
+ }
+ break;
+ }
+ }
+
+ private void dump(IndentingPrintWriter pw) {
+ pw.println();
+ pw.print(ConnectivityController.class.getSimpleName());
+ pw.println(":");
+ pw.increaseIndent();
+
+ pw.print(KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY,
+ AVOID_UNDEFINED_TRANSPORT_AFFINITY).println();
+
+ pw.decreaseIndent();
+ }
+ }
+
private class UidDefaultNetworkCallback extends NetworkCallback {
private int mUid;
@Nullable
@@ -1676,6 +1862,18 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
+ private static class CachedNetworkMetadata {
+ public NetworkCapabilities networkCapabilities;
+ public boolean satisfiesTransportAffinities;
+
+ public String toString() {
+ return "CNM{"
+ + networkCapabilities.toString()
+ + ", satisfiesTransportAffinities=" + satisfiesTransportAffinities
+ + "}";
+ }
+ }
+
private static class UidStats {
public final int uid;
public int baseBias;
@@ -1739,6 +1937,17 @@ public final class ConnectivityController extends RestrictingController implemen
}
}
+ @VisibleForTesting
+ @NonNull
+ CcConfig getCcConfig() {
+ return mCcConfig;
+ }
+
+ @Override
+ public void dumpConstants(IndentingPrintWriter pw) {
+ mCcConfig.dump(pw);
+ }
+
@GuardedBy("mLock")
@Override
public void dumpControllerStateLocked(IndentingPrintWriter pw,
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 0e03ea1ebe7d..70f9a52f3299 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
@@ -247,6 +247,12 @@ public final class FlexibilityController extends StateController {
mPrefetchLifeCycleStart.delete(userId);
}
+ boolean isEnabled() {
+ synchronized (mLock) {
+ return mFlexibilityEnabled;
+ }
+ }
+
/** Checks if the flexibility constraint is actively satisfied for a given job. */
@GuardedBy("mLock")
boolean isFlexibilitySatisfiedLocked(JobStatus js) {
@@ -262,7 +268,8 @@ public final class FlexibilityController extends StateController {
int getNumSatisfiedRequiredConstraintsLocked(JobStatus js) {
return Integer.bitCount(mSatisfiedFlexibleConstraints)
// Connectivity is job-specific, so must be handled separately.
- + (js.getHasAccessToUnmetered() ? 1 : 0);
+ + (js.canApplyTransportAffinities()
+ && js.areTransportAffinitiesSatisfied() ? 1 : 0);
}
/**
@@ -495,7 +502,7 @@ public final class FlexibilityController extends StateController {
final int curPercent = getCurPercentOfLifecycleLocked(js, nowElapsed);
int toDrop = 0;
final int jsMaxFlexibleConstraints = NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS
- + (js.getPreferUnmetered() ? 1 : 0);
+ + (js.canApplyTransportAffinities() ? 1 : 0);
for (int i = 0; i < jsMaxFlexibleConstraints; i++) {
if (curPercent >= mPercentToDropConstraints[i]) {
toDrop++;
@@ -661,7 +668,6 @@ public final class FlexibilityController extends StateController {
}
}
- @VisibleForTesting
class FcConfig {
private boolean mShouldReevaluateConstraints = false;
@@ -682,7 +688,7 @@ public final class FlexibilityController extends StateController {
static final String KEY_RESCHEDULED_JOB_DEADLINE_MS =
FC_CONFIG_PREFIX + "rescheduled_job_deadline_ms";
- private static final boolean DEFAULT_FLEXIBILITY_ENABLED = false;
+ static final boolean DEFAULT_FLEXIBILITY_ENABLED = false;
@VisibleForTesting
static final long DEFAULT_DEADLINE_PROXIMITY_LIMIT_MS = 15 * MINUTE_IN_MILLIS;
@VisibleForTesting
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 cb6cc2bd58aa..d6ada4cd7fdc 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
@@ -16,7 +16,6 @@
package com.android.server.job.controllers;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
@@ -163,9 +162,6 @@ public final class JobStatus {
*/
private int mNumDroppedFlexibleConstraints;
- /** If the job is going to be passed an unmetered network. */
- private boolean mHasAccessToUnmetered;
-
/** If the effective bucket has been downgraded once due to being buggy. */
private boolean mIsDowngradedDueToBuggyApp;
@@ -562,11 +558,10 @@ public final class JobStatus {
/** The job's dynamic requirements have been satisfied. */
private boolean mReadyDynamicSatisfied;
- /**
- * The job prefers an unmetered network if it has the connectivity constraint but is
- * okay with any meteredness.
- */
- private final boolean mPreferUnmetered;
+ /** Whether to apply the optimization transport preference logic to this job. */
+ private final boolean mCanApplyTransportAffinities;
+ /** True if the optimization transport preference is satisfied for this job. */
+ private boolean mTransportAffinitiesSatisfied;
/** The reason a job most recently went from ready to not ready. */
private int mReasonReadyToUnready = JobParameters.STOP_REASON_UNDEFINED;
@@ -671,12 +666,12 @@ public final class JobStatus {
}
mHasExemptedMediaUrisOnly = exemptedMediaUrisOnly;
- mPreferUnmetered = job.getRequiredNetwork() != null
- && !job.getRequiredNetwork().hasCapability(NET_CAPABILITY_NOT_METERED);
+ mCanApplyTransportAffinities = job.getRequiredNetwork() != null
+ && job.getRequiredNetwork().getTransportTypes().length == 0;
final boolean lacksSomeFlexibleConstraints =
((~requiredConstraints) & SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS) != 0
- || mPreferUnmetered;
+ || mCanApplyTransportAffinities;
final boolean satisfiesMinWindowException =
(latestRunTimeElapsedMillis - earliestRunTimeElapsedMillis)
>= MIN_WINDOW_FOR_FLEXIBILITY_MS;
@@ -688,7 +683,7 @@ public final class JobStatus {
&& (numFailures + numSystemStops) != 1
&& lacksSomeFlexibleConstraints) {
mNumRequiredFlexibleConstraints =
- NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mPreferUnmetered ? 1 : 0);
+ NUM_SYSTEM_WIDE_FLEXIBLE_CONSTRAINTS + (mCanApplyTransportAffinities ? 1 : 0);
requiredConstraints |= CONSTRAINT_FLEXIBLE;
} else {
mNumRequiredFlexibleConstraints = 0;
@@ -1585,17 +1580,16 @@ public final class JobStatus {
mOriginalLatestRunTimeElapsedMillis = latestRunTimeElapsed;
}
- /** Sets the jobs access to an unmetered network. */
- void setHasAccessToUnmetered(boolean access) {
- mHasAccessToUnmetered = access;
+ boolean areTransportAffinitiesSatisfied() {
+ return mTransportAffinitiesSatisfied;
}
- boolean getHasAccessToUnmetered() {
- return mHasAccessToUnmetered;
+ void setTransportAffinitiesSatisfied(boolean isSatisfied) {
+ mTransportAffinitiesSatisfied = isSatisfied;
}
- boolean getPreferUnmetered() {
- return mPreferUnmetered;
+ boolean canApplyTransportAffinities() {
+ return mCanApplyTransportAffinities;
}
@JobParameters.StopReason
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
index 64e86f9ab1fd..10f8510c7c70 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/ConnectivityControllerTest.java
@@ -24,7 +24,9 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_TEST;
import static android.net.NetworkCapabilities.TRANSPORT_VPN;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -38,6 +40,10 @@ import static com.android.server.job.Flags.FLAG_RELAX_PREFETCH_CONNECTIVITY_CONS
import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
+import static com.android.server.job.controllers.ConnectivityController.CcConfig.KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY;
+import static com.android.server.job.controllers.ConnectivityController.TRANSPORT_AFFINITY_AVOID;
+import static com.android.server.job.controllers.ConnectivityController.TRANSPORT_AFFINITY_PREFER;
+import static com.android.server.job.controllers.ConnectivityController.TRANSPORT_AFFINITY_UNDEFINED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -64,16 +70,19 @@ import android.net.ConnectivityManager.NetworkCallback;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
+import android.net.NetworkRequest;
import android.os.Build;
import android.os.Looper;
import android.os.SystemClock;
import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.DeviceConfig;
import android.telephony.CellSignalStrength;
import android.telephony.SignalStrength;
import android.telephony.TelephonyCallback;
import android.telephony.TelephonyManager;
import android.util.DataUnit;
+import com.android.server.AppSchedulingModuleThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerInternal;
import com.android.server.job.JobSchedulerService;
@@ -114,6 +123,7 @@ public class ConnectivityControllerTest {
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private Constants mConstants;
+ private DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder;
private FlexibilityController mFlexibilityController;
private static final int UID_RED = 10001;
@@ -135,6 +145,9 @@ public class ConnectivityControllerTest {
LocalServices.removeServiceForTest(JobSchedulerInternal.class);
LocalServices.addService(JobSchedulerInternal.class, mock(JobSchedulerInternal.class));
+ mDeviceConfigPropertiesBuilder =
+ new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_JOB_SCHEDULER);
+
// Freeze the clocks at this moment in time
JobSchedulerService.sSystemClock =
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
@@ -164,7 +177,7 @@ public class ConnectivityControllerTest {
when(mPackageManager.hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE)).thenReturn(false);
mFlexibilityController =
- new FlexibilityController(mService, mock(PrefetchController.class));
+ spy(new FlexibilityController(mService, mock(PrefetchController.class)));
}
@Test
@@ -954,6 +967,12 @@ public class ConnectivityControllerTest {
@Test
public void testUpdates() throws Exception {
+ ConnectivityController.sNetworkTransportAffinities.put(
+ NetworkCapabilities.TRANSPORT_CELLULAR, TRANSPORT_AFFINITY_AVOID);
+ ConnectivityController.sNetworkTransportAffinities.put(
+ NetworkCapabilities.TRANSPORT_WIFI, TRANSPORT_AFFINITY_PREFER);
+ ConnectivityController.sNetworkTransportAffinities.put(
+ NetworkCapabilities.TRANSPORT_TEST, TRANSPORT_AFFINITY_UNDEFINED);
final ArgumentCaptor<NetworkCallback> callbackCaptor =
ArgumentCaptor.forClass(NetworkCallback.class);
doNothing().when(mConnManager).registerNetworkCallback(any(), callbackCaptor.capture());
@@ -966,16 +985,24 @@ public class ConnectivityControllerTest {
doNothing().when(mConnManager).registerDefaultNetworkCallbackForUid(
eq(UID_BLUE), blueCallbackCaptor.capture(), any());
+ doReturn(true).when(mFlexibilityController).isEnabled();
+
final ConnectivityController controller = new ConnectivityController(mService,
mFlexibilityController);
-
final Network meteredNet = mock(Network.class);
final NetworkCapabilities meteredCaps = createCapabilitiesBuilder().build();
final Network unmeteredNet = mock(Network.class);
final NetworkCapabilities unmeteredCaps = createCapabilitiesBuilder()
.addCapability(NET_CAPABILITY_NOT_METERED)
.build();
+ final NetworkCapabilities meteredWifiCaps = createCapabilitiesBuilder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build();
+ final NetworkCapabilities unmeteredCelullarCaps = createCapabilitiesBuilder()
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .addTransportType(TRANSPORT_CELLULAR)
+ .build();
final JobStatus red = createJobStatus(createJob()
.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
@@ -983,11 +1010,29 @@ public class ConnectivityControllerTest {
final JobStatus blue = createJobStatus(createJob()
.setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY), UID_BLUE);
- assertFalse(red.getPreferUnmetered());
- assertTrue(blue.getPreferUnmetered());
+ final JobStatus red2 = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetwork(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR)
+ .build()),
+ UID_RED);
+ final JobStatus blue2 = createJobStatus(createJob()
+ .setEstimatedNetworkBytes(DataUnit.MEBIBYTES.toBytes(1), 0)
+ .setRequiredNetwork(
+ new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_WIFI)
+ .build()),
+ UID_BLUE);
+ assertTrue(red.canApplyTransportAffinities());
+ assertTrue(blue.canApplyTransportAffinities());
+ assertFalse(red2.canApplyTransportAffinities());
+ assertFalse(blue2.canApplyTransportAffinities());
controller.maybeStartTrackingJobLocked(red, null);
controller.maybeStartTrackingJobLocked(blue, null);
+ controller.maybeStartTrackingJobLocked(red2, null);
+ controller.maybeStartTrackingJobLocked(blue2, null);
final NetworkCallback generalCallback = callbackCaptor.getValue();
final NetworkCallback redCallback = redCallbackCaptor.getValue();
final NetworkCallback blueCallback = blueCallbackCaptor.getValue();
@@ -998,9 +1043,13 @@ public class ConnectivityControllerTest {
answerNetwork(generalCallback, blueCallback, null, null, null);
assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(red.getHasAccessToUnmetered());
assertFalse(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(blue.getHasAccessToUnmetered());
+ assertFalse(red2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
}
// Metered network
@@ -1011,12 +1060,26 @@ public class ConnectivityControllerTest {
generalCallback.onCapabilitiesChanged(meteredNet, meteredCaps);
assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(red.getHasAccessToUnmetered());
assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(blue.getHasAccessToUnmetered());
+ assertFalse(red2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ // No transport is specified. Accept the network for transport affinity.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, false);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertTrue(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
+ // No transport is specified. Avoid the network for transport affinity.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, true);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
}
- // Unmetered network background
+ // Unmetered network background for general; metered network for apps
{
answerNetwork(generalCallback, redCallback, meteredNet, meteredNet, meteredCaps);
answerNetwork(generalCallback, blueCallback, meteredNet, meteredNet, meteredCaps);
@@ -1024,10 +1087,22 @@ public class ConnectivityControllerTest {
generalCallback.onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(red.getHasAccessToUnmetered());
-
assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(blue.getHasAccessToUnmetered());
+
+ // No transport is specified. Accept the network for transport affinity.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, false);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertTrue(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
+ // No transport is specified. Avoid the network for transport affinity.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, true);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
}
// Lost metered network
@@ -1038,10 +1113,7 @@ public class ConnectivityControllerTest {
generalCallback.onLost(meteredNet);
assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(red.getHasAccessToUnmetered());
-
assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertTrue(blue.getHasAccessToUnmetered());
}
// Specific UID was blocked
@@ -1052,9 +1124,99 @@ public class ConnectivityControllerTest {
generalCallback.onCapabilitiesChanged(unmeteredNet, unmeteredCaps);
assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertFalse(red.getHasAccessToUnmetered());
assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
- assertTrue(blue.getHasAccessToUnmetered());
+ }
+
+ // Metered wifi
+ {
+ answerNetwork(generalCallback, redCallback, null, meteredNet, meteredWifiCaps);
+ answerNetwork(generalCallback, blueCallback, unmeteredNet, meteredNet, meteredWifiCaps);
+
+ generalCallback.onCapabilitiesChanged(meteredNet, meteredWifiCaps);
+
+ assertFalse(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(red2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+ // Wifi is preferred.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, false);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertTrue(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertTrue(blue2.areTransportAffinitiesSatisfied());
+ // Wifi is preferred.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, true);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertTrue(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertTrue(blue2.areTransportAffinitiesSatisfied());
+ }
+
+ // Unmetered cellular
+ {
+ answerNetwork(generalCallback, redCallback, meteredNet,
+ unmeteredNet, unmeteredCelullarCaps);
+ answerNetwork(generalCallback, blueCallback, meteredNet,
+ unmeteredNet, unmeteredCelullarCaps);
+
+ generalCallback.onCapabilitiesChanged(unmeteredNet, unmeteredCelullarCaps);
+
+ assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(red2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+ // Cellular is avoided.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, false);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
+ // Cellular is avoided.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, true);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
+ }
+
+ // Undefined affinity
+ final NetworkCapabilities unmeteredTestCaps = createCapabilitiesBuilder()
+ .addCapability(NET_CAPABILITY_NOT_METERED)
+ .addTransportType(TRANSPORT_TEST)
+ .build();
+ {
+ answerNetwork(generalCallback, redCallback, unmeteredNet,
+ unmeteredNet, unmeteredTestCaps);
+ answerNetwork(generalCallback, blueCallback, unmeteredNet,
+ unmeteredNet, unmeteredTestCaps);
+
+ generalCallback.onCapabilitiesChanged(unmeteredNet, unmeteredTestCaps);
+
+ assertTrue(red.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertTrue(blue.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(red2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+ assertFalse(blue2.isConstraintSatisfied(JobStatus.CONSTRAINT_CONNECTIVITY));
+
+ // Undefined is preferred.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, false);
+ controller.onConstantsUpdatedLocked();
+ assertTrue(red.areTransportAffinitiesSatisfied());
+ assertTrue(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
+ // Undefined is avoided.
+ setDeviceConfigBoolean(controller, KEY_AVOID_UNDEFINED_TRANSPORT_AFFINITY, true);
+ controller.onConstantsUpdatedLocked();
+ assertFalse(red.areTransportAffinitiesSatisfied());
+ assertFalse(blue.areTransportAffinitiesSatisfied());
+ assertFalse(red2.areTransportAffinitiesSatisfied());
+ assertFalse(blue2.areTransportAffinitiesSatisfied());
}
}
@@ -1462,4 +1624,24 @@ public class ConnectivityControllerTest {
return new JobStatus(job.build(), uid, null, -1, 0, null, null,
earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0, 0, 0, null, 0, 0);
}
+
+ private void setDeviceConfigBoolean(ConnectivityController connectivityController,
+ String key, boolean val) {
+ mDeviceConfigPropertiesBuilder.setBoolean(key, val);
+ synchronized (connectivityController.mLock) {
+ connectivityController.prepareForUpdatedConstantsLocked();
+ mFlexibilityController.prepareForUpdatedConstantsLocked();
+ connectivityController.getCcConfig()
+ .processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
+ mFlexibilityController.getFcConfig()
+ .processConstantLocked(mDeviceConfigPropertiesBuilder.build(), key);
+ connectivityController.onConstantsUpdatedLocked();
+ mFlexibilityController.onConstantsUpdatedLocked();
+ }
+ waitForNonDelayedMessagesProcessed();
+ }
+
+ private void waitForNonDelayedMessagesProcessed() {
+ AppSchedulingModuleThread.getHandler().runWithScissors(() -> {}, 15_000);
+ }
}
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 bb9dcf1c85cc..ee68b6d0e546 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
@@ -692,15 +692,15 @@ public class FlexibilityControllerTest {
}
@Test
- public void testConnectionToUnMeteredNetwork() {
+ public void testTransportAffinity() {
JobInfo.Builder jb = createJob(0).setRequiredNetworkType(NETWORK_TYPE_ANY);
JobStatus js = createJobStatus("testTopAppBypass", jb);
synchronized (mFlexibilityController.mLock) {
- js.setHasAccessToUnmetered(false);
+ js.setTransportAffinitiesSatisfied(false);
assertEquals(0, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
- js.setHasAccessToUnmetered(true);
+ js.setTransportAffinitiesSatisfied(true);
assertEquals(1, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
- js.setHasAccessToUnmetered(false);
+ js.setTransportAffinitiesSatisfied(false);
assertEquals(0, mFlexibilityController.getNumSatisfiedRequiredConstraintsLocked(js));
}
}
@@ -937,10 +937,10 @@ public class FlexibilityControllerTest {
ArraySet<JobStatus> jobs = trackedJobs.get(i);
for (int j = 0; j < jobs.size(); j++) {
JobStatus js = jobs.valueAt(j);
- final int isUnMetered = js.getPreferUnmetered()
- && js.getHasAccessToUnmetered() ? 1 : 0;
+ final int transportAffinitySatisfied = js.canApplyTransportAffinities()
+ && js.areTransportAffinitiesSatisfied() ? 1 : 0;
assertEquals(js.getNumRequiredFlexibleConstraints()
- <= numSatisfiedConstraints + isUnMetered,
+ <= numSatisfiedConstraints + transportAffinitySatisfied,
js.isConstraintSatisfied(CONSTRAINT_FLEXIBLE));
}
}