diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java index e6bc5015b4..120486c1df 100755 --- a/service/src/com/android/server/ConnectivityService.java +++ b/service/src/com/android/server/ConnectivityService.java @@ -391,7 +391,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // Timeout in case the "actively prefer bad wifi" feature is on private static final int ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS = 20 * 1000; // Timeout in case the "actively prefer bad wifi" feature is off - private static final int DONT_ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS = 8 * 1000; + private static final int DEFAULT_EVALUATION_TIMEOUT_MS = 8 * 1000; // Default to 30s linger time-out, and 5s for nascent network. Modifiable only for testing. private static final String LINGER_DELAY_PROPERTY = "persist.netmon.linger"; @@ -9939,10 +9939,25 @@ public class ConnectivityService extends IConnectivityManager.Stub networkAgent.networkMonitor().notifyNetworkConnected(params.linkProperties, params.networkCapabilities); } - final long delay = !avoidBadWifi() && activelyPreferBadWifi() - ? ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS - : DONT_ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS; - scheduleEvaluationTimeout(networkAgent.network, delay); + final long evaluationDelay; + if (!networkAgent.networkCapabilities.hasSingleTransport(TRANSPORT_WIFI)) { + // If the network is anything other than pure wifi, use the default timeout. + evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS; + } else if (networkAgent.networkAgentConfig.isExplicitlySelected()) { + // If the network is explicitly selected, use the default timeout because it's + // shorter and the user is likely staring at the screen expecting it to validate + // right away. + evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS; + } else if (avoidBadWifi() || !activelyPreferBadWifi()) { + // If avoiding bad wifi, or if not avoiding but also not preferring bad wifi + evaluationDelay = DEFAULT_EVALUATION_TIMEOUT_MS; + } else { + // It's wifi, automatically connected, and bad wifi is preferred : use the + // longer timeout to avoid the device switching to captive portals with bad + // signal or very slow response. + evaluationDelay = ACTIVELY_PREFER_BAD_WIFI_INITIAL_TIMEOUT_MS; + } + scheduleEvaluationTimeout(networkAgent.network, evaluationDelay); // Whether a particular NetworkRequest listen should cause signal strength thresholds to // be communicated to a particular NetworkAgent depends only on the network's immutable, diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java index 57c3acc9a2..a5cbb4c972 100755 --- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java +++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java @@ -2247,12 +2247,12 @@ public class ConnectivityServiceTest { mDestroySocketsWrapper.destroyLiveTcpSocketsByOwnerUids(ownerUids); } - final ArrayTrackRecord.ReadHead mScheduledEvaluationTimeouts = - new ArrayTrackRecord().newReadHead(); + final ArrayTrackRecord>.ReadHead mScheduledEvaluationTimeouts = + new ArrayTrackRecord>().newReadHead(); @Override public void scheduleEvaluationTimeout(@NonNull Handler handler, @NonNull final Network network, final long delayMs) { - mScheduledEvaluationTimeouts.add(delayMs); + mScheduledEvaluationTimeouts.add(new Pair<>(network.netId, delayMs)); super.scheduleEvaluationTimeout(handler, network, delayMs); } } @@ -6124,7 +6124,7 @@ public class ConnectivityServiceTest { } public void doTestPreferBadWifi(final boolean avoidBadWifi, - final boolean preferBadWifi, + final boolean preferBadWifi, final boolean explicitlySelected, @NonNull Predicate checkUnvalidationTimeout) throws Exception { // Pretend we're on a carrier that restricts switching away from bad wifi, and // depending on the parameter one that may indeed prefer bad wifi. @@ -6148,10 +6148,13 @@ public class ConnectivityServiceTest { mDefaultNetworkCallback.expectAvailableThenValidatedCallbacks(mCellAgent); mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI); + mWiFiAgent.explicitlySelected(explicitlySelected, false /* acceptUnvalidated */); mWiFiAgent.connect(false); wifiCallback.expectAvailableCallbacksUnvalidated(mWiFiAgent); - mDeps.mScheduledEvaluationTimeouts.poll(TIMEOUT_MS, t -> checkUnvalidationTimeout.test(t)); + assertNotNull(mDeps.mScheduledEvaluationTimeouts.poll(TIMEOUT_MS, + t -> t.first == mWiFiAgent.getNetwork().netId + && checkUnvalidationTimeout.test(t.second))); if (!avoidBadWifi && preferBadWifi) { expectUnvalidationCheckWillNotify(mWiFiAgent, NotificationType.LOST_INTERNET); @@ -6167,27 +6170,33 @@ public class ConnectivityServiceTest { // Starting with U this mode is no longer supported and can't actually be tested assumeFalse(mDeps.isAtLeastU()); doTestPreferBadWifi(false /* avoidBadWifi */, false /* preferBadWifi */, - timeout -> timeout < 14_000); + false /* explicitlySelected */, timeout -> timeout < 14_000); } @Test - public void testPreferBadWifi_doNotAvoid_doPrefer() throws Exception { + public void testPreferBadWifi_doNotAvoid_doPrefer_notExplicit() throws Exception { doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */, - timeout -> timeout > 14_000); + false /* explicitlySelected */, timeout -> timeout > 14_000); + } + + @Test + public void testPreferBadWifi_doNotAvoid_doPrefer_explicitlySelected() throws Exception { + doTestPreferBadWifi(false /* avoidBadWifi */, true /* preferBadWifi */, + true /* explicitlySelected */, timeout -> timeout < 14_000); } @Test public void testPreferBadWifi_doAvoid_doNotPrefer() throws Exception { // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway. doTestPreferBadWifi(true /* avoidBadWifi */, false /* preferBadWifi */, - timeout -> timeout < 14_000); + false /* explicitlySelected */, timeout -> timeout < 14_000); } @Test public void testPreferBadWifi_doAvoid_doPrefer() throws Exception { // If avoidBadWifi=true, then preferBadWifi should be irrelevant. Test anyway. doTestPreferBadWifi(true /* avoidBadWifi */, true /* preferBadWifi */, - timeout -> timeout < 14_000); + false /* explicitlySelected */, timeout -> timeout < 14_000); } @Test