WifiWatchdogStateMachine.java revision d7b3e6a39b6b2e155b24ef470023bafb3b9fa35a
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; 35654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.provider.Settings; 36d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport android.provider.Settings.Secure; 37654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport android.util.Slog; 38654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 39654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.Protocol; 40654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.State; 41654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport com.android.internal.util.StateMachine; 42654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 43654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.BufferedInputStream; 44654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.IOException; 45654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.InputStream; 46654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.io.PrintWriter; 47654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.HttpURLConnection; 48654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.net.URL; 49654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.HashSet; 50654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.List; 51654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levyimport java.util.Scanner; 52d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levyimport java.util.regex.Pattern; 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 70d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 71d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final boolean VDBG = true; //TODO : Remove this before merge 72654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final boolean DBG = true; 73654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final String WWSM_TAG = "WifiWatchdogStateMachine"; 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 */ 79654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int LOW_SIGNAL_CUTOFF = 1; 80654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 81d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS = 2 * 60 * 1000; 82d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_DNS_CHECK_LONG_INTERVAL_MS = 10 * 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; 86d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final int DEFAULT_NUM_DNS_PINGS = 5; 87d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final int DEFAULT_MIN_DNS_RESPONSES = 3; 88654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final long DNS_PING_INTERVAL_MS = 100; 89654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 90d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final int DEFAULT_DNS_PING_TIMEOUT_MS = 1500; 91d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 92d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final long DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS = 15 * 1000; 93d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 94d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final String DEFAULT_WALLED_GARDEN_URL = "http://www.google.com/"; 95d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final String DEFAULT_WALLED_GARDEN_PATTERN = "<title>.*Google.*</title>"; 96d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 97654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 98654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int BASE = Protocol.BASE_WIFI_WATCHDOG; 99654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 100654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 101654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the enable setting of WWS may have changed 102654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 103654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_WATCHDOG_TOGGLED = BASE + 1; 104654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 105654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 106654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the wifi network state has changed. Passed w/ original intent 107654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * which has a non-null networkInfo object 108654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 109654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_NETWORK_STATE_CHANGE = BASE + 2; 110654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 111654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Indicates the signal has changed. Passed with arg1 112654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * {@link #mNetEventCounter} and arg2 [raw signal strength] 113654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 114654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_RSSI_CHANGE = BASE + 3; 115654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_SCAN_RESULTS_AVAILABLE = BASE + 4; 116654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int EVENT_WIFI_RADIO_STATE_CHANGE = BASE + 5; 117d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static final int EVENT_WATCHDOG_SETTINGS_CHANGE = BASE + 6; 118654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 119654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_CHECK_STEP = BASE + 100; 120654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_HANDLE_WALLED_GARDEN = BASE + 101; 121654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_HANDLE_BAD_AP = BASE + 102; 122654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 123654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * arg1 == mOnlineWatchState.checkCount 124654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 125654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_SINGLE_DNS_CHECK = BASE + 103; 126654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static final int MESSAGE_NETWORK_FOLLOWUP = BASE + 104; 127654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 128654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Context mContext; 129654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ContentResolver mContentResolver; 130654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiManager mWifiManager; 131654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsPinger mDnsPinger; 132654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private IntentFilter mIntentFilter; 133654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BroadcastReceiver mBroadcastReceiver; 134654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 135654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DefaultState mDefaultState = new DefaultState(); 136654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogDisabledState mWatchdogDisabledState = new WatchdogDisabledState(); 137654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WatchdogEnabledState mWatchdogEnabledState = new WatchdogEnabledState(); 138654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private NotConnectedState mNotConnectedState = new NotConnectedState(); 139654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private ConnectedState mConnectedState = new ConnectedState(); 140654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckingState mDnsCheckingState = new DnsCheckingState(); 141654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private OnlineWatchState mOnlineWatchState = new OnlineWatchState(); 142654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private DnsCheckFailureState mDnsCheckFailureState = new DnsCheckFailureState(); 143654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WalledGardenState mWalledGardenState = new WalledGardenState(); 144654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private BlacklistedApState mBlacklistedApState = new BlacklistedApState(); 145654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 146d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mDnsCheckShortIntervalMs; 147d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mDnsCheckLongIntervalMs; 148d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mWalledGardenIntervalMs; 149d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mMaxSsidBlacklists; 150d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mNumDnsPings; 151d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mMinDnsResponses; 152d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mDnsPingTimeoutMs; 153d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private long mBlacklistFollowupIntervalMs; 154d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private boolean mWalledGardenTestEnabled; 155d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private String mWalledGardenUrl; 156d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private Pattern mWalledGardenPattern; 157d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 158d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private boolean mShowDisabledNotification; 159654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 160654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The {@link WifiInfo} object passed to WWSM on network broadcasts 161654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 162654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiInfo mInitialConnInfo; 163654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private int mNetEventCounter = 0; 164654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 165654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 166654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Currently maintained but not used, TODO 167654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 168654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private HashSet<String> mBssids = new HashSet<String>(); 169d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private int mNumCheckFailures = 0; 170654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 171654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private Long mLastWalledGardenCheckTime = null; 172654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 173654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 174654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * This is set by the blacklisted state and reset when connected to a new AP. 175654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * It triggers a disableNetwork call if a DNS check fails. 176654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 177654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean mDisableAPNextFailure = false; 178654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 179654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 180654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * STATE MAP 181654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Default 182654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 183654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Disabled Enabled 184654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * / \ 185d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * NotConnected Connected 186654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * /---------\ 187654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * (all other states) 188654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 189654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private WifiWatchdogStateMachine(Context context) { 190654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy super(WWSM_TAG); 191654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext = context; 192654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContentResolver = context.getContentResolver(); 193654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 194654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDnsPinger = new DnsPinger("WifiWatchdogServer.DnsPinger", context, 195654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy ConnectivityManager.TYPE_WIFI); 196654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 197654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setupNetworkReceiver(); 198654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 199654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // The content observer to listen needs a handler 200654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy registerForSettingsChanges(); 201d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy registerForWatchdogToggle(); 202654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDefaultState); 203654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogDisabledState, mDefaultState); 204654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWatchdogEnabledState, mDefaultState); 205654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mNotConnectedState, mWatchdogEnabledState); 206654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mConnectedState, mWatchdogEnabledState); 207654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckingState, mConnectedState); 208654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mDnsCheckFailureState, mConnectedState); 209654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mWalledGardenState, mConnectedState); 210654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mBlacklistedApState, mConnectedState); 211654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy addState(mOnlineWatchState, mConnectedState); 212654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 213654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy setInitialState(mWatchdogDisabledState); 214d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy updateSettings(); 215d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mShowDisabledNotification = getSettingsBoolean(mContentResolver, 216d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, true); 217654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 218654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 219654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) { 220654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context); 221654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.start(); 222654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy wwsm.sendMessage(EVENT_WATCHDOG_TOGGLED); 223654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wwsm; 224654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 225654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 226654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 227654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 228654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 229654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void setupNetworkReceiver() { 230654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBroadcastReceiver = new BroadcastReceiver() { 231654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 232654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onReceive(Context context, Intent intent) { 233654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String action = intent.getAction(); 234654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 235654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_NETWORK_STATE_CHANGE, intent); 236654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) { 237654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(EVENT_RSSI_CHANGE, mNetEventCounter, 238654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200)).sendToTarget(); 239654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 240654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_SCAN_RESULTS_AVAILABLE); 241654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 242654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE, 243654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 244654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.WIFI_STATE_UNKNOWN)); 245654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 246654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 247654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 248654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 249654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter = new IntentFilter(); 250654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 251654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 252654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 253654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 254654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 255654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 256654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 257654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Observes the watchdog on/off setting, and takes action when changed. 258654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 259d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void registerForWatchdogToggle() { 260654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 261654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 262654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void onChange(boolean selfChange) { 263654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessage(EVENT_WATCHDOG_TOGGLED); 264654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 265654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy }; 266654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 267654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.getContentResolver().registerContentObserver( 268654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_ON), 269654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy false, contentObserver); 270654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 271654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 272654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 273d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Observes watchdogs secure setting changes. 274d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 275d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void registerForSettingsChanges() { 276d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy ContentObserver contentObserver = new ContentObserver(this.getHandler()) { 277d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy @Override 278d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy public void onChange(boolean selfChange) { 279d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy sendMessage(EVENT_WATCHDOG_SETTINGS_CHANGE); 280d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 281d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy }; 282d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 283d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 284d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor( 285d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS), 286d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 287d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 288d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS), 289d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 290d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 291d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS), 292d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 293d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 294d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS), 295d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 296d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 297d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_NUM_DNS_PINGS), 298d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 299d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 300d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES), 301d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 302d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 303d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS), 304d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 305d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 306d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor( 307d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS), 308d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 309d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 310d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED), 311d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 312d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 313d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL), 314d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 315d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mContext.getContentResolver().registerContentObserver( 316d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.getUriFor(Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN), 317d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy false, contentObserver); 318d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 319d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 320d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 321654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * DNS based detection techniques do not work at all hotspots. The one sure 322654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * way to check a walled garden is to see if a URL fetch on a known address 323654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * fetches the data we expect 324654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 325654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWalledGardenConnection() { 326654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy InputStream in = null; 327654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy HttpURLConnection urlConnection = null; 328654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy try { 329d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy URL url = new URL(mWalledGardenUrl); 330654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection = (HttpURLConnection) url.openConnection(); 331654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy in = new BufferedInputStream(urlConnection.getInputStream()); 332654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Scanner scanner = new Scanner(in); 333d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (scanner.findInLine(mWalledGardenPattern) != null) { 334654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 335654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 336654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return true; 337654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 338654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } catch (IOException e) { 339654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 340654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } finally { 341654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (in != null) { 342654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy try { 343654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy in.close(); 344654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } catch (IOException e) { 345654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 346654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 347654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (urlConnection != null) 348654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy urlConnection.disconnect(); 349654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 350654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 351654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 352654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean rssiStrengthAboveCutoff(int rssi) { 353654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return WifiManager.calculateSignalLevel(rssi, WIFI_SIGNAL_LEVELS) > LOW_SIGNAL_CUTOFF; 354654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 355654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 356654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void dump(PrintWriter pw) { 357654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("WatchdogStatus: "); 358654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.print("State " + getCurrentState()); 359654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println(", network [" + mInitialConnInfo + "]"); 360d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy pw.print("checkFailures " + mNumCheckFailures); 361654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println(", bssids: " + mBssids); 362654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy pw.println("lastSingleCheck: " + mOnlineWatchState.lastCheckTime); 363654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 364654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 365654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean isWatchdogEnabled() { 366d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return getSettingsBoolean(mContentResolver, Settings.Secure.WIFI_WATCHDOG_ON, true); 367654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 368654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 369d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void updateSettings() { 370d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsCheckShortIntervalMs = Secure.getLong(mContentResolver, 371d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_CHECK_SHORT_INTERVAL_MS, 372d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_CHECK_SHORT_INTERVAL_MS); 373d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsCheckLongIntervalMs = Secure.getLong(mContentResolver, 374d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_CHECK_LONG_INTERVAL_MS, 375d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_CHECK_LONG_INTERVAL_MS); 376d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mMaxSsidBlacklists = Secure.getInt(mContentResolver, 377d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_MAX_SSID_BLACKLISTS, 378d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_MAX_SSID_BLACKLISTS); 379d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumDnsPings = Secure.getInt(mContentResolver, 380d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_NUM_DNS_PINGS, 381d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_NUM_DNS_PINGS); 382d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mMinDnsResponses = Secure.getInt(mContentResolver, 383d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_MIN_DNS_RESPONSES, 384d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_MIN_DNS_RESPONSES); 385d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsPingTimeoutMs = Secure.getInt(mContentResolver, 386d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_DNS_PING_TIMEOUT_MS, 387d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_DNS_PING_TIMEOUT_MS); 388d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mBlacklistFollowupIntervalMs = Secure.getLong(mContentResolver, 389d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_BLACKLIST_FOLLOWUP_INTERVAL_MS, 390d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_BLACKLIST_FOLLOWUP_INTERVAL_MS); 391d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenTestEnabled = getSettingsBoolean(mContentResolver, 392d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_TEST_ENABLED, true); 393d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenUrl = getSettingsStr(mContentResolver, 394d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_URL, 395d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_WALLED_GARDEN_URL); 396d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenPattern = Pattern.compile(getSettingsStr(mContentResolver, 397d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_WALLED_GARDEN_PATTERN, 398d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_WALLED_GARDEN_PATTERN)); 399d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mWalledGardenIntervalMs = Secure.getLong(mContentResolver, 400d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Secure.WIFI_WATCHDOG_WALLED_GARDEN_INTERVAL_MS, 401d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy DEFAULT_WALLED_GARDEN_INTERVAL_MS); 402d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 403654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 404654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 405654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Helper to return wait time left given a min interval and last run 406654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 407654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param interval minimum wait interval 408654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param lastTime last time action was performed in 409654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * SystemClock.elapsedRealtime(). Null if never. 410654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @return non negative time to wait 411654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 412654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static long waitTime(long interval, Long lastTime) { 413654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (lastTime == null) 414654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return 0; 415654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long wait = interval + lastTime - SystemClock.elapsedRealtime(); 416654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return wait > 0 ? wait : 0; 417654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 418654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 419654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private static String wifiInfoToStr(WifiInfo wifiInfo) { 420654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) 421654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "null"; 422654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return "(" + wifiInfo.getSSID() + ", " + wifiInfo.getBSSID() + ")"; 423654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 424654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 425654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 426654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * 427654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 428654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void resetWatchdogState() { 429654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mInitialConnInfo = null; 430654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 431654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime = null; 432d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumCheckFailures = 0; 433654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBssids.clear(); 434654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 435654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 436654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void popUpBrowser() { 437654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Uri uri = Uri.parse("http://www.google.com"); 438654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent intent = new Intent(Intent.ACTION_VIEW, uri); 439654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | 440654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent.FLAG_ACTIVITY_NEW_TASK); 441654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.startActivity(intent); 442654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 443654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 444d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void displayDisabledNetworkNotification() { 445d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Resources r = Resources.getSystem(); 446d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy CharSequence title = 447d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled); 448d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy CharSequence msg = 449d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy r.getText(com.android.internal.R.string.wifi_watchdog_network_disabled_detailed); 450d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 451d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Notification wifiDisabledWarning = new Notification.Builder(mContext) 452d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setSmallIcon(com.android.internal.R.drawable.stat_sys_warning) 453d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setDefaults(Notification.DEFAULT_ALL) 454d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setTicker(title) 455d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setContentTitle(title) 456d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setContentText(msg) 457d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setContentIntent(PendingIntent.getActivity(mContext, 0, 458d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy new Intent(Settings.ACTION_WIFI_IP_SETTINGS) 459d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0)) 460d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setWhen(System.currentTimeMillis()) 461d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .setAutoCancel(true) 462d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .getNotification(); 463d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 464d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy NotificationManager notificationManager = (NotificationManager) mContext 465d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy .getSystemService(Context.NOTIFICATION_SERVICE); 466d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 467d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy notificationManager.notify("WifiWatchdog", wifiDisabledWarning.icon, wifiDisabledWarning); 468654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 469654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 470654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DefaultState extends State { 471654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 472654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 473d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy switch (msg.what) { 474d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy case EVENT_WATCHDOG_SETTINGS_CHANGE: 475d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy updateSettings(); 476d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (VDBG) { 477d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Slog.d(WWSM_TAG, "Updating wifi-watchdog secure settings"); 478d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 479d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return HANDLED; 480d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 481654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 482654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Caught message " + msg.what + " in state " + 483654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy getCurrentState().getName()); 484654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 485654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 486654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 487654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 488654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 489654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogDisabledState extends State { 490654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 491654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 492654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 493654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 494654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (isWatchdogEnabled()) 495654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 496654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 497654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 498654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 499654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 500654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 501654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 502654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WatchdogEnabledState extends State { 503654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 504654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 505654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 506654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.registerReceiver(mBroadcastReceiver, mIntentFilter); 507654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiWatchdogService enabled"); 508654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 509654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 510654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 511654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 512654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 513654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WATCHDOG_TOGGLED: 514654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!isWatchdogEnabled()) 515654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mWatchdogDisabledState); 516654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 517654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_NETWORK_STATE_CHANGE: 518654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Intent stateChangeIntent = (Intent) msg.obj; 519654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy NetworkInfo networkInfo = (NetworkInfo) 520654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy stateChangeIntent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 521654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 522654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (networkInfo.getState()) { 523654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case CONNECTED: 524654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // WifiInfo wifiInfo = (WifiInfo) 525654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // stateChangeIntent 526654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // .getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); 527654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // TODO : Replace with above code when API is changed 528654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 529654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo == null) { 530654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.e(WWSM_TAG, "Connected --> WifiInfo object null!"); 531654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 532654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 533654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 534654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (wifiInfo.getSSID() == null || wifiInfo.getBSSID() == null) { 535654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.e(WWSM_TAG, "Received wifiInfo object with null elts: " 536654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + wifiInfoToStr(wifiInfo)); 537654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 538654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 539654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 540654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy initConnection(wifiInfo); 541654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 542654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 543654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 544654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case DISCONNECTED: 545654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case DISCONNECTING: 546654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 547654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 548654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 549654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 550654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 551654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_WIFI_RADIO_STATE_CHANGE: 552654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if ((Integer) msg.obj == WifiManager.WIFI_STATE_DISABLING) { 553654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiStateDisabling -- Resetting WatchdogState"); 554654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 555654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mNetEventCounter++; 556654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 557654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 558654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 559654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 560654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 561654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 562654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 563654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 564654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 565654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * @param wifiInfo Info object with non-null ssid and bssid 566654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 567654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void initConnection(WifiInfo wifiInfo) { 568654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 569654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Connected:: old " + wifiInfoToStr(mInitialConnInfo) + 570654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy " ==> new " + wifiInfoToStr(wifiInfo)); 571654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 572654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 573654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (mInitialConnInfo == null || !wifiInfo.getSSID().equals(mInitialConnInfo.getSSID())) { 574654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy resetWatchdogState(); 575654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else if (!wifiInfo.getBSSID().equals(mInitialConnInfo.getBSSID())) { 576654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = false; 577654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 578654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mInitialConnInfo = wifiInfo; 579654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 580654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 581654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 582654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void exit() { 583654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mContext.unregisterReceiver(mBroadcastReceiver); 584654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "WifiWatchdogService disabled"); 585654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 586654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 587654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 588654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class NotConnectedState extends State { 589654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 590654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 591654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class ConnectedState extends State { 592654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 593654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 594654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 595654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_SCAN_RESULTS_AVAILABLE: 596654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String curSsid = mInitialConnInfo.getSSID(); 597654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy List<ScanResult> results = mWifiManager.getScanResults(); 598654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int oldNumBssids = mBssids.size(); 599654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 600654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (results == null) { 601654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 602654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "updateBssids: Got null scan results!"); 603654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 604654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 605654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 606654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 607654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy for (ScanResult result : results) { 608654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (result == null || result.SSID == null) { 609654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 610654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Received invalid scan result: " + result); 611654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 612654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy continue; 613654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 614654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (curSsid.equals(result.SSID)) 615654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mBssids.add(result.BSSID); 616654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 617654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 618d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy case EVENT_WATCHDOG_SETTINGS_CHANGE: 619d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy // Stop current checks, but let state update 620d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy transitionTo(mOnlineWatchState); 621d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return NOT_HANDLED; 622654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 623654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 624654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 625654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 626654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 627654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 628654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckingState extends State { 629654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int dnsCheckTries = 0; 630654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int dnsCheckSuccesses = 0; 631654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy String dnsCheckLogStr = ""; 632654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 633654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 634654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 635654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckSuccesses = 0; 636654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckTries = 0; 637654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 638654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Starting DNS pings at " + SystemClock.elapsedRealtime()); 639d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy dnsCheckLogStr = String.format("Pinging %s on ssid [%s]: ", 640d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsPinger.getDns(), mInitialConnInfo.getSSID()); 641654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 642654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 643654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendCheckStepMessage(0); 644654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 645654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 646654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 647654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 648654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_CHECK_STEP) { 649654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 650654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 651654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 652654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Check step out of sync, ignoring..."); 653654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 654654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 655654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 656654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long pingResponseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), 657d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsPingTimeoutMs); 658654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 659654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckTries++; 660654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) 661654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckSuccesses++; 662654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 663654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 664654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (pingResponseTime >= 0) { 665654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckLogStr += "|" + pingResponseTime; 666654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 667654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy dnsCheckLogStr += "|x"; 668654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 669654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 670654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 671654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 672654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, dnsCheckLogStr); 673654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 674654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 675654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 676654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * After a full ping count, if we have more responses than this 677654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * cutoff, the outcome is success; else it is 'failure'. 678654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 679654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 680654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 681654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Our final success count will be at least this big, so we're 682654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * guaranteed to succeed. 683654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 684d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (dnsCheckSuccesses >= mMinDnsResponses) { 685654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // DNS CHECKS OK, NOW WALLED GARDEN 686654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 687654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, dnsCheckLogStr + "| SUCCESS"); 688654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 689654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 690654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (!shouldCheckWalledGarden()) { 691654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 692654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 693654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 694654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 695654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime = SystemClock.elapsedRealtime(); 696654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (isWalledGardenConnection()) { 697654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) 698654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, 699654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy "Walled garden test complete - walled garden detected"); 700654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mWalledGardenState); 701654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 702654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) 703654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Walled garden test complete - online"); 704654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 705654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 706654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 707654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 708654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 709654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 710654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Our final count will be at most the current count plus the 711654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * remaining pings - we're guaranteed to fail. 712654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 713d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy int remainingChecks = mNumDnsPings - dnsCheckTries; 714d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (remainingChecks + dnsCheckSuccesses < mMinDnsResponses) { 715654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 716654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, dnsCheckLogStr + "| FAILURE"); 717654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 718654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckFailureState); 719654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 720654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 721654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 722654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // Still in dns check step 723654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendCheckStepMessage(DNS_PING_INTERVAL_MS); 724654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 725654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 726654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 727654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private boolean shouldCheckWalledGarden() { 728d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (!mWalledGardenTestEnabled) { 729654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) 730654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Skipping walled garden check - disabled"); 731654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 732654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 733d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy long waitTime = waitTime(mWalledGardenIntervalMs, 734654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mLastWalledGardenCheckTime); 735654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (waitTime > 0) { 736654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 737654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Skipping walled garden check - wait " + 738654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime + " ms."); 739654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 740654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return false; 741654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 742654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return true; 743654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 744654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 745d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private void sendCheckStepMessage(long delay) { 746d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_CHECK_STEP, mNetEventCounter, 0), delay); 747d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 748d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 749654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 750654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 751654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class OnlineWatchState extends State { 752654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 753654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * Signals a short-wait message is enqueued for the current 'guard' counter 754654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 755654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean unstableSignalChecks = false; 756654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 757654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 758654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * The signal is unstable. We should enqueue a short-wait check, if one is enqueued 759654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * already 760654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 761654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy boolean signalUnstable = false; 762654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 763654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 764654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * A monotonic counter to ensure that at most one check message will be processed from any 765654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * set of check messages currently enqueued. Avoids duplicate checks when a low-signal 766654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy * event is observed. 767654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 768654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int checkGuard = 0; 769654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Long lastCheckTime = null; 770654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 771654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 772654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 773654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 774654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = false; 775654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 776654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 777654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 778654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 779654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 780654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 781654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 782654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy switch (msg.what) { 783654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case EVENT_RSSI_CHANGE: 784654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 785654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 786654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Rssi change message out of sync, ignoring"); 787654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 788654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 789654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 790654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy int newRssi = msg.arg2; 791654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy signalUnstable = !rssiStrengthAboveCutoff(newRssi); 792654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 793654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "OnlineWatchState:: new rssi " + newRssi + " --> level " + 794654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy WifiManager.calculateSignalLevel(newRssi, WIFI_SIGNAL_LEVELS)); 795654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 796654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 797654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable && !unstableSignalChecks) { 798654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 799654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Sending triggered check msg"); 800654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 801654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 802654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 803654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 804654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy case MESSAGE_SINGLE_DNS_CHECK: 805654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != checkGuard) { 806654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 807654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Single check msg out of sync, ignoring."); 808654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 809654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 810654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 811654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy lastCheckTime = SystemClock.elapsedRealtime(); 812654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long responseTime = mDnsPinger.pingDns(mDnsPinger.getDns(), 813d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mDnsPingTimeoutMs); 814654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (responseTime >= 0) { 815654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 816654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Ran a single DNS ping. Response time: " 817654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy + responseTime); 818654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 819654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 820654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy checkGuard++; 821654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = false; 822654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy triggerSingleDnsCheck(); 823654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 824654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (DBG) { 825654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.d(WWSM_TAG, "Single dns ping failure. Starting full checks."); 826654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 827654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 828654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 829654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 830654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 831654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 832654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 833654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 834654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy /** 835d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Times a dns check with an interval based on {@link #signalUnstable} 836654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy */ 837654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy private void triggerSingleDnsCheck() { 838654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy long waitInterval; 839654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (signalUnstable) { 840d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy waitInterval = mDnsCheckShortIntervalMs; 841654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy unstableSignalChecks = true; 842654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 843d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy waitInterval = mDnsCheckLongIntervalMs; 844654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 845654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_SINGLE_DNS_CHECK, checkGuard, 0), 846654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy waitTime(waitInterval, lastCheckTime)); 847654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 848654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 849654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 850654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class DnsCheckFailureState extends State { 851654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 852654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 853d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mNumCheckFailures++; 854654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_BAD_AP, mNetEventCounter, 0).sendToTarget(); 855654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 856654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 857654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 858654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 859654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_BAD_AP) { 860654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 861654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 862654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 863654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 864654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 865654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "Msg out of sync, ignoring..."); 866654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 867654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 868654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 869654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 870d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (mDisableAPNextFailure || mNumCheckFailures >= mMaxSsidBlacklists) { 871654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy // TODO : Unban networks if they had low signal ? 872654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.i(WWSM_TAG, "Disabling current SSID " + wifiInfoToStr(mInitialConnInfo) 873d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + ". " + "numCheckFailures " + mNumCheckFailures 874d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + ", numAPs " + mBssids.size()); 875654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.disableNetwork(mInitialConnInfo.getNetworkId()); 876d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy if (mShowDisabledNotification) { 877d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy displayDisabledNetworkNotification(); 878d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mShowDisabledNotification = false; 879d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy putSettingsBoolean(mContentResolver, 880d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Settings.Secure.WIFI_WATCHDOG_SHOW_DISABLED_NETWORK_POPUP, false); 881d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 882654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mNotConnectedState); 883654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } else { 884d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy Slog.i(WWSM_TAG, "Blacklisting current BSSID. " + wifiInfoToStr(mInitialConnInfo) 885d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy + "numCheckFailures " + mNumCheckFailures + ", numAPs " + mBssids.size()); 886654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 887654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.addToBlacklist(mInitialConnInfo.getBSSID()); 888654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mWifiManager.reassociate(); 889654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mBlacklistedApState); 890654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 891654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 892654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 893654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 894654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 895654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class WalledGardenState extends State { 896654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 897654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 898654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy obtainMessage(MESSAGE_HANDLE_WALLED_GARDEN, mNetEventCounter, 0).sendToTarget(); 899654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 900654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 901654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 902654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 903654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_HANDLE_WALLED_GARDEN) { 904654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 905654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 906654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 907654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 908654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 909654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "WalledGardenState::Msg out of sync, ignoring..."); 910654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 911654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 912654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 913654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy popUpBrowser(); 914654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mOnlineWatchState); 915654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 916654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 917654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 918654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 919654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy class BlacklistedApState extends State { 920654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 921654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public void enter() { 922654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy mDisableAPNextFailure = true; 923654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy sendMessageDelayed(obtainMessage(MESSAGE_NETWORK_FOLLOWUP, mNetEventCounter, 0), 924d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy mBlacklistFollowupIntervalMs); 925654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 926654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 927654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy @Override 928654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy public boolean processMessage(Message msg) { 929654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.what != MESSAGE_NETWORK_FOLLOWUP) { 930654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return NOT_HANDLED; 931654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 932654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 933654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (msg.arg1 != mNetEventCounter) { 934654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy if (VDBG) { 935654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy Slog.v(WWSM_TAG, "BlacklistedApState::Msg out of sync, ignoring..."); 936654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 937654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 938654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 939654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy 940654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy transitionTo(mDnsCheckingState); 941654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy return HANDLED; 942654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 943654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy } 944d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 945d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 946d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 947d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for retrieving a single secure settings value 948d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * as a string with a default value. 949d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 950d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 951d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to retrieve. 952d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param def Value to return if the setting is not defined. 953d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 954d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return The setting's current value, or 'def' if it is not defined 955d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 956d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static String getSettingsStr(ContentResolver cr, String name, String def) { 957d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy String v = Settings.Secure.getString(cr, name); 958d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return v != null ? v : def; 959d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 960d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 961d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 962d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for retrieving a single secure settings value 963d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * as a boolean. Note that internally setting values are always 964d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * stored as strings; this function converts the string to a boolean 965d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * for you. The default value will be returned if the setting is 966d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * not defined or not a valid boolean. 967d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 968d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 969d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to retrieve. 970d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param def Value to return if the setting is not defined. 971d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 972d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return The setting's current value, or 'def' if it is not defined 973d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * or not a valid boolean. 974d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 975d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static boolean getSettingsBoolean(ContentResolver cr, String name, boolean def) { 976d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return Settings.Secure.getInt(cr, name, def ? 1 : 0) == 1; 977d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 978d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 979d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy /** 980d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * Convenience function for updating a single settings value as an 981d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * integer. This will either create a new entry in the table if the 982d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * given name does not exist, or modify the value of the existing row 983d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * with that name. Note that internally setting values are always 984d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * stored as strings, so this function converts the given value to a 985d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * string before storing it. 986d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * 987d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param cr The ContentResolver to access. 988d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param name The name of the setting to modify. 989d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @param value The new value for the setting. 990d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy * @return true if the value was set, false on database errors 991d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy */ 992d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy private static boolean putSettingsBoolean(ContentResolver cr, String name, boolean value) { 993d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy return Settings.Secure.putInt(cr, name, value ? 1 : 0); 994d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy } 995d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 996d7b3e6a39b6b2e155b24ef470023bafb3b9fa35aIsaac Levy 997654f5090754e4e1bf4c1736d0a24769a15a6037eIsaac Levy} 998