WifiWatchdogStateMachine.java revision 19380daaf46815c80bd89fd9ca3af3c4095952b5
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 19d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.app.Notification; 20d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.app.NotificationManager; 21d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.app.PendingIntent; 22654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.BroadcastReceiver; 23654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.ContentResolver; 24654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.Context; 25654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.Intent; 26654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.content.IntentFilter; 27d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.content.res.Resources; 28654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.database.ContentObserver; 29654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.ConnectivityManager; 30654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.DnsPinger; 31654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.NetworkInfo; 32654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.net.Uri; 33654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.os.Message; 34654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.os.SystemClock; 354ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levyimport android.os.SystemProperties; 36654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.provider.Settings; 37d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.provider.Settings.Secure; 389b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwaltimport android.util.Log; 39654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 406b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriffimport com.android.internal.R; 41654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.Protocol; 42654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.State; 43654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.StateMachine; 44654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 45654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.IOException; 46654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.PrintWriter; 47654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.HttpURLConnection; 48d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levyimport java.net.InetAddress; 49654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.URL; 5079e43f679d6102066ee9eff862912806f53bb0e8Isaac Levyimport java.util.HashMap; 51654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.HashSet; 52654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.List; 53654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 54654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy/** 55654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * {@link WifiWatchdogStateMachine} monitors the initial connection to a Wi-Fi 56654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * network with multiple access points. After the framework successfully 57654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * connects to an access point, the watchdog verifies connectivity by 'pinging' 58654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * the configured DNS server using {@link DnsPinger}. 59654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * <p> 60654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * On DNS check failure, the BSSID is blacklisted if it is reasonably likely 61654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * that another AP might have internet access; otherwise the SSID is disabled. 62654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * <p> 63654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * On DNS success, the WatchdogService initiates a walled garden check via an 64654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * http get. A browser window is activated if a walled garden is detected. 65654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 66654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @hide 67654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 68654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levypublic class WifiWatchdogStateMachine extends StateMachine { 69654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 707f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff private static final boolean DBG = false; 717f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff private static final String TAG = "WifiWatchdogStateMachine"; 726b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private static final String DISABLED_NETWORK_NOTIFICATION_ID = "WifiWatchdog.networkdisabled"; 736b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private static final String WALLED_GARDEN_NOTIFICATION_ID = "WifiWatchdog.walledgarden"; 74654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 75654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int WIFI_SIGNAL_LEVELS = 4; 76654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 77654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Low signal is defined as less than or equal to cut off 78654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 79998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final int LOW_SIGNAL_CUTOFF = 0; 80654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 81d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS = 2 * 60 * 1000; 82998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 60 * 60 * 1000; 83d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_WALLED_GARDEN_INTERVAL_MS = 30 * 60 * 1000; 84654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 85d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final int DEFAULT_MAX_SSID_BLACKLISTS = 7; 86998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final int DEFAULT_NUM_DNS_PINGS = 5; // Multiple pings to detect setup issues 87998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final int DEFAULT_MIN_DNS_RESPONSES = 1; 88654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 8988bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 2000; 90d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 91d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; 92d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 9388bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy // See http://go/clientsdns for usage approval 9488bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy private static final String DEFAULT_WALLED_GARDEN_URL = 9588bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy "http://clients3.google.com/generate_204"; 9688bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy private static final int WALLED_GARDEN_SOCKET_TIMEOUT_MS = 10000; 97a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff 98a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff /* Some carrier apps might have support captive portal handling. Add some delay to allow 99a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff app authentication to be done before our test. 100a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff TODO: This should go away once we provide an API to apps to disable walled garden test 101a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff for certain SSIDs 102a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff */ 103a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int WALLED_GARDEN_START_DELAY_MS = 3000; 104a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff 105998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final int DNS_INTRATEST_PING_INTERVAL_MS = 200; 106998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff /* With some router setups, it takes a few hunder milli-seconds before connection is active */ 107998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff private static final int DNS_START_DELAY_MS = 1000; 108654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 109654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int BASE = Protocol.BASE_WIFI_WATCHDOG; 110654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 111654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 112654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the enable setting of WWS may have changed 113654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 114a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1; 115654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 116654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 117654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the wifi network state has changed. Passed w/ original intent 118654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * which has a non-null networkInfo object 119654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 120a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2; 121654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 122654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the signal has changed. Passed with arg1 123654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * {@link #mNetEventCounter} and arg2 [raw signal strength] 124654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 125a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_RSSI_CHANGE = BASE + 3; 126a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4; 127a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5; 128a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6; 129654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 130a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 100; 131a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int MESSAGE_HANDLE_BAD_AP = BASE + 101; 132654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 133654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * arg1 == mOnlineWatchState.checkCount 134654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 135a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int MESSAGE_SINGLE_DNS_CHECK = BASE + 102; 136a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int MESSAGE_NETWORK_FOLLOWUP = BASE + 103; 137a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private static final int MESSAGE_DELAYED_WALLED_GARDEN_CHECK = BASE + 104; 138654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 139654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Context mContext; 140654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ContentResolver mContentResolver; 141654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiManager mWifiManager; 142654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsPinger mDnsPinger; 143654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private IntentFilter mIntentFilter; 144654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BroadcastReceiver mBroadcastReceiver; 145654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 146654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DefaultState mDefaultState = new DefaultState(); 147654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState(); 148654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState(); 149654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private NotConnectedState mNotConnectedState = new NotConnectedState(); 150654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ConnectedState mConnectedState = new ConnectedState(); 151654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckingState mDnsCheckingState = new DnsCheckingState(); 152654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private OnlineWatchState mOnlineWatchState = new OnlineWatchState(); 15319380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff private OnlineState mOnlineState = new OnlineState(); 154654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState(); 155a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff private DelayWalledGardenState mDelayWalledGardenState = new DelayWalledGardenState(); 156654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WalledGardenState mWalledGardenState = new WalledGardenState(); 157654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BlacklistedApState mBlacklistedApState = new BlacklistedApState(); 158654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 159d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mDnsCheckShortIntervalMs; 160d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mDnsCheckLongIntervalMs; 161d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mWalledGardenIntervalMs; 162d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mMaxSsidBlacklists; 163d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mNumDnsPings; 164d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mMinDnsResponses; 165d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mDnsPingTimeoutMs; 166d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mBlacklistFollowupIntervalMs; 16719380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff private boolean mPoorNetworkDetectionEnabled; 168d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private boolean mWalledGardenTestEnabled; 169d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private String mWalledGardenUrl; 170d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 171d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private boolean mShowDisabledNotification; 172654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 173654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The {@link WifiInfo} object passed to WWSM on network broadcasts 174654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 1758dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy private WifiInfo mConnectionInfo; 176654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private int mNetEventCounter = 0; 177654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 178654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 179654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Currently maintained but not used, TODO 180654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 181654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private HashSet<String> mBssids = new HashSet<String>(); 182d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mNumCheckFailures = 0; 183654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 184654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Long mLastWalledGardenCheckTime = null; 185654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 186654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 187654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * This is set by the blacklisted state and reset when connected to a new AP. 188654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * It triggers a disableNetwork call if a DNS check fails. 189654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 190654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean mDisableAPNextFailure = false; 1919b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt private static boolean sWifiOnly = false; 1926b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private boolean mDisabledNotificationShown; 1936b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private boolean mWalledGardenNotificationShown; 1948dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy public boolean mHasConnectedWifiManager = false; 195654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 196654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 197654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * STATE MAP 198654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Default 199654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 200654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Disabled Enabled 201654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 202d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * NotConnected Connected 203654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * /---------\ 204654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * (all other states) 205654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 206654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiWatchdogStateMachine(Context context) { 2077f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff super(TAG); 208654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext = context; 209654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContentResolver = context.getContentResolver(); 210654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 211d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mDnsPinger = new DnsPinger(mContext, "WifiWatchdogStateMachine.DnsPinger", 212d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy this.getHandler().getLooper(), this.getHandler(), 213d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy ConnectivityManager.TYPE_WIFI); 214654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 215654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setupNetworkReceiver(); 216654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 217654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // The content observer to listen needs a handler 218654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy registerForSettingsChanges(); 219d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy registerForWatchdogToggle(); 220654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDefaultState); 221654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogDisabledState, mDefaultState); 222654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogEnabledState, mDefaultState); 223654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mNotConnectedState, mWatchdogEnabledState); 224654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mConnectedState, mWatchdogEnabledState); 225654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckingState, mConnectedState); 226654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckFailureState, mConnectedState); 227a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff addState(mDelayWalledGardenState, mConnectedState); 228654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWalledGardenState, mConnectedState); 229654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mBlacklistedApState, mConnectedState); 230654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mOnlineWatchState, mConnectedState); 23119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff addState(mOnlineState, mConnectedState); 232654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 233654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setInitialState(mWatchdogDisabledState); 234d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy updateSettings(); 235654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 236654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 237654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) { 2384ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy ContentResolver contentResolver = context.getContentResolver(); 2399b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt 2409b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt ConnectivityManager cm = (ConnectivityManager) context.getSystemService( 2419b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt Context.CONNECTIVITY_SERVICE); 2429b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false); 2439b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt 2444ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy // Disable for wifi only devices. 2454ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy if (Settings.Secure.getString(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON) == null && 2469b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt sWifiOnly) { 2474ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy putSettingsBoolean(contentResolver, Settings.Secure.WIFI_WATCHDOG_ON, false); 2484ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy } 249654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); 250654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.start(); 251654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED); 252654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wwsm; 253654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 254654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 255654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 256654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 257654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 258654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void setupNetworkReceiver() { 259654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBroadcastReceiver = new BroadcastReceiver() { 260654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 261654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onReceive(Context context, Intent intent) { 262654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String action = intent.getAction(); 263654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 264654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_NETWORK_STATE_CHANGE, intent); 265654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 266654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(EVENT_RSSI_CHANGE, mNetEventCounter, 267654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)).sendToTarget(); 268654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 269654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_SCAN_RESULTS_AVAILABLE); 270654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 271654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE, 272654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 273654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.WIFI_STATE_UNKNOWN)); 274654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 275654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 276654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 277654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 278654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter = new IntentFilter(); 279654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 280654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 281654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 282654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 283654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 284654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 285654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 286654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Observes the watchdog on/off setting, and takes action when changed. 287654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 288d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void registerForWatchdogToggle() { 289654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 290654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 291654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onChange(boolean selfChange) { 292654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WATCHDOG_TOGGLED); 293654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 294654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 295654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 296654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.getContentResolver().registerContentObserver( 297654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), 298654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy false, contentObserver); 299654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 300654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 301654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 302d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Observes watchdogs secure setting changes. 303d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 304d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void registerForSettingsChanges() { 305d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 306d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy @Override 307d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy public void onChange(boolean selfChange) { 308d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy sendMessage(EVENT_WATCHDOG_SETTINGS_CHANGE); 309d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 310d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy }; 311d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 312d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 313d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor( 314d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS), 315d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 316d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 317d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS), 318d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 319d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 320d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS), 321d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 322d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 323d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS), 324d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 325d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 326d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_NUM_DNS_PINGS), 327d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 328d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 329d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES), 330d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 331d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 332d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS), 333d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 334d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 335d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor( 336d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS), 337d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 338d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 339d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED), 340d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 341d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 342d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL), 343d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 3448dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mContext.getContentResolver().registerContentObserver( 3458dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP) 3468dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy , false, contentObserver); 347d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 348d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 349d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 350654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * DNS based detection techniques do not work at all hotspots. The one sure 351654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * way to check a walled garden is to see if a URL fetch on a known address 352654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * fetches the data we expect 353654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 354654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWalledGardenConnection() { 355654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy HttpURLConnection urlConnection = null; 356654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy try { 357d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy URL url = new URL(mWalledGardenUrl); 358654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection = (HttpURLConnection) url.openConnection(); 35988bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy urlConnection.setInstanceFollowRedirects(false); 36088bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy urlConnection.setConnectTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS); 36188bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy urlConnection.setReadTimeout(WALLED_GARDEN_SOCKET_TIMEOUT_MS); 36288bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy urlConnection.setUseCaches(false); 36388bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy urlConnection.getInputStream(); 36488bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy // We got a valid response, but not from the real google 36588bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy return urlConnection.getResponseCode() != 204; 366654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } catch (IOException e) { 36788bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy if (DBG) { 3687f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Walled garden check - probably not a portal: exception " + e); 36988bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy } 370654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 371654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } finally { 37288bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy if (urlConnection != null) { 373654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection.disconnect(); 37488bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy } 375654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 376654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 377654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 378654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean rssiStrengthAboveCutoff(int rssi) { 379654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return WifiManager.calculateSignalLevel(rssi, WIFI_SIGNAL_LEVELS) > LOW_SIGNAL_CUTOFF; 380654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 381654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 382654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void dump(PrintWriter pw) { 383654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("WatchdogStatus: "); 384654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("State " + getCurrentState()); 3858dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy pw.println(", network [" + mConnectionInfo + "]"); 386d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy pw.print("checkFailures " + mNumCheckFailures); 387654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println(", bssids: " + mBssids); 388654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime); 389654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 390654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 391654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWatchdogEnabled() { 39219380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff return getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); 393654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 394654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 395d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void updateSettings() { 396d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsCheckShortIntervalMs = Secure.getLong(mContentResolver, 397d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS, 398d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS); 399d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsCheckLongIntervalMs = Secure.getLong(mContentResolver, 400d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS, 401d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_CHECK_LONG_INTERVAL_MS); 402d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mMaxSsidBlacklists = Secure.getInt(mContentResolver, 403d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS, 404d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_MAX_SSID_BLACKLISTS); 405d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumDnsPings = Secure.getInt(mContentResolver, 406d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_NUM_DNS_PINGS, 407d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_NUM_DNS_PINGS); 408d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mMinDnsResponses = Secure.getInt(mContentResolver, 409d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES, 410d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_MIN_DNS_RESPONSES); 411d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsPingTimeoutMs = Secure.getInt(mContentResolver, 412d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS, 413d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_PING_TIMEOUT_MS); 414d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mBlacklistFollowupIntervalMs = Secure.getLong(mContentResolver, 415d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS, 416d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS); 41719380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff //TODO: enable this by default after changing watchdog behavior 41819380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff //Also, update settings description 41919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff mPoorNetworkDetectionEnabled = getSettingsBoolean(mContentResolver, 42019380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff Settings.Secure.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, false); 421d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver, 422d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true); 423d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenUrl = getSettingsStr(mContentResolver, 424d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL, 425d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_WALLED_GARDEN_URL); 426d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenIntervalMs = Secure.getLong(mContentResolver, 427d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS, 428d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_WALLED_GARDEN_INTERVAL_MS); 4298dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mShowDisabledNotification = getSettingsBoolean(mContentResolver, 4308dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true); 431d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 432654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 433654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 434654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Helper to return wait time left given a min interval and last run 435654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 436654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param interval minimum wait interval 437654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param lastTime last time action was performed in 438654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * SystemClock.elapsedRealtime(). Null if never. 439654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @return non negative time to wait 440654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 441654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static long waitTime(long interval, Long lastTime) { 442654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (lastTime == null) 443654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return 0; 444654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long wait = interval + lastTime - SystemClock.elapsedRealtime(); 445654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wait > 0 ? wait : 0; 446654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 447654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 448654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static String wifiInfoToStr(WifiInfo wifiInfo) { 449654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) 450654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "null"; 451654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "(" + wifiInfo.getSSID() + ", " + wifiInfo.getBSSID() + ")"; 452654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 453654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 454654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 4558dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy * Uses {@link #mConnectionInfo}. 4568dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy */ 4578dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy private void updateBssids() { 4588dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy String curSsid = mConnectionInfo.getSSID(); 4598dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy List<ScanResult> results = mWifiManager.getScanResults(); 4608dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy int oldNumBssids = mBssids.size(); 4618dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy 4628dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (results == null) { 4638dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (DBG) { 4647f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("updateBssids: Got null scan results!"); 4658dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4668dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy return; 4678dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4688dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy 4698dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy for (ScanResult result : results) { 4708dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (result == null || result.SSID == null) { 4718dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (DBG) { 4727f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Received invalid scan result: " + result); 4738dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4748dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy continue; 4758dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4768dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (curSsid.equals(result.SSID)) 4778dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mBssids.add(result.BSSID); 4788dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4798dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 4808dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy 481654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void resetWatchdogState() { 4827f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 4837f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Resetting watchdog state..."); 48488bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy } 4858dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mConnectionInfo = null; 486654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 487654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime = null; 488d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumCheckFailures = 0; 489654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBssids.clear(); 4906b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setDisabledNetworkNotificationVisible(false); 4916b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setWalledGardenNotificationVisible(false); 492654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 493654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 4946b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private void setWalledGardenNotificationVisible(boolean visible) { 4956b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff // If it should be hidden and it is already hidden, then noop 4966b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff if (!visible && !mWalledGardenNotificationShown) { 4976b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff return; 4986b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff } 499654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 500d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Resources r = Resources.getSystem(); 501d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy NotificationManager notificationManager = (NotificationManager) mContext 5026b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .getSystemService(Context.NOTIFICATION_SERVICE); 5036b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5046b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff if (visible) { 5056b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mWalledGardenUrl)); 5066b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK); 5076b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5086b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff CharSequence title = r.getString(R.string.wifi_available_sign_in, 0); 5096b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff CharSequence details = r.getString(R.string.wifi_available_sign_in_detailed, 5106b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff mConnectionInfo.getSSID()); 5116b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5126b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff Notification notification = new Notification(); 5136b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.when = 0; 5146b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.icon = com.android.internal.R.drawable.stat_notify_wifi_in_range; 5156b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.flags = Notification.FLAG_AUTO_CANCEL; 5166b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0); 5176b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.tickerText = title; 5186b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notification.setLatestEventInfo(mContext, title, details, notification.contentIntent); 5196b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5206b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notificationManager.notify(WALLED_GARDEN_NOTIFICATION_ID, 1, notification); 5216b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff } else { 5226b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notificationManager.cancel(WALLED_GARDEN_NOTIFICATION_ID, 1); 5236b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff } 5246b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff mWalledGardenNotificationShown = visible; 5258dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 5268dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy 5276b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff private void setDisabledNetworkNotificationVisible(boolean visible) { 5286b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff // If it should be hidden and it is already hidden, then noop 5296b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff if (!visible && !mDisabledNotificationShown) { 5306b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff return; 5316b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff } 5326b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5336b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff Resources r = Resources.getSystem(); 5346b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff NotificationManager notificationManager = (NotificationManager) mContext 5356b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .getSystemService(Context.NOTIFICATION_SERVICE); 5366b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5376b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff if (visible) { 5386b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff CharSequence title = r.getText(R.string.wifi_watchdog_network_disabled); 5396b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff String msg = mConnectionInfo.getSSID() + 5406b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff r.getText(R.string.wifi_watchdog_network_disabled_detailed); 5416b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5426b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff Notification wifiDisabledWarning = new Notification.Builder(mContext) 5436b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setSmallIcon(R.drawable.stat_sys_warning) 5446b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setDefaults(Notification.DEFAULT_ALL) 5456b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setTicker(title) 5466b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setContentTitle(title) 5476b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setContentText(msg) 5486b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setContentIntent(PendingIntent.getActivity(mContext, 0, 5496b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff new Intent(WifiManager.ACTION_PICK_WIFI_NETWORK) 5506b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0)) 5516b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setWhen(System.currentTimeMillis()) 5526b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .setAutoCancel(true) 5536b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff .getNotification(); 5546b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff 5556b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notificationManager.notify(DISABLED_NETWORK_NOTIFICATION_ID, 1, wifiDisabledWarning); 5566b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff } else { 5576b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff notificationManager.cancel(DISABLED_NETWORK_NOTIFICATION_ID, 1); 5588dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 5596b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff mDisabledNotificationShown = visible; 560654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 561654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 562654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DefaultState extends State { 563654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 564654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 565d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy switch (msg.what) { 566d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy case EVENT_WATCHDOG_SETTINGS_CHANGE: 567d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy updateSettings(); 5687f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 5697f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Updating wifi-watchdog secure settings"); 570d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 571d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return HANDLED; 572d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 5737f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 5747f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Caught message " + msg.what + " in state " + 575654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy getCurrentState().getName()); 576654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 577654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 578654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 579654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 580654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 581654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogDisabledState extends State { 582654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 583654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 584654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 585654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 586654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (isWatchdogEnabled()) 587654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 588654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 589654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 590654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 591654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 592654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 593654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 594654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogEnabledState extends State { 595654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 596654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 597654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 598654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); 5997f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) log("WifiWatchdogService enabled"); 600654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 601654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 602654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 603654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 604654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 605654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 606654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!isWatchdogEnabled()) 607654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mWatchdogDisabledState); 608654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 609654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_NETWORK_STATE_CHANGE: 610654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent stateChangeIntent = (Intent) msg.obj; 611654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy NetworkInfo networkInfo = (NetworkInfo) 612654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 613654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 6146b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setDisabledNetworkNotificationVisible(false); 6156b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setWalledGardenNotificationVisible(false); 616654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (networkInfo.getState()) { 617654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case CONNECTED: 61888bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy WifiInfo wifiInfo = (WifiInfo) 61988bae17cfd3de40758c5296d15f012f06f08748aIsaac Levy stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); 620654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) { 6217f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff loge("Connected --> WifiInfo object null!"); 622654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 623654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 624654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 625654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) { 6267f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff loge("Received wifiInfo object with null elts: " 627654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + wifiInfoToStr(wifiInfo)); 628654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 629654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 630654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 631654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy initConnection(wifiInfo); 6328dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mConnectionInfo = wifiInfo; 633654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 63419380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff if (mPoorNetworkDetectionEnabled) { 63519380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff updateBssids(); 63619380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mDnsCheckingState); 63719380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } else { 63819380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mDelayWalledGardenState); 63919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 64032f04e9009046f72242932bf4e820802148e423aIrfan Sheriff break; 64132f04e9009046f72242932bf4e820802148e423aIrfan Sheriff default: 642654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 643654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 64432f04e9009046f72242932bf4e820802148e423aIrfan Sheriff break; 645654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 646654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 647654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WIFI_RADIO_STATE_CHANGE: 648654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { 6497f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) log("WifiStateDisabling -- Resetting WatchdogState"); 650654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 651654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 652654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 653654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 654654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 655654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 656654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 657654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 658654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 659654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 660654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 661654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param wifiInfo Info object with non-null ssid and bssid 662654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 663654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void initConnection(WifiInfo wifiInfo) { 6647f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 6657f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Connected:: old " + wifiInfoToStr(mConnectionInfo) + 666654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy " ==> new " + wifiInfoToStr(wifiInfo)); 667654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 668654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 6698dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (mConnectionInfo == null || !wifiInfo.getSSID().equals(mConnectionInfo.getSSID())) { 670654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 6718dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } else if (!wifiInfo.getBSSID().equals(mConnectionInfo.getBSSID())) { 672654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 673654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 674654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 675654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 676654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 677654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void exit() { 678654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.unregisterReceiver(mBroadcastReceiver); 6797f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) log("WifiWatchdogService disabled"); 680654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 681654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 682654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 683654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class NotConnectedState extends State { 684654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 685654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 686654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class ConnectedState extends State { 687654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 688654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 689654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 690654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_SCAN_RESULTS_AVAILABLE: 69119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff if (mPoorNetworkDetectionEnabled) { 69219380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff updateBssids(); 69319380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 694654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 695d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy case EVENT_WATCHDOG_SETTINGS_CHANGE: 69619380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff updateSettings(); 69719380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff if (mPoorNetworkDetectionEnabled) { 69819380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineWatchState); 69919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } else { 70019380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineState); 70119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 70219380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff return HANDLED; 703654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 704654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 705654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 706654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 707654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 708654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckingState extends State { 70979e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy List<InetAddress> mDnsList; 71079e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy int[] dnsCheckSuccesses; 71179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy String dnsCheckLogStr; 71279e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy String[] dnsResponseStrs; 71379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy /** Keeps track of active dns pings. Map is from pingID to index in mDnsList */ 71479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy HashMap<Integer, Integer> idDnsMap = new HashMap<Integer, Integer>(); 715654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 716654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 717654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 71879e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy mDnsList = mDnsPinger.getDnsList(); 71979e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy int numDnses = mDnsList.size(); 72079e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsCheckSuccesses = new int[numDnses]; 72179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsResponseStrs = new String[numDnses]; 72279e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy for (int i = 0; i < numDnses; i++) 72379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsResponseStrs[i] = ""; 72479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy 725654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 726d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ", 72779e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy mDnsList, mConnectionInfo.getSSID()); 7287f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log(dnsCheckLogStr); 729654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 730654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 73179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy idDnsMap.clear(); 732d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy for (int i=0; i < mNumDnsPings; i++) { 73379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy for (int j = 0; j < numDnses; j++) { 73479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy idDnsMap.put(mDnsPinger.pingDnsAsync(mDnsList.get(j), mDnsPingTimeoutMs, 735998196d64d35c1767dbb08f059fe3af171e44e1dIrfan Sheriff DNS_START_DELAY_MS + DNS_INTRATEST_PING_INTERVAL_MS * i), j); 73679e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy } 737d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 738654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 739654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 740654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 741654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 742d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy if (msg.what != DnsPinger.DNS_PING_RESULT) { 743654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 744654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 745654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 746d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int pingID = msg.arg1; 747d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int pingResponseTime = msg.arg2; 748654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 74979e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy Integer dnsServerId = idDnsMap.get(pingID); 75079e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (dnsServerId == null) { 7517f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff loge("Received a Dns response with unknown ID!"); 752d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy return HANDLED; 753d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 75479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy 75579e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy idDnsMap.remove(pingID); 756654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) 75779e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsCheckSuccesses[dnsServerId]++; 758654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 759654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 760654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) { 76179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsResponseStrs[dnsServerId] += "|" + pingResponseTime; 762654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 76379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy dnsResponseStrs[dnsServerId] += "|x"; 764654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 765654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 766654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 767654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 768654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * After a full ping count, if we have more responses than this 769654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * cutoff, the outcome is success; else it is 'failure'. 770654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 771654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 772654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 773654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Our final success count will be at least this big, so we're 774654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * guaranteed to succeed. 775654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 77679e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (dnsCheckSuccesses[dnsServerId] >= mMinDnsResponses) { 777654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // DNS CHECKS OK, NOW WALLED GARDEN 778654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 7797f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log(makeLogString() + " SUCCESS"); 780654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 781654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 782654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!shouldCheckWalledGarden()) { 783654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 784654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 785654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 786654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 787a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff transitionTo(mDelayWalledGardenState); 788654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 789654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 790654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 79179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (idDnsMap.isEmpty()) { 792654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 7937f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log(makeLogString() + " FAILURE"); 794654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 795654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckFailureState); 796654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 797654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 798654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 799654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 800654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 801654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 80279e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy private String makeLogString() { 80379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy String logStr = dnsCheckLogStr; 80479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy for (String respStr : dnsResponseStrs) 80579e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy logStr += " [" + respStr + "]"; 80679e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy return logStr; 80779e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy } 80879e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy 809d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy @Override 810d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public void exit() { 811d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mDnsPinger.cancelPings(); 812d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 813d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 814654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean shouldCheckWalledGarden() { 815d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (!mWalledGardenTestEnabled) { 8167f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) 8177f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Skipping walled garden check - disabled"); 818654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 819654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 820d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy long waitTime = waitTime(mWalledGardenIntervalMs, 821654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime); 822654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (waitTime > 0) { 823654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 8247f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Skipping walled garden check - wait " + 825654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime + " ms."); 826654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 827654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 828654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 829654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return true; 830654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 831654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 832654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 833a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff class DelayWalledGardenState extends State { 834a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff @Override 835a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff public void enter() { 836a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff sendMessageDelayed(MESSAGE_DELAYED_WALLED_GARDEN_CHECK, WALLED_GARDEN_START_DELAY_MS); 837a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } 838a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff 839a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff @Override 840a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff public boolean processMessage(Message msg) { 841a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff switch (msg.what) { 842a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff case MESSAGE_DELAYED_WALLED_GARDEN_CHECK: 843a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff mLastWalledGardenCheckTime = SystemClock.elapsedRealtime(); 844a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff if (isWalledGardenConnection()) { 845a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff if (DBG) log("Walled garden test complete - walled garden detected"); 846a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff transitionTo(mWalledGardenState); 847a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } else { 848a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff if (DBG) log("Walled garden test complete - online"); 84919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff if (mPoorNetworkDetectionEnabled) { 85019380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineWatchState); 85119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } else { 85219380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineState); 85319380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 854a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } 855a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff return HANDLED; 856a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff default: 857a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff return NOT_HANDLED; 858a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } 859a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } 860a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff } 861a81ac7c450d9d534c46abc7000cc53779a72c283Irfan Sheriff 862654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class OnlineWatchState extends State { 863654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 864654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Signals a short-wait message is enqueued for the current 'guard' counter 865654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 866654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean unstableSignalChecks = false; 867654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 868654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 869654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The signal is unstable. We should enqueue a short-wait check, if one is enqueued 870654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * already 871654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 872654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean signalUnstable = false; 873654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 874654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 875654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * A monotonic counter to ensure that at most one check message will be processed from any 876654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * set of check messages currently enqueued. Avoids duplicate checks when a low-signal 877654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * event is observed. 878654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 879654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int checkGuard = 0; 880654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Long lastCheckTime = null; 881654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 88279e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy /** Keeps track of dns pings. Map is from pingID to InetAddress used for ping */ 88379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy HashMap<Integer, InetAddress> pingInfoMap = new HashMap<Integer, InetAddress>(); 884d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 885654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 886654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 887654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 888654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = false; 889654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 890654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 89179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy pingInfoMap.clear(); 892654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 893654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 894654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 895654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 896654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 897654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 898654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_RSSI_CHANGE: 899654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 900654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 9017f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Rssi change message out of sync, ignoring"); 902654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 903654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 904654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 905654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int newRssi = msg.arg2; 906654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = !rssiStrengthAboveCutoff(newRssi); 9077f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 9087f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("OnlineWatchState:: new rssi " + newRssi + " --> level " + 909654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS)); 910654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 911654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 912654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable && !unstableSignalChecks) { 9137f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 9147f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Sending triggered check msg"); 915654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 916654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 917654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 918654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 919654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case MESSAGE_SINGLE_DNS_CHECK: 920654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != checkGuard) { 9217f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 9227f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Single check msg out of sync, ignoring."); 923654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 924654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 925654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 926654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 92779e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy pingInfoMap.clear(); 92879e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy for (InetAddress curDns: mDnsPinger.getDnsList()) { 92979e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy pingInfoMap.put(mDnsPinger.pingDnsAsync(curDns, mDnsPingTimeoutMs, 0), 93079e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy curDns); 93179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy } 932d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy return HANDLED; 933d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy case DnsPinger.DNS_PING_RESULT: 93479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy InetAddress curDnsServer = pingInfoMap.get(msg.arg1); 93579e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (curDnsServer == null) { 936d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy return HANDLED; 937d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 93879e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy pingInfoMap.remove(msg.arg1); 939d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy int responseTime = msg.arg2; 940654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (responseTime >= 0) { 9417f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 9427f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Single DNS ping OK. Response time: " 94379e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy + responseTime + " from DNS " + curDnsServer); 944654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 94579e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy pingInfoMap.clear(); 946654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 947654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 948654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 949654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 950654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 95179e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (pingInfoMap.isEmpty()) { 95279e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy if (DBG) { 9537f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Single dns ping failure. All dns servers failed, " 95479e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy + "starting full checks."); 95579e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy } 95679e43f679d6102066ee9eff862912806f53bb0e8Isaac Levy transitionTo(mDnsCheckingState); 957654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 958654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 959654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 960654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 961654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 962654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 963654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 964d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy @Override 965d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy public void exit() { 966d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy mDnsPinger.cancelPings(); 967d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy } 968d2fe04b71a89a0608eb7c67065dead2a1f540122Isaac Levy 969654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 970d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Times a dns check with an interval based on {@link #signalUnstable} 971654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 972654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void triggerSingleDnsCheck() { 973654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long waitInterval; 974654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable) { 975d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy waitInterval = mDnsCheckShortIntervalMs; 976654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = true; 977654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 978d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy waitInterval = mDnsCheckLongIntervalMs; 979654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 980654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0), 981654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime(waitInterval, lastCheckTime)); 982654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 983654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 984654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 98519380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff 98619380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff /* Child state of ConnectedState indicating that we are online 98719380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff * and there is nothing to do 98819380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff */ 98919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff class OnlineState extends State { 99019380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 99119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff 992654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckFailureState extends State { 9934ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy 994654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 995654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 996d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumCheckFailures++; 997654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget(); 998654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 999654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1000654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 1001654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 1002654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_BAD_AP) { 1003654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 1004654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1005654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1006654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 10077f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 10087f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Msg out of sync, ignoring..."); 1009654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1010654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1011654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1012654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 10138dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (mDisableAPNextFailure || mNumCheckFailures >= mBssids.size() 10148dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy || mNumCheckFailures >= mMaxSsidBlacklists) { 10159b2886e24301e5d4e7052ec4a6eaff273d3f516cRobert Greenwalt if (sWifiOnly) { 10167f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Would disable bad network, but device has no mobile data!" + 10174ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy " Going idle..."); 10184ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy // This state should be called idle -- will be changing flow. 10194ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy transitionTo(mNotConnectedState); 10204ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy return HANDLED; 10214ad39d6ac16961df0e7a3e4b4e7075aaa5202787Isaac Levy } 10228dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy 1023654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // TODO : Unban networks if they had low signal ? 10247f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Disabling current SSID " + wifiInfoToStr(mConnectionInfo) 1025d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + ". " + "numCheckFailures " + mNumCheckFailures 1026d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + ", numAPs " + mBssids.size()); 10278dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy int networkId = mConnectionInfo.getNetworkId(); 10288dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (!mHasConnectedWifiManager) { 10298dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mWifiManager.asyncConnect(mContext, getHandler()); 10308dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mHasConnectedWifiManager = true; 10318dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy } 10328dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mWifiManager.disableNetwork(networkId, WifiConfiguration.DISABLED_DNS_FAILURE); 10338dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy if (mShowDisabledNotification && mConnectionInfo.isExplicitConnect()) { 10346b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setDisabledNetworkNotificationVisible(true); 1035d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 1036654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 1037654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 10387f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("Blacklisting current BSSID. " + wifiInfoToStr(mConnectionInfo) 1039d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size()); 1040654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 10418dc6a1b2823f374a176fb21b8a174664a5f825faIsaac Levy mWifiManager.addToBlacklist(mConnectionInfo.getBSSID()); 1042654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.reassociate(); 1043654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mBlacklistedApState); 1044654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1045654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1046654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1047654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1048654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1049654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WalledGardenState extends State { 1050654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 1051654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 1052654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_WALLED_GARDEN, mNetEventCounter, 0).sendToTarget(); 1053654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1054654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1055654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 1056654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 1057654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_WALLED_GARDEN) { 1058654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 1059654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1060654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1061654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 10627f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 10637f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("WalledGardenState::Msg out of sync, ignoring..."); 1064654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1065654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1066654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 10676b66e9e4c95b1c866ea63a0122fc199994fd7053Irfan Sheriff setWalledGardenNotificationVisible(true); 106819380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff if (mPoorNetworkDetectionEnabled) { 106919380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineWatchState); 107019380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } else { 107119380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff transitionTo(mOnlineState); 107219380daaf46815c80bd89fd9ca3af3c4095952b5Irfan Sheriff } 1073654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1074654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1075654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1076654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1077654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class BlacklistedApState extends State { 1078654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 1079654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 1080654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = true; 1081654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0), 1082d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mBlacklistFollowupIntervalMs); 1083654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1084654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1085654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 1086654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 1087654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_NETWORK_FOLLOWUP) { 1088654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 1089654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1090654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1091654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 10927f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff if (DBG) { 10937f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff log("BlacklistedApState::Msg out of sync, ignoring..."); 1094654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1095654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1096654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1097654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 1098654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 1099654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 1100654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1101654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 1102d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 1103d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 1104d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 1105d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for retrieving a single secure settings value 1106d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * as a string with a default value. 1107d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 1108d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 1109d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to retrieve. 1110d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param def Value to return if the setting is not defined. 1111d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 1112d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return The setting's current value, or 'def' if it is not defined 1113d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 1114d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static String getSettingsStr(ContentResolver cr, String name, String def) { 1115d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy String v = Settings.Secure.getString(cr, name); 1116d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return v != null ? v : def; 1117d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 1118d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 1119d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 1120d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for retrieving a single secure settings value 1121d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * as a boolean. Note that internally setting values are always 1122d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * stored as strings; this function converts the string to a boolean 1123d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * for you. The default value will be returned if the setting is 1124d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * not defined or not a valid boolean. 1125d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 1126d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 1127d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to retrieve. 1128d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param def Value to return if the setting is not defined. 1129d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 1130d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return The setting's current value, or 'def' if it is not defined 1131d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * or not a valid boolean. 1132d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 1133d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static boolean getSettingsBoolean(ContentResolver cr, String name, boolean def) { 1134d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return Settings.Secure.getInt(cr, name, def ? 1 : 0) == 1; 1135d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 1136d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 1137d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 1138d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for updating a single settings value as an 1139d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * integer. This will either create a new entry in the table if the 1140d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * given name does not exist, or modify the value of the existing row 1141d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * with that name. Note that internally setting values are always 1142d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * stored as strings, so this function converts the given value to a 1143d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * string before storing it. 1144d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 1145d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 1146d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to modify. 1147d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param value The new value for the setting. 1148d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return true if the value was set, false on database errors 1149d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 1150d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static boolean putSettingsBoolean(ContentResolver cr, String name, boolean value) { 1151d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return Settings.Secure.putInt(cr, name, value ? 1 : 0); 1152d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 1153d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 11547f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff private void log(String s) { 11557f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff Log.d(TAG, s); 11567f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff } 1157d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 11587f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff private void loge(String s) { 11597f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff Log.e(TAG, s); 11607f8a12c75cf2b376fce58fc22b5ecb1b64acf110Irfan Sheriff } 1161654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy} 1162