WifiWatchdogStateMachine.java revision 654f5090754e4e1bf4c1736d0a24769a15a6037e
1654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy/* 2654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Copyright (C) 2011 The Android Open Source Project 3654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 4654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Licensed under the Apache License, Version 2.0 (the "License"); 5654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * you may not use this file except in compliance with the License. 6654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * You may obtain a copy of the License at 7654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 8654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * http://www.apache.org/licenses/LICENSE-2.0 9654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 10654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Unless required by applicable law or agreed to in writing, software 11654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * distributed under the License is distributed on an "AS IS" BASIS, 12654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * See the License for the specific language governing permissions and 14654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * limitations under the License. 15654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 16654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 17654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levypackage android.net.wifi; 18654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 19654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.BroadcastReceiver; 20654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.ContentResolver; 21654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.Context; 22654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.Intent; 23654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.IntentFilter; 24654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.database.ContentObserver; 25654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.ConnectivityManager; 26654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.DnsPinger; 27654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.NetworkInfo; 28654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.Uri; 29654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.os.Message; 30654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.os.SystemClock; 31654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.provider.Settings; 32654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.text.TextUtils; 33654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.util.Slog; 34654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 35654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.Protocol; 36654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.State; 37654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.StateMachine; 38654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 39654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.BufferedInputStream; 40654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.IOException; 41654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.InputStream; 42654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.PrintWriter; 43654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.HttpURLConnection; 44654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.URL; 45654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.HashSet; 46654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.List; 47654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.Scanner; 48654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 49654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy/** 50654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi 51654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * network with multiple access points. After the framework successfully 52654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * connects to an access point, the watchdog verifies connectivity by 'pinging' 53654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * the configured DNS server using {@link DnsPinger}. 54654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * <p> 55654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * On DNS check failure, the BSSID is blacklisted if it is reasonably likely 56654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * that another AP might have internet access; otherwise the SSID is disabled. 57654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * <p> 58654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * On DNS success, the WatchdogService initiates a walled garden check via an 59654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * http get. A browser window is activated if a walled garden is detected. 60654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 61654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @hide 62654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 63654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levypublic class WifiWatchdogStateMachine extends StateMachine { 64654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 65654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final boolean VDBG = false; 66654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final boolean DBG = true; 67654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final String WWSM_TAG = "WifiWatchdogStateMachine"; 68654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 69654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int WIFI_SIGNAL_LEVELS = 4; 70654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 71654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Low signal is defined as less than or equal to cut off 72654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 73654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int LOW_SIGNAL_CUTOFF = 1; 74654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 75654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long MIN_LOW_SIGNAL_CHECK_INTERVAL_MS = 2 * 60 * 1000; 76654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long MIN_SINGLE_DNS_CHECK_INTERVAL_MS = 10 * 60 * 1000; 77654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long MIN_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; 78654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 79654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MAX_CHECKS_PER_SSID = 7; 80654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int NUM_DNS_PINGS = 5; 81654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final double MIN_DNS_RESPONSE_RATE = 0.50; 82654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 83654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int DNS_PING_TIMEOUT_MS = 800; 84654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long DNS_PING_INTERVAL_MS = 100; 85654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 86654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; 87654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 88654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int BASE = Protocol.BASE_WIFI_WATCHDOG; 89654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 90654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 91654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the enable setting of WWS may have changed 92654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 93654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1; 94654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 95654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 96654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the wifi network state has changed. Passed w/ original intent 97654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * which has a non-null networkInfo object 98654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 99654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2; 100654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 101654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the signal has changed. Passed with arg1 102654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * {@link #mNetEventCounter} and arg2 [raw signal strength] 103654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 104654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_RSSI_CHANGE = BASE + 3; 105654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4; 106654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5; 107654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 108654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_CHECK_STEP = BASE + 100; 109654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101; 110654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_HANDLE_BAD_AP = BASE + 102; 111654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 112654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * arg1 == mOnlineWatchState.checkCount 113654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 114654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_SINGLE_DNS_CHECK = BASE + 103; 115654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_NETWORK_FOLLOWUP = BASE + 104; 116654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 117654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Context mContext; 118654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ContentResolver mContentResolver; 119654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiManager mWifiManager; 120654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsPinger mDnsPinger; 121654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private IntentFilter mIntentFilter; 122654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BroadcastReceiver mBroadcastReceiver; 123654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 124654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DefaultState mDefaultState = new DefaultState(); 125654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState(); 126654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState(); 127654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private NotConnectedState mNotConnectedState = new NotConnectedState(); 128654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ConnectedState mConnectedState = new ConnectedState(); 129654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckingState mDnsCheckingState = new DnsCheckingState(); 130654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private OnlineWatchState mOnlineWatchState = new OnlineWatchState(); 131654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState(); 132654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WalledGardenState mWalledGardenState = new WalledGardenState(); 133654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BlacklistedApState mBlacklistedApState = new BlacklistedApState(); 134654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 135654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 136654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The {@link WifiInfo} object passed to WWSM on network broadcasts 137654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 138654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiInfo mInitialConnInfo; 139654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private int mNetEventCounter = 0; 140654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 141654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 142654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Currently maintained but not used, TODO 143654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 144654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private HashSet<String> mBssids = new HashSet<String>(); 145654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private int mNumFullDNSchecks = 0; 146654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 147654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Long mLastWalledGardenCheckTime = null; 148654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 149654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 150654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * This is set by the blacklisted state and reset when connected to a new AP. 151654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * It triggers a disableNetwork call if a DNS check fails. 152654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 153654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean mDisableAPNextFailure = false; 154654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 155654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 156654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * STATE MAP 157654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Default 158654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 159654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Disabled Enabled 160654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 161654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Disconnected Connected 162654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * /---------\ 163654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * (all other states) 164654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 165654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiWatchdogStateMachine(Context context) { 166654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy super(WWSM_TAG); 167654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext = context; 168654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContentResolver = context.getContentResolver(); 169654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 170654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context, 171654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy ConnectivityManager.TYPE_WIFI); 172654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 173654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setupNetworkReceiver(); 174654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 175654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // The content observer to listen needs a handler 176654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy registerForSettingsChanges(); 177654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDefaultState); 178654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogDisabledState, mDefaultState); 179654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogEnabledState, mDefaultState); 180654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mNotConnectedState, mWatchdogEnabledState); 181654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mConnectedState, mWatchdogEnabledState); 182654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckingState, mConnectedState); 183654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckFailureState, mConnectedState); 184654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWalledGardenState, mConnectedState); 185654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mBlacklistedApState, mConnectedState); 186654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mOnlineWatchState, mConnectedState); 187654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 188654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setInitialState(mWatchdogDisabledState); 189654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 190654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 191654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) { 192654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); 193654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.start(); 194654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED); 195654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wwsm; 196654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 197654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 198654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 199654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 200654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 201654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void setupNetworkReceiver() { 202654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBroadcastReceiver = new BroadcastReceiver() { 203654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 204654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onReceive(Context context, Intent intent) { 205654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String action = intent.getAction(); 206654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 207654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_NETWORK_STATE_CHANGE, intent); 208654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 209654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(EVENT_RSSI_CHANGE, mNetEventCounter, 210654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)).sendToTarget(); 211654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 212654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_SCAN_RESULTS_AVAILABLE); 213654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 214654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE, 215654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 216654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.WIFI_STATE_UNKNOWN)); 217654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 218654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 219654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 220654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 221654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter = new IntentFilter(); 222654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 223654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 224654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 225654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 226654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 227654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 228654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 229654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Observes the watchdog on/off setting, and takes action when changed. 230654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 231654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void registerForSettingsChanges() { 232654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 233654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 234654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onChange(boolean selfChange) { 235654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WATCHDOG_TOGGLED); 236654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 237654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 238654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 239654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.getContentResolver().registerContentObserver( 240654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), 241654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy false, contentObserver); 242654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 243654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 244654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 245654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * DNS based detection techniques do not work at all hotspots. The one sure 246654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * way to check a walled garden is to see if a URL fetch on a known address 247654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * fetches the data we expect 248654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 249654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWalledGardenConnection() { 250654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy InputStream in = null; 251654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy HttpURLConnection urlConnection = null; 252654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy try { 253654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy URL url = new URL(getWalledGardenUrl()); 254654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection = (HttpURLConnection) url.openConnection(); 255654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy in = new BufferedInputStream(urlConnection.getInputStream()); 256654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Scanner scanner = new Scanner(in); 257654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (scanner.findInLine(getWalledGardenPattern()) != null) { 258654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 259654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 260654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return true; 261654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 262654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } catch (IOException e) { 263654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 264654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } finally { 265654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (in != null) { 266654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy try { 267654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy in.close(); 268654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } catch (IOException e) { 269654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 270654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 271654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (urlConnection != null) 272654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection.disconnect(); 273654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 274654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 275654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 276654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean rssiStrengthAboveCutoff(int rssi) { 277654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return WifiManager.calculateSignalLevel(rssi, WIFI_SIGNAL_LEVELS) > LOW_SIGNAL_CUTOFF; 278654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 279654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 280654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void dump(PrintWriter pw) { 281654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("WatchdogStatus: "); 282654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("State " + getCurrentState()); 283654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println(", network [" + mInitialConnInfo + "]"); 284654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("checkCount " + mNumFullDNSchecks); 285654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println(", bssids: " + mBssids); 286654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime); 287654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 288654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 289654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 290654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED 291654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 292654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Boolean isWalledGardenTestEnabled() { 293654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return Settings.Secure.getInt(mContentResolver, 294654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, 1) == 1; 295654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 296654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 297654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 298654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_URL 299654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 300654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private String getWalledGardenUrl() { 301654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String url = Settings.Secure.getString(mContentResolver, 302654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL); 303654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (TextUtils.isEmpty(url)) 304654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "http://www.google.com/"; 305654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return url; 306654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 307654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 308654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 309654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @see android.provider.Settings.Secure#WIFI_WATCHDOG_WALLED_GARDEN_PATTERN 310654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 311654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private String getWalledGardenPattern() { 312654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String pattern = Settings.Secure.getString(mContentResolver, 313654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN); 314654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (TextUtils.isEmpty(pattern)) 315654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "<title>.*Google.*</title>"; 316654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return pattern; 317654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 318654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 319654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 320654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @see android.provider.Settings.Secure#WIFI_WATCHDOG_ON 321654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 322654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWatchdogEnabled() { 323654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return Settings.Secure.getInt(mContentResolver, 324654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.WIFI_WATCHDOG_ON, 1) == 1; 325654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 326654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 327654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 328654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 329654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Helper to return wait time left given a min interval and last run 330654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 331654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param interval minimum wait interval 332654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param lastTime last time action was performed in 333654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * SystemClock.elapsedRealtime(). Null if never. 334654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @return non negative time to wait 335654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 336654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static long waitTime(long interval, Long lastTime) { 337654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (lastTime == null) 338654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return 0; 339654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long wait = interval + lastTime - SystemClock.elapsedRealtime(); 340654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wait > 0 ? wait : 0; 341654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 342654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 343654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static String wifiInfoToStr(WifiInfo wifiInfo) { 344654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) 345654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "null"; 346654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "(" + wifiInfo.getSSID() + ", " + wifiInfo.getBSSID() + ")"; 347654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 348654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 349654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 350654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 351654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 352654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void resetWatchdogState() { 353654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mInitialConnInfo = null; 354654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 355654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime = null; 356654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNumFullDNSchecks = 0; 357654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBssids.clear(); 358654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 359654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 360654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void popUpBrowser() { 361654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Uri uri = Uri.parse("http://www.google.com"); 362654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent intent = new Intent(Intent.ACTION_VIEW, uri); 363654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | 364654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent.FLAG_ACTIVITY_NEW_TASK); 365654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.startActivity(intent); 366654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 367654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 368654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void sendCheckStepMessage(long delay) { 369654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay); 370654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 371654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 372654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DefaultState extends State { 373654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 374654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 375654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 376654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " + 377654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy getCurrentState().getName()); 378654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 379654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 380654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 381654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 382654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 383654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogDisabledState extends State { 384654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 385654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 386654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 387654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 388654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (isWatchdogEnabled()) 389654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 390654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 391654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 392654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 393654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 394654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 395654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 396654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogEnabledState extends State { 397654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 398654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 399654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 400654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); 401654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiWatchdogService enabled"); 402654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 403654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 404654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 405654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 406654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 407654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 408654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!isWatchdogEnabled()) 409654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mWatchdogDisabledState); 410654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 411654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_NETWORK_STATE_CHANGE: 412654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent stateChangeIntent = (Intent) msg.obj; 413654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy NetworkInfo networkInfo = (NetworkInfo) 414654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 415654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 416654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (networkInfo.getState()) { 417654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case CONNECTED: 418654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // WifiInfo wifiInfo = (WifiInfo) 419654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // stateChangeIntent 420654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); 421654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // TODO : Replace with above code when API is changed 422654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 423654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) { 424654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!"); 425654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 426654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 427654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 428654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) { 429654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.e(WWSM_TAG, "Received wifiInfo object with null elts: " 430654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + wifiInfoToStr(wifiInfo)); 431654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 432654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 433654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 434654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy initConnection(wifiInfo); 435654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 436654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 437654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 438654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case DISCONNECTED: 439654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case DISCONNECTING: 440654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 441654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 442654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 443654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 444654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 445654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WIFI_RADIO_STATE_CHANGE: 446654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { 447654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiStateDisabling -- Resetting WatchdogState"); 448654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 449654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 450654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 451654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 452654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 453654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 454654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 455654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 456654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 457654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 458654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 459654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param wifiInfo Info object with non-null ssid and bssid 460654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 461654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void initConnection(WifiInfo wifiInfo) { 462654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 463654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) + 464654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy " ==> new " + wifiInfoToStr(wifiInfo)); 465654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 466654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 467654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) { 468654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 469654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) { 470654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 471654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 472654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mInitialConnInfo = wifiInfo; 473654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 474654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 475654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 476654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void exit() { 477654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.unregisterReceiver(mBroadcastReceiver); 478654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiWatchdogService disabled"); 479654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 480654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 481654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 482654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class NotConnectedState extends State { 483654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 484654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 485654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class ConnectedState extends State { 486654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 487654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 488654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 489654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_SCAN_RESULTS_AVAILABLE: 490654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String curSsid = mInitialConnInfo.getSSID(); 491654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy List<ScanResult> results = mWifiManager.getScanResults(); 492654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int oldNumBssids = mBssids.size(); 493654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 494654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (results == null) { 495654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 496654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "updateBssids: Got null scan results!"); 497654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 498654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 499654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 500654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 501654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy for (ScanResult result : results) { 502654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (result == null || result.SSID == null) { 503654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 504654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Received invalid scan result: " + result); 505654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 506654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy continue; 507654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 508654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (curSsid.equals(result.SSID)) 509654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBssids.add(result.BSSID); 510654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 511654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 512654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 513654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 514654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 515654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 516654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 517654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 518654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckingState extends State { 519654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int dnsCheckTries = 0; 520654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int dnsCheckSuccesses = 0; 521654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String dnsCheckLogStr = ""; 522654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 523654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 524654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 525654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNumFullDNSchecks++; 526654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckSuccesses = 0; 527654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckTries = 0; 528654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 529654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); 530654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckLogStr = String.format("Dns Check %d. Pinging %s on ssid [%s]: ", 531654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNumFullDNSchecks, mDnsPinger.getDns(), mInitialConnInfo.getSSID()); 532654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 533654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 534654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendCheckStepMessage(0); 535654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 536654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 537654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 538654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 539654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_CHECK_STEP) { 540654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 541654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 542654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 543654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Check step out of sync, ignoring..."); 544654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 545654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 546654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 547654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), 548654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy DNS_PING_TIMEOUT_MS); 549654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 550654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckTries++; 551654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) 552654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckSuccesses++; 553654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 554654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 555654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) { 556654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckLogStr += "|" + pingResponseTime; 557654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 558654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckLogStr += "|x"; 559654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 560654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 561654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 562654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 563654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, dnsCheckLogStr); 564654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 565654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 566654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 567654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * After a full ping count, if we have more responses than this 568654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * cutoff, the outcome is success; else it is 'failure'. 569654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 570654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy double pingResponseCutoff = MIN_DNS_RESPONSE_RATE * NUM_DNS_PINGS; 571654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int remainingChecks = NUM_DNS_PINGS - dnsCheckTries; 572654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 573654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 574654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Our final success count will be at least this big, so we're 575654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * guaranteed to succeed. 576654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 577654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (dnsCheckSuccesses >= pingResponseCutoff) { 578654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // DNS CHECKS OK, NOW WALLED GARDEN 579654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 580654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, dnsCheckLogStr + "| SUCCESS"); 581654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 582654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 583654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!shouldCheckWalledGarden()) { 584654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 585654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 586654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 587654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 588654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime = SystemClock.elapsedRealtime(); 589654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (isWalledGardenConnection()) { 590654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) 591654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, 592654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy "Walled garden test complete - walled garden detected"); 593654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mWalledGardenState); 594654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 595654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) 596654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Walled garden test complete - online"); 597654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 598654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 599654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 600654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 601654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 602654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 603654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Our final count will be at most the current count plus the 604654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * remaining pings - we're guaranteed to fail. 605654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 606654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (remainingChecks + dnsCheckSuccesses < pingResponseCutoff) { 607654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 608654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, dnsCheckLogStr + "| FAILURE"); 609654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 610654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckFailureState); 611654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 612654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 613654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 614654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // Still in dns check step 615654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendCheckStepMessage(DNS_PING_INTERVAL_MS); 616654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 617654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 618654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 619654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean shouldCheckWalledGarden() { 620654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!isWalledGardenTestEnabled()) { 621654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) 622654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Skipping walled garden check - disabled"); 623654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 624654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 625654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long waitTime = waitTime(MIN_WALLED_GARDEN_INTERVAL_MS, 626654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime); 627654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (waitTime > 0) { 628654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 629654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Skipping walled garden check - wait " + 630654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime + " ms."); 631654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 632654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 633654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 634654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return true; 635654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 636654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 637654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 638654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 639654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class OnlineWatchState extends State { 640654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 641654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Signals a short-wait message is enqueued for the current 'guard' counter 642654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 643654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean unstableSignalChecks = false; 644654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 645654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 646654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The signal is unstable. We should enqueue a short-wait check, if one is enqueued 647654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * already 648654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 649654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean signalUnstable = false; 650654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 651654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 652654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * A monotonic counter to ensure that at most one check message will be processed from any 653654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * set of check messages currently enqueued. Avoids duplicate checks when a low-signal 654654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * event is observed. 655654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 656654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int checkGuard = 0; 657654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Long lastCheckTime = null; 658654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 659654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 660654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 661654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 662654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = false; 663654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 664654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 665654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 666654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 667654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 668654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 669654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 670654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 671654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_RSSI_CHANGE: 672654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 673654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 674654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Rssi change message out of sync, ignoring"); 675654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 676654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 677654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 678654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int newRssi = msg.arg2; 679654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = !rssiStrengthAboveCutoff(newRssi); 680654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 681654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "OnlineWatchState:: new rssi " + newRssi + " --> level " + 682654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS)); 683654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 684654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 685654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable && !unstableSignalChecks) { 686654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 687654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Sending triggered check msg"); 688654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 689654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 690654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 691654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 692654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case MESSAGE_SINGLE_DNS_CHECK: 693654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != checkGuard) { 694654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 695654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Single check msg out of sync, ignoring."); 696654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 697654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 698654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 699654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 700654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), 701654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy DNS_PING_TIMEOUT_MS); 702654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (responseTime >= 0) { 703654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 704654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: " 705654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + responseTime); 706654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 707654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 708654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 709654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 710654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 711654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 712654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 713654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Single dns ping failure. Starting full checks."); 714654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 715654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 716654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 717654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 718654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 719654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 720654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 721654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 722654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 723654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Times a dns check with an interval based on {@link #curSignalStable} 724654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 725654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void triggerSingleDnsCheck() { 726654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long waitInterval; 727654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable) { 728654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitInterval = MIN_LOW_SIGNAL_CHECK_INTERVAL_MS; 729654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = true; 730654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 731654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitInterval = MIN_SINGLE_DNS_CHECK_INTERVAL_MS; 732654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 733654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0), 734654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime(waitInterval, lastCheckTime)); 735654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 736654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 737654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 738654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckFailureState extends State { 739654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 740654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 741654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget(); 742654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 743654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 744654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 745654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 746654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_BAD_AP) { 747654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 748654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 749654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 750654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 751654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 752654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Msg out of sync, ignoring..."); 753654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 754654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 755654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 756654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 757654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (mDisableAPNextFailure || mNumFullDNSchecks >= MAX_CHECKS_PER_SSID) { 758654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // TODO : Unban networks if they had low signal ? 759654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo) 760654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + ". " + 761654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); 762654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId()); 763654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 764654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 765654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mInitialConnInfo) + 766654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy "numChecks " + mNumFullDNSchecks + ", numAPs " + mBssids.size()); 767654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 768654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID()); 769654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.reassociate(); 770654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mBlacklistedApState); 771654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 772654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 773654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 774654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 775654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 776654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WalledGardenState extends State { 777654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 778654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 779654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_WALLED_GARDEN, mNetEventCounter, 0).sendToTarget(); 780654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 781654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 782654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 783654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 784654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_WALLED_GARDEN) { 785654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 786654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 787654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 788654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 789654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 790654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "WalledGardenState::Msg out of sync, ignoring..."); 791654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 792654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 793654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 794654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy popUpBrowser(); 795654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 796654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 797654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 798654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 799654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 800654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class BlacklistedApState extends State { 801654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 802654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 803654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = true; 804654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0), 805654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy BLACKLIST_FOLLOWUP_INTERVAL_MS); 806654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 807654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 808654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 809654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 810654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_NETWORK_FOLLOWUP) { 811654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 812654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 813654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 814654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 815654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 816654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "BlacklistedApState::Msg out of sync, ignoring..."); 817654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 818654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 819654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 820654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 821654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 822654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 823654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 824654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 825654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy} 826