Ignore loss of IPv6 provisioning when not avoiding bad Wi-Fi.

Bug: 31827713
Change-Id: I81471f2f3e6c1c4d7bdfebc9dd321bb9d76ad0b6
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index de2c0c6..d0ab606 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -657,7 +657,7 @@
     // object that is a correct and complete assessment of what changed, taking
     // account of the asymmetries described in the comments in this function.
     // Then switch to using it everywhere (IpReachabilityMonitor, etc.).
-    private static ProvisioningChange compareProvisioning(
+    private ProvisioningChange compareProvisioning(
             LinkProperties oldLp, LinkProperties newLp) {
         ProvisioningChange delta;
 
@@ -688,6 +688,21 @@
         final boolean lostIPv4Address = oldLp.hasIPv4Address() && !newLp.hasIPv4Address();
         final boolean lostIPv6Router = oldLp.hasIPv6DefaultRoute() && !newLp.hasIPv6DefaultRoute();
 
+        // If bad wifi avoidance is disabled, then ignore IPv6 loss of
+        // provisioning. Otherwise, when a hotspot that loses Internet
+        // access sends out a 0-lifetime RA to its clients, the clients
+        // will disconnect and then reconnect, avoiding the bad hotspot,
+        // instead of getting stuck on the bad hotspot. http://b/31827713 .
+        //
+        // This is incorrect because if the hotspot then regains Internet
+        // access with a different prefix, TCP connections on the
+        // deprecated addresses will remain stuck.
+        //
+        // Note that we can still be disconnected by IpReachabilityMonitor
+        // if the IPv6 default gateway (but not the IPv6 DNS servers; see
+        // accompanying code in IpReachabilityMonitor) is unreachable.
+        final boolean ignoreIPv6ProvisioningLoss = !mAvoidBadWifiTracker.currentValue();
+
         // Additionally:
         //
         // Partial configurations (e.g., only an IPv4 address with no DNS
@@ -700,7 +715,7 @@
         // Because on such a network isProvisioned() will always return false,
         // delta will never be LOST_PROVISIONING. So check for loss of
         // provisioning here too.
-        if (lostIPv4Address || lostIPv6) {
+        if (lostIPv4Address || (lostIPv6 && !ignoreIPv6ProvisioningLoss)) {
             delta = ProvisioningChange.LOST_PROVISIONING;
         }
 
@@ -709,7 +724,7 @@
         // If the previous link properties had a global IPv6 address and an
         // IPv6 default route then also consider the loss of that default route
         // to be a loss of provisioning. See b/27962810.
-        if (oldLp.hasGlobalIPv6Address() && lostIPv6Router) {
+        if (oldLp.hasGlobalIPv6Address() && (lostIPv6Router && !ignoreIPv6ProvisioningLoss)) {
             delta = ProvisioningChange.LOST_PROVISIONING;
         }