WifiMonitor.java revision b98d878f43748a64c68ffe05ce64c5b7c72fe922
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 Project 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Pattern; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.regex.Matcher; 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Listens for events from the wpa_supplicant server, and passes them on 280d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff * to the {@link WifiStateMachine} for handling. Runs in its own thread. 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @hide 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WifiMonitor { 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String TAG = "WifiMonitor"; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Events we receive from the supplicant daemon */ 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int CONNECTED = 1; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DISCONNECTED = 2; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int STATE_CHANGE = 3; 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int SCAN_RESULTS = 4; 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int LINK_SPEED = 5; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int TERMINATING = 6; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int DRIVER_STATE = 7; 45b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff private static final int EAP_FAILURE = 8; 46b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff private static final int UNKNOWN = 9; 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 57fcb659b66756ac02bd1491ae1365b27e8509a890Irfan Sheriff /* WPS events */ 58fcb659b66756ac02bd1491ae1365b27e8509a890Irfan Sheriff private static final String wpsOverlapEvent = "WPS-OVERLAP-DETECTED"; 59fcb659b66756ac02bd1491ae1365b27e8509a890Irfan Sheriff 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Names of events from wpa_supplicant (minus the prefix). In the 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * format descriptions, * "<code>x</code>" 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * designates a dynamic value that needs to be parsed out from the event 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * string 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-CONNECTED - Connection to xx:xx:xx:xx:xx:xx completed 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>xx:xx:xx:xx:xx:xx</code> is the BSSID of the associated access point 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String connectedEvent = "CONNECTED"; 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-DISCONNECTED - Disconnect event - remove keys 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String disconnectedEvent = "DISCONNECTED"; 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-STATE-CHANGE x 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>x</code> is the numerical value of the new state. 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String stateChangeEvent = "STATE-CHANGE"; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-SCAN-RESULTS ready 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String scanResultsEvent = "SCAN-RESULTS"; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-LINK-SPEED x Mb/s 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@code x} is the link speed in Mb/sec. 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String linkSpeedEvent = "LINK-SPEED"; 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-TERMINATING - signal x 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>x</code> is the signal that caused termination. 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String terminatingEvent = "TERMINATING"; 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <pre> 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-DRIVER-STATE state 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * </pre> 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <code>state</code> is either STARTED or STOPPED 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final String driverStateEvent = "DRIVER-STATE"; 114b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff /** 115b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff * <pre> 116b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff * CTRL-EVENT-EAP-FAILURE EAP authentication failed 117b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff * </pre> 118b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff */ 119b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff private static final String eapFailureEvent = "EAP-FAILURE"; 120b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff 121b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff /** 122b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff * This indicates an authentication failure on EAP FAILURE event 123b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff */ 124b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff private static final String eapAuthFailure = "EAP authentication failed"; 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Regex pattern for extracting an Ethernet-style MAC address from a string. 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Matches a strings like the following:<pre> 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * CTRL-EVENT-CONNECTED - Connection to 00:1e:58:ec:d5:6d completed (reauth) [id=1 id_str=]</pre> 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static Pattern mConnectedEventPattern = 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Pattern.compile("((?:[0-9a-f]{2}:){5}[0-9a-f]{2}) .* \\[id=([0-9]+) "); 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1340d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff private final WifiStateMachine mWifiStateMachine; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13605d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 13705d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * This indicates the supplicant connection for the monitor is closed 13805d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 13905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff private static final String monitorSocketClosed = "connection closed"; 14005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 14105d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 14205d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * This indicates a read error on the monitor socket conenction 14305d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 14405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff private static final String wpaRecvError = "recv error"; 14505d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 14605d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 14705d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * Tracks consecutive receive errors 14805d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 14905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff private int mRecvErrors = 0; 15005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 15105d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 15205d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * Max errors before we close supplicant connection 15305d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 15405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff private static final int MAX_RECV_ERRORS = 10; 15505d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 1560d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff public WifiMonitor(WifiStateMachine wifiStateMachine) { 1570d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine = wifiStateMachine; 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void startMonitoring() { 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project new MonitorThread().start(); 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project class MonitorThread extends Thread { 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public MonitorThread() { 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super("WifiMonitor"); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 168a2a1b911a31dd94ee75e94845f762b91f1db1368Irfan Sheriff 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (connectToSupplicant()) { 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Send a message indicating that it is now possible to send commands 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // to the supplicant 1740d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifySupplicantConnection(); 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 1760d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifySupplicantLost(); 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project //noinspection InfiniteLoopStatement 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (;;) { 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventStr = WifiNative.waitForEvent(); 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Skip logging the common but mostly uninteresting scan-results event 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD && eventStr.indexOf(scanResultsEvent) == -1) { 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.v(TAG, "Event [" + eventStr + "]"); 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!eventStr.startsWith(eventPrefix)) { 18905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (eventStr.startsWith(wpaEventPrefix) && 19005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 0 < eventStr.indexOf(passwordKeyMayBeIncorrectEvent)) { 191b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff mWifiStateMachine.notifyAuthenticationFailure(); 192fcb659b66756ac02bd1491ae1365b27e8509a890Irfan Sheriff } else if (eventStr.startsWith(wpsOverlapEvent)) { 193fcb659b66756ac02bd1491ae1365b27e8509a890Irfan Sheriff mWifiStateMachine.notifyWpsOverlap(); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventName = eventStr.substring(eventPrefixLen); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int nameEnd = eventName.indexOf(' '); 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameEnd != -1) 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventName = eventName.substring(0, nameEnd); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventName.length() == 0) { 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD) Log.i(TAG, "Received wpa_supplicant event with empty event name"); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Map event name into event enum 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int event; 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (eventName.equals(connectedEvent)) 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = CONNECTED; 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(disconnectedEvent)) 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = DISCONNECTED; 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(stateChangeEvent)) 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = STATE_CHANGE; 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(scanResultsEvent)) 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = SCAN_RESULTS; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(linkSpeedEvent)) 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = LINK_SPEED; 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else if (eventName.equals(terminatingEvent)) 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = TERMINATING; 222b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff else if (eventName.equals(driverStateEvent)) 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = DRIVER_STATE; 224b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff else if (eventName.equals(eapFailureEvent)) 225b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff event = EAP_FAILURE; 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project else 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project event = UNKNOWN; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String eventData = eventStr; 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == DRIVER_STATE || event == LINK_SPEED) 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventData.split(" ")[1]; 232b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff else if (event == STATE_CHANGE || event == EAP_FAILURE) { 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ind = eventStr.indexOf(" "); 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ind != -1) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventStr.substring(ind + 1); 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int ind = eventStr.indexOf(" - "); 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (ind != -1) { 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project eventData = eventStr.substring(ind + 3); 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (event == STATE_CHANGE) { 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleSupplicantStateChange(eventData); 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == DRIVER_STATE) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleDriverEvent(eventData); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (event == TERMINATING) { 24905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 25005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * If monitor socket is closed, we have already 25105d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * stopped the supplicant, simply exit the monitor thread 25205d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 25305d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (eventData.startsWith(monitorSocketClosed)) { 25405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (Config.LOGD) { 25505d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff Log.d(TAG, "Monitor socket is closed, exiting thread"); 25605d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } 25705d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff break; 25805d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } 25905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 26005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff /** 26105d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * Close the supplicant connection if we see 26205d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff * too many recv errors 26305d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff */ 26405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (eventData.startsWith(wpaRecvError)) { 26505d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (++mRecvErrors > MAX_RECV_ERRORS) { 26605d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff if (Config.LOGD) { 26705d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff Log.d(TAG, "too many recv errors, closing connection"); 26805d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } 26905d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } else { 27005d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff continue; 27105d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } 27205d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff } 27305d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff 27405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff // notify and exit 2750d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifySupplicantLost(); 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 277b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff } else if (event == EAP_FAILURE) { 278b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff if (eventData.startsWith(eapAuthFailure)) { 279b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff mWifiStateMachine.notifyAuthenticationFailure(); 280b98d878f43748a64c68ffe05ce64c5b7c72fe922Irfan Sheriff } 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleEvent(event, eventData); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28405d72117f9b449914979b008c17edd6c5645565bIrfan Sheriff mRecvErrors = 0; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean connectToSupplicant() { 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int connectTries = 0; 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (true) { 292a2a1b911a31dd94ee75e94845f762b91f1db1368Irfan Sheriff if (WifiNative.connectToSupplicant()) { 293a8fbe1fb74d3bd40b73c90c85ac25e5176475ca5Irfan Sheriff return true; 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 295c949b9c3ffe5ed9e2112a15224a86c55651fedfdIrfan Sheriff if (connectTries++ < 5) { 296c949b9c3ffe5ed9e2112a15224a86c55651fedfdIrfan Sheriff nap(1); 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleDriverEvent(String state) { 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state == null) { 3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.equals("STOPPED")) { 3090d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifyDriverStopped(); 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (state.equals("STARTED")) { 3110d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifyDriverStarted(); 312f75aa36fc86989ca3bae2f46207e6b897a32d7aeRobert Greenwalt } else if (state.equals("HANGED")) { 3130d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifyDriverHung(); 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle all supplicant events except STATE-CHANGE 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param event the event type 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param remainder the rest of the string following the 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * event name and " — " 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void handleEvent(int event, String remainder) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project switch (event) { 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case DISCONNECTED: 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case CONNECTED: 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder); 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case SCAN_RESULTS: 3340d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifyScanResultsAvailable(); 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project case UNKNOWN: 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Handle the supplicant STATE-CHANGE event 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param dataString New supplicant state string in the format: 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * id=network-id state=new-state 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleSupplicantStateChange(String dataString) { 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] dataTokens = dataString.split(" "); 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3500049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff String BSSID = null; 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int networkId = -1; 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int newState = -1; 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (String token : dataTokens) { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String[] nameValue = token.split("="); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameValue.length != 2) { 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3590049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff if (nameValue[0].equals("BSSID")) { 3600049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff BSSID = nameValue[1]; 3610049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff continue; 3620049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff } 3630049a1bf3f8bae3a10cfeff38aefce215bf1298bIrfan Sheriff 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int value; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project value = Integer.parseInt(nameValue[1]); 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "STATE-CHANGE non-integer parameter: " + token); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (nameValue[0].equals("id")) { 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = value; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (nameValue[0].equals("state")) { 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newState = value; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newState == -1) return; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SupplicantState newSupplicantState = SupplicantState.INVALID; 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (SupplicantState state : SupplicantState.values()) { 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (state.ordinal() == newState) { 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project newSupplicantState = state; 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newSupplicantState == SupplicantState.INVALID) { 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Log.w(TAG, "Invalid supplicant state: " + newState); 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3910d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifySupplicantStateChange(networkId, BSSID, newSupplicantState); 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) { 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String BSSID = null; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int networkId = -1; 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (newState == NetworkInfo.DetailedState.CONNECTED) { 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Matcher match = mConnectedEventPattern.matcher(data); 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!match.find()) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (Config.LOGD) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BSSID = match.group(1); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = Integer.parseInt(match.group(2)); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (NumberFormatException e) { 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project networkId = -1; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4110d25534fed91f636def5776ddc4605005bd7471cIrfan Sheriff mWifiStateMachine.notifyNetworkStateChange(newState, BSSID, networkId); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sleep for a period of time. 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param secs the number of seconds to sleep 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static void nap(int secs) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Thread.sleep(secs * 1000); 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } catch (InterruptedException ignore) { 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 425