Merge "Add local-only hotspot info into tether state change broadcast"
This commit is contained in:
@@ -301,7 +301,8 @@ public class ConnectivityManager {
|
|||||||
/**
|
/**
|
||||||
* Broadcast Action: A tetherable connection has come or gone.
|
* Broadcast Action: A tetherable connection has come or gone.
|
||||||
* Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER},
|
* Uses {@code ConnectivityManager.EXTRA_AVAILABLE_TETHER},
|
||||||
* {@code ConnectivityManager.EXTRA_ACTIVE_TETHER} and
|
* {@code ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY},
|
||||||
|
* {@code ConnectivityManager.EXTRA_ACTIVE_TETHER}, and
|
||||||
* {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate
|
* {@code ConnectivityManager.EXTRA_ERRORED_TETHER} to indicate
|
||||||
* the current state of tethering. Each include a list of
|
* the current state of tethering. Each include a list of
|
||||||
* interface names in that state (may be empty).
|
* interface names in that state (may be empty).
|
||||||
@@ -320,10 +321,17 @@ public class ConnectivityManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
* gives a String[] listing all the interfaces currently tethered
|
* gives a String[] listing all the interfaces currently in local-only
|
||||||
* (ie, has dhcp support and packets potentially forwarded/NATed)
|
* mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
|
||||||
*/
|
*/
|
||||||
public static final String EXTRA_ACTIVE_TETHER = "activeArray";
|
public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
* gives a String[] listing all the interfaces currently tethered
|
||||||
|
* (ie, has DHCPv4 support and packets potentially forwarded/NATed)
|
||||||
|
*/
|
||||||
|
public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @hide
|
* @hide
|
||||||
|
|||||||
@@ -623,9 +623,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
private void sendTetherStateChangedBroadcast() {
|
private void sendTetherStateChangedBroadcast() {
|
||||||
if (!getConnectivityManager().isTetheringSupported()) return;
|
if (!getConnectivityManager().isTetheringSupported()) return;
|
||||||
|
|
||||||
ArrayList<String> availableList = new ArrayList<String>();
|
final ArrayList<String> availableList = new ArrayList<>();
|
||||||
ArrayList<String> activeList = new ArrayList<String>();
|
final ArrayList<String> tetherList = new ArrayList<>();
|
||||||
ArrayList<String> erroredList = new ArrayList<String>();
|
final ArrayList<String> localOnlyList = new ArrayList<>();
|
||||||
|
final ArrayList<String> erroredList = new ArrayList<>();
|
||||||
|
|
||||||
boolean wifiTethered = false;
|
boolean wifiTethered = false;
|
||||||
boolean usbTethered = false;
|
boolean usbTethered = false;
|
||||||
@@ -641,6 +642,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
erroredList.add(iface);
|
erroredList.add(iface);
|
||||||
} else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
|
} else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
|
||||||
availableList.add(iface);
|
availableList.add(iface);
|
||||||
|
} else if (tetherState.lastState == IControlsTethering.STATE_LOCAL_HOTSPOT) {
|
||||||
|
localOnlyList.add(iface);
|
||||||
} else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
|
} else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
|
||||||
if (cfg.isUsb(iface)) {
|
if (cfg.isUsb(iface)) {
|
||||||
usbTethered = true;
|
usbTethered = true;
|
||||||
@@ -649,25 +652,25 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
} else if (cfg.isBluetooth(iface)) {
|
} else if (cfg.isBluetooth(iface)) {
|
||||||
bluetoothTethered = true;
|
bluetoothTethered = true;
|
||||||
}
|
}
|
||||||
activeList.add(iface);
|
tetherList.add(iface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
|
final Intent bcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
|
||||||
broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
|
bcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
|
||||||
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
|
||||||
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
|
bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER, availableList);
|
||||||
availableList);
|
bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY, localOnlyList);
|
||||||
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
|
bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, tetherList);
|
||||||
broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
|
bcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER, erroredList);
|
||||||
erroredList);
|
mContext.sendStickyBroadcastAsUser(bcast, UserHandle.ALL);
|
||||||
mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
|
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Log.d(TAG, String.format(
|
Log.d(TAG, String.format(
|
||||||
"sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
|
"sendTetherStateChangedBroadcast %s=[%s] %s=[%s] %s=[%s] %s=[%s]",
|
||||||
TextUtils.join(",", availableList),
|
"avail", TextUtils.join(",", availableList),
|
||||||
TextUtils.join(",", activeList),
|
"local_only", TextUtils.join(",", localOnlyList),
|
||||||
TextUtils.join(",", erroredList)));
|
"tether", TextUtils.join(",", tetherList),
|
||||||
|
"error", TextUtils.join(",", erroredList)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usbTethered) {
|
if (usbTethered) {
|
||||||
@@ -1338,7 +1341,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
mForwardedDownstreams.remove(who);
|
mForwardedDownstreams.remove(who);
|
||||||
}
|
}
|
||||||
|
|
||||||
class InitialState extends TetherMasterUtilState {
|
class InitialState extends State {
|
||||||
@Override
|
@Override
|
||||||
public boolean processMessage(Message message) {
|
public boolean processMessage(Message message) {
|
||||||
maybeLogMessage(this, message.what);
|
maybeLogMessage(this, message.what);
|
||||||
@@ -1516,7 +1519,8 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ErrorState extends State {
|
class ErrorState extends State {
|
||||||
int mErrorNotification;
|
private int mErrorNotification;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean processMessage(Message message) {
|
public boolean processMessage(Message message) {
|
||||||
boolean retValue = true;
|
boolean retValue = true;
|
||||||
@@ -1534,6 +1538,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void notify(int msgType) {
|
void notify(int msgType) {
|
||||||
mErrorNotification = msgType;
|
mErrorNotification = msgType;
|
||||||
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
for (TetherInterfaceStateMachine sm : mNotifyList) {
|
||||||
@@ -1542,6 +1547,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SetIpForwardingEnabledErrorState extends ErrorState {
|
class SetIpForwardingEnabledErrorState extends ErrorState {
|
||||||
@Override
|
@Override
|
||||||
public void enter() {
|
public void enter() {
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.ContextWrapper;
|
import android.content.ContextWrapper;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.hardware.usb.UsbManager;
|
import android.hardware.usb.UsbManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
@@ -53,12 +55,16 @@ import android.telephony.CarrierConfigManager;
|
|||||||
|
|
||||||
import com.android.internal.util.test.BroadcastInterceptingContext;
|
import com.android.internal.util.test.BroadcastInterceptingContext;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class TetheringTest {
|
public class TetheringTest {
|
||||||
@@ -81,7 +87,9 @@ public class TetheringTest {
|
|||||||
private final TestLooper mLooper = new TestLooper();
|
private final TestLooper mLooper = new TestLooper();
|
||||||
private final String mTestIfname = "test_wlan0";
|
private final String mTestIfname = "test_wlan0";
|
||||||
|
|
||||||
|
private Vector<Intent> mIntents;
|
||||||
private BroadcastInterceptingContext mServiceContext;
|
private BroadcastInterceptingContext mServiceContext;
|
||||||
|
private BroadcastReceiver mBroadcastReceiver;
|
||||||
private Tethering mTethering;
|
private Tethering mTethering;
|
||||||
|
|
||||||
private class MockContext extends BroadcastInterceptingContext {
|
private class MockContext extends BroadcastInterceptingContext {
|
||||||
@@ -100,7 +108,8 @@ public class TetheringTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before public void setUp() throws Exception {
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
|
when(mResources.getStringArray(com.android.internal.R.array.config_tether_dhcp_range))
|
||||||
.thenReturn(new String[0]);
|
.thenReturn(new String[0]);
|
||||||
@@ -118,10 +127,24 @@ public class TetheringTest {
|
|||||||
.thenReturn(new InterfaceConfiguration());
|
.thenReturn(new InterfaceConfiguration());
|
||||||
|
|
||||||
mServiceContext = new MockContext(mContext);
|
mServiceContext = new MockContext(mContext);
|
||||||
|
mIntents = new Vector<>();
|
||||||
|
mBroadcastReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
mIntents.addElement(intent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mServiceContext.registerReceiver(mBroadcastReceiver,
|
||||||
|
new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
|
||||||
mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
|
mTethering = new Tethering(mServiceContext, mNMService, mStatsService, mPolicyManager,
|
||||||
mLooper.getLooper(), mSystemProperties);
|
mLooper.getLooper(), mSystemProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
mServiceContext.unregisterReceiver(mBroadcastReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
private void setupForRequiredProvisioning() {
|
private void setupForRequiredProvisioning() {
|
||||||
// Produce some acceptable looking provision app setting if requested.
|
// Produce some acceptable looking provision app setting if requested.
|
||||||
when(mResources.getStringArray(
|
when(mResources.getStringArray(
|
||||||
@@ -180,6 +203,23 @@ public class TetheringTest {
|
|||||||
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyInterfaceServingModeStarted() throws Exception {
|
||||||
|
verify(mNMService, times(1)).listInterfaces();
|
||||||
|
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
|
||||||
|
verify(mNMService, times(1))
|
||||||
|
.setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
|
||||||
|
verify(mNMService, times(1)).tetherInterface(mTestIfname);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyTetheringBroadcast(String ifname, String whichExtra) {
|
||||||
|
// Verify that ifname is in the whichExtra array of the tether state changed broadcast.
|
||||||
|
final Intent bcast = mIntents.get(0);
|
||||||
|
assertEquals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED, bcast.getAction());
|
||||||
|
final ArrayList<String> ifnames = bcast.getStringArrayListExtra(whichExtra);
|
||||||
|
assertTrue(ifnames.contains(ifname));
|
||||||
|
mIntents.remove(bcast);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void workingLocalOnlyHotspot() throws Exception {
|
public void workingLocalOnlyHotspot() throws Exception {
|
||||||
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
|
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
|
||||||
@@ -193,14 +233,12 @@ public class TetheringTest {
|
|||||||
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
|
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mNMService, times(1)).listInterfaces();
|
verifyInterfaceServingModeStarted();
|
||||||
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
|
verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
|
||||||
verify(mNMService, times(1))
|
|
||||||
.setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
|
|
||||||
verify(mNMService, times(1)).tetherInterface(mTestIfname);
|
|
||||||
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));
|
||||||
verifyNoMoreInteractions(mNMService);
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_LOCAL_ONLY);
|
||||||
// UpstreamNetworkMonitor will be started, and will register two callbacks:
|
// UpstreamNetworkMonitor will be started, and will register two callbacks:
|
||||||
// a "listen all" and a "track default".
|
// a "listen all" and a "track default".
|
||||||
verify(mConnectivityManager, times(1)).registerNetworkCallback(
|
verify(mConnectivityManager, times(1)).registerNetworkCallback(
|
||||||
@@ -252,14 +290,12 @@ public class TetheringTest {
|
|||||||
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
|
sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
|
||||||
mLooper.dispatchAll();
|
mLooper.dispatchAll();
|
||||||
|
|
||||||
verify(mNMService, times(1)).listInterfaces();
|
verifyInterfaceServingModeStarted();
|
||||||
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
|
verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
|
||||||
verify(mNMService, times(1))
|
|
||||||
.setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
|
|
||||||
verify(mNMService, times(1)).tetherInterface(mTestIfname);
|
|
||||||
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));
|
||||||
verifyNoMoreInteractions(mNMService);
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_ACTIVE_TETHER);
|
||||||
// UpstreamNetworkMonitor will be started, and will register two callbacks:
|
// UpstreamNetworkMonitor will be started, and will register two callbacks:
|
||||||
// a "listen all" and a "track default".
|
// a "listen all" and a "track default".
|
||||||
verify(mConnectivityManager, times(1)).registerNetworkCallback(
|
verify(mConnectivityManager, times(1)).registerNetworkCallback(
|
||||||
|
|||||||
Reference in New Issue
Block a user