Support ignoring penalty for bad wifi networks

This patch adds a way to configure devices so that a validated network
that becomes unvalidated is not penalized in the network scoring and
selection logic.

The intent is to prevent devices configured to do so from switching to a
lower scoring network such as cellular networks when a higher scoring
network such as wifi networks loses internet connectivity.

Bug: 31075769
Change-Id: Ie7e0f2607d214a178367fedfbef6c44768fa00a4
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5d0508c..4c30dc2 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2704,6 +2704,15 @@
                 PROMPT_UNVALIDATED_DELAY_MS);
     }
 
+    @VisibleForTesting
+    public boolean avoidBadWifi() {
+        int defaultAvoidBadWifi =
+            mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi);
+        int avoid = Settings.Global.getInt(mContext.getContentResolver(),
+            Settings.Global.NETWORK_AVOID_BAD_WIFI, defaultAvoidBadWifi);
+        return avoid == 1;
+    }
+
     private void handlePromptUnvalidated(Network network) {
         if (VDBG) log("handlePromptUnvalidated " + network);
         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 780be3c..3503eac 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -113,6 +113,7 @@
 // a NetworkRequest, ConnectivityService will cancel the future disconnection of the NetworkAgent's
 // AsyncChannel, and the network is no longer considered "lingering".
 public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
+
     public NetworkInfo networkInfo;
     // This Network object should always be used if possible, so as to encourage reuse of the
     // enclosed socket factory and connection pool.  Avoid creating other Network objects.
@@ -354,13 +355,20 @@
         }
 
         int score = currentScore;
-        if (!lastValidated && !pretendValidated) {
+        if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty()) {
             score -= UNVALIDATED_SCORE_PENALTY;
         }
         if (score < 0) score = 0;
         return score;
     }
 
+    // Return true on devices configured to ignore score penalty for wifi networks
+    // that become unvalidated (b/31075769).
+    private boolean ignoreWifiUnvalidationPenalty() {
+        boolean isWifi = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
+        return isWifi && !mConnService.avoidBadWifi() && everValidated;
+    }
+
     // Get the current score for this Network.  This may be modified from what the
     // NetworkAgent sent, as it has modifiers applied to it.
     public int getCurrentScore() {