Loading core/jni/android_net_NetUtils.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -141,7 +141,7 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr dns, server, &lease, vendorInfo, domains, mtu); } if (result != 0) { ALOGD("dhcp_do_request failed"); ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new"); } env->ReleaseStringUTFChars(ifname, nameStr); Loading core/jni/android_net_wifi_Wifi.cpp +26 −40 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ namespace android { static jint DBG = false; static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuflen) static int doCommand(char *cmd, char *replybuf, int replybuflen) { size_t reply_len = replybuflen - 1; if (::wifi_command(ifname, cmd, BUF_SIZE, replybuf, &reply_len) != 0) if (::wifi_command(cmd, replybuf, &reply_len) != 0) return -1; else { // Strip off trailing newline Loading @@ -49,7 +49,7 @@ static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuf } } static jint doIntCommand(const char *ifname, const char* fmt, ...) static jint doIntCommand(const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; Loading @@ -60,13 +60,13 @@ static jint doIntCommand(const char *ifname, const char* fmt, ...) return -1; } char reply[BUF_SIZE]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return -1; } return static_cast<jint>(atoi(reply)); } static jboolean doBooleanCommand(const char *ifname, const char* expect, const char* fmt, ...) static jboolean doBooleanCommand(const char* expect, const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; Loading @@ -77,14 +77,14 @@ static jboolean doBooleanCommand(const char *ifname, const char* expect, const c return JNI_FALSE; } char reply[BUF_SIZE]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return JNI_FALSE; } return (strcmp(reply, expect) == 0); } // Send a command to the supplicant, and return the reply as a String static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, ...) { static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; va_start(args, fmt); Loading @@ -94,7 +94,7 @@ static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, return NULL; } char reply[4096]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return NULL; } // TODO: why not just NewStringUTF? Loading Loading @@ -127,23 +127,20 @@ static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0); } static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface) static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject) { ScopedUtfChars ifname(env, jIface); return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0); return (jboolean)(::wifi_connect_to_supplicant() == 0); } static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface) static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject) { ScopedUtfChars ifname(env, jIface); ::wifi_close_supplicant_connection(ifname.c_str()); ::wifi_close_supplicant_connection(); } static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface) static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject) { char buf[EVENT_BUF_SIZE]; ScopedUtfChars ifname(env, jIface); int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf); int nread = ::wifi_wait_for_event(buf, sizeof buf); if (nread > 0) { return env->NewStringUTF(buf); } else { Loading @@ -151,43 +148,36 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIfac } } static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return JNI_FALSE; } if (DBG) ALOGD("doBoolean: %s", command.c_str()); return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str()); return doBooleanCommand("OK", "%s", command.c_str()); } static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return -1; } if (DBG) ALOGD("doInt: %s", command.c_str()); return doIntCommand(ifname.c_str(), "%s", command.c_str()); return doIntCommand("%s", command.c_str()); } static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return NULL; } if (DBG) ALOGD("doString: %s", command.c_str()); return doStringCommand(env, ifname.c_str(), "%s", command.c_str()); return doStringCommand(env, "%s", command.c_str()); } Loading @@ -205,17 +195,13 @@ static JNINativeMethod gWifiMethods[] = { { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, { "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant }, { "connectToSupplicant", "(Ljava/lang/String;)Z", (void *)android_net_wifi_connectToSupplicant }, { "closeSupplicantConnection", "(Ljava/lang/String;)V", { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant }, { "closeSupplicantConnectionNative", "()V", (void *)android_net_wifi_closeSupplicantConnection }, { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_waitForEvent }, { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand }, { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand }, { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent }, { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand }, { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand }, { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand }, }; Loading wifi/java/android/net/wifi/WifiMonitor.java +328 −178 Original line number Diff line number Diff line Loading @@ -32,7 +32,10 @@ import android.util.Log; import com.android.internal.util.Protocol; import com.android.internal.util.StateMachine; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import java.util.regex.Matcher; Loading @@ -44,6 +47,7 @@ import java.util.regex.Matcher; */ public class WifiMonitor { private static final boolean DBG = false; private static final String TAG = "WifiMonitor"; /** Events we receive from the supplicant daemon */ Loading Loading @@ -279,9 +283,6 @@ public class WifiMonitor { /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */ private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED"; private final StateMachine mStateMachine; private final WifiNative mWifiNative; /* Supplicant events reported to a state machine */ private static final int BASE = Protocol.BASE_WIFI_MONITOR; Loading Loading @@ -346,49 +347,222 @@ public class WifiMonitor { */ private static final String WPA_RECV_ERROR_STR = "recv error"; /** * Tracks consecutive receive errors */ private int mRecvErrors = 0; /** * Max errors before we close supplicant connection */ private static final int MAX_RECV_ERRORS = 10; private final String mInterfaceName; private final WifiNative mWifiNative; private final StateMachine mWifiStateMachine; private boolean mMonitoring; public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) { mStateMachine = wifiStateMachine; if (DBG) Log.d(TAG, "Creating WifiMonitor"); mWifiNative = wifiNative; mInterfaceName = wifiNative.mInterfaceName; mWifiStateMachine = wifiStateMachine; mMonitoring = false; WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this); } public void startMonitoring() { new MonitorThread().start(); WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName); } class MonitorThread extends Thread { public MonitorThread() { super("WifiMonitor"); public void stopMonitoring() { WifiMonitorSingleton.getMonitor().stopMonitoring(mInterfaceName); } public void run() { public void stopSupplicant() { WifiMonitorSingleton.getMonitor().stopSupplicant(); } if (connectToSupplicant()) { // Send a message indicating that it is now possible to send commands // to the supplicant mStateMachine.sendMessage(SUP_CONNECTION_EVENT); } else { mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); public void killSupplicant(boolean p2pSupported) { WifiMonitorSingleton.getMonitor().killSupplicant(p2pSupported); } private static class WifiMonitorSingleton { private static Object sSingletonLock = new Object(); private static WifiMonitorSingleton sWifiMonitorSingleton = null; private HashMap<String, WifiMonitor> mIfaceMap = new HashMap<String, WifiMonitor>(); private boolean mConnected = false; private WifiNative mWifiNative; private WifiMonitorSingleton() { } static WifiMonitorSingleton getMonitor() { if (DBG) Log.d(TAG, "WifiMonitorSingleton gotten"); synchronized (sSingletonLock) { if (sWifiMonitorSingleton == null) { if (DBG) Log.d(TAG, "WifiMonitorSingleton created"); sWifiMonitorSingleton = new WifiMonitorSingleton(); } } return sWifiMonitorSingleton; } public synchronized void startMonitoring(String iface) { WifiMonitor m = mIfaceMap.get(iface); if (m == null) { Log.e(TAG, "startMonitor called with unknown iface=" + iface); return; } Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected); if (mConnected) { m.mMonitoring = true; m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT); } else { if (DBG) Log.d(TAG, "connecting to supplicant"); int connectTries = 0; while (true) { if (mWifiNative.connectToSupplicant()) { m.mMonitoring = true; m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT); new MonitorThread(mWifiNative, this).start(); mConnected = true; break; } if (connectTries++ < 5) { try { Thread.sleep(1000); } catch (InterruptedException ignore) { } } else { mIfaceMap.remove(iface); m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); break; } } } } public synchronized void stopMonitoring(String iface) { WifiMonitor m = mIfaceMap.get(iface); if (DBG) Log.d(TAG, "stopMonitoring(" + iface + ") = " + m.mWifiStateMachine); m.mMonitoring = false; m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); } public synchronized void registerInterfaceMonitor(String iface, WifiMonitor m) { if (DBG) Log.d(TAG, "registerInterface(" + iface + "+" + m.mWifiStateMachine + ")"); mIfaceMap.put(iface, m); if (mWifiNative == null) { mWifiNative = m.mWifiNative; } } public synchronized void unregisterInterfaceMonitor(String iface) { // REVIEW: When should we call this? If this isn't called, then WifiMonitor // objects will remain in the mIfaceMap; and won't ever get deleted WifiMonitor m = mIfaceMap.remove(iface); if (DBG) Log.d(TAG, "unregisterInterface(" + iface + "+" + m.mWifiStateMachine + ")"); } public synchronized void stopSupplicant() { mWifiNative.stopSupplicant(); } public synchronized void killSupplicant(boolean p2pSupported) { mWifiNative.killSupplicant(p2pSupported); mConnected = false; Iterator<Map.Entry<String, WifiMonitor>> it = mIfaceMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); WifiMonitor m = e.getValue(); m.mMonitoring = false; } } private synchronized WifiMonitor getMonitor(String iface) { return mIfaceMap.get(iface); } } private static class MonitorThread extends Thread { private final WifiNative mWifiNative; private final WifiMonitorSingleton mWifiMonitorSingleton; private int mRecvErrors = 0; private StateMachine mStateMachine = null; public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) { super("WifiMonitor"); mWifiNative = wifiNative; mWifiMonitorSingleton = wifiMonitorSingleton; } public void run() { //noinspection InfiniteLoopStatement for (;;) { String eventStr = mWifiNative.waitForEvent(); // Skip logging the common but mostly uninteresting scan-results event if (false && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { Log.d(TAG, "Event [" + eventStr + "]"); } WifiMonitor m = null; mStateMachine = null; if (eventStr.startsWith("IFNAME=")) { int space = eventStr.indexOf(' '); if (space != -1) { String iface = eventStr.substring(7,space); m = mWifiMonitorSingleton.getMonitor(iface); if (m != null) { if (m.mMonitoring) { mStateMachine = m.mWifiStateMachine; eventStr = eventStr.substring(space + 1); } else { if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface + ") is stopped"); continue; } } else { eventStr = eventStr.substring(space + 1); } } } if (mStateMachine != null) { if (dispatchEvent(eventStr)) { break; } } else { if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id"); boolean done = false; Iterator<Map.Entry<String, WifiMonitor>> it = mWifiMonitorSingleton.mIfaceMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); m = e.getValue(); mStateMachine = m.mWifiStateMachine; if (dispatchEvent(eventStr)) { done = true; } } if (done) { // After this thread terminates, we'll no longer // be connected to the supplicant if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events"); mWifiMonitorSingleton.mConnected = false; break; } } } } /* @return true if the event was supplicant disconnection */ private boolean dispatchEvent(String eventStr) { if (!eventStr.startsWith(EVENT_PREFIX_STR)) { if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) && 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) { Loading @@ -406,7 +580,10 @@ public class WifiMonitor { } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) { handleHostApEvents(eventStr); } continue; else { if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr); } return false; } String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR); Loading @@ -414,8 +591,8 @@ public class WifiMonitor { if (nameEnd != -1) eventName = eventName.substring(0, nameEnd); if (eventName.length() == 0) { if (false) Log.i(TAG, "Received wpa_supplicant event with empty event name"); continue; if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name"); return false; } /* * Map event name into event enum Loading Loading @@ -468,17 +645,17 @@ public class WifiMonitor { */ if (eventData.startsWith(WPA_RECV_ERROR_STR)) { if (++mRecvErrors > MAX_RECV_ERRORS) { if (false) { if (DBG) { Log.d(TAG, "too many recv errors, closing connection"); } } else { continue; return false; } } // notify and exit mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); break; return true; } else if (event == EAP_FAILURE) { if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) { mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); Loading @@ -489,22 +666,6 @@ public class WifiMonitor { handleEvent(event, eventData); } mRecvErrors = 0; } } private boolean connectToSupplicant() { int connectTries = 0; while (true) { if (mWifiNative.connectToSupplicant()) { return true; } if (connectTries++ < 5) { nap(1); } else { break; } } return false; } Loading Loading @@ -723,7 +884,6 @@ public class WifiMonitor { } notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState); } } private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) { String BSSID = null; Loading @@ -731,7 +891,7 @@ public class WifiMonitor { if (newState == NetworkInfo.DetailedState.CONNECTED) { Matcher match = mConnectedEventPattern.matcher(data); if (!match.find()) { if (false) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); if (DBG) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); } else { BSSID = match.group(1); try { Loading @@ -740,9 +900,9 @@ public class WifiMonitor { networkId = -1; } } } notifyNetworkStateChange(newState, BSSID, networkId); } } /** * Send the state machine a notification that the state of Wifi connectivity Loading Loading @@ -779,15 +939,5 @@ public class WifiMonitor { mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT, new StateChangeResult(networkId, wifiSsid, BSSID, newState))); } /** * Sleep for a period of time. * @param secs the number of seconds to sleep */ private static void nap(int secs) { try { Thread.sleep(secs * 1000); } catch (InterruptedException ignore) { } } } wifi/java/android/net/wifi/WifiNative.java +28 −25 File changed.Preview size limit exceeded, changes collapsed. Show changes wifi/java/android/net/wifi/WifiStateMachine.java +6 −8 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.util.Log; import android.util.LruCache; import android.text.TextUtils; Loading Loading @@ -543,7 +544,6 @@ public class WifiStateMachine extends StateMachine { public WifiStateMachine(Context context, String wlanInterface) { super("WifiStateMachine"); mContext = context; mInterfaceName = wlanInterface; Loading Loading @@ -888,6 +888,7 @@ public class WifiStateMachine extends StateMachine { * TODO: doc */ public void setOperationalMode(int mode) { if (DBG) log("setting operational mode to " + String.valueOf(mode)); sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); } Loading Loading @@ -1756,8 +1757,7 @@ public class WifiStateMachine extends StateMachine { /* Socket connection can be lost when we do a graceful shutdown * or when the driver is hung. Ensure supplicant is stopped here. */ mWifiNative.killSupplicant(mP2pSupported); mWifiNative.closeSupplicantConnection(); mWifiMonitor.killSupplicant(mP2pSupported); sendSupplicantConnectionChangedBroadcast(false); setWifiState(WIFI_STATE_DISABLED); } Loading Loading @@ -2139,7 +2139,7 @@ public class WifiStateMachine extends StateMachine { * Avoids issues with drivers that do not handle interface down * on a running supplicant properly. */ mWifiNative.killSupplicant(mP2pSupported); mWifiMonitor.killSupplicant(mP2pSupported); if(mWifiNative.startSupplicant(mP2pSupported)) { setWifiState(WIFI_STATE_ENABLING); if (DBG) log("Supplicant start successful"); Loading Loading @@ -2222,7 +2222,7 @@ public class WifiStateMachine extends StateMachine { case WifiMonitor.SUP_DISCONNECTION_EVENT: if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { loge("Failed to setup control channel, restart supplicant"); mWifiNative.killSupplicant(mP2pSupported); mWifiMonitor.killSupplicant(mP2pSupported); transitionTo(mInitialState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); } else { Loading Loading @@ -2329,9 +2329,7 @@ public class WifiStateMachine extends StateMachine { } if (DBG) log("stopping supplicant"); if (!mWifiNative.stopSupplicant()) { loge("Failed to stop supplicant"); } mWifiMonitor.stopSupplicant(); /* Send ourselves a delayed message to indicate failure after a wait time */ sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, Loading Loading
core/jni/android_net_NetUtils.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -141,7 +141,7 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr dns, server, &lease, vendorInfo, domains, mtu); } if (result != 0) { ALOGD("dhcp_do_request failed"); ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new"); } env->ReleaseStringUTFChars(ifname, nameStr); Loading
core/jni/android_net_wifi_Wifi.cpp +26 −40 Original line number Diff line number Diff line Loading @@ -33,11 +33,11 @@ namespace android { static jint DBG = false; static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuflen) static int doCommand(char *cmd, char *replybuf, int replybuflen) { size_t reply_len = replybuflen - 1; if (::wifi_command(ifname, cmd, BUF_SIZE, replybuf, &reply_len) != 0) if (::wifi_command(cmd, replybuf, &reply_len) != 0) return -1; else { // Strip off trailing newline Loading @@ -49,7 +49,7 @@ static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuf } } static jint doIntCommand(const char *ifname, const char* fmt, ...) static jint doIntCommand(const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; Loading @@ -60,13 +60,13 @@ static jint doIntCommand(const char *ifname, const char* fmt, ...) return -1; } char reply[BUF_SIZE]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return -1; } return static_cast<jint>(atoi(reply)); } static jboolean doBooleanCommand(const char *ifname, const char* expect, const char* fmt, ...) static jboolean doBooleanCommand(const char* expect, const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; Loading @@ -77,14 +77,14 @@ static jboolean doBooleanCommand(const char *ifname, const char* expect, const c return JNI_FALSE; } char reply[BUF_SIZE]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return JNI_FALSE; } return (strcmp(reply, expect) == 0); } // Send a command to the supplicant, and return the reply as a String static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, ...) { static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) { char buf[BUF_SIZE]; va_list args; va_start(args, fmt); Loading @@ -94,7 +94,7 @@ static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, return NULL; } char reply[4096]; if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) { if (doCommand(buf, reply, sizeof(reply)) != 0) { return NULL; } // TODO: why not just NewStringUTF? Loading Loading @@ -127,23 +127,20 @@ static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0); } static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface) static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject) { ScopedUtfChars ifname(env, jIface); return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0); return (jboolean)(::wifi_connect_to_supplicant() == 0); } static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface) static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject) { ScopedUtfChars ifname(env, jIface); ::wifi_close_supplicant_connection(ifname.c_str()); ::wifi_close_supplicant_connection(); } static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface) static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject) { char buf[EVENT_BUF_SIZE]; ScopedUtfChars ifname(env, jIface); int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf); int nread = ::wifi_wait_for_event(buf, sizeof buf); if (nread > 0) { return env->NewStringUTF(buf); } else { Loading @@ -151,43 +148,36 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIfac } } static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return JNI_FALSE; } if (DBG) ALOGD("doBoolean: %s", command.c_str()); return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str()); return doBooleanCommand("OK", "%s", command.c_str()); } static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return -1; } if (DBG) ALOGD("doInt: %s", command.c_str()); return doIntCommand(ifname.c_str(), "%s", command.c_str()); return doIntCommand("%s", command.c_str()); } static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface, jstring jCommand) static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jCommand) { ScopedUtfChars ifname(env, jIface); ScopedUtfChars command(env, jCommand); if (command.c_str() == NULL) { return NULL; } if (DBG) ALOGD("doString: %s", command.c_str()); return doStringCommand(env, ifname.c_str(), "%s", command.c_str()); return doStringCommand(env, "%s", command.c_str()); } Loading @@ -205,17 +195,13 @@ static JNINativeMethod gWifiMethods[] = { { "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver }, { "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant }, { "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant }, { "connectToSupplicant", "(Ljava/lang/String;)Z", (void *)android_net_wifi_connectToSupplicant }, { "closeSupplicantConnection", "(Ljava/lang/String;)V", { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant }, { "closeSupplicantConnectionNative", "()V", (void *)android_net_wifi_closeSupplicantConnection }, { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_waitForEvent }, { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z", (void*) android_net_wifi_doBooleanCommand }, { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I", (void*) android_net_wifi_doIntCommand }, { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent }, { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand }, { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand }, { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;", (void*) android_net_wifi_doStringCommand }, }; Loading
wifi/java/android/net/wifi/WifiMonitor.java +328 −178 Original line number Diff line number Diff line Loading @@ -32,7 +32,10 @@ import android.util.Log; import com.android.internal.util.Protocol; import com.android.internal.util.StateMachine; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import java.util.regex.Matcher; Loading @@ -44,6 +47,7 @@ import java.util.regex.Matcher; */ public class WifiMonitor { private static final boolean DBG = false; private static final String TAG = "WifiMonitor"; /** Events we receive from the supplicant daemon */ Loading Loading @@ -279,9 +283,6 @@ public class WifiMonitor { /* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */ private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED"; private final StateMachine mStateMachine; private final WifiNative mWifiNative; /* Supplicant events reported to a state machine */ private static final int BASE = Protocol.BASE_WIFI_MONITOR; Loading Loading @@ -346,49 +347,222 @@ public class WifiMonitor { */ private static final String WPA_RECV_ERROR_STR = "recv error"; /** * Tracks consecutive receive errors */ private int mRecvErrors = 0; /** * Max errors before we close supplicant connection */ private static final int MAX_RECV_ERRORS = 10; private final String mInterfaceName; private final WifiNative mWifiNative; private final StateMachine mWifiStateMachine; private boolean mMonitoring; public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) { mStateMachine = wifiStateMachine; if (DBG) Log.d(TAG, "Creating WifiMonitor"); mWifiNative = wifiNative; mInterfaceName = wifiNative.mInterfaceName; mWifiStateMachine = wifiStateMachine; mMonitoring = false; WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this); } public void startMonitoring() { new MonitorThread().start(); WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName); } class MonitorThread extends Thread { public MonitorThread() { super("WifiMonitor"); public void stopMonitoring() { WifiMonitorSingleton.getMonitor().stopMonitoring(mInterfaceName); } public void run() { public void stopSupplicant() { WifiMonitorSingleton.getMonitor().stopSupplicant(); } if (connectToSupplicant()) { // Send a message indicating that it is now possible to send commands // to the supplicant mStateMachine.sendMessage(SUP_CONNECTION_EVENT); } else { mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); public void killSupplicant(boolean p2pSupported) { WifiMonitorSingleton.getMonitor().killSupplicant(p2pSupported); } private static class WifiMonitorSingleton { private static Object sSingletonLock = new Object(); private static WifiMonitorSingleton sWifiMonitorSingleton = null; private HashMap<String, WifiMonitor> mIfaceMap = new HashMap<String, WifiMonitor>(); private boolean mConnected = false; private WifiNative mWifiNative; private WifiMonitorSingleton() { } static WifiMonitorSingleton getMonitor() { if (DBG) Log.d(TAG, "WifiMonitorSingleton gotten"); synchronized (sSingletonLock) { if (sWifiMonitorSingleton == null) { if (DBG) Log.d(TAG, "WifiMonitorSingleton created"); sWifiMonitorSingleton = new WifiMonitorSingleton(); } } return sWifiMonitorSingleton; } public synchronized void startMonitoring(String iface) { WifiMonitor m = mIfaceMap.get(iface); if (m == null) { Log.e(TAG, "startMonitor called with unknown iface=" + iface); return; } Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected); if (mConnected) { m.mMonitoring = true; m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT); } else { if (DBG) Log.d(TAG, "connecting to supplicant"); int connectTries = 0; while (true) { if (mWifiNative.connectToSupplicant()) { m.mMonitoring = true; m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT); new MonitorThread(mWifiNative, this).start(); mConnected = true; break; } if (connectTries++ < 5) { try { Thread.sleep(1000); } catch (InterruptedException ignore) { } } else { mIfaceMap.remove(iface); m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); break; } } } } public synchronized void stopMonitoring(String iface) { WifiMonitor m = mIfaceMap.get(iface); if (DBG) Log.d(TAG, "stopMonitoring(" + iface + ") = " + m.mWifiStateMachine); m.mMonitoring = false; m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); } public synchronized void registerInterfaceMonitor(String iface, WifiMonitor m) { if (DBG) Log.d(TAG, "registerInterface(" + iface + "+" + m.mWifiStateMachine + ")"); mIfaceMap.put(iface, m); if (mWifiNative == null) { mWifiNative = m.mWifiNative; } } public synchronized void unregisterInterfaceMonitor(String iface) { // REVIEW: When should we call this? If this isn't called, then WifiMonitor // objects will remain in the mIfaceMap; and won't ever get deleted WifiMonitor m = mIfaceMap.remove(iface); if (DBG) Log.d(TAG, "unregisterInterface(" + iface + "+" + m.mWifiStateMachine + ")"); } public synchronized void stopSupplicant() { mWifiNative.stopSupplicant(); } public synchronized void killSupplicant(boolean p2pSupported) { mWifiNative.killSupplicant(p2pSupported); mConnected = false; Iterator<Map.Entry<String, WifiMonitor>> it = mIfaceMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); WifiMonitor m = e.getValue(); m.mMonitoring = false; } } private synchronized WifiMonitor getMonitor(String iface) { return mIfaceMap.get(iface); } } private static class MonitorThread extends Thread { private final WifiNative mWifiNative; private final WifiMonitorSingleton mWifiMonitorSingleton; private int mRecvErrors = 0; private StateMachine mStateMachine = null; public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) { super("WifiMonitor"); mWifiNative = wifiNative; mWifiMonitorSingleton = wifiMonitorSingleton; } public void run() { //noinspection InfiniteLoopStatement for (;;) { String eventStr = mWifiNative.waitForEvent(); // Skip logging the common but mostly uninteresting scan-results event if (false && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) { Log.d(TAG, "Event [" + eventStr + "]"); } WifiMonitor m = null; mStateMachine = null; if (eventStr.startsWith("IFNAME=")) { int space = eventStr.indexOf(' '); if (space != -1) { String iface = eventStr.substring(7,space); m = mWifiMonitorSingleton.getMonitor(iface); if (m != null) { if (m.mMonitoring) { mStateMachine = m.mWifiStateMachine; eventStr = eventStr.substring(space + 1); } else { if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface + ") is stopped"); continue; } } else { eventStr = eventStr.substring(space + 1); } } } if (mStateMachine != null) { if (dispatchEvent(eventStr)) { break; } } else { if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id"); boolean done = false; Iterator<Map.Entry<String, WifiMonitor>> it = mWifiMonitorSingleton.mIfaceMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry<String, WifiMonitor> e = it.next(); m = e.getValue(); mStateMachine = m.mWifiStateMachine; if (dispatchEvent(eventStr)) { done = true; } } if (done) { // After this thread terminates, we'll no longer // be connected to the supplicant if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events"); mWifiMonitorSingleton.mConnected = false; break; } } } } /* @return true if the event was supplicant disconnection */ private boolean dispatchEvent(String eventStr) { if (!eventStr.startsWith(EVENT_PREFIX_STR)) { if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) && 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) { Loading @@ -406,7 +580,10 @@ public class WifiMonitor { } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) { handleHostApEvents(eventStr); } continue; else { if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr); } return false; } String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR); Loading @@ -414,8 +591,8 @@ public class WifiMonitor { if (nameEnd != -1) eventName = eventName.substring(0, nameEnd); if (eventName.length() == 0) { if (false) Log.i(TAG, "Received wpa_supplicant event with empty event name"); continue; if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name"); return false; } /* * Map event name into event enum Loading Loading @@ -468,17 +645,17 @@ public class WifiMonitor { */ if (eventData.startsWith(WPA_RECV_ERROR_STR)) { if (++mRecvErrors > MAX_RECV_ERRORS) { if (false) { if (DBG) { Log.d(TAG, "too many recv errors, closing connection"); } } else { continue; return false; } } // notify and exit mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT); break; return true; } else if (event == EAP_FAILURE) { if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) { mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT); Loading @@ -489,22 +666,6 @@ public class WifiMonitor { handleEvent(event, eventData); } mRecvErrors = 0; } } private boolean connectToSupplicant() { int connectTries = 0; while (true) { if (mWifiNative.connectToSupplicant()) { return true; } if (connectTries++ < 5) { nap(1); } else { break; } } return false; } Loading Loading @@ -723,7 +884,6 @@ public class WifiMonitor { } notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState); } } private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) { String BSSID = null; Loading @@ -731,7 +891,7 @@ public class WifiMonitor { if (newState == NetworkInfo.DetailedState.CONNECTED) { Matcher match = mConnectedEventPattern.matcher(data); if (!match.find()) { if (false) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); if (DBG) Log.d(TAG, "Could not find BSSID in CONNECTED event string"); } else { BSSID = match.group(1); try { Loading @@ -740,9 +900,9 @@ public class WifiMonitor { networkId = -1; } } } notifyNetworkStateChange(newState, BSSID, networkId); } } /** * Send the state machine a notification that the state of Wifi connectivity Loading Loading @@ -779,15 +939,5 @@ public class WifiMonitor { mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT, new StateChangeResult(networkId, wifiSsid, BSSID, newState))); } /** * Sleep for a period of time. * @param secs the number of seconds to sleep */ private static void nap(int secs) { try { Thread.sleep(secs * 1000); } catch (InterruptedException ignore) { } } }
wifi/java/android/net/wifi/WifiNative.java +28 −25 File changed.Preview size limit exceeded, changes collapsed. Show changes
wifi/java/android/net/wifi/WifiStateMachine.java +6 −8 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.os.SystemProperties; import android.os.UserHandle; import android.os.WorkSource; import android.provider.Settings; import android.util.Log; import android.util.LruCache; import android.text.TextUtils; Loading Loading @@ -543,7 +544,6 @@ public class WifiStateMachine extends StateMachine { public WifiStateMachine(Context context, String wlanInterface) { super("WifiStateMachine"); mContext = context; mInterfaceName = wlanInterface; Loading Loading @@ -888,6 +888,7 @@ public class WifiStateMachine extends StateMachine { * TODO: doc */ public void setOperationalMode(int mode) { if (DBG) log("setting operational mode to " + String.valueOf(mode)); sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0); } Loading Loading @@ -1756,8 +1757,7 @@ public class WifiStateMachine extends StateMachine { /* Socket connection can be lost when we do a graceful shutdown * or when the driver is hung. Ensure supplicant is stopped here. */ mWifiNative.killSupplicant(mP2pSupported); mWifiNative.closeSupplicantConnection(); mWifiMonitor.killSupplicant(mP2pSupported); sendSupplicantConnectionChangedBroadcast(false); setWifiState(WIFI_STATE_DISABLED); } Loading Loading @@ -2139,7 +2139,7 @@ public class WifiStateMachine extends StateMachine { * Avoids issues with drivers that do not handle interface down * on a running supplicant properly. */ mWifiNative.killSupplicant(mP2pSupported); mWifiMonitor.killSupplicant(mP2pSupported); if(mWifiNative.startSupplicant(mP2pSupported)) { setWifiState(WIFI_STATE_ENABLING); if (DBG) log("Supplicant start successful"); Loading Loading @@ -2222,7 +2222,7 @@ public class WifiStateMachine extends StateMachine { case WifiMonitor.SUP_DISCONNECTION_EVENT: if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) { loge("Failed to setup control channel, restart supplicant"); mWifiNative.killSupplicant(mP2pSupported); mWifiMonitor.killSupplicant(mP2pSupported); transitionTo(mInitialState); sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS); } else { Loading Loading @@ -2329,9 +2329,7 @@ public class WifiStateMachine extends StateMachine { } if (DBG) log("stopping supplicant"); if (!mWifiNative.stopSupplicant()) { loge("Failed to stop supplicant"); } mWifiMonitor.stopSupplicant(); /* Send ourselves a delayed message to indicate failure after a wait time */ sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED, Loading