WifiMonitor.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.net.wifi; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Config; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.NetworkInfo; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.NetworkStateTracker; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Matcher; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Listens for events from the wpa_supplicant server, and passes them on 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to the {@link WifiStateTracker} for handling. Runs in its own thread. 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WifiMonitor { 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "WifiMonitor"; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Events we receive from the supplicant daemon */ 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CONNECTED = 1; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DISCONNECTED = 2; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_CHANGE = 3; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SCAN_RESULTS = 4; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LINK_SPEED = 5; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TERMINATING = 6; 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DRIVER_STATE = 7; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int UNKNOWN = 8; 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** All events coming from the supplicant start with this prefix */ 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String eventPrefix = "CTRL-EVENT-"; 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int eventPrefixLen = eventPrefix.length(); 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** All WPA events coming from the supplicant start with this prefix */ 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String wpaEventPrefix = "WPA:"; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String passwordKeyMayBeIncorrectEvent = 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "pre-shared key may be incorrect"; 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Names of events from wpa_supplicant (minus the prefix). In the 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * format descriptions, * "<code>x</code>" 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * designates a dynamic value that needs to be parsed out from the event 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * string 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>xx:xx:xx:xx:xx:xx</code> is the BSSID of the associated access point 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String connectedEvent = "CONNECTED"; 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String disconnectedEvent = "DISCONNECTED"; 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-STATE-CHANGE x 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>x</code> is the numerical value of the new state. 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String stateChangeEvent = "STATE-CHANGE"; 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-SCAN-RESULTS ready 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String scanResultsEvent = "SCAN-RESULTS"; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-LINK-SPEED x Mb/s 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@code x} is the link speed in Mb/sec. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String linkSpeedEvent = "LINK-SPEED"; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-TERMINATING - signal x 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>x</code> is the signal that caused termination. 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String terminatingEvent = "TERMINATING"; 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-DRIVER-STATE state 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>state</code> is either STARTED or STOPPED 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String driverStateEvent = "DRIVER-STATE"; 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Regex pattern for extracting an Ethernet-style MAC address from a string. 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Matches a strings like the following:<pre> 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]</pre> 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Pattern mConnectedEventPattern = 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) "); 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final WifiStateTracker mWifiStateTracker; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public WifiMonitor(WifiStateTracker tracker) { 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker = tracker; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startMonitoring() { 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MonitorThread().start(); 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public NetworkStateTracker getNetworkStateTracker() { 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mWifiStateTracker; 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class MonitorThread extends Thread { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MonitorThread() { 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("WifiMonitor"); 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (connectToSupplicant()) { 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send a message indicating that it is now possible to send commands 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to the supplicant 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifySupplicantConnection(); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifySupplicantLost(); 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection InfiniteLoopStatement 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (;;) { 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventStr = WifiNative.waitForEvent(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventStr == null) { 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Skip logging the common but mostly uninteresting scan-results event 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD && eventStr.indexOf(scanResultsEvent) == -1) { 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Event [" + eventStr + "]"); 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!eventStr.startsWith(eventPrefix)) { 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventStr.startsWith(wpaEventPrefix) && 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) { 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handlePasswordKeyMayBeIncorrect(); 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventName = eventStr.substring(eventPrefixLen); 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nameEnd = eventName.indexOf(' '); 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameEnd != -1) 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventName = eventName.substring(0, nameEnd); 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventName.length() == 0) { 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD) Log.i(TAG, "Received wpa_supplicant event with empty event name"); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Map event name into event enum 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventName.equals(connectedEvent)) 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = CONNECTED; 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(disconnectedEvent)) 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = DISCONNECTED; 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(stateChangeEvent)) 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = STATE_CHANGE; 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(scanResultsEvent)) 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = SCAN_RESULTS; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(linkSpeedEvent)) 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = LINK_SPEED; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(terminatingEvent)) 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = TERMINATING; 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(driverStateEvent)) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = DRIVER_STATE; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = UNKNOWN; 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventData = eventStr; 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == DRIVER_STATE || event == LINK_SPEED) 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventData.split(" ")[1]; 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (event == STATE_CHANGE) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ind = eventStr.indexOf(" "); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ind != -1) { 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventStr.substring(ind + 1); 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ind = eventStr.indexOf(" - "); 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ind != -1) { 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventStr.substring(ind + 3); 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == STATE_CHANGE) { 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleSupplicantStateChange(eventData); 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == DRIVER_STATE) { 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleDriverEvent(eventData); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == TERMINATING) { 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifySupplicantLost(); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If supplicant is gone, exit the thread 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleEvent(event, eventData); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean connectToSupplicant() { 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int connectTries = 0; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (mWifiStateTracker) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (WifiNative.connectToSupplicant()) { 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (connectTries++ < 3) { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project nap(5); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handlePasswordKeyMayBeIncorrect() { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyPasswordKeyMayBeIncorrect(); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleDriverEvent(String state) { 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.equals("STOPPED")) { 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyDriverStopped(); 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (state.equals("STARTED")) { 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyDriverStarted(); 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle all supplicant events except STATE-CHANGE 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param event the event type 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param remainder the rest of the string following the 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * event name and " — " 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void handleEvent(int event, String remainder) { 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (event) { 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case DISCONNECTED: 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder); 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case CONNECTED: 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder); 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SCAN_RESULTS: 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyScanResultsAvailable(); 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case UNKNOWN: 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the supplicant STATE-CHANGE event 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dataString New supplicant state string in the format: 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * id=network-id state=new-state 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleSupplicantStateChange(String dataString) { 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] dataTokens = dataString.split(" "); 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int networkId = -1; 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newState = -1; 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String token : dataTokens) { 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] nameValue = token.split("="); 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameValue.length != 2) { 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int value; 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = Integer.parseInt(nameValue[1]); 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "STATE-CHANGE non-integer parameter: " + token); 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameValue[0].equals("id")) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = value; 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (nameValue[0].equals("state")) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newState = value; 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newState == -1) return; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SupplicantState newSupplicantState = SupplicantState.INVALID; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (SupplicantState state : SupplicantState.values()) { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.ordinal() == newState) { 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newSupplicantState = state; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSupplicantState == SupplicantState.INVALID) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Invalid supplicant state: " + newState); 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyStateChange(networkId, newSupplicantState); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) { 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String BSSID = null; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int networkId = -1; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newState == NetworkInfo.DetailedState.CONNECTED) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Matcher match = mConnectedEventPattern.matcher(data); 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!match.find()) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BSSID = match.group(1); 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = Integer.parseInt(match.group(2)); 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = -1; 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWifiStateTracker.notifyStateChange(newState, BSSID, networkId); 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sleep for a period of time. 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param secs the number of seconds to sleep 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void nap(int secs) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Thread.sleep(secs * 1000); 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException ignore) { 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 363