Add option to skip and avoid captive portals.
am: 5139717c74
Change-Id: Id38d5c03d06822f9b20abd65db9dd04c90110b63
This commit is contained in:
@@ -2261,11 +2261,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
synchronized (mNetworkForNetId) {
|
synchronized (mNetworkForNetId) {
|
||||||
nai = mNetworkForNetId.get(netId);
|
nai = mNetworkForNetId.get(netId);
|
||||||
}
|
}
|
||||||
// If captive portal status has changed, update capabilities.
|
// If captive portal status has changed, update capabilities or disconnect.
|
||||||
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
|
if (nai != null && (visible != nai.lastCaptivePortalDetected)) {
|
||||||
final int oldScore = nai.getCurrentScore();
|
final int oldScore = nai.getCurrentScore();
|
||||||
nai.lastCaptivePortalDetected = visible;
|
nai.lastCaptivePortalDetected = visible;
|
||||||
nai.everCaptivePortalDetected |= visible;
|
nai.everCaptivePortalDetected |= visible;
|
||||||
|
if (nai.lastCaptivePortalDetected &&
|
||||||
|
Settings.Global.CAPTIVE_PORTAL_MODE_AVOID == getCaptivePortalMode()) {
|
||||||
|
if (DBG) log("Avoiding captive portal network: " + nai.name());
|
||||||
|
nai.asyncChannel.sendMessage(
|
||||||
|
NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
|
||||||
|
teardownUnneededNetwork(nai);
|
||||||
|
break;
|
||||||
|
}
|
||||||
updateCapabilities(oldScore, nai, nai.networkCapabilities);
|
updateCapabilities(oldScore, nai, nai.networkCapabilities);
|
||||||
}
|
}
|
||||||
if (!visible) {
|
if (!visible) {
|
||||||
@@ -2286,6 +2294,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int getCaptivePortalMode() {
|
||||||
|
return Settings.Global.getInt(mContext.getContentResolver(),
|
||||||
|
Settings.Global.CAPTIVE_PORTAL_MODE,
|
||||||
|
Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
|
private boolean maybeHandleNetworkAgentInfoMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
private final IdleableHandlerThread mHandlerThread;
|
private final IdleableHandlerThread mHandlerThread;
|
||||||
private final ConditionVariable mDisconnected = new ConditionVariable();
|
private final ConditionVariable mDisconnected = new ConditionVariable();
|
||||||
private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
|
private final ConditionVariable mNetworkStatusReceived = new ConditionVariable();
|
||||||
|
private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
|
||||||
private int mScore;
|
private int mScore;
|
||||||
private NetworkAgent mNetworkAgent;
|
private NetworkAgent mNetworkAgent;
|
||||||
private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
|
private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
|
||||||
@@ -291,6 +292,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
mRedirectUrl = redirectUrl;
|
mRedirectUrl = redirectUrl;
|
||||||
mNetworkStatusReceived.open();
|
mNetworkStatusReceived.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void preventAutomaticReconnect() {
|
||||||
|
mPreventReconnectReceived.open();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// Waits for the NetworkAgent to be registered, which includes the creation of the
|
// Waits for the NetworkAgent to be registered, which includes the creation of the
|
||||||
// NetworkMonitor.
|
// NetworkMonitor.
|
||||||
@@ -375,11 +381,6 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
mWrappedNetworkMonitor.gen204ProbeResult = 200;
|
mWrappedNetworkMonitor.gen204ProbeResult = 200;
|
||||||
mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
|
mWrappedNetworkMonitor.gen204ProbeRedirectUrl = redirectUrl;
|
||||||
connect(false);
|
connect(false);
|
||||||
waitFor(new Criteria() { public boolean get() {
|
|
||||||
NetworkCapabilities caps = mCm.getNetworkCapabilities(getNetwork());
|
|
||||||
return caps != null && caps.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL);} });
|
|
||||||
mWrappedNetworkMonitor.gen204ProbeResult = 500;
|
|
||||||
mWrappedNetworkMonitor.gen204ProbeRedirectUrl = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disconnect() {
|
public void disconnect() {
|
||||||
@@ -391,6 +392,10 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
return new Network(mNetworkAgent.netId);
|
return new Network(mNetworkAgent.netId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConditionVariable getPreventReconnectReceived() {
|
||||||
|
return mPreventReconnectReceived;
|
||||||
|
}
|
||||||
|
|
||||||
public ConditionVariable getDisconnectedCV() {
|
public ConditionVariable getDisconnectedCV() {
|
||||||
return mDisconnected;
|
return mDisconnected;
|
||||||
}
|
}
|
||||||
@@ -597,6 +602,7 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected CaptivePortalProbeResult isCaptivePortal() {
|
protected CaptivePortalProbeResult isCaptivePortal() {
|
||||||
|
if (!mIsCaptivePortalCheckEnabled) { return new CaptivePortalProbeResult(204); }
|
||||||
return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
|
return new CaptivePortalProbeResult(gen204ProbeResult, gen204ProbeRedirectUrl, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,6 +749,9 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
mService.systemReady();
|
mService.systemReady();
|
||||||
mCm = new WrappedConnectivityManager(getContext(), mService);
|
mCm = new WrappedConnectivityManager(getContext(), mService);
|
||||||
mCm.bindProcessToNetwork(null);
|
mCm.bindProcessToNetwork(null);
|
||||||
|
|
||||||
|
// Ensure that the default setting for Captive Portals is used for most tests
|
||||||
|
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_PROMPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void tearDown() throws Exception {
|
public void tearDown() throws Exception {
|
||||||
@@ -1704,6 +1713,47 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
validatedCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LargeTest
|
||||||
|
public void testAvoidOrIgnoreCaptivePortals() {
|
||||||
|
final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
|
||||||
|
final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
|
||||||
|
.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
|
||||||
|
mCm.registerNetworkCallback(captivePortalRequest, captivePortalCallback);
|
||||||
|
|
||||||
|
final TestNetworkCallback validatedCallback = new TestNetworkCallback();
|
||||||
|
final NetworkRequest validatedRequest = new NetworkRequest.Builder()
|
||||||
|
.addCapability(NET_CAPABILITY_VALIDATED).build();
|
||||||
|
mCm.registerNetworkCallback(validatedRequest, validatedCallback);
|
||||||
|
|
||||||
|
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_AVOID);
|
||||||
|
// Bring up a network with a captive portal.
|
||||||
|
// Expect it to fail to connect and not result in any callbacks.
|
||||||
|
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||||
|
String firstRedirectUrl = "http://example.com/firstPath";
|
||||||
|
|
||||||
|
ConditionVariable disconnectCv = mWiFiNetworkAgent.getDisconnectedCV();
|
||||||
|
ConditionVariable avoidCv = mWiFiNetworkAgent.getPreventReconnectReceived();
|
||||||
|
mWiFiNetworkAgent.connectWithCaptivePortal(firstRedirectUrl);
|
||||||
|
waitFor(disconnectCv);
|
||||||
|
waitFor(avoidCv);
|
||||||
|
|
||||||
|
assertNoCallbacks(captivePortalCallback, validatedCallback);
|
||||||
|
|
||||||
|
// Now test ignore mode.
|
||||||
|
setCaptivePortalMode(Settings.Global.CAPTIVE_PORTAL_MODE_IGNORE);
|
||||||
|
|
||||||
|
// Bring up a network with a captive portal.
|
||||||
|
// Since we're ignoring captive portals, the network will validate.
|
||||||
|
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
|
||||||
|
String secondRedirectUrl = "http://example.com/secondPath";
|
||||||
|
mWiFiNetworkAgent.connectWithCaptivePortal(secondRedirectUrl);
|
||||||
|
|
||||||
|
// Expect NET_CAPABILITY_VALIDATED onAvailable callback.
|
||||||
|
validatedCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
|
||||||
|
// But there should be no CaptivePortal callback.
|
||||||
|
captivePortalCallback.assertNoCallback();
|
||||||
|
}
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public void testInvalidNetworkSpecifier() {
|
public void testInvalidNetworkSpecifier() {
|
||||||
boolean execptionCalled = true;
|
boolean execptionCalled = true;
|
||||||
@@ -1844,6 +1894,11 @@ public class ConnectivityServiceTest extends AndroidTestCase {
|
|||||||
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
mCm.unregisterNetworkCallback(cellNetworkCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setCaptivePortalMode(int mode) {
|
||||||
|
ContentResolver cr = mServiceContext.getContentResolver();
|
||||||
|
Settings.Global.putInt(cr, Settings.Global.CAPTIVE_PORTAL_MODE, mode);
|
||||||
|
}
|
||||||
|
|
||||||
private void setMobileDataAlwaysOn(boolean enable) {
|
private void setMobileDataAlwaysOn(boolean enable) {
|
||||||
ContentResolver cr = mServiceContext.getContentResolver();
|
ContentResolver cr = mServiceContext.getContentResolver();
|
||||||
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
|
Settings.Global.putInt(cr, Settings.Global.MOBILE_DATA_ALWAYS_ON, enable ? 1 : 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user