Conditionally accept loss of on-link IPv6 DNS servers

Permit this if and only if we're not "avoiding bad wifi" in general.

Bug: 31827713
Change-Id: I0874ec2d1d09e913ccdbe9f6e178090400808a04
(cherry picked from commit 5b437d6ff91116f25be946e07d5d90cd25c372a4)
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index fc91f51..d5dd15f 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -1068,7 +1068,8 @@
                             public void notifyLost(InetAddress ip, String logMsg) {
                                 mCallback.onReachabilityLost(logMsg);
                             }
-                        });
+                        },
+                        mAvoidBadWifiTracker);
             }
         }
 
diff --git a/services/net/java/android/net/ip/IpReachabilityMonitor.java b/services/net/java/android/net/ip/IpReachabilityMonitor.java
index c6da3c3..a6bb40c 100644
--- a/services/net/java/android/net/ip/IpReachabilityMonitor.java
+++ b/services/net/java/android/net/ip/IpReachabilityMonitor.java
@@ -34,6 +34,7 @@
 import android.net.netlink.StructNdaCacheInfo;
 import android.net.netlink.StructNdMsg;
 import android.net.netlink.StructNlMsgHdr;
+import android.net.util.AvoidBadWifiTracker;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.system.ErrnoException;
@@ -42,6 +43,7 @@
 import android.util.Log;
 
 import java.io.InterruptedIOException;
+import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
@@ -149,6 +151,7 @@
     private final String mInterfaceName;
     private final int mInterfaceIndex;
     private final Callback mCallback;
+    private final AvoidBadWifiTracker mAvoidBadWifiTracker;
     private final NetlinkSocketObserver mNetlinkSocketObserver;
     private final Thread mObserverThread;
     private final IpConnectivityLog mMetricsLog = new IpConnectivityLog();
@@ -219,8 +222,12 @@
         return errno;
     }
 
-    public IpReachabilityMonitor(Context context, String ifName, Callback callback)
-                throws IllegalArgumentException {
+    public IpReachabilityMonitor(Context context, String ifName, Callback callback) {
+        this(context, ifName, callback, null);
+    }
+
+    public IpReachabilityMonitor(Context context, String ifName, Callback callback,
+            AvoidBadWifiTracker tracker) throws IllegalArgumentException {
         mInterfaceName = ifName;
         int ifIndex = -1;
         try {
@@ -232,6 +239,7 @@
         mWakeLock = ((PowerManager) context.getSystemService(Context.POWER_SERVICE)).newWakeLock(
                 PowerManager.PARTIAL_WAKE_LOCK, TAG + "." + mInterfaceName);
         mCallback = callback;
+        mAvoidBadWifiTracker = tracker;
         mNetlinkSocketObserver = new NetlinkSocketObserver();
         mObserverThread = new Thread(mNetlinkSocketObserver);
         mObserverThread.start();
@@ -355,7 +363,11 @@
                         whatIfLp.removeRoute(route);
                     }
                 }
-                whatIfLp.removeDnsServer(ip);
+
+                if (avoidingBadLinks() || !(ip instanceof Inet6Address)) {
+                    // We should do this unconditionally, but alas we cannot: b/31827713.
+                    whatIfLp.removeDnsServer(ip);
+                }
             }
 
             delta = LinkProperties.compareProvisioning(mLinkProperties, whatIfLp);
@@ -373,6 +385,10 @@
         logNudFailed(delta);
     }
 
+    private boolean avoidingBadLinks() {
+        return (mAvoidBadWifiTracker != null) ? mAvoidBadWifiTracker.currentValue() : true;
+    }
+
     public void probeAll() {
         Set<InetAddress> ipProbeList = new HashSet<InetAddress>();
         synchronized (mLock) {