Merge "p2p: mirgrate p2p into tethering modes"
This commit is contained in:
@@ -472,6 +472,14 @@ public class ConnectivityManager {
|
|||||||
@SystemApi
|
@SystemApi
|
||||||
public static final int TETHERING_BLUETOOTH = 2;
|
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
|
* Extra used for communicating with the TetherService. Includes the type of tethering to
|
||||||
* enable if any.
|
* enable if any.
|
||||||
|
|||||||
@@ -386,6 +386,12 @@
|
|||||||
<string-array translatable="false" name="config_tether_wifi_regexs">
|
<string-array translatable="false" name="config_tether_wifi_regexs">
|
||||||
</string-array>
|
</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
|
<!-- 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
|
WiMAX interfaces. If the device doesn't want to support tethering over Wifi this
|
||||||
should be empty. An example would be "softap.*" -->
|
should be empty. An example would be "softap.*" -->
|
||||||
|
|||||||
@@ -1914,6 +1914,7 @@
|
|||||||
<java-symbol type="bool" name="config_tether_upstream_automatic" />
|
<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_usb_regexs" />
|
||||||
<java-symbol type="array" name="config_tether_wifi_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_usbHostBlacklist" />
|
||||||
<java-symbol type="array" name="config_serialPorts" />
|
<java-symbol type="array" name="config_serialPorts" />
|
||||||
<java-symbol type="array" name="radioAttributes" />
|
<java-symbol type="array" name="radioAttributes" />
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
|||||||
import static android.net.ConnectivityManager.TETHERING_INVALID;
|
import static android.net.ConnectivityManager.TETHERING_INVALID;
|
||||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
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_MASTER_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
import static android.net.ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL;
|
||||||
@@ -77,6 +78,9 @@ import android.net.util.PrefixUtils;
|
|||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.net.util.VersionedBroadcastListener;
|
import android.net.util.VersionedBroadcastListener;
|
||||||
import android.net.wifi.WifiManager;
|
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.Binder;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -290,6 +294,7 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
filter.addAction(CONNECTIVITY_ACTION);
|
filter.addAction(CONNECTIVITY_ACTION);
|
||||||
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
|
||||||
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
|
filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
|
||||||
|
filter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
|
||||||
mContext.registerReceiver(mStateReceiver, filter, null, handler);
|
mContext.registerReceiver(mStateReceiver, filter, null, handler);
|
||||||
|
|
||||||
filter = new IntentFilter();
|
filter = new IntentFilter();
|
||||||
@@ -354,6 +359,8 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
|
|
||||||
if (cfg.isWifi(iface)) {
|
if (cfg.isWifi(iface)) {
|
||||||
return TETHERING_WIFI;
|
return TETHERING_WIFI;
|
||||||
|
} else if (cfg.isWifiP2p(iface)) {
|
||||||
|
return TETHERING_WIFI_P2P;
|
||||||
} else if (cfg.isUsb(iface)) {
|
} else if (cfg.isUsb(iface)) {
|
||||||
return TETHERING_USB;
|
return TETHERING_USB;
|
||||||
} else if (cfg.isBluetooth(iface)) {
|
} else if (cfg.isBluetooth(iface)) {
|
||||||
@@ -527,6 +534,7 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
|
|
||||||
public void untetherAll() {
|
public void untetherAll() {
|
||||||
stopTethering(TETHERING_WIFI);
|
stopTethering(TETHERING_WIFI);
|
||||||
|
stopTethering(TETHERING_WIFI_P2P);
|
||||||
stopTethering(TETHERING_USB);
|
stopTethering(TETHERING_USB);
|
||||||
stopTethering(TETHERING_BLUETOOTH);
|
stopTethering(TETHERING_BLUETOOTH);
|
||||||
}
|
}
|
||||||
@@ -713,6 +721,8 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
handleConnectivityAction(intent);
|
handleConnectivityAction(intent);
|
||||||
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
|
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
|
||||||
handleWifiApAction(intent);
|
handleWifiApAction(intent);
|
||||||
|
} else if (action.equals(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION)) {
|
||||||
|
handleWifiP2pAction(intent);
|
||||||
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
|
} else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
|
||||||
mLog.log("OBSERVED configuration changed");
|
mLog.log("OBSERVED configuration changed");
|
||||||
updateConfiguration();
|
updateConfiguration();
|
||||||
@@ -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
|
@VisibleForTesting
|
||||||
@@ -823,14 +866,11 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void disableWifiIpServingLocked(String ifname, int apState) {
|
private void disableWifiIpServingLockedCommon(int tetheringType, String ifname, int apState) {
|
||||||
mLog.log("Canceling WiFi tethering request - AP_STATE=" + apState);
|
mLog.log("Canceling WiFi tethering request -"
|
||||||
|
+ " type=" + tetheringType
|
||||||
// Regardless of whether we requested this transition, the AP has gone
|
+ " interface=" + ifname
|
||||||
// down. Don't try to tether again unless we're requested to do so.
|
+ " state=" + apState);
|
||||||
// TODO: Remove this altogether, once Wi-Fi reliably gives us an
|
|
||||||
// interface name with every broadcast.
|
|
||||||
mWifiTetherRequested = false;
|
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(ifname)) {
|
if (!TextUtils.isEmpty(ifname)) {
|
||||||
final TetherState ts = mTetherStates.get(ifname);
|
final TetherState ts = mTetherStates.get(ifname);
|
||||||
@@ -842,7 +882,7 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
|
|
||||||
for (int i = 0; i < mTetherStates.size(); i++) {
|
for (int i = 0; i < mTetherStates.size(); i++) {
|
||||||
final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
|
final IpServer ipServer = mTetherStates.valueAt(i).ipServer;
|
||||||
if (ipServer.interfaceType() == TETHERING_WIFI) {
|
if (ipServer.interfaceType() == tetheringType) {
|
||||||
ipServer.unwanted();
|
ipServer.unwanted();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -853,6 +893,20 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
: "specified interface: " + ifname));
|
: "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) {
|
private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
|
||||||
// Map wifiIpMode values to IpServer.Callback serving states, inferring
|
// Map wifiIpMode values to IpServer.Callback serving states, inferring
|
||||||
// from mWifiTetherRequested as a final "best guess".
|
// from mWifiTetherRequested as a final "best guess".
|
||||||
@@ -870,7 +924,7 @@ public class Tethering extends BaseNetworkObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(ifname)) {
|
if (!TextUtils.isEmpty(ifname)) {
|
||||||
maybeTrackNewInterfaceLocked(ifname, TETHERING_WIFI);
|
maybeTrackNewInterfaceLocked(ifname);
|
||||||
changeInterfaceState(ifname, ipServingMode);
|
changeInterfaceState(ifname, ipServingMode);
|
||||||
} else {
|
} else {
|
||||||
mLog.e(String.format(
|
mLog.e(String.format(
|
||||||
|
|||||||
@@ -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_dhcp_range;
|
||||||
import static com.android.internal.R.array.config_tether_upstream_types;
|
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_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.array.config_tether_wifi_regexs;
|
||||||
import static com.android.internal.R.bool.config_tether_upstream_automatic;
|
import static com.android.internal.R.bool.config_tether_upstream_automatic;
|
||||||
import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
|
import static com.android.internal.R.integer.config_mobile_hotspot_provision_check_period;
|
||||||
@@ -85,6 +86,7 @@ public class TetheringConfiguration {
|
|||||||
|
|
||||||
public final String[] tetherableUsbRegexs;
|
public final String[] tetherableUsbRegexs;
|
||||||
public final String[] tetherableWifiRegexs;
|
public final String[] tetherableWifiRegexs;
|
||||||
|
public final String[] tetherableWifiP2pRegexs;
|
||||||
public final String[] tetherableBluetoothRegexs;
|
public final String[] tetherableBluetoothRegexs;
|
||||||
public final boolean isDunRequired;
|
public final boolean isDunRequired;
|
||||||
public final boolean chooseUpstreamAutomatically;
|
public final boolean chooseUpstreamAutomatically;
|
||||||
@@ -110,6 +112,7 @@ public class TetheringConfiguration {
|
|||||||
// us an interface name. Careful consideration needs to be given to
|
// us an interface name. Careful consideration needs to be given to
|
||||||
// implications for Settings and for provisioning checks.
|
// implications for Settings and for provisioning checks.
|
||||||
tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
|
tetherableWifiRegexs = getResourceStringArray(res, config_tether_wifi_regexs);
|
||||||
|
tetherableWifiP2pRegexs = getResourceStringArray(res, config_tether_wifi_p2p_regexs);
|
||||||
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
|
tetherableBluetoothRegexs = getResourceStringArray(res, config_tether_bluetooth_regexs);
|
||||||
|
|
||||||
isDunRequired = checkDunRequired(ctx, subId);
|
isDunRequired = checkDunRequired(ctx, subId);
|
||||||
@@ -138,6 +141,15 @@ public class TetheringConfiguration {
|
|||||||
return matchesDownstreamRegexs(iface, tetherableWifiRegexs);
|
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) {
|
public boolean isBluetooth(String iface) {
|
||||||
return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
|
return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
|
||||||
}
|
}
|
||||||
@@ -152,6 +164,7 @@ public class TetheringConfiguration {
|
|||||||
|
|
||||||
dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
|
dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
|
||||||
dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
|
dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
|
||||||
|
dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
|
||||||
dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
|
dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
|
||||||
|
|
||||||
pw.print("isDunRequired: ");
|
pw.print("isDunRequired: ");
|
||||||
@@ -178,6 +191,7 @@ public class TetheringConfiguration {
|
|||||||
sj.add(String.format("subId:%d", subId));
|
sj.add(String.format("subId:%d", subId));
|
||||||
sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
|
sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs)));
|
||||||
sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
|
sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs)));
|
||||||
|
sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs)));
|
||||||
sj.add(String.format("tetherableBluetoothRegexs:%s",
|
sj.add(String.format("tetherableBluetoothRegexs:%s",
|
||||||
makeString(tetherableBluetoothRegexs)));
|
makeString(tetherableBluetoothRegexs)));
|
||||||
sj.add(String.format("isDunRequired:%s", isDunRequired));
|
sj.add(String.format("isDunRequired:%s", isDunRequired));
|
||||||
|
|||||||
@@ -93,6 +93,8 @@ public class IpServer extends StateMachine {
|
|||||||
private static final int USB_PREFIX_LENGTH = 24;
|
private static final int USB_PREFIX_LENGTH = 24;
|
||||||
private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
|
private static final String WIFI_HOST_IFACE_ADDR = "192.168.43.1";
|
||||||
private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
|
private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
|
||||||
|
private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1";
|
||||||
|
private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24;
|
||||||
|
|
||||||
// TODO: have PanService use some visible version of this constant
|
// TODO: have PanService use some visible version of this constant
|
||||||
private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
|
private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
|
||||||
@@ -403,6 +405,9 @@ public class IpServer extends StateMachine {
|
|||||||
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
|
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) {
|
||||||
ipAsString = getRandomWifiIPv4Address();
|
ipAsString = getRandomWifiIPv4Address();
|
||||||
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
|
prefixLen = WIFI_HOST_IFACE_PREFIX_LENGTH;
|
||||||
|
} else if (mInterfaceType == ConnectivityManager.TETHERING_WIFI_P2P) {
|
||||||
|
ipAsString = WIFI_P2P_IFACE_ADDR;
|
||||||
|
prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
|
||||||
} else {
|
} else {
|
||||||
// BT configures the interface elsewhere: only start DHCP.
|
// BT configures the interface elsewhere: only start DHCP.
|
||||||
final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR);
|
final Inet4Address srvAddr = (Inet4Address) numericToInetAddress(BLUETOOTH_IFACE_ADDR);
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ package android.net.ip;
|
|||||||
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
||||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||||
|
import static android.net.ConnectivityManager.TETHERING_WIFI_P2P;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
import static android.net.ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR;
|
||||||
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
||||||
import static android.net.ip.IpServer.STATE_AVAILABLE;
|
import static android.net.ip.IpServer.STATE_AVAILABLE;
|
||||||
|
import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
|
||||||
import static android.net.ip.IpServer.STATE_TETHERED;
|
import static android.net.ip.IpServer.STATE_TETHERED;
|
||||||
import static android.net.ip.IpServer.STATE_UNAVAILABLE;
|
import static android.net.ip.IpServer.STATE_UNAVAILABLE;
|
||||||
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
|
||||||
@@ -255,6 +257,23 @@ public class IpServerTest {
|
|||||||
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void canBeTetheredAsWifiP2p() throws Exception {
|
||||||
|
initStateMachine(TETHERING_WIFI_P2P);
|
||||||
|
|
||||||
|
dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_LOCAL_ONLY);
|
||||||
|
InOrder inOrder = inOrder(mCallback, mNMService);
|
||||||
|
inOrder.verify(mNMService).getInterfaceConfig(IFACE_NAME);
|
||||||
|
inOrder.verify(mNMService).setInterfaceConfig(IFACE_NAME, mInterfaceConfiguration);
|
||||||
|
inOrder.verify(mNMService).tetherInterface(IFACE_NAME);
|
||||||
|
inOrder.verify(mCallback).updateInterfaceState(
|
||||||
|
mIpServer, STATE_LOCAL_ONLY, TETHER_ERROR_NO_ERROR);
|
||||||
|
inOrder.verify(mCallback).updateLinkProperties(
|
||||||
|
eq(mIpServer), mLinkPropertiesCaptor.capture());
|
||||||
|
assertIPv4AddressAndDirectlyConnectedRoute(mLinkPropertiesCaptor.getValue());
|
||||||
|
verifyNoMoreInteractions(mNMService, mStatsService, mCallback);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void handlesFirstUpstreamChange() throws Exception {
|
public void handlesFirstUpstreamChange() throws Exception {
|
||||||
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
|
initTetheredStateMachine(TETHERING_BLUETOOTH, null);
|
||||||
@@ -418,6 +437,14 @@ public class IpServerTest {
|
|||||||
assertDhcpStarted(new IpPrefix("192.168.44.0/24"));
|
assertDhcpStarted(new IpPrefix("192.168.44.0/24"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void startsDhcpServerOnWifiP2p() throws Exception {
|
||||||
|
initTetheredStateMachine(TETHERING_WIFI_P2P, UPSTREAM_IFACE);
|
||||||
|
dispatchTetherConnectionChanged(UPSTREAM_IFACE);
|
||||||
|
|
||||||
|
assertDhcpStarted(new IpPrefix("192.168.49.0/24"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void doesNotStartDhcpServerIfDisabled() throws Exception {
|
public void doesNotStartDhcpServerIfDisabled() throws Exception {
|
||||||
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
|
initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, true /* usingLegacyDhcp */);
|
||||||
|
|||||||
@@ -25,8 +25,10 @@ import static android.net.ConnectivityManager.EXTRA_ACTIVE_TETHER;
|
|||||||
import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
|
import static android.net.ConnectivityManager.EXTRA_AVAILABLE_TETHER;
|
||||||
import static android.net.ConnectivityManager.TETHERING_USB;
|
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||||
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||||
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
|
import static android.net.ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
|
||||||
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
import static android.net.ConnectivityManager.TYPE_MOBILE;
|
||||||
|
import static android.net.ConnectivityManager.TYPE_WIFI_P2P;
|
||||||
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
import static android.net.dhcp.IDhcpServer.STATUS_SUCCESS;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
|
||||||
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
|
||||||
@@ -90,6 +92,9 @@ import android.net.util.NetworkConstants;
|
|||||||
import android.net.util.SharedLog;
|
import android.net.util.SharedLog;
|
||||||
import android.net.wifi.WifiConfiguration;
|
import android.net.wifi.WifiConfiguration;
|
||||||
import android.net.wifi.WifiManager;
|
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.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.INetworkManagementService;
|
import android.os.INetworkManagementService;
|
||||||
@@ -140,6 +145,7 @@ public class TetheringTest {
|
|||||||
private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
|
private static final String TEST_XLAT_MOBILE_IFNAME = "v4-test_rmnet_data0";
|
||||||
private static final String TEST_USB_IFNAME = "test_rndis0";
|
private static final String TEST_USB_IFNAME = "test_rndis0";
|
||||||
private static final String TEST_WLAN_IFNAME = "test_wlan0";
|
private static final String TEST_WLAN_IFNAME = "test_wlan0";
|
||||||
|
private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
|
||||||
|
|
||||||
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
|
private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
|
||||||
|
|
||||||
@@ -216,9 +222,10 @@ public class TetheringTest {
|
|||||||
assertTrue("Non-mocked interface " + ifName,
|
assertTrue("Non-mocked interface " + ifName,
|
||||||
ifName.equals(TEST_USB_IFNAME)
|
ifName.equals(TEST_USB_IFNAME)
|
||||||
|| ifName.equals(TEST_WLAN_IFNAME)
|
|| ifName.equals(TEST_WLAN_IFNAME)
|
||||||
|| ifName.equals(TEST_MOBILE_IFNAME));
|
|| ifName.equals(TEST_MOBILE_IFNAME)
|
||||||
|
|| ifName.equals(TEST_P2P_IFNAME));
|
||||||
final String[] ifaces = new String[] {
|
final String[] ifaces = new String[] {
|
||||||
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME };
|
TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME};
|
||||||
return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
|
return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
|
||||||
MacAddress.ALL_ZEROS_ADDRESS);
|
MacAddress.ALL_ZEROS_ADDRESS);
|
||||||
}
|
}
|
||||||
@@ -361,6 +368,8 @@ public class TetheringTest {
|
|||||||
.thenReturn(new String[] { "test_rndis\\d" });
|
.thenReturn(new String[] { "test_rndis\\d" });
|
||||||
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
|
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
|
||||||
.thenReturn(new String[]{ "test_wlan\\d" });
|
.thenReturn(new String[]{ "test_wlan\\d" });
|
||||||
|
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
|
||||||
|
.thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
|
||||||
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
|
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
|
||||||
.thenReturn(new String[0]);
|
.thenReturn(new String[0]);
|
||||||
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
|
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
|
||||||
@@ -369,7 +378,7 @@ public class TetheringTest {
|
|||||||
.thenReturn(false);
|
.thenReturn(false);
|
||||||
when(mNMService.listInterfaces())
|
when(mNMService.listInterfaces())
|
||||||
.thenReturn(new String[] {
|
.thenReturn(new String[] {
|
||||||
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME});
|
TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
|
||||||
when(mNMService.getInterfaceConfig(anyString()))
|
when(mNMService.getInterfaceConfig(anyString()))
|
||||||
.thenReturn(new InterfaceConfiguration());
|
.thenReturn(new InterfaceConfiguration());
|
||||||
when(mRouterAdvertisementDaemon.start())
|
when(mRouterAdvertisementDaemon.start())
|
||||||
@@ -423,6 +432,31 @@ public class TetheringTest {
|
|||||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String[] P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST = {
|
||||||
|
android.Manifest.permission.ACCESS_FINE_LOCATION,
|
||||||
|
android.Manifest.permission.ACCESS_WIFI_STATE
|
||||||
|
};
|
||||||
|
|
||||||
|
private void sendWifiP2pConnectionChanged(
|
||||||
|
boolean isGroupFormed, boolean isGroupOwner, String ifname) {
|
||||||
|
WifiP2pInfo p2pInfo = new WifiP2pInfo();
|
||||||
|
p2pInfo.groupFormed = isGroupFormed;
|
||||||
|
p2pInfo.isGroupOwner = isGroupOwner;
|
||||||
|
|
||||||
|
NetworkInfo networkInfo = new NetworkInfo(TYPE_WIFI_P2P, 0, null, null);
|
||||||
|
|
||||||
|
WifiP2pGroup group = new WifiP2pGroup();
|
||||||
|
group.setIsGroupOwner(isGroupOwner);
|
||||||
|
group.setInterface(ifname);
|
||||||
|
|
||||||
|
final Intent intent = new Intent(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);
|
||||||
|
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO, p2pInfo);
|
||||||
|
intent.putExtra(WifiP2pManager.EXTRA_NETWORK_INFO, networkInfo);
|
||||||
|
intent.putExtra(WifiP2pManager.EXTRA_WIFI_P2P_GROUP, group);
|
||||||
|
mServiceContext.sendBroadcastAsUserMultiplePermissions(intent, UserHandle.ALL,
|
||||||
|
P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
|
||||||
|
}
|
||||||
|
|
||||||
private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
|
private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
|
||||||
final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
|
final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
|
||||||
intent.putExtra(USB_CONNECTED, connected);
|
intent.putExtra(USB_CONNECTED, connected);
|
||||||
@@ -436,11 +470,11 @@ public class TetheringTest {
|
|||||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyInterfaceServingModeStarted() throws Exception {
|
private void verifyInterfaceServingModeStarted(String ifname) throws Exception {
|
||||||
verify(mNMService, times(1)).getInterfaceConfig(TEST_WLAN_IFNAME);
|
verify(mNMService, times(1)).getInterfaceConfig(ifname);
|
||||||
verify(mNMService, times(1))
|
verify(mNMService, times(1))
|
||||||
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
|
.setInterfaceConfig(eq(ifname), any(InterfaceConfiguration.class));
|
||||||
verify(mNMService, times(1)).tetherInterface(TEST_WLAN_IFNAME);
|
verify(mNMService, times(1)).tetherInterface(ifname);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyTetheringBroadcast(String ifname, String whichExtra) {
|
private void verifyTetheringBroadcast(String ifname, String whichExtra) {
|
||||||
@@ -530,7 +564,7 @@ public class TetheringTest {
|
|||||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
|
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_LOCAL_ONLY);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verifyInterfaceServingModeStarted();
|
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
|
||||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||||
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
||||||
verify(mNMService, times(1)).startTethering(any(String[].class));
|
verify(mNMService, times(1)).startTethering(any(String[].class));
|
||||||
@@ -542,8 +576,9 @@ public class TetheringTest {
|
|||||||
verifyNoMoreInteractions(mWifiManager);
|
verifyNoMoreInteractions(mWifiManager);
|
||||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
|
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
|
||||||
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
|
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
|
||||||
// TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
|
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||||
assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
|
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||||
|
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||||
|
|
||||||
// Emulate externally-visible WifiManager effects, when hotspot mode
|
// Emulate externally-visible WifiManager effects, when hotspot mode
|
||||||
// is being torn down.
|
// is being torn down.
|
||||||
@@ -552,9 +587,9 @@ public class TetheringTest {
|
|||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
|
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
|
||||||
// TODO: Why is {g,s}etInterfaceConfig() called more than once?
|
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
|
||||||
verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
|
verify(mNMService, times(2)).getInterfaceConfig(TEST_WLAN_IFNAME);
|
||||||
verify(mNMService, atLeastOnce())
|
verify(mNMService, times(2))
|
||||||
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
|
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
|
||||||
verify(mNMService, times(1)).stopTethering();
|
verify(mNMService, times(1)).stopTethering();
|
||||||
verify(mNMService, times(1)).setIpForwardingEnabled(false);
|
verify(mNMService, times(1)).setIpForwardingEnabled(false);
|
||||||
@@ -770,7 +805,7 @@ public class TetheringTest {
|
|||||||
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verifyInterfaceServingModeStarted();
|
verifyInterfaceServingModeStarted(TEST_WLAN_IFNAME);
|
||||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||||
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
||||||
verify(mNMService, times(1)).startTethering(any(String[].class));
|
verify(mNMService, times(1)).startTethering(any(String[].class));
|
||||||
@@ -785,8 +820,9 @@ public class TetheringTest {
|
|||||||
// In tethering mode, in the default configuration, an explicit request
|
// In tethering mode, in the default configuration, an explicit request
|
||||||
// for a mobile network is also made.
|
// for a mobile network is also made.
|
||||||
verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
|
verify(mUpstreamNetworkMonitor, times(1)).registerMobileNetworkRequest();
|
||||||
// TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
|
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||||
assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
|
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||||
|
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||||
|
|
||||||
/////
|
/////
|
||||||
// We do not currently emulate any upstream being found.
|
// We do not currently emulate any upstream being found.
|
||||||
@@ -809,7 +845,7 @@ public class TetheringTest {
|
|||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
|
verify(mNMService, times(1)).untetherInterface(TEST_WLAN_IFNAME);
|
||||||
// TODO: Why is {g,s}etInterfaceConfig() called more than once?
|
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
|
||||||
verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
|
verify(mNMService, atLeastOnce()).getInterfaceConfig(TEST_WLAN_IFNAME);
|
||||||
verify(mNMService, atLeastOnce())
|
verify(mNMService, atLeastOnce())
|
||||||
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
|
.setInterfaceConfig(eq(TEST_WLAN_IFNAME), any(InterfaceConfiguration.class));
|
||||||
@@ -857,8 +893,9 @@ public class TetheringTest {
|
|||||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
|
||||||
verify(mWifiManager).updateInterfaceIpState(
|
verify(mWifiManager).updateInterfaceIpState(
|
||||||
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
|
TEST_WLAN_IFNAME, WifiManager.IFACE_IP_MODE_TETHERED);
|
||||||
// TODO: Figure out why this isn't exactly once, for sendTetherStateChangedBroadcast().
|
// There are 3 state change event:
|
||||||
assertTrue(1 <= mTetheringDependencies.isTetheringSupportedCalls);
|
// AVAILABLE -> STATE_TETHERED -> STATE_AVAILABLE.
|
||||||
|
assertEquals(3, mTetheringDependencies.isTetheringSupportedCalls);
|
||||||
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
verifyTetheringBroadcast(TEST_WLAN_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||||
// This is called, but will throw.
|
// This is called, but will throw.
|
||||||
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
||||||
@@ -1031,6 +1068,133 @@ public class TetheringTest {
|
|||||||
assertEquals(fakeSubId, newConfig.subId);
|
assertEquals(fakeSubId, newConfig.subId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void workingWifiP2pGroupOwner(
|
||||||
|
boolean emulateInterfaceStatusChanged) throws Exception {
|
||||||
|
if (emulateInterfaceStatusChanged) {
|
||||||
|
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||||
|
}
|
||||||
|
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
verifyInterfaceServingModeStarted(TEST_P2P_IFNAME);
|
||||||
|
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_AVAILABLE_TETHER);
|
||||||
|
verify(mNMService, times(1)).setIpForwardingEnabled(true);
|
||||||
|
verify(mNMService, times(1)).startTethering(any(String[].class));
|
||||||
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
verifyTetheringBroadcast(TEST_P2P_IFNAME, EXTRA_ACTIVE_LOCAL_ONLY);
|
||||||
|
verify(mUpstreamNetworkMonitor, times(1)).startObserveAllNetworks();
|
||||||
|
// This will be called twice, one is on entering IpServer.STATE_AVAILABLE,
|
||||||
|
// and another one is on IpServer.STATE_TETHERED/IpServer.STATE_LOCAL_ONLY.
|
||||||
|
assertEquals(2, mTetheringDependencies.isTetheringSupportedCalls);
|
||||||
|
|
||||||
|
assertEquals(TETHER_ERROR_NO_ERROR, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
||||||
|
|
||||||
|
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
|
||||||
|
// is being removed.
|
||||||
|
sendWifiP2pConnectionChanged(false, true, TEST_P2P_IFNAME);
|
||||||
|
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mNMService, times(1)).untetherInterface(TEST_P2P_IFNAME);
|
||||||
|
// {g,s}etInterfaceConfig() called twice for enabling and disabling IPv4.
|
||||||
|
verify(mNMService, times(2)).getInterfaceConfig(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, times(2))
|
||||||
|
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
|
||||||
|
verify(mNMService, times(1)).stopTethering();
|
||||||
|
verify(mNMService, times(1)).setIpForwardingEnabled(false);
|
||||||
|
verify(mUpstreamNetworkMonitor, never()).getCurrentPreferredUpstream();
|
||||||
|
verify(mUpstreamNetworkMonitor, never()).selectPreferredUpstreamType(any());
|
||||||
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
// Asking for the last error after the per-interface state machine
|
||||||
|
// has been reaped yields an unknown interface error.
|
||||||
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void workingWifiP2pGroupClient(
|
||||||
|
boolean emulateInterfaceStatusChanged) throws Exception {
|
||||||
|
if (emulateInterfaceStatusChanged) {
|
||||||
|
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||||
|
}
|
||||||
|
sendWifiP2pConnectionChanged(true, false, TEST_P2P_IFNAME);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never())
|
||||||
|
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
|
||||||
|
verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never()).setIpForwardingEnabled(true);
|
||||||
|
verify(mNMService, never()).startTethering(any(String[].class));
|
||||||
|
|
||||||
|
// Emulate externally-visible WifiP2pManager effects, when wifi p2p group
|
||||||
|
// is being removed.
|
||||||
|
sendWifiP2pConnectionChanged(false, false, TEST_P2P_IFNAME);
|
||||||
|
mTethering.interfaceRemoved(TEST_P2P_IFNAME);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mNMService, never()).untetherInterface(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never())
|
||||||
|
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
|
||||||
|
verify(mNMService, never()).stopTethering();
|
||||||
|
verify(mNMService, never()).setIpForwardingEnabled(false);
|
||||||
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
// Asking for the last error after the per-interface state machine
|
||||||
|
// has been reaped yields an unknown interface error.
|
||||||
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupOwnerWithIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupOwner(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupOwnerSansIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupOwner(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void workingWifiP2pGroupOwnerLegacyMode(
|
||||||
|
boolean emulateInterfaceStatusChanged) throws Exception {
|
||||||
|
// change to legacy mode and update tethering information by chaning SIM
|
||||||
|
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_p2p_regexs))
|
||||||
|
.thenReturn(new String[]{});
|
||||||
|
final int fakeSubId = 1234;
|
||||||
|
mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId);
|
||||||
|
|
||||||
|
if (emulateInterfaceStatusChanged) {
|
||||||
|
mTethering.interfaceStatusChanged(TEST_P2P_IFNAME, true);
|
||||||
|
}
|
||||||
|
sendWifiP2pConnectionChanged(true, true, TEST_P2P_IFNAME);
|
||||||
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
|
verify(mNMService, never()).getInterfaceConfig(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never())
|
||||||
|
.setInterfaceConfig(eq(TEST_P2P_IFNAME), any(InterfaceConfiguration.class));
|
||||||
|
verify(mNMService, never()).tetherInterface(TEST_P2P_IFNAME);
|
||||||
|
verify(mNMService, never()).setIpForwardingEnabled(true);
|
||||||
|
verify(mNMService, never()).startTethering(any(String[].class));
|
||||||
|
assertEquals(TETHER_ERROR_UNKNOWN_IFACE, mTethering.getLastTetherError(TEST_P2P_IFNAME));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupOwnerLegacyModeWithIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupOwnerLegacyMode(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupOwnerLegacyModeSansIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupOwnerLegacyMode(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupClientWithIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupClient(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void workingWifiP2pGroupClientSansIfaceChanged() throws Exception {
|
||||||
|
workingWifiP2pGroupClient(false);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
// TODO: Test that a request for hotspot mode doesn't interfere with an
|
||||||
// already operating tethering mode interface.
|
// already operating tethering mode interface.
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user