Nat464Xlat: clat management cleanup

This patch does some minor refactoring of clat starting/stopping code:
 - remove unused LinkProperties arguments in updateClat
 - remove unused Context argument in Nat464Xlat ctor
 - introduce ensureClatIsStarted and ensureClatIsStopped methods and
   simplify updateClat
 - add clatd to NetworkAgentInfo toString() method
 - clarify some comments

This changes prepare for moving BaseNetworkObserver callbacks to
ConnectivityService.

Bug: 62997041
Bug: 64571917
Test: runtest frameworks-net
      manually connected to IPv6 only network and went to test-ipv6.com

Merged-In: Idb204784614cfe700f73255a7a7b78c5e9ee6eca
Merged-In: Ic3808a1afe48efac745b1b378fb12cc5678918ec
Merged-In: Ia769aef6ef8b258f44f8979003d271c96264f1b5
Merged-In: I1a19e6fbb0cb13262e90b171d861062469078fb6
Merged-In: I06661bd6bd1456ba34a3bbdb52c120ac01da9d61
Merged-In: Ifccff9f3cfccdb2cdddf2f07561f0787a48bc0f8

(cherry picked from commit b577d65825e623a9868664486482ed137b98b504)

Change-Id: Ibb02888633df9643030336c4dbea6c569a47554c
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index ec83a03..adf536b 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2269,7 +2269,7 @@
             }
             nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
             mNetworkAgentInfos.remove(msg.replyTo);
-            updateClat(null, nai.linkProperties, nai);
+            maybeStopClat(nai);
             synchronized (mNetworkForNetId) {
                 // Remove the NetworkAgent, but don't mark the netId as
                 // available until we've told netd to delete it below.
@@ -4382,7 +4382,8 @@
         updateRoutes(newLp, oldLp, netId);
         updateDnses(newLp, oldLp, netId);
 
-        updateClat(newLp, oldLp, networkAgent);
+        // Start or stop clat accordingly to network state.
+        updateClat(networkAgent);
         if (isDefaultNetwork(networkAgent)) {
             handleApplyDefaultProxy(newLp.getHttpProxy());
         } else {
@@ -4397,18 +4398,32 @@
         mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
     }
 
-    private void updateClat(LinkProperties newLp, LinkProperties oldLp, NetworkAgentInfo nai) {
-        final boolean wasRunningClat = nai.clatd != null && nai.clatd.isStarted();
-        final boolean shouldRunClat = Nat464Xlat.requiresClat(nai);
-
-        if (!wasRunningClat && shouldRunClat) {
-            nai.clatd = new Nat464Xlat(mContext, mNetd, mTrackerHandler, nai);
-            nai.clatd.start();
-        } else if (wasRunningClat && !shouldRunClat) {
-            nai.clatd.stop();
+    private void updateClat(NetworkAgentInfo nai) {
+        if (Nat464Xlat.requiresClat(nai)) {
+            maybeStartClat(nai);
+        } else {
+            maybeStopClat(nai);
         }
     }
 
+    /** Ensure clat has started for this network. */
+    private void maybeStartClat(NetworkAgentInfo nai) {
+        if (nai.clatd != null && nai.clatd.isStarted()) {
+            return;
+        }
+        nai.clatd = new Nat464Xlat(mNetd, mTrackerHandler, nai);
+        nai.clatd.start();
+    }
+
+    /** Ensure clat has stopped for this network. */
+    private void maybeStopClat(NetworkAgentInfo nai) {
+        if (nai.clatd == null) {
+            return;
+        }
+        nai.clatd.stop();
+        nai.clatd = null;
+    }
+
     private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) {
         // Marks are only available on WiFi interaces. Checking for
         // marks on unsupported interfaces is harmless.
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index b390884..27426d7 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -18,7 +18,6 @@
 
 import java.net.Inet4Address;
 
-import android.content.Context;
 import android.net.InterfaceConfiguration;
 import android.net.ConnectivityManager;
 import android.net.LinkAddress;
@@ -35,17 +34,18 @@
 import com.android.internal.util.ArrayUtils;
 
 /**
- * @hide
- *
  * Class to manage a 464xlat CLAT daemon.
+ *
+ * @hide
  */
 public class Nat464Xlat extends BaseNetworkObserver {
-    private static final String TAG = "Nat464Xlat";
+    private static final String TAG = Nat464Xlat.class.getSimpleName();
 
     // This must match the interface prefix in clatd.c.
     private static final String CLAT_PREFIX = "v4-";
 
-    // The network types we will start clatd on.
+    // The network types we will start clatd on,
+    // allowing clat only on networks for which we can support IPv6-only.
     private static final int[] NETWORK_TYPES = {
             ConnectivityManager.TYPE_MOBILE,
             ConnectivityManager.TYPE_WIFI,
@@ -76,9 +76,7 @@
     private String mIface;
     private boolean mIsRunning;
 
-    public Nat464Xlat(
-            Context context, INetworkManagementService nmService,
-            Handler handler, NetworkAgentInfo nai) {
+    public Nat464Xlat(INetworkManagementService nmService, Handler handler, NetworkAgentInfo nai) {
         mNMService = nmService;
         mHandler = handler;
         mNetwork = nai;
@@ -90,13 +88,14 @@
      * @return true if the network requires clat, false otherwise.
      */
     public static boolean requiresClat(NetworkAgentInfo nai) {
+        // TODO: migrate to NetworkCapabilities.TRANSPORT_*.
         final int netType = nai.networkInfo.getType();
+        final boolean supported = ArrayUtils.contains(NETWORK_TYPES, nai.networkInfo.getType());
         final boolean connected = nai.networkInfo.isConnected();
+        // We only run clat on networks that don't have a native IPv4 address.
         final boolean hasIPv4Address =
-                (nai.linkProperties != null) ? nai.linkProperties.hasIPv4Address() : false;
-        // Only support clat on mobile and wifi for now, because these are the only IPv6-only
-        // networks we can connect to.
-        return connected && !hasIPv4Address && ArrayUtils.contains(NETWORK_TYPES, netType);
+                (nai.linkProperties != null) && nai.linkProperties.hasIPv4Address();
+        return supported && connected && !hasIPv4Address;
     }
 
     /**
@@ -227,6 +226,7 @@
     }
 
     private void maybeSetIpv6NdOffload(String iface, boolean on) {
+        // TODO: migrate to NetworkCapabilities.TRANSPORT_*.
         if (mNetwork.networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
             return;
         }
@@ -286,4 +286,9 @@
             }
         }
     }
+
+    @Override
+    public String toString() {
+        return "mBaseIface: " + mBaseIface + ", mIface: " + mIface + ", mIsRunning: " + mIsRunning;
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 2a618bc..872923a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -562,13 +562,13 @@
                 "acceptUnvalidated{" + networkMisc.acceptUnvalidated + "} " +
                 "everCaptivePortalDetected{" + everCaptivePortalDetected + "} " +
                 "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} " +
+                "clat{" + clatd + "} " +
                 "}";
     }
 
     public String name() {
         return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" +
-                networkInfo.getSubtypeName() + ") - " +
-                (network == null ? "null" : network.toString()) + "]";
+                networkInfo.getSubtypeName() + ") - " + Objects.toString(network) + "]";
     }
 
     // Enables sorting in descending order of score.