Update the avoid bad wifi settings on the handler thread.

Currently, every call to avoidBadWifi fetches the current value
of the config variable and setting whenever it is called. This
means that the score of an unvalidated wifi network can
unpredictably change at any time, creating a data race.

Instead, persist the value and only update it when something
changes.

Bug: 31075769
Change-Id: I0f4e0e742c91ef77fabc95d3ebb494338396aca5
(cherry picked from commit 2618c1b7f0c8816375e662b89eceb8b2c69237e7)
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 66d23a2..59c8840 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -851,6 +851,15 @@
                 Settings.Global.NETWORK_SWITCH_NOTIFICATION_RATE_LIMIT_MILLIS,
                 LingerMonitor.DEFAULT_NOTIFICATION_RATE_LIMIT_MILLIS);
         mLingerMonitor = new LingerMonitor(mContext, mNotifier, dailyLimit, rateLimit);
+
+        intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            public void onReceive(Context context, Intent intent) {
+                mHandler.sendEmptyMessage(EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI);
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+        updateAvoidBadWifi();
     }
 
     private NetworkRequest createInternetRequestForTransport(int transportType) {
@@ -2719,17 +2728,29 @@
                 PROMPT_UNVALIDATED_DELAY_MS);
     }
 
-    @VisibleForTesting
+    private boolean mAvoidBadWifi;
+
     public boolean avoidBadWifi() {
+        return mAvoidBadWifi;
+    }
+
+    @VisibleForTesting
+    public boolean updateAvoidBadWifi() {
         // There are two modes: either we always automatically avoid unvalidated wifi, or we show a
         // dialog and don't switch to it. The behaviour is controlled by the NETWORK_AVOID_BAD_WIFI
         // setting. If the setting has no value, then the value is taken from the config value,
         // which can be changed via OEM/carrier overlays.
+        //
+        // The only valid values for NETWORK_AVOID_BAD_WIFI are null and unset. Currently, the unit
+        // test uses 0 in order to avoid having to mock out fetching the carrier setting.
         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;
+
+        boolean prev = mAvoidBadWifi;
+        mAvoidBadWifi = (avoid == 1);
+        return mAvoidBadWifi != prev;
     }
 
     private void showValidationNotification(NetworkAgentInfo nai, NotificationType type) {
@@ -2868,7 +2889,9 @@
                     break;
                 }
                 case EVENT_CONFIGURE_NETWORK_AVOID_BAD_WIFI: {
-                    rematchAllNetworksAndRequests(null, 0);
+                    if (updateAvoidBadWifi()) {
+                        rematchAllNetworksAndRequests(null, 0);
+                    }
                     break;
                 }
                 case EVENT_REQUEST_LINKPROPERTIES: