Loading core/java/android/net/ConnectivityManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,14 @@ public class ConnectivityManager { @SystemApi public static final int TETHERING_BLUETOOTH = 2; /** * Wifi P2p tethering type. * Wifi P2p tethering is set through events automatically, and don't * need to start from #startTethering(int, boolean, OnStartTetheringCallback). * @hide */ public static final int TETHERING_WIFI_P2P = 3; /** * Extra used for communicating with the TetherService. Includes the type of tethering to * enable if any. Loading core/res/res/values/config.xml +6 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,12 @@ <string-array translatable="false" name="config_tether_wifi_regexs"> </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this should be empty. An example would be "p2p-p2p.*" --> <string-array translatable="false" name="config_tether_wifi_p2p_regexs"> </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable WiMAX interfaces. If the device doesn't want to support tethering over Wifi this should be empty. An example would be "softap.*" --> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1915,6 +1915,7 @@ <java-symbol type="bool" name="config_tether_upstream_automatic" /> <java-symbol type="array" name="config_tether_usb_regexs" /> <java-symbol type="array" name="config_tether_wifi_regexs" /> <java-symbol type="array" name="config_tether_wifi_p2p_regexs" /> <java-symbol type="array" name="config_usbHostBlacklist" /> <java-symbol type="array" name="config_serialPorts" /> <java-symbol type="array" name="radioAttributes" /> Loading services/core/java/com/android/server/connectivity/Tethering.java +64 −10 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.ConnectivityManager.TETHERING_WIFI_P2P; import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL; Loading Loading @@ -77,6 +78,9 @@ import android.net.util.PrefixUtils; import android.net.util.SharedLog; import android.net.util.VersionedBroadcastListener; import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pGroup; import android.net.wifi.p2p.WifiP2pInfo; import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -290,6 +294,7 @@ public class Tethering extends BaseNetworkObserver { filter.addAction(CONNECTIVITY_ACTION); filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); mContext.registerReceiver(mStateReceiver, filter, null, handler); filter = new IntentFilter(); Loading Loading @@ -354,6 +359,8 @@ public class Tethering extends BaseNetworkObserver { if (cfg.isWifi(iface)) { return TETHERING_WIFI; } else if (cfg.isWifiP2p(iface)) { return TETHERING_WIFI_P2P; } else if (cfg.isUsb(iface)) { return TETHERING_USB; } else if (cfg.isBluetooth(iface)) { Loading Loading @@ -527,6 +534,7 @@ public class Tethering extends BaseNetworkObserver { public void untetherAll() { stopTethering(TETHERING_WIFI); stopTethering(TETHERING_WIFI_P2P); stopTethering(TETHERING_USB); stopTethering(TETHERING_BLUETOOTH); } Loading Loading @@ -713,6 +721,8 @@ public class Tethering extends BaseNetworkObserver { handleConnectivityAction(intent); } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { handleWifiApAction(intent); } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { handleWifiP2pAction(intent); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { mLog.log("OBSERVED configuration changed"); updateConfiguration(); Loading Loading @@ -789,6 +799,39 @@ public class Tethering extends BaseNetworkObserver { } } } private void handleWifiP2pAction(Intent intent) { if (mConfig.isWifiP2pLegacyTetheringMode()) return; final WifiP2pInfo p2pInfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); final WifiP2pGroup group = (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); if (VDBG) { Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group); } if (p2pInfo == null) return; // When a p2p group is disconnected, p2pInfo would be cleared. // group is still valid for detecting whether this device is group owner. if (group == null || !group.isGroupOwner() || TextUtils.isEmpty(group.getInterface())) return; synchronized (Tethering.this.mPublicSync) { // Enter below only if this device is Group Owner with a valid interface. if (p2pInfo.groupFormed) { TetherState tetherState = mTetherStates.get(group.getInterface()); if (tetherState == null || (tetherState.lastState != IpServer.STATE_TETHERED && tetherState.lastState != IpServer.STATE_LOCAL_ONLY)) { enableWifiIpServingLocked(group.getInterface(), IFACE_IP_MODE_LOCAL_ONLY); } } else { disableWifiP2pIpServingLocked(group.getInterface()); } } } } @VisibleForTesting Loading Loading @@ -823,14 +866,11 @@ public class Tethering extends BaseNetworkObserver { } } private void disableWifiIpServingLocked(String ifname, int apState) { mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState); // Regardless of whether we requested this transition, the AP has gone // down. Don't try to tether again unless we're requested to do so. // TODO: Remove this altogether, once Wi-Fi reliably gives us an // interface name with every broadcast. mWifiTetherRequested = false; private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) { mLog.log("Canceling WiFi tethering request -" + " type=" + tetheringType + " interface=" + ifname + " state=" + apState); if (!TextUtils.isEmpty(ifname)) { final TetherState ts = mTetherStates.get(ifname); Loading @@ -842,7 +882,7 @@ public class Tethering extends BaseNetworkObserver { for (int i = 0; i < mTetherStates.size(); i++) { final IpServer ipServer = mTetherStates.valueAt(i).ipServer; if (ipServer.interfaceType() == TETHERING_WIFI) { if (ipServer.interfaceType() == tetheringType) { ipServer.unwanted(); return; } Loading @@ -853,6 +893,20 @@ public class Tethering extends BaseNetworkObserver { : "specified interface: " + ifname)); } private void disableWifiIpServingLocked(String ifname, int apState) { // Regardless of whether we requested this transition, the AP has gone // down. Don't try to tether again unless we're requested to do so. // TODO: Remove this altogether, once Wi-Fi reliably gives us an // interface name with every broadcast. mWifiTetherRequested = false; disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState); } private void disableWifiP2pIpServingLocked(String ifname) { disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0); } private void enableWifiIpServingLocked(String ifname, int wifiIpMode) { // Map wifiIpMode values to IpServer.Callback serving states, inferring // from mWifiTetherRequested as a final "best guess". Loading @@ -870,7 +924,7 @@ public class Tethering extends BaseNetworkObserver { } if (!TextUtils.isEmpty(ifname)) { maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI); maybeTrackNewInterfaceLocked(ifname); changeInterfaceState(ifname, ipServingMode); } else { mLog.e(String.format( Loading services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java +14 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static com.android.internal.R.array.config_tether_bluetooth_regexs; import static com.android.internal.R.array.config_tether_dhcp_range; import static com.android.internal.R.array.config_tether_upstream_types; import static com.android.internal.R.array.config_tether_usb_regexs; import static com.android.internal.R.array.config_tether_wifi_p2p_regexs; import static com.android.internal.R.array.config_tether_wifi_regexs; import static com.android.internal.R.bool.config_tether_upstream_automatic; import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period; Loading Loading @@ -85,6 +86,7 @@ public class TetheringConfiguration { public final String[] tetherableUsbRegexs; public final String[] tetherableWifiRegexs; public final String[] tetherableWifiP2pRegexs; public final String[] tetherableBluetoothRegexs; public final boolean isDunRequired; public final boolean chooseUpstreamAutomatically; Loading @@ -110,6 +112,7 @@ public class TetheringConfiguration { // us an interface name. Careful consideration needs to be given to // implications for Settings and for provisioning checks. tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs); tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs); tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs); isDunRequired = checkDunRequired(ctx, subId); Loading Loading @@ -138,6 +141,15 @@ public class TetheringConfiguration { return matchesDownstreamRegexs(iface, tetherableWifiRegexs); } /** Check whether this interface is Wifi P2P interface. */ public boolean isWifiP2p(String iface) { return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs); } public boolean isWifiP2pLegacyTetheringMode() { return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0); } public boolean isBluetooth(String iface) { return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs); } Loading @@ -152,6 +164,7 @@ public class TetheringConfiguration { dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs); dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs); dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs); pw.print("isDunRequired: "); Loading @@ -178,6 +191,7 @@ public class TetheringConfiguration { sj.add(String.format("subId:%d", subId)); sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs))); sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs))); sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs))); sj.add(String.format("tetherableBluetoothRegexs:%s", makeString(tetherableBluetoothRegexs))); sj.add(String.format("isDunRequired:%s", isDunRequired)); Loading Loading
core/java/android/net/ConnectivityManager.java +8 −0 Original line number Diff line number Diff line Loading @@ -472,6 +472,14 @@ public class ConnectivityManager { @SystemApi public static final int TETHERING_BLUETOOTH = 2; /** * Wifi P2p tethering type. * Wifi P2p tethering is set through events automatically, and don't * need to start from #startTethering(int, boolean, OnStartTetheringCallback). * @hide */ public static final int TETHERING_WIFI_P2P = 3; /** * Extra used for communicating with the TetherService. Includes the type of tethering to * enable if any. Loading
core/res/res/values/config.xml +6 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,12 @@ <string-array translatable="false" name="config_tether_wifi_regexs"> </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable Wifi P2P interfaces. If the device doesn't want to support tethering over Wifi P2p this should be empty. An example would be "p2p-p2p.*" --> <string-array translatable="false" name="config_tether_wifi_p2p_regexs"> </string-array> <!-- List of regexpressions describing the interface (if any) that represent tetherable WiMAX interfaces. If the device doesn't want to support tethering over Wifi this should be empty. An example would be "softap.*" --> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -1915,6 +1915,7 @@ <java-symbol type="bool" name="config_tether_upstream_automatic" /> <java-symbol type="array" name="config_tether_usb_regexs" /> <java-symbol type="array" name="config_tether_wifi_regexs" /> <java-symbol type="array" name="config_tether_wifi_p2p_regexs" /> <java-symbol type="array" name="config_usbHostBlacklist" /> <java-symbol type="array" name="config_serialPorts" /> <java-symbol type="array" name="radioAttributes" /> Loading
services/core/java/com/android/server/connectivity/Tethering.java +64 −10 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import static android.net.ConnectivityManager.TETHERING_WIFI_P2P; import static android.net.ConnectivityManager.TETHER_ERROR_MASTER_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR; import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL; Loading Loading @@ -77,6 +78,9 @@ import android.net.util.PrefixUtils; import android.net.util.SharedLog; import android.net.util.VersionedBroadcastListener; import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pGroup; import android.net.wifi.p2p.WifiP2pInfo; import android.net.wifi.p2p.WifiP2pManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; Loading Loading @@ -290,6 +294,7 @@ public class Tethering extends BaseNetworkObserver { filter.addAction(CONNECTIVITY_ACTION); filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION); mContext.registerReceiver(mStateReceiver, filter, null, handler); filter = new IntentFilter(); Loading Loading @@ -354,6 +359,8 @@ public class Tethering extends BaseNetworkObserver { if (cfg.isWifi(iface)) { return TETHERING_WIFI; } else if (cfg.isWifiP2p(iface)) { return TETHERING_WIFI_P2P; } else if (cfg.isUsb(iface)) { return TETHERING_USB; } else if (cfg.isBluetooth(iface)) { Loading Loading @@ -527,6 +534,7 @@ public class Tethering extends BaseNetworkObserver { public void untetherAll() { stopTethering(TETHERING_WIFI); stopTethering(TETHERING_WIFI_P2P); stopTethering(TETHERING_USB); stopTethering(TETHERING_BLUETOOTH); } Loading Loading @@ -713,6 +721,8 @@ public class Tethering extends BaseNetworkObserver { handleConnectivityAction(intent); } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { handleWifiApAction(intent); } else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) { handleWifiP2pAction(intent); } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) { mLog.log("OBSERVED configuration changed"); updateConfiguration(); Loading Loading @@ -789,6 +799,39 @@ public class Tethering extends BaseNetworkObserver { } } } private void handleWifiP2pAction(Intent intent) { if (mConfig.isWifiP2pLegacyTetheringMode()) return; final WifiP2pInfo p2pInfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO); final WifiP2pGroup group = (WifiP2pGroup) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP); if (VDBG) { Log.d(TAG, "WifiP2pAction: P2pInfo: " + p2pInfo + " Group: " + group); } if (p2pInfo == null) return; // When a p2p group is disconnected, p2pInfo would be cleared. // group is still valid for detecting whether this device is group owner. if (group == null || !group.isGroupOwner() || TextUtils.isEmpty(group.getInterface())) return; synchronized (Tethering.this.mPublicSync) { // Enter below only if this device is Group Owner with a valid interface. if (p2pInfo.groupFormed) { TetherState tetherState = mTetherStates.get(group.getInterface()); if (tetherState == null || (tetherState.lastState != IpServer.STATE_TETHERED && tetherState.lastState != IpServer.STATE_LOCAL_ONLY)) { enableWifiIpServingLocked(group.getInterface(), IFACE_IP_MODE_LOCAL_ONLY); } } else { disableWifiP2pIpServingLocked(group.getInterface()); } } } } @VisibleForTesting Loading Loading @@ -823,14 +866,11 @@ public class Tethering extends BaseNetworkObserver { } } private void disableWifiIpServingLocked(String ifname, int apState) { mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState); // Regardless of whether we requested this transition, the AP has gone // down. Don't try to tether again unless we're requested to do so. // TODO: Remove this altogether, once Wi-Fi reliably gives us an // interface name with every broadcast. mWifiTetherRequested = false; private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) { mLog.log("Canceling WiFi tethering request -" + " type=" + tetheringType + " interface=" + ifname + " state=" + apState); if (!TextUtils.isEmpty(ifname)) { final TetherState ts = mTetherStates.get(ifname); Loading @@ -842,7 +882,7 @@ public class Tethering extends BaseNetworkObserver { for (int i = 0; i < mTetherStates.size(); i++) { final IpServer ipServer = mTetherStates.valueAt(i).ipServer; if (ipServer.interfaceType() == TETHERING_WIFI) { if (ipServer.interfaceType() == tetheringType) { ipServer.unwanted(); return; } Loading @@ -853,6 +893,20 @@ public class Tethering extends BaseNetworkObserver { : "specified interface: " + ifname)); } private void disableWifiIpServingLocked(String ifname, int apState) { // Regardless of whether we requested this transition, the AP has gone // down. Don't try to tether again unless we're requested to do so. // TODO: Remove this altogether, once Wi-Fi reliably gives us an // interface name with every broadcast. mWifiTetherRequested = false; disableWifiIpServingLockedCommon(TETHERING_WIFI, ifname, apState); } private void disableWifiP2pIpServingLocked(String ifname) { disableWifiIpServingLockedCommon(TETHERING_WIFI_P2P, ifname, /* dummy */ 0); } private void enableWifiIpServingLocked(String ifname, int wifiIpMode) { // Map wifiIpMode values to IpServer.Callback serving states, inferring // from mWifiTetherRequested as a final "best guess". Loading @@ -870,7 +924,7 @@ public class Tethering extends BaseNetworkObserver { } if (!TextUtils.isEmpty(ifname)) { maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI); maybeTrackNewInterfaceLocked(ifname); changeInterfaceState(ifname, ipServingMode); } else { mLog.e(String.format( Loading
services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java +14 −0 Original line number Diff line number Diff line Loading @@ -28,6 +28,7 @@ import static com.android.internal.R.array.config_tether_bluetooth_regexs; import static com.android.internal.R.array.config_tether_dhcp_range; import static com.android.internal.R.array.config_tether_upstream_types; import static com.android.internal.R.array.config_tether_usb_regexs; import static com.android.internal.R.array.config_tether_wifi_p2p_regexs; import static com.android.internal.R.array.config_tether_wifi_regexs; import static com.android.internal.R.bool.config_tether_upstream_automatic; import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period; Loading Loading @@ -85,6 +86,7 @@ public class TetheringConfiguration { public final String[] tetherableUsbRegexs; public final String[] tetherableWifiRegexs; public final String[] tetherableWifiP2pRegexs; public final String[] tetherableBluetoothRegexs; public final boolean isDunRequired; public final boolean chooseUpstreamAutomatically; Loading @@ -110,6 +112,7 @@ public class TetheringConfiguration { // us an interface name. Careful consideration needs to be given to // implications for Settings and for provisioning checks. tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs); tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs); tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs); isDunRequired = checkDunRequired(ctx, subId); Loading Loading @@ -138,6 +141,15 @@ public class TetheringConfiguration { return matchesDownstreamRegexs(iface, tetherableWifiRegexs); } /** Check whether this interface is Wifi P2P interface. */ public boolean isWifiP2p(String iface) { return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs); } public boolean isWifiP2pLegacyTetheringMode() { return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0); } public boolean isBluetooth(String iface) { return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs); } Loading @@ -152,6 +164,7 @@ public class TetheringConfiguration { dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs); dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs); dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs); pw.print("isDunRequired: "); Loading @@ -178,6 +191,7 @@ public class TetheringConfiguration { sj.add(String.format("subId:%d", subId)); sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs))); sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs))); sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs))); sj.add(String.format("tetherableBluetoothRegexs:%s", makeString(tetherableBluetoothRegexs))); sj.add(String.format("isDunRequired:%s", isDunRequired)); Loading