Update Tethering.

Adds telephony support, async model, multiple tethered iface suport,
better notifications, device config.

bug:2413855
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d435df5..badb767 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -125,13 +125,21 @@
 
     /**
      * @hide
+     * gives a String[]
      */
-    public static final String EXTRA_AVAILABLE_TETHER_COUNT = "availableCount";
+    public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
 
     /**
      * @hide
+     * gives a String[]
      */
-    public static final String EXTRA_ACTIVE_TETHER_COUNT = "activeCount";
+    public static final String EXTRA_ACTIVE_TETHER = "activeArray";
+
+    /**
+     * @hide
+     * gives a String[]
+     */
+    public static final String EXTRA_ERRORED_TETHER = "erroredArray";
 
     /**
      * The Default Mobile data connection.  When active, all data traffic
@@ -400,4 +408,37 @@
             return false;
         }
     }
+
+    /**
+     * {@hide}
+     */
+    public boolean isTetheringSupported() {
+        try {
+            return mService.isTetheringSupported();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * {@hide}
+     */
+    public String[] getTetherableUsbRegexs() {
+        try {
+            return mService.getTetherableUsbRegexs();
+        } catch (RemoteException e) {
+            return new String[0];
+        }
+    }
+
+    /**
+     * {@hide}
+     */
+    public String[] getTetherableWifiRegexs() {
+        try {
+            return mService.getTetherableWifiRegexs();
+        } catch (RemoteException e) {
+            return new String[0];
+        }
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index caa3f2b..508e9c3 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -55,7 +55,13 @@
 
     boolean untether(String iface);
 
+    boolean isTetheringSupported();
+
     String[] getTetherableIfaces();
 
     String[] getTetheredIfaces();
+
+    String[] getTetherableUsbRegexs();
+
+    String[] getTetherableWifiRegexs();
 }
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 4259016..108246d 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -798,6 +798,12 @@
                 "ConnectivityService");
     }
 
+    private void enforceTetherAccessPermission() {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_NETWORK_STATE,
+                "ConnectivityService");
+    }
+
     /**
      * Handle a {@code DISCONNECTED} event. If this pertains to the non-active
      * network, we ignore it. If it is for the active network, we send out a
@@ -1289,6 +1295,8 @@
             pw.println(requester.toString());
         }
         pw.println();
+
+        mTethering.dump(fd, pw, args);
     }
 
     // must be stateless - things change under us.
@@ -1386,24 +1394,54 @@
     // javadoc from interface
     public boolean tether(String iface) {
         enforceTetherChangePermission();
-        return mTethering.tether(iface);
+        return isTetheringSupported() && mTethering.tether(iface);
     }
 
     // javadoc from interface
     public boolean untether(String iface) {
         enforceTetherChangePermission();
-        return mTethering.untether(iface);
+        return isTetheringSupported() && mTethering.untether(iface);
+    }
+
+    // TODO - proper iface API for selection by property, inspection, etc
+    public String[] getTetherableUsbRegexs() {
+        enforceTetherAccessPermission();
+        if (isTetheringSupported()) {
+            return mTethering.getTetherableUsbRegexs();
+        } else {
+            return new String[0];
+        }
+    }
+
+    public String[] getTetherableWifiRegexs() {
+        enforceTetherAccessPermission();
+        if (isTetheringSupported()) {
+            return mTethering.getTetherableWifiRegexs();
+        } else {
+            return new String[0];
+        }
     }
 
     // TODO - move iface listing, queries, etc to new module
     // javadoc from interface
     public String[] getTetherableIfaces() {
-        enforceAccessPermission();
+        enforceTetherAccessPermission();
         return mTethering.getTetherableIfaces();
     }
 
     public String[] getTetheredIfaces() {
-        enforceAccessPermission();
+        enforceTetherAccessPermission();
         return mTethering.getTetheredIfaces();
     }
+
+    // if ro.tether.denied = true we default to no tethering
+    // gservices could set the secure setting to 1 though to enable it on a build where it
+    // had previously been turned off.
+    public boolean isTetheringSupported() {
+        enforceTetherAccessPermission();
+        int defaultVal = (SystemProperties.get("ro.tether.denied").equals("true") ? 0 : 1);
+        return ((Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.TETHER_SUPPORTED, defaultVal) != 0) &&
+                (mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null));
+    }
 }