Make Ethernet interfaces more testable.

This CL adds a setIncludeTestInterfaces method to EthernetManager
that, when called, causes the Ethernet service to recognize and
manage test interfaces created by TestNetworkManager.

Bug: 150644681
Test: Tested by EthernetTetheringTest in same topic
Change-Id: I86eef7a93267f800dbfc8eafd307effa76a344ca
Merged-In: I86eef7a93267f800dbfc8eafd307effa76a344ca
(cherry picked from commit 4978dbd5fb6592fc4e7be08d02783752245da634)
diff --git a/java/com/android/server/ethernet/EthernetServiceImpl.java b/java/com/android/server/ethernet/EthernetServiceImpl.java
index 1cf38b4..3fc6aab 100644
--- a/java/com/android/server/ethernet/EthernetServiceImpl.java
+++ b/java/com/android/server/ethernet/EthernetServiceImpl.java
@@ -164,14 +164,23 @@
     }
 
     @Override
+    public void setIncludeTestInterfaces(boolean include) {
+        NetworkStack.checkNetworkStackPermissionOr(mContext,
+                android.Manifest.permission.NETWORK_SETTINGS);
+        mTracker.setIncludeTestInterfaces(include);
+    }
+
+    @Override
     public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        NetworkStack.checkNetworkStackPermissionOr(mContext,
+                android.Manifest.permission.NETWORK_SETTINGS);
         mTracker.requestTetheredInterface(callback);
     }
 
     @Override
     public void releaseTetheredInterface(ITetheredInterfaceCallback callback) {
-        NetworkStack.checkNetworkStackPermission(mContext);
+        NetworkStack.checkNetworkStackPermissionOr(mContext,
+                android.Manifest.permission.NETWORK_SETTINGS);
         mTracker.releaseTetheredInterface(callback);
     }
 
diff --git a/java/com/android/server/ethernet/EthernetTracker.java b/java/com/android/server/ethernet/EthernetTracker.java
index 58803d1..91453ab 100644
--- a/java/com/android/server/ethernet/EthernetTracker.java
+++ b/java/com/android/server/ethernet/EthernetTracker.java
@@ -16,6 +16,8 @@
 
 package com.android.server.ethernet;
 
+import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
+
 import android.annotation.Nullable;
 import android.content.Context;
 import android.net.IEthernetServiceListener;
@@ -68,8 +70,12 @@
     private final static String TAG = EthernetTracker.class.getSimpleName();
     private final static boolean DBG = EthernetNetworkFactory.DBG;
 
-    /** Product-dependent regular expression of interface names we track. */
-    private final String mIfaceMatch;
+    /**
+     * Interface names we track. This is a product-dependent regular expression, plus,
+     * if setIncludeTestInterfaces is true, any test interfaces.
+     */
+    private String mIfaceMatch;
+    private boolean mIncludeTestInterfaces = false;
 
     /** Mapping between {iface name | mac address} -> {NetworkCapabilities} */
     private final ConcurrentHashMap<String, NetworkCapabilities> mNetworkCapabilities =
@@ -111,8 +117,7 @@
         mNMService = INetworkManagementService.Stub.asInterface(b);
 
         // Interface match regex.
-        mIfaceMatch = context.getResources().getString(
-                com.android.internal.R.string.config_ethernet_iface_regex);
+        updateIfaceMatchRegexp();
 
         // Read default Ethernet interface configuration from resources
         final String[] interfaceConfigs = context.getResources().getStringArray(
@@ -187,6 +192,12 @@
         mListeners.unregister(listener);
     }
 
+    public void setIncludeTestInterfaces(boolean include) {
+        mIncludeTestInterfaces = include;
+        updateIfaceMatchRegexp();
+        trackAvailableInterfaces();
+    }
+
     public void requestTetheredInterface(ITetheredInterfaceCallback callback) {
         mHandler.post(() -> {
             if (!mTetheredInterfaceRequests.register(callback)) {
@@ -348,7 +359,8 @@
         if (DBG) Log.i(TAG, "maybeTrackInterface " + iface);
         // If we don't already track this interface, and if this interface matches
         // our regex, start tracking it.
-        if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)) {
+        if (!iface.matches(mIfaceMatch) || mFactory.hasInterface(iface)
+                || iface.equals(mDefaultInterface)) {
             return;
         }
 
@@ -572,6 +584,16 @@
         return new IpConfiguration(IpAssignment.DHCP, ProxySettings.NONE, null, null);
     }
 
+    private void updateIfaceMatchRegexp() {
+        final String testInterfaceMatch = TEST_TAP_PREFIX + ".*";
+        final String match = mContext.getResources().getString(
+                com.android.internal.R.string.config_ethernet_iface_regex);
+        mIfaceMatch = mIncludeTestInterfaces
+                ? "(" + match + "|" + TEST_TAP_PREFIX + "\\d+)"
+                : match;
+        Log.d(TAG, "Interface match regexp set to '" + mIfaceMatch + "'");
+    }
+
     private void postAndWaitForRunnable(Runnable r) {
         mHandler.runWithScissors(r, 2000L /* timeout */);
     }