summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Kweku Adams <kwekua@google.com> 2023-11-06 22:25:49 +0000
committer Kweku Adams <kwekua@google.com> 2023-11-06 22:43:30 +0000
commit366583d33138d8565e8fa774b3a8dbc05418de9a (patch)
treede8b5d9421f40a71302e8775ab5e9fb52e4d0adf
parent896c5c42c7a2dd9271957872fc1b29d96c1884ea (diff)
Add transport affinities for flex scheduling.
Switch the flex network behavior from unmetered vs metered to looking at network transports. Transport affinities indicate which transports are preferred for running jobs, and which ones the system should try to avoid, if possible. By default, when flex scheduling is enabled, the system will avoid running jobs on the cellular network and prefer running jobs on wifi and/or ethernet networks. Watches tend to send most traffic over the bluetooth network. However, there are plans to modify job network traffic in other ways for watches. For now, watches will be excluded from network flex scheduling until those plans are resolved. Bug: 236261941 Bug: 299329948 Bug: 299346198 Test: atest CtsJobSchedulerTestCases:ConnectivityConstraintTest Test: atest CtsJobSchedulerTestCases:FlexibilityConstraintTest Test: atest frameworks/base/services/tests/mockingservicestests/src/com/android/server/job Test: atest frameworks/base/services/tests/servicestests/src/com/android/server/job Change-Id: I675d72b18ae6ddc43fb1503d481ff9bb56c2dcb6
-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));
}
}