First pass at USB Tethering.
bug:2281900
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 30799ec..d435df5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -116,6 +116,24 @@
"android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";
/**
+ * Broadcast Action: A tetherable connection has come or gone
+ * TODO - finish the doc
+ * @hide
+ */
+ public static final String ACTION_TETHER_STATE_CHANGED =
+ "android.net.conn.TETHER_STATE_CHANGED";
+
+ /**
+ * @hide
+ */
+ public static final String EXTRA_AVAILABLE_TETHER_COUNT = "availableCount";
+
+ /**
+ * @hide
+ */
+ public static final String EXTRA_ACTIVE_TETHER_COUNT = "activeCount";
+
+ /**
* The Default Mobile data connection. When active, all data traffic
* will use this connection by default. Should not coexist with other
* default connections.
@@ -338,4 +356,48 @@
}
mService = service;
}
+
+ /**
+ * {@hide}
+ */
+ public String[] getTetherableIfaces() {
+ try {
+ return mService.getTetherableIfaces();
+ } catch (RemoteException e) {
+ return new String[0];
+ }
+ }
+
+ /**
+ * {@hide}
+ */
+ public String[] getTetheredIfaces() {
+ try {
+ return mService.getTetheredIfaces();
+ } catch (RemoteException e) {
+ return new String[0];
+ }
+ }
+
+ /**
+ * {@hide}
+ */
+ public boolean tether(String iface) {
+ try {
+ return mService.tether(iface);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
+ * {@hide}
+ */
+ public boolean untether(String iface) {
+ try {
+ return mService.untether(iface);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 9f59cce..caa3f2b 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -50,4 +50,12 @@
boolean getBackgroundDataSetting();
void setBackgroundDataSetting(boolean allowBackgroundData);
+
+ boolean tether(String iface);
+
+ boolean untether(String iface);
+
+ String[] getTetherableIfaces();
+
+ String[] getTetheredIfaces();
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index aa4956f..4259016 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -43,6 +43,8 @@
import com.android.internal.telephony.Phone;
+import com.android.server.connectivity.Tethering;
+
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -62,6 +64,9 @@
private static final String NETWORK_RESTORE_DELAY_PROP_NAME =
"android.telephony.apn-restore";
+
+ private Tethering mTethering;
+
/**
* Sometimes we want to refer to the individual network state
* trackers separately, and sometimes we just want to treat them
@@ -308,6 +313,8 @@
continue;
}
}
+
+ mTethering = new Tethering(mContext);
}
@@ -784,6 +791,13 @@
"ConnectivityService");
}
+ // TODO Make this a special check when it goes public
+ private void enforceTetherChangePermission() {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_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
@@ -1368,4 +1382,28 @@
}
}
}
+
+ // javadoc from interface
+ public boolean tether(String iface) {
+ enforceTetherChangePermission();
+ return mTethering.tether(iface);
+ }
+
+ // javadoc from interface
+ public boolean untether(String iface) {
+ enforceTetherChangePermission();
+ return mTethering.untether(iface);
+ }
+
+ // TODO - move iface listing, queries, etc to new module
+ // javadoc from interface
+ public String[] getTetherableIfaces() {
+ enforceAccessPermission();
+ return mTethering.getTetherableIfaces();
+ }
+
+ public String[] getTetheredIfaces() {
+ enforceAccessPermission();
+ return mTethering.getTetheredIfaces();
+ }
}