/** * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} * @param enable {@code true} to enable, {@code false} to disable. * @return {@code true} if the enable/disable operation was * started or is already in the queue. */ public synchronized boolean setWifiEnabled(boolean enable) { enforceChangePermission(); Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); if (DBG) { Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n"); } if (enable) { reportStartWorkSource(); } mWifiStateMachine.setWifiEnabled(enable); /* * Caller might not have WRITE_SECURE_SETTINGS, * only CHANGE_WIFI_STATE is enforced */ long ident = Binder.clearCallingIdentity(); try { handleWifiToggled(enable); } finally { Binder.restoreCallingIdentity(ident); } if (enable) { if (!mIsReceiverRegistered) { registerForBroadcasts(); mIsReceiverRegistered = true; } } else if (mIsReceiverRegistered) { mContext.unregisterReceiver(mReceiver); mIsReceiverRegistered = false; } return true; }
public void setWifiEnabled(boolean enable) { mLastEnableUid.set(Binder.getCallingUid()); if (enable) { /* Argument is the state that is entered prior to load */ sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0)); sendMessage(CMD_START_SUPPLICANT); } else { sendMessage(CMD_STOP_SUPPLICANT); /* Argument is the state that is entered upon success */ sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0)); } }
当前stateMachine应为DriverUnloadedState,转到mDriverLoadingState状态
class DriverUnloadedState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch (message.what) { case CMD_LOAD_DRIVER: transitionTo(mDriverLoadingState); break; default: return NOT_HANDLED; } return HANDLED; } }
class DriverLoadingState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); final Message message = new Message(); message.copyFrom(getCurrentMessage()); /* TODO: add a timeout to fail when driver load is hung. * Similarly for driver unload. */ new Thread(new Runnable() { public void run() { mWakeLock.acquire(); //enabling state switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_ENABLING); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_ENABLING); break; } if(mWifiNative.loadDriver()) { if (DBG) log("Driver load successful"); sendMessage(CMD_LOAD_DRIVER_SUCCESS); } else { loge("Failed to load driver!"); switch(message.arg1) { case WIFI_STATE_ENABLING: setWifiState(WIFI_STATE_UNKNOWN); break; case WIFI_AP_STATE_ENABLING: setWifiApState(WIFI_AP_STATE_FAILED); break; } sendMessage(CMD_LOAD_DRIVER_FAILURE); } mWakeLock.release(); } }).start(); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch (message.what) { case CMD_LOAD_DRIVER_SUCCESS: transitionTo(mDriverLoadedState); break; case CMD_LOAD_DRIVER_FAILURE: transitionTo(mDriverFailedState); break; case CMD_LOAD_DRIVER: case CMD_UNLOAD_DRIVER: case CMD_START_SUPPLICANT: case CMD_STOP_SUPPLICANT: case CMD_START_AP: case CMD_STOP_AP: case CMD_START_DRIVER: case CMD_STOP_DRIVER: case CMD_SET_SCAN_MODE: case CMD_SET_SCAN_TYPE: case CMD_SET_COUNTRY_CODE: case CMD_SET_FREQUENCY_BAND: case CMD_START_PACKET_FILTERING: case CMD_STOP_PACKET_FILTERING: deferMessage(message); break; default: return NOT_HANDLED; } return HANDLED; } }
在DriverLoadingState 中产生第一个native函数:mWifiNative.loadDriver
通过JNI最终调用到wifi.c,
int wifi_load_driver() { do_wifi_workaround();// leon 1 #ifdef WIFI_DRIVER_MODULE_PATH char driver_status[PROPERTY_VALUE_MAX]; int count = 100; /* wait at most 20 seconds for completion */ if (is_wifi_driver_loaded()) {
return 0; } if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)// leon 2 return -1; #ifdef BOARD_WIFI_ATHEROS if (insmod(DRIVER_MODULE_PATH_2, DRIVER_MODULE_ARG_2) < 0) return -1; if (insmod(DRIVER_MODULE_PATH_3, DRIVER_MODULE_ARG_3) < 0) return -1; property_set("ctl.start", ADD_P2P); #endif if (strcmp(FIRMWARE_LOADER,"") == 0) { if (strcmp(WIFI_DRIVER_MODULE_NAME, "8192cu") == 0) usleep(1600000); else usleep(WIFI_DRIVER_LOADER_DELAY); property_set(DRIVER_PROP_NAME, "ok"); } else { property_set("ctl.start", FIRMWARE_LOADER); } sched_yield(); while (count-- > 0) { if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) { if (strcmp(driver_status, "ok") == 0) return 0; else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) { wifi_unload_driver(); return -1; } } usleep(200000); } property_set(DRIVER_PROP_NAME, "timeout"); wifi_unload_driver(); return -1; #else property_set(DRIVER_PROP_NAME, "ok"); return 0; #endif }
#define WIFI_FIX_SVC "wififix" int do_wifi_workaround() { property_set("ctl.start", WIFI_FIX_SVC); return 0; }
driver 加载成功后,将状态转移到transitionTo(mDriverLoadedState);
接下来执行sendMessage(CMD_START_SUPPLICANT);
class DriverLoadedState extends State { @Override public void enter() { if (DBG) log(getName() + "\n"); EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName()); } @Override public boolean processMessage(Message message) { if (DBG) log(getName() + message.toString() + "\n"); switch(message.what) { case CMD_UNLOAD_DRIVER: transitionTo(mDriverUnloadingState); break; case CMD_START_SUPPLICANT: try { mNwService.wifiFirmwareReload(mInterfaceName, "STA"); } catch (Exception e) { loge("Failed to reload STA firmware " + e); // continue } try { //A runtime crash can leave the interface up and //this affects connectivity when supplicant starts up. //Ensure interface is down before a supplicant start.
mNwService.setInterfaceDown(mInterfaceName); //Set privacy extensions mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true); } catch (RemoteException re) { loge("Unable to change interface settings: " + re); } catch (IllegalStateException ie) { loge("Unable to change interface settings: " + ie); } /* Stop a running supplicant after a runtime restart * Avoids issues with drivers that do not handle interface down * on a running supplicant properly. */ if (DBG) log("Kill any running supplicant"); mWifiNative.killSupplicant(mP2pSupported); if(mWifiNative.startSupplicant(mP2pSupported)) { if (DBG) log("Supplicant start successful"); mWifiMonitor.startMonitoring(); transitionTo(mSupplicantStartingState); } else { loge("Failed to start supplicant!"); sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_UNKNOWN, 0)); } break; case CMD_START_AP: transitionTo(mSoftApStartingState); break; default: return NOT_HANDLED; } return HANDLED; } }
/* @param mode can be "AP", "STA" or "P2P" */ @Override public void wifiFirmwareReload(String wlanIface, String mode) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); try { mConnector.execute("softap", "fwreload", wlanIface, mode); } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); } }
property_set("ctl.start", "wififix" );
insmod /system/lib/dhd.ko
usleep 1000,000
property_set(DRIVER_PROP_NAME, "ok");//static const char DRIVER_PROP_NAME[] = "wlan.driver.status";
//间隔0.2s,总计20s
reload firmware,没有搞清楚是如何加载的。
killall wps
mWifiNative.startSupplicant(mP2pSupported)
原文:http://www.cnblogs.com/leino11121/p/3765988.html