am da6da090: Captive portal handling
* commit 'da6da0907b28d4704aabbdb1bbeb4300954670d1': Captive portal handling
This commit is contained in:
@@ -12606,6 +12606,7 @@ package android.net {
|
||||
method public static final android.net.NetworkInfo.DetailedState[] values();
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState BLOCKED;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState CAPTIVE_PORTAL_CHECK;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTED;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState CONNECTING;
|
||||
enum_constant public static final android.net.NetworkInfo.DetailedState DISCONNECTED;
|
||||
|
||||
@@ -133,6 +133,11 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captivePortalCheckComplete() {
|
||||
// not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-enable connectivity to a network after a {@link #teardown()}.
|
||||
*/
|
||||
|
||||
282
core/java/android/net/CaptivePortalTracker.java
Normal file
282
core/java/android/net/CaptivePortalTracker.java
Normal file
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (C) 2012 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.net;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.IConnectivityManager;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* This class allows captive portal detection
|
||||
* @hide
|
||||
*/
|
||||
public class CaptivePortalTracker {
|
||||
private static final boolean DBG = true;
|
||||
private static final String TAG = "CaptivePortalTracker";
|
||||
|
||||
private static final String DEFAULT_SERVER = "clients3.google.com";
|
||||
private static final String NOTIFICATION_ID = "CaptivePortal.Notification";
|
||||
|
||||
private static final int SOCKET_TIMEOUT_MS = 10000;
|
||||
|
||||
private String mServer;
|
||||
private String mUrl;
|
||||
private boolean mNotificationShown = false;
|
||||
private boolean mIsCaptivePortalCheckEnabled = false;
|
||||
private InternalHandler mHandler;
|
||||
private IConnectivityManager mConnService;
|
||||
private Context mContext;
|
||||
private NetworkInfo mNetworkInfo;
|
||||
private boolean mIsCaptivePortal = false;
|
||||
|
||||
private static final int DETECT_PORTAL = 0;
|
||||
private static final int HANDLE_CONNECT = 1;
|
||||
|
||||
/**
|
||||
* Activity Action: Switch to the captive portal network
|
||||
* <p>Input: Nothing.
|
||||
* <p>Output: Nothing.
|
||||
*/
|
||||
public static final String ACTION_SWITCH_TO_CAPTIVE_PORTAL
|
||||
= "android.net.SWITCH_TO_CAPTIVE_PORTAL";
|
||||
|
||||
private CaptivePortalTracker(Context context, NetworkInfo info, IConnectivityManager cs) {
|
||||
mContext = context;
|
||||
mNetworkInfo = info;
|
||||
mConnService = cs;
|
||||
|
||||
HandlerThread handlerThread = new HandlerThread("CaptivePortalThread");
|
||||
handlerThread.start();
|
||||
mHandler = new InternalHandler(handlerThread.getLooper());
|
||||
mHandler.obtainMessage(DETECT_PORTAL).sendToTarget();
|
||||
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(ACTION_SWITCH_TO_CAPTIVE_PORTAL);
|
||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||
|
||||
mContext.registerReceiver(mReceiver, filter);
|
||||
|
||||
mServer = Settings.Secure.getString(mContext.getContentResolver(),
|
||||
Settings.Secure.CAPTIVE_PORTAL_SERVER);
|
||||
if (mServer == null) mServer = DEFAULT_SERVER;
|
||||
|
||||
mIsCaptivePortalCheckEnabled = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.CAPTIVE_PORTAL_DETECTION_ENABLED, 1) == 1;
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(ACTION_SWITCH_TO_CAPTIVE_PORTAL)) {
|
||||
notifyPortalCheckComplete();
|
||||
} else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
||||
NetworkInfo info = intent.getParcelableExtra(
|
||||
ConnectivityManager.EXTRA_NETWORK_INFO);
|
||||
mHandler.obtainMessage(HANDLE_CONNECT, info).sendToTarget();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public static CaptivePortalTracker detect(Context context, NetworkInfo info,
|
||||
IConnectivityManager cs) {
|
||||
CaptivePortalTracker captivePortal = new CaptivePortalTracker(context, info, cs);
|
||||
return captivePortal;
|
||||
}
|
||||
|
||||
private class InternalHandler extends Handler {
|
||||
public InternalHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case DETECT_PORTAL:
|
||||
InetAddress server = lookupHost(mServer);
|
||||
if (server != null) {
|
||||
requestRouteToHost(server);
|
||||
if (isCaptivePortal(server)) {
|
||||
if (DBG) log("Captive portal " + mNetworkInfo);
|
||||
setNotificationVisible(true);
|
||||
mIsCaptivePortal = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
notifyPortalCheckComplete();
|
||||
quit();
|
||||
break;
|
||||
case HANDLE_CONNECT:
|
||||
NetworkInfo info = (NetworkInfo) msg.obj;
|
||||
if (info.getType() != mNetworkInfo.getType()) break;
|
||||
|
||||
if (info.getState() == NetworkInfo.State.CONNECTED ||
|
||||
info.getState() == NetworkInfo.State.DISCONNECTED) {
|
||||
setNotificationVisible(false);
|
||||
}
|
||||
|
||||
/* Connected to a captive portal */
|
||||
if (info.getState() == NetworkInfo.State.CONNECTED &&
|
||||
mIsCaptivePortal) {
|
||||
launchBrowser();
|
||||
quit();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
loge("Unhandled message " + msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void quit() {
|
||||
mIsCaptivePortal = false;
|
||||
getLooper().quit();
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
private void launchBrowser() {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
}
|
||||
|
||||
private void notifyPortalCheckComplete() {
|
||||
try {
|
||||
mConnService.captivePortalCheckComplete(mNetworkInfo);
|
||||
} catch(RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void requestRouteToHost(InetAddress server) {
|
||||
try {
|
||||
mConnService.requestRouteToHostAddress(mNetworkInfo.getType(),
|
||||
server.getAddress());
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Do a URL fetch on a known server to see if we get the data we expect
|
||||
*/
|
||||
private boolean isCaptivePortal(InetAddress server) {
|
||||
HttpURLConnection urlConnection = null;
|
||||
if (!mIsCaptivePortalCheckEnabled) return false;
|
||||
|
||||
mUrl = "http://" + server.getHostAddress() + "/generate_204";
|
||||
try {
|
||||
URL url = new URL(mUrl);
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
urlConnection.setInstanceFollowRedirects(false);
|
||||
urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
|
||||
urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.getInputStream();
|
||||
// we got a valid response, but not from the real google
|
||||
return urlConnection.getResponseCode() != 204;
|
||||
} catch (IOException e) {
|
||||
if (DBG) log("Probably not a portal: exception " + e);
|
||||
return false;
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private InetAddress lookupHost(String hostname) {
|
||||
InetAddress inetAddress[];
|
||||
try {
|
||||
inetAddress = InetAddress.getAllByName(hostname);
|
||||
} catch (UnknownHostException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (InetAddress a : inetAddress) {
|
||||
if (a instanceof Inet4Address) return a;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private void setNotificationVisible(boolean visible) {
|
||||
// if it should be hidden and it is already hidden, then noop
|
||||
if (!visible && !mNotificationShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
Resources r = Resources.getSystem();
|
||||
NotificationManager notificationManager = (NotificationManager) mContext
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (visible) {
|
||||
CharSequence title = r.getString(R.string.wifi_available_sign_in, 0);
|
||||
CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed,
|
||||
mNetworkInfo.getExtraInfo());
|
||||
|
||||
Notification notification = new Notification();
|
||||
notification.when = 0;
|
||||
notification.icon = com.android.internal.R.drawable.stat_notify_wifi_in_range;
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
notification.contentIntent = PendingIntent.getBroadcast(mContext, 0,
|
||||
new Intent(CaptivePortalTracker.ACTION_SWITCH_TO_CAPTIVE_PORTAL), 0);
|
||||
|
||||
notification.tickerText = title;
|
||||
notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
|
||||
|
||||
notificationManager.notify(NOTIFICATION_ID, 1, notification);
|
||||
} else {
|
||||
notificationManager.cancel(NOTIFICATION_ID, 1);
|
||||
}
|
||||
mNotificationShown = visible;
|
||||
}
|
||||
|
||||
private static void log(String s) {
|
||||
Log.d(TAG, s);
|
||||
}
|
||||
|
||||
private static void loge(String s) {
|
||||
Log.e(TAG, s);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -921,4 +921,15 @@ public class ConnectivityManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public void captivePortalCheckComplete(NetworkInfo info) {
|
||||
try {
|
||||
mService.captivePortalCheckComplete(info);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -119,6 +119,10 @@ public class DummyDataStateTracker implements NetworkStateTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void captivePortalCheckComplete() {
|
||||
// not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the detailed state of a network, and if it is a
|
||||
* change from the previous state, send a notification to
|
||||
|
||||
@@ -274,6 +274,11 @@ public class EthernetDataTracker implements NetworkStateTracker {
|
||||
return mLinkUp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captivePortalCheckComplete() {
|
||||
// not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the wireless radio off for a network.
|
||||
* @param turnOn {@code true} to turn the radio on, {@code false}
|
||||
|
||||
@@ -124,4 +124,6 @@ interface IConnectivityManager
|
||||
LegacyVpnInfo getLegacyVpnInfo();
|
||||
|
||||
boolean updateLockdownVpn();
|
||||
|
||||
void captivePortalCheckComplete(in NetworkInfo info);
|
||||
}
|
||||
|
||||
@@ -381,6 +381,11 @@ public class MobileDataStateTracker implements NetworkStateTracker {
|
||||
return (setEnableApn(mApnType, false) != PhoneConstants.APN_REQUEST_FAILED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captivePortalCheckComplete() {
|
||||
// not implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the detailed state of a network, and if it is a
|
||||
* change from the previous state, send a notification to
|
||||
|
||||
@@ -79,7 +79,9 @@ public class NetworkInfo implements Parcelable {
|
||||
/** Access to this network is blocked. */
|
||||
BLOCKED,
|
||||
/** Link has poor connectivity. */
|
||||
VERIFYING_POOR_LINK
|
||||
VERIFYING_POOR_LINK,
|
||||
/** Checking if network is a captive portal */
|
||||
CAPTIVE_PORTAL_CHECK,
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,6 +99,7 @@ public class NetworkInfo implements Parcelable {
|
||||
stateMap.put(DetailedState.AUTHENTICATING, State.CONNECTING);
|
||||
stateMap.put(DetailedState.OBTAINING_IPADDR, State.CONNECTING);
|
||||
stateMap.put(DetailedState.VERIFYING_POOR_LINK, State.CONNECTING);
|
||||
stateMap.put(DetailedState.CAPTIVE_PORTAL_CHECK, State.CONNECTING);
|
||||
stateMap.put(DetailedState.CONNECTED, State.CONNECTED);
|
||||
stateMap.put(DetailedState.SUSPENDED, State.SUSPENDED);
|
||||
stateMap.put(DetailedState.DISCONNECTING, State.DISCONNECTING);
|
||||
|
||||
@@ -122,6 +122,11 @@ public interface NetworkStateTracker {
|
||||
*/
|
||||
public boolean reconnect();
|
||||
|
||||
/**
|
||||
* Ready to switch on to the network after captive portal check
|
||||
*/
|
||||
public void captivePortalCheckComplete();
|
||||
|
||||
/**
|
||||
* Turn the wireless radio off for a network.
|
||||
* @param turnOn {@code true} to turn the radio on, {@code false}
|
||||
|
||||
@@ -3278,13 +3278,6 @@ public final class Settings {
|
||||
"wifi_watchdog_rssi_fetch_interval_ms";
|
||||
|
||||
|
||||
/**
|
||||
* ms delay before rechecking a connect SSID for walled garden with a http download.
|
||||
* @hide
|
||||
*/
|
||||
public static final String WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS =
|
||||
"wifi_watchdog_walled_garden_interval_ms";
|
||||
|
||||
/**
|
||||
* Number of ARP pings per check.
|
||||
* @hide
|
||||
@@ -3321,23 +3314,6 @@ public final class Settings {
|
||||
public static final String WIFI_SUSPEND_OPTIMIZATIONS_ENABLED =
|
||||
"wifi_suspend_optimizations_enabled";
|
||||
|
||||
/**
|
||||
* Setting to turn off walled garden test on Wi-Fi. Feature is enabled by default and
|
||||
* the setting needs to be set to 0 to disable it.
|
||||
* @hide
|
||||
*/
|
||||
public static final String WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED =
|
||||
"wifi_watchdog_walled_garden_test_enabled";
|
||||
|
||||
/**
|
||||
* The URL used for walled garden check upon a new conection. WifiWatchdogService
|
||||
* fetches the URL and checks to see if {@link #WIFI_WATCHDOG_WALLED_GARDEN_PATTERN}
|
||||
* is not part of the title string to notify the user on the presence of a walled garden.
|
||||
* @hide
|
||||
*/
|
||||
public static final String WIFI_WATCHDOG_WALLED_GARDEN_URL =
|
||||
"wifi_watchdog_walled_garden_url";
|
||||
|
||||
/**
|
||||
* The maximum number of times we will retry a connection to an access
|
||||
* point for which we have failed in acquiring an IP address from DHCP.
|
||||
@@ -3361,6 +3337,21 @@ public final class Settings {
|
||||
*/
|
||||
public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
|
||||
|
||||
/**
|
||||
* Setting to turn off captive portal detection. Feature is enabled by default and
|
||||
* the setting needs to be set to 0 to disable it.
|
||||
* @hide
|
||||
*/
|
||||
public static final String CAPTIVE_PORTAL_DETECTION_ENABLED =
|
||||
"captive_portal_detection_enabled";
|
||||
|
||||
/**
|
||||
* The server used for captive portal detection upon a new conection. A 204 response
|
||||
* code from the server is used for validation.
|
||||
* @hide
|
||||
*/
|
||||
public static final String CAPTIVE_PORTAL_SERVER = "captive_portal_server";
|
||||
|
||||
/**
|
||||
* Maximum amount of time in milliseconds to hold a wakelock while waiting for mobile
|
||||
* data connectivity to be established after a disconnect from Wi-Fi.
|
||||
|
||||
@@ -42,6 +42,7 @@ import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.CaptivePortalTracker;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.DummyDataStateTracker;
|
||||
import android.net.EthernetDataTracker;
|
||||
@@ -166,6 +167,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
*/
|
||||
private NetworkStateTracker mNetTrackers[];
|
||||
|
||||
/* Handles captive portal check on a network */
|
||||
private CaptivePortalTracker mCaptivePortalTracker;
|
||||
|
||||
/**
|
||||
* The link properties that define the current links
|
||||
*/
|
||||
@@ -1363,8 +1367,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
return false;
|
||||
}
|
||||
NetworkStateTracker tracker = mNetTrackers[networkType];
|
||||
DetailedState netState = tracker.getNetworkInfo().getDetailedState();
|
||||
|
||||
if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
|
||||
if (tracker == null || (netState != DetailedState.CONNECTED &&
|
||||
netState != DetailedState.CAPTIVE_PORTAL_CHECK) ||
|
||||
tracker.isTeardownRequested()) {
|
||||
if (VDBG) {
|
||||
log("requestRouteToHostAddress on down network " +
|
||||
@@ -1966,32 +1972,29 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
};
|
||||
|
||||
private void handleConnect(NetworkInfo info) {
|
||||
final int type = info.getType();
|
||||
private boolean isNewNetTypePreferredOverCurrentNetType(int type) {
|
||||
if ((type != mNetworkPreference &&
|
||||
mNetConfigs[mActiveDefaultNetwork].priority >
|
||||
mNetConfigs[type].priority) ||
|
||||
mNetworkPreference == mActiveDefaultNetwork) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
setupDataActivityTracking(type);
|
||||
private void handleConnect(NetworkInfo info) {
|
||||
final int newNetType = info.getType();
|
||||
|
||||
setupDataActivityTracking(newNetType);
|
||||
|
||||
// snapshot isFailover, because sendConnectedBroadcast() resets it
|
||||
boolean isFailover = info.isFailover();
|
||||
final NetworkStateTracker thisNet = mNetTrackers[type];
|
||||
final NetworkStateTracker thisNet = mNetTrackers[newNetType];
|
||||
final String thisIface = thisNet.getLinkProperties().getInterfaceName();
|
||||
|
||||
// if this is a default net and other default is running
|
||||
// kill the one not preferred
|
||||
if (mNetConfigs[type].isDefault()) {
|
||||
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
|
||||
if ((type != mNetworkPreference &&
|
||||
mNetConfigs[mActiveDefaultNetwork].priority >
|
||||
mNetConfigs[type].priority) ||
|
||||
mNetworkPreference == mActiveDefaultNetwork) {
|
||||
// don't accept this one
|
||||
if (VDBG) {
|
||||
log("Not broadcasting CONNECT_ACTION " +
|
||||
"to torn down network " + info.getTypeName());
|
||||
}
|
||||
teardown(thisNet);
|
||||
return;
|
||||
} else {
|
||||
if (mNetConfigs[newNetType].isDefault()) {
|
||||
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != newNetType) {
|
||||
if (isNewNetTypePreferredOverCurrentNetType(newNetType)) {
|
||||
// tear down the other
|
||||
NetworkStateTracker otherNet =
|
||||
mNetTrackers[mActiveDefaultNetwork];
|
||||
@@ -2004,6 +2007,14 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
teardown(thisNet);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// don't accept this one
|
||||
if (VDBG) {
|
||||
log("Not broadcasting CONNECT_ACTION " +
|
||||
"to torn down network " + info.getTypeName());
|
||||
}
|
||||
teardown(thisNet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
synchronized (ConnectivityService.this) {
|
||||
@@ -2017,7 +2028,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
1000);
|
||||
}
|
||||
}
|
||||
mActiveDefaultNetwork = type;
|
||||
mActiveDefaultNetwork = newNetType;
|
||||
// this will cause us to come up initially as unconnected and switching
|
||||
// to connected after our normal pause unless somebody reports us as reall
|
||||
// disconnected
|
||||
@@ -2029,19 +2040,47 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
}
|
||||
thisNet.setTeardownRequested(false);
|
||||
updateNetworkSettings(thisNet);
|
||||
handleConnectivityChange(type, false);
|
||||
handleConnectivityChange(newNetType, false);
|
||||
sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
|
||||
|
||||
// notify battery stats service about this network
|
||||
if (thisIface != null) {
|
||||
try {
|
||||
BatteryStatsService.getService().noteNetworkInterfaceType(thisIface, type);
|
||||
BatteryStatsService.getService().noteNetworkInterfaceType(thisIface, newNetType);
|
||||
} catch (RemoteException e) {
|
||||
// ignored; service lives in system_server
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleCaptivePortalTrackerCheck(NetworkInfo info) {
|
||||
if (DBG) log("Captive portal check " + info);
|
||||
int type = info.getType();
|
||||
final NetworkStateTracker thisNet = mNetTrackers[type];
|
||||
if (mNetConfigs[type].isDefault()) {
|
||||
if (mActiveDefaultNetwork != -1 && mActiveDefaultNetwork != type) {
|
||||
if (isNewNetTypePreferredOverCurrentNetType(type)) {
|
||||
if (DBG) log("Captive check on " + info.getTypeName());
|
||||
mCaptivePortalTracker = CaptivePortalTracker.detect(mContext, info,
|
||||
ConnectivityService.this);
|
||||
return;
|
||||
} else {
|
||||
if (DBG) log("Tear down low priority net " + info.getTypeName());
|
||||
teardown(thisNet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
thisNet.captivePortalCheckComplete();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void captivePortalCheckComplete(NetworkInfo info) {
|
||||
mNetTrackers[info.getType()].captivePortalCheckComplete();
|
||||
mCaptivePortalTracker = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup data activity tracking for the given network interface.
|
||||
*
|
||||
@@ -2630,6 +2669,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
|
||||
if (info.getDetailedState() ==
|
||||
NetworkInfo.DetailedState.FAILED) {
|
||||
handleConnectionFailure(info);
|
||||
} else if (info.getDetailedState() ==
|
||||
DetailedState.CAPTIVE_PORTAL_CHECK) {
|
||||
handleCaptivePortalTrackerCheck(info);
|
||||
} else if (state == NetworkInfo.State.DISCONNECTED) {
|
||||
handleDisconnect(info);
|
||||
} else if (state == NetworkInfo.State.SUSPENDED) {
|
||||
|
||||
@@ -412,6 +412,7 @@ public class WifiService extends IWifiManager.Stub {
|
||||
switch(mNetworkInfo.getDetailedState()) {
|
||||
case CONNECTED:
|
||||
case DISCONNECTED:
|
||||
case CAPTIVE_PORTAL_CHECK:
|
||||
evaluateTrafficStatsPolling();
|
||||
resetNotification();
|
||||
break;
|
||||
@@ -606,6 +607,12 @@ public class WifiService extends IWifiManager.Stub {
|
||||
"WifiService");
|
||||
}
|
||||
|
||||
private void enforceConnectivityInternalPermission() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.CONNECTIVITY_INTERNAL,
|
||||
"ConnectivityService");
|
||||
}
|
||||
|
||||
/**
|
||||
* see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
|
||||
* @param enable {@code true} to enable, {@code false} to disable.
|
||||
@@ -910,7 +917,7 @@ public class WifiService extends IWifiManager.Stub {
|
||||
*
|
||||
*/
|
||||
public void startWifi() {
|
||||
enforceChangePermission();
|
||||
enforceConnectivityInternalPermission();
|
||||
/* TODO: may be add permissions for access only to connectivity service
|
||||
* TODO: if a start issued, keep wifi alive until a stop issued irrespective
|
||||
* of WifiLock & device idle status unless wifi enabled status is toggled
|
||||
@@ -920,20 +927,24 @@ public class WifiService extends IWifiManager.Stub {
|
||||
mWifiStateMachine.reconnectCommand();
|
||||
}
|
||||
|
||||
public void captivePortalCheckComplete() {
|
||||
enforceConnectivityInternalPermission();
|
||||
mWifiStateMachine.captivePortalCheckComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* see {@link android.net.wifi.WifiManager#stopWifi}
|
||||
*
|
||||
*/
|
||||
public void stopWifi() {
|
||||
enforceChangePermission();
|
||||
/* TODO: may be add permissions for access only to connectivity service
|
||||
enforceConnectivityInternalPermission();
|
||||
/*
|
||||
* TODO: if a stop is issued, wifi is brought up only by startWifi
|
||||
* unless wifi enabled status is toggled
|
||||
*/
|
||||
mWifiStateMachine.setDriverStart(false, mEmergencyCallbackMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* see {@link android.net.wifi.WifiManager#addToBlacklist}
|
||||
*
|
||||
|
||||
@@ -106,5 +106,7 @@ interface IWifiManager
|
||||
Messenger getWifiStateMachineMessenger();
|
||||
|
||||
String getConfigFile();
|
||||
|
||||
void captivePortalCheckComplete();
|
||||
}
|
||||
|
||||
|
||||
@@ -1971,4 +1971,11 @@ public class WifiManager {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void captivePortalCheckComplete() {
|
||||
try {
|
||||
mService.captivePortalCheckComplete();
|
||||
} catch (RemoteException e) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,6 +256,8 @@ public class WifiStateMachine extends StateMachine {
|
||||
static final int CMD_DELAYED_STOP_DRIVER = BASE + 18;
|
||||
/* A delayed message sent to start driver when it fail to come up */
|
||||
static final int CMD_DRIVER_START_TIMED_OUT = BASE + 19;
|
||||
/* Ready to switch to network as default */
|
||||
static final int CMD_CAPTIVE_CHECK_COMPLETE = BASE + 20;
|
||||
|
||||
/* Start the soft access point */
|
||||
static final int CMD_START_AP = BASE + 21;
|
||||
@@ -459,6 +461,8 @@ public class WifiStateMachine extends StateMachine {
|
||||
private State mObtainingIpState = new ObtainingIpState();
|
||||
/* Waiting for link quality verification to be complete */
|
||||
private State mVerifyingLinkState = new VerifyingLinkState();
|
||||
/* Waiting for captive portal check to be complete */
|
||||
private State mCaptivePortalCheckState = new CaptivePortalCheckState();
|
||||
/* Connected with IP addr */
|
||||
private State mConnectedState = new ConnectedState();
|
||||
/* disconnect issued, waiting for network disconnect confirmation */
|
||||
@@ -695,6 +699,7 @@ public class WifiStateMachine extends StateMachine {
|
||||
addState(mL2ConnectedState, mConnectModeState);
|
||||
addState(mObtainingIpState, mL2ConnectedState);
|
||||
addState(mVerifyingLinkState, mL2ConnectedState);
|
||||
addState(mCaptivePortalCheckState, mL2ConnectedState);
|
||||
addState(mConnectedState, mL2ConnectedState);
|
||||
addState(mDisconnectingState, mConnectModeState);
|
||||
addState(mDisconnectedState, mConnectModeState);
|
||||
@@ -865,6 +870,10 @@ public class WifiStateMachine extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
public void captivePortalCheckComplete() {
|
||||
sendMessage(obtainMessage(CMD_CAPTIVE_CHECK_COMPLETE));
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: doc
|
||||
*/
|
||||
@@ -1616,7 +1625,7 @@ public class WifiStateMachine extends StateMachine {
|
||||
}
|
||||
|
||||
if (state != mNetworkInfo.getDetailedState()) {
|
||||
mNetworkInfo.setDetailedState(state, null, null);
|
||||
mNetworkInfo.setDetailedState(state, null, mWifiInfo.getSSID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3253,6 +3262,26 @@ public class WifiStateMachine extends StateMachine {
|
||||
//stay here
|
||||
break;
|
||||
case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
|
||||
transitionTo(mCaptivePortalCheckState);
|
||||
break;
|
||||
default:
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
return HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
class CaptivePortalCheckState extends State {
|
||||
@Override
|
||||
public void enter() {
|
||||
setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
|
||||
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CAPTIVE_PORTAL_CHECK);
|
||||
sendNetworkStateChangeBroadcast(mLastBssid);
|
||||
}
|
||||
@Override
|
||||
public boolean processMessage(Message message) {
|
||||
switch (message.what) {
|
||||
case CMD_CAPTIVE_CHECK_COMPLETE:
|
||||
try {
|
||||
mNwService.enableIpv6(mInterfaceName);
|
||||
} catch (RemoteException re) {
|
||||
@@ -3260,7 +3289,6 @@ public class WifiStateMachine extends StateMachine {
|
||||
} catch (IllegalStateException e) {
|
||||
loge("Failed to enable IPv6: " + e);
|
||||
}
|
||||
|
||||
setNetworkDetailedState(DetailedState.CONNECTED);
|
||||
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CONNECTED);
|
||||
sendNetworkStateChangeBroadcast(mLastBssid);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.IntentFilter;
|
||||
import android.net.LinkCapabilities;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.NetworkInfo.DetailedState;
|
||||
import android.net.NetworkStateTracker;
|
||||
import android.net.wifi.p2p.WifiP2pManager;
|
||||
import android.os.Handler;
|
||||
@@ -112,6 +113,14 @@ public class WifiStateTracker implements NetworkStateTracker {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captive check is complete, switch to network
|
||||
*/
|
||||
@Override
|
||||
public void captivePortalCheckComplete() {
|
||||
mWifiManager.captivePortalCheckComplete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn the wireless radio off for a network.
|
||||
* @param turnOn {@code true} to turn the radio on, {@code false}
|
||||
@@ -235,9 +244,10 @@ public class WifiStateTracker implements NetworkStateTracker {
|
||||
mLinkCapabilities = new LinkCapabilities();
|
||||
}
|
||||
// don't want to send redundent state messages
|
||||
// TODO can this be fixed in WifiStateMachine?
|
||||
// but send portal check detailed state notice
|
||||
NetworkInfo.State state = mNetworkInfo.getState();
|
||||
if (mLastState == state) {
|
||||
if (mLastState == state &&
|
||||
mNetworkInfo.getDetailedState() != DetailedState.CAPTIVE_PORTAL_CHECK) {
|
||||
return;
|
||||
} else {
|
||||
mLastState = state;
|
||||
|
||||
@@ -16,20 +16,15 @@
|
||||
|
||||
package android.net.wifi;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.Uri;
|
||||
import android.net.wifi.RssiPacketCountInfo;
|
||||
import android.os.Message;
|
||||
import android.os.SystemClock;
|
||||
@@ -44,10 +39,7 @@ import com.android.internal.util.Protocol;
|
||||
import com.android.internal.util.State;
|
||||
import com.android.internal.util.StateMachine;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.DecimalFormat;
|
||||
|
||||
/**
|
||||
@@ -100,8 +92,7 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
private static final int EVENT_SCREEN_OFF = BASE + 9;
|
||||
|
||||
/* Internal messages */
|
||||
private static final int CMD_DELAYED_WALLED_GARDEN_CHECK = BASE + 11;
|
||||
private static final int CMD_RSSI_FETCH = BASE + 12;
|
||||
private static final int CMD_RSSI_FETCH = BASE + 11;
|
||||
|
||||
/* Notifications from/to WifiStateMachine */
|
||||
static final int POOR_LINK_DETECTED = BASE + 21;
|
||||
@@ -266,27 +257,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
new MaxAvoidTime( 0 * 60000, -55 ),
|
||||
};
|
||||
|
||||
|
||||
private static final String WALLED_GARDEN_NOTIFICATION_ID = "WifiWatchdog.walledgarden";
|
||||
|
||||
private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000;
|
||||
|
||||
/**
|
||||
* See http://go/clientsdns for usage approval
|
||||
*/
|
||||
private static final String DEFAULT_WALLED_GARDEN_URL =
|
||||
"http://clients3.google.com/generate_204";
|
||||
private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000;
|
||||
|
||||
/**
|
||||
* Some carrier apps might have support captive portal handling. Add some
|
||||
* delay to allow app authentication to be done before our test. TODO: This
|
||||
* should go away once we provide an API to apps to disable walled garden
|
||||
* test for certain SSIDs
|
||||
*/
|
||||
private static final int WALLED_GARDEN_START_DELAY_MS = 3000;
|
||||
|
||||
|
||||
/* Framework related */
|
||||
private Context mContext;
|
||||
private ContentResolver mContentResolver;
|
||||
@@ -300,13 +270,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
/* System settingss related */
|
||||
private static boolean sWifiOnly = false;
|
||||
private boolean mPoorNetworkDetectionEnabled;
|
||||
private long mWalledGardenIntervalMs;
|
||||
private boolean mWalledGardenTestEnabled;
|
||||
private String mWalledGardenUrl;
|
||||
|
||||
/* Wall garden detection related */
|
||||
private long mLastWalledGardenCheckTime = 0;
|
||||
private boolean mWalledGardenNotificationShown;
|
||||
|
||||
/* Poor link detection related */
|
||||
private LruCache<String, BssidStatistics> mBssidCache =
|
||||
@@ -325,7 +288,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
private NotConnectedState mNotConnectedState = new NotConnectedState();
|
||||
private VerifyingLinkState mVerifyingLinkState = new VerifyingLinkState();
|
||||
private ConnectedState mConnectedState = new ConnectedState();
|
||||
private WalledGardenCheckState mWalledGardenCheckState = new WalledGardenCheckState();
|
||||
private OnlineWatchState mOnlineWatchState = new OnlineWatchState();
|
||||
private LinkMonitoringState mLinkMonitoringState = new LinkMonitoringState();
|
||||
private OnlineState mOnlineState = new OnlineState();
|
||||
@@ -359,7 +321,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
addState(mNotConnectedState, mWatchdogEnabledState);
|
||||
addState(mVerifyingLinkState, mWatchdogEnabledState);
|
||||
addState(mConnectedState, mWatchdogEnabledState);
|
||||
addState(mWalledGardenCheckState, mConnectedState);
|
||||
addState(mOnlineWatchState, mConnectedState);
|
||||
addState(mLinkMonitoringState, mConnectedState);
|
||||
addState(mOnlineState, mConnectedState);
|
||||
@@ -379,13 +340,12 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
Context.CONNECTIVITY_SERVICE);
|
||||
sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
|
||||
|
||||
// Watchdog is always enabled. Poor network detection & walled garden detection
|
||||
// can individually be turned on/off
|
||||
// Watchdog is always enabled. Poor network detection can be seperately turned on/off
|
||||
// TODO: Remove this setting & clean up state machine since we always have
|
||||
// watchdog in an enabled state
|
||||
putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true);
|
||||
|
||||
// disable poor network avoidance, but keep watchdog active for walled garden detection
|
||||
// disable poor network avoidance
|
||||
if (sWifiOnly) {
|
||||
logd("Disabling poor network avoidance for wi-fi only device");
|
||||
putSettingsBoolean(contentResolver,
|
||||
@@ -457,45 +417,9 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
}
|
||||
};
|
||||
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS),
|
||||
false, contentObserver);
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED),
|
||||
false, contentObserver);
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED),
|
||||
false, contentObserver);
|
||||
mContext.getContentResolver().registerContentObserver(
|
||||
Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL),
|
||||
false, contentObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* DNS based detection techniques do not work at all hotspots. The one sure
|
||||
* way to check a walled garden is to see if a URL fetch on a known address
|
||||
* fetches the data we expect
|
||||
*/
|
||||
private boolean isWalledGardenConnection() {
|
||||
HttpURLConnection urlConnection = null;
|
||||
try {
|
||||
URL url = new URL(mWalledGardenUrl);
|
||||
urlConnection = (HttpURLConnection) url.openConnection();
|
||||
urlConnection.setInstanceFollowRedirects(false);
|
||||
urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
|
||||
urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS);
|
||||
urlConnection.setUseCaches(false);
|
||||
urlConnection.getInputStream();
|
||||
// we got a valid response, but not from the real google
|
||||
return urlConnection.getResponseCode() != 204;
|
||||
} catch (IOException e) {
|
||||
if (DBG) logd("Walled garden check - probably not a portal: exception " + e);
|
||||
return false;
|
||||
} finally {
|
||||
if (urlConnection != null) {
|
||||
urlConnection.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dump(PrintWriter pw) {
|
||||
@@ -504,10 +428,7 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
pw.println("mWifiInfo: [" + mWifiInfo + "]");
|
||||
pw.println("mLinkProperties: [" + mLinkProperties + "]");
|
||||
pw.println("mCurrentSignalLevel: [" + mCurrentSignalLevel + "]");
|
||||
pw.println("mWalledGardenIntervalMs: [" + mWalledGardenIntervalMs + "]");
|
||||
pw.println("mPoorNetworkDetectionEnabled: [" + mPoorNetworkDetectionEnabled + "]");
|
||||
pw.println("mWalledGardenTestEnabled: [" + mWalledGardenTestEnabled + "]");
|
||||
pw.println("mWalledGardenUrl: [" + mWalledGardenUrl + "]");
|
||||
}
|
||||
|
||||
private boolean isWatchdogEnabled() {
|
||||
@@ -521,47 +442,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
|
||||
mPoorNetworkDetectionEnabled = getSettingsBoolean(mContentResolver,
|
||||
Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, true);
|
||||
mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver,
|
||||
Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true);
|
||||
mWalledGardenUrl = getSettingsStr(mContentResolver,
|
||||
Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL,
|
||||
DEFAULT_WALLED_GARDEN_URL);
|
||||
mWalledGardenIntervalMs = Secure.getLong(mContentResolver,
|
||||
Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS,
|
||||
DEFAULT_WALLED_GARDEN_INTERVAL_MS);
|
||||
}
|
||||
|
||||
private void setWalledGardenNotificationVisible(boolean visible) {
|
||||
// if it should be hidden and it is already hidden, then noop
|
||||
if (!visible && !mWalledGardenNotificationShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
Resources r = Resources.getSystem();
|
||||
NotificationManager notificationManager = (NotificationManager) mContext
|
||||
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
if (visible) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mWalledGardenUrl));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
CharSequence title = r.getString(R.string.wifi_available_sign_in, 0);
|
||||
CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed,
|
||||
mWifiInfo.getSSID());
|
||||
|
||||
Notification notification = new Notification();
|
||||
notification.when = 0;
|
||||
notification.icon = com.android.internal.R.drawable.stat_notify_wifi_in_range;
|
||||
notification.flags = Notification.FLAG_AUTO_CANCEL;
|
||||
notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
|
||||
notification.tickerText = title;
|
||||
notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
|
||||
|
||||
notificationManager.notify(WALLED_GARDEN_NOTIFICATION_ID, 1, notification);
|
||||
} else {
|
||||
notificationManager.cancel(WALLED_GARDEN_NOTIFICATION_ID, 1);
|
||||
}
|
||||
mWalledGardenNotificationShown = visible;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -587,7 +467,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
case EVENT_NETWORK_STATE_CHANGE:
|
||||
case EVENT_SUPPLICANT_STATE_CHANGE:
|
||||
case EVENT_BSSID_CHANGE:
|
||||
case CMD_DELAYED_WALLED_GARDEN_CHECK:
|
||||
case CMD_RSSI_FETCH:
|
||||
case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
|
||||
case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
|
||||
@@ -685,11 +564,7 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
}
|
||||
break;
|
||||
case CONNECTED:
|
||||
if (shouldCheckWalledGarden()) {
|
||||
transitionTo(mWalledGardenCheckState);
|
||||
} else {
|
||||
transitionTo(mOnlineWatchState);
|
||||
}
|
||||
transitionTo(mOnlineWatchState);
|
||||
break;
|
||||
default:
|
||||
transitionTo(mNotConnectedState);
|
||||
@@ -716,7 +591,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
|
||||
setWalledGardenNotificationVisible(false);
|
||||
return HANDLED;
|
||||
}
|
||||
}
|
||||
@@ -833,38 +707,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking for wall garden.
|
||||
*/
|
||||
class WalledGardenCheckState extends State {
|
||||
private int mWalledGardenToken = 0;
|
||||
@Override
|
||||
public void enter() {
|
||||
if (DBG) logd(getName());
|
||||
sendMessageDelayed(obtainMessage(CMD_DELAYED_WALLED_GARDEN_CHECK,
|
||||
++mWalledGardenToken, 0), WALLED_GARDEN_START_DELAY_MS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case CMD_DELAYED_WALLED_GARDEN_CHECK:
|
||||
if (msg.arg1 == mWalledGardenToken) {
|
||||
mLastWalledGardenCheckTime = SystemClock.elapsedRealtime();
|
||||
if (isWalledGardenConnection()) {
|
||||
if (DBG) logd("Walled garden detected");
|
||||
setWalledGardenNotificationVisible(true);
|
||||
}
|
||||
transitionTo(mOnlineWatchState);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NOT_HANDLED;
|
||||
}
|
||||
return HANDLED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RSSI is high enough and don't need link monitoring.
|
||||
*/
|
||||
@@ -1037,22 +879,6 @@ public class WifiWatchdogStateMachine extends StateMachine {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldCheckWalledGarden() {
|
||||
if (!mWalledGardenTestEnabled) {
|
||||
if (DBG) logd("Skipping walled garden check - disabled");
|
||||
return false;
|
||||
}
|
||||
|
||||
long waitTime = (mWalledGardenIntervalMs + mLastWalledGardenCheckTime)
|
||||
- SystemClock.elapsedRealtime();
|
||||
|
||||
if (mLastWalledGardenCheckTime != 0 && waitTime > 0) {
|
||||
if (DBG) logd("Skipping walled garden check - wait " + waitTime + " ms.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void updateCurrentBssid(String bssid) {
|
||||
if (DBG) logd("Update current BSSID to " + (bssid != null ? bssid : "null"));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user