《ANDROID移植WIFI設(shè)計(jì)原理(源碼分析)》由會(huì)員分享,可在線閱讀,更多相關(guān)《ANDROID移植WIFI設(shè)計(jì)原理(源碼分析)(7頁(yè)珍藏版)》請(qǐng)?jiān)谘b配圖網(wǎng)上搜索。
1、Android移植: wifi設(shè)計(jì)原理(源碼分析) 博客分類: AndroidAndroidEXT初始化在 SystemServer 啟動(dòng)的時(shí)候,會(huì)生成一個(gè) ConnectivityService 的實(shí)例, try Log.i(TAG, Starting Connectivity Service.); ServiceManager.addService(Context.CONNECTIVITY_SERVICE, newConnectivityService(context); catch (Throwable e) Log.e(TAG, Failure starting Connectivit
2、y Service, e); ConnectivityService 的構(gòu)造函數(shù)會(huì)創(chuàng)建 WifiService, if (DBG) Log.v(TAG, Starting Wifi Service.); mWifiStateTracker = new WifiStateTracker(context, handler); WifiService wifiService = new WifiService(context, mWifiStateTracker); ServiceManager.addService(Context.WIFI_SERVICE, wifiService);WifiSt
3、ateTracker 會(huì)創(chuàng)建 WifiMonitor 接收來(lái)自底層的事件,WifiService 和 WifiMonitor 是整個(gè)模塊的核心。WifiService 負(fù)責(zé)啟動(dòng)關(guān)閉 wpa_supplicant、啟動(dòng)關(guān)閉 WifiMonitor 監(jiān)視線程和把命令下發(fā)給 wpa_supplicant,而 WifiMonitor 則負(fù)責(zé)從 wpa_supplicant 接收事件通知。連接 AP1. 使能 WIFIWirelessSettings 在初始化的時(shí)候配置了由 WifiEnabler 來(lái)處理 Wifi 按鈕, private void initToggles() mWifiEnabler
4、= new WifiEnabler( this, (WifiManager) getSystemService(WIFI_SERVICE), (CheckBoxPreference) findPreference(KEY_TOGGLE_WIFI);當(dāng)用戶按下 Wifi 按鈕后, Android 會(huì)調(diào)用 WifiEnabler 的 onPreferenceChange, 再由 WifiEnabler調(diào)用 WifiManager 的 setWifiEnabled 接口函數(shù),通過(guò) AIDL,實(shí)際調(diào)用的是 WifiService 的setWifiEnabled 函數(shù),WifiService 接著向自身
5、發(fā)送一條 MESSAGE_ENABLE_WIFI 消息,在處理該消息的代碼中做真正的使能工作:首先裝載 WIFI 內(nèi)核模塊(該模塊的位置硬編碼為/system/lib/modules/wlan.ko ), 然 后 啟 動(dòng) wpa_supplicant ( 配 置 文 件 硬 編 碼 為/data/misc/wifi/wpa_supplicant.conf) 再通過(guò) WifiStateTracker 來(lái)啟動(dòng) WifiMonitor 中的監(jiān)視 ,線程。 private boolean setWifiEnabledBlocking(boolean enable) final int eventual
6、WifiState = enable ? WIFI_STATE_ENABLED :WIFI_STATE_DISABLED; updateWifiState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING); if (enable) if (!WifiNative.loadDriver() Log.e(TAG, Failed to load Wi-Fi driver.); updateWifiState(WIFI_STATE_UNKNOWN); return false; if (!WifiNative.startSupplicant()
7、WifiNative.unloadDriver(); Log.e(TAG, Failed to start supplicant daemon.); updateWifiState(WIFI_STATE_UNKNOWN); return false; mWifiStateTracker.startEventLoop(); / Success! persistWifiEnabled(enable); updateWifiState(eventualWifiState); return true; 當(dāng)使能成功后,會(huì)廣播發(fā)送 WIFI_STATE_CHANGED_ACTION 這個(gè) Intent 通
8、知外界 WIFI已 經(jīng) 成 功 使 能 了 。 WifiEnabler 創(chuàng) 建 的 時(shí) 候 就 會(huì) 向 Android 注 冊(cè) 接 收WIFI_STATE_CHANGED_ACTION,因此它會(huì)收到該 Intent,從而開始掃描。 private void handleWifiStateChanged(int wifiState) if (wifiState = WIFI_STATE_ENABLED) loadConfiguredAccessPoints(); attemptScan(); 2. 查找 AP掃描的入口函數(shù)是 WifiService 的 startScan,它其實(shí)也就是往 wpa
9、_supplicant 發(fā)送 SCAN 命令。static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz) jboolean result; / Ignore any error from setting the scan mode. / The scan will still work. (void)doBooleanCommand(DRIVER SCAN-ACTIVE, OK); result = doBooleanCommand(SCAN, OK); (void)doBooleanCommand(DRIV
10、ER SCAN-PASSIVE, OK); return result;當(dāng) wpa_supplicant 處理完 SCAN 命令后,它會(huì)向控制通道發(fā)送事件通知掃描完成,從而wifi_wait_for_event 函數(shù)會(huì)接收到該事件,由此 WifiMonitor 中的 MonitorThread 會(huì)被執(zhí)行來(lái)出來(lái)這個(gè)事件, void handleEvent(int event, String remainder) case SCAN_RESULTS: mWifiStateTracker.notifyScanResultsAvailable(); break;WifiStateTracker 則接著
11、廣播發(fā)送 SCAN_RESULTS_AVAILABLE_ACTION 這個(gè) Intent case EVENT_SCAN_RESULTS_AVAILABLE: mContext.sendBroadcast(newIntent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);WifiLayer 注冊(cè)了接收 SCAN_RESULTS_AVAILABLE_ACTION 這個(gè) Intent,所以它的相關(guān)處理函數(shù) handleScanResultsAvailable 會(huì)被調(diào)用,在該函數(shù)中,先會(huì)去拿到 SCAN 的結(jié)果(最終是往 wpa_supplicant 發(fā)送 S
12、CAN_RESULT 命令并讀取返回值來(lái)實(shí)現(xiàn)的) , List list = mWifiManager.getScanResults();對(duì)每一個(gè)掃描返回的 AP,WifiLayer 會(huì)調(diào)用 WifiSettings 的 onAccessPointSetChanged 函數(shù),從而最終把該 AP 加到 GUI 顯示列表中。 public void onAccessPointSetChanged(AccessPointState ap, boolean added) AccessPointPreference pref = mAps.get(ap); if (added) if (pref = n
13、ull) pref = new AccessPointPreference(this, ap); mAps.put(ap, pref); else pref.setEnabled(true); mApCategory.addPreference(pref); 3. 配置 AP 參數(shù)當(dāng)用戶在 WifiSettings 界面上選擇了一個(gè) AP 后,會(huì)顯示配置 AP 參數(shù)的一個(gè)對(duì)話框, public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preferencepreference) if (preference
14、 instanceof AccessPointPreference) AccessPointState state = (AccessPointPreference)preference).getAccessPointState(); showAccessPointDialog(state, AccessPointDialog.MODE_INFO); 4. 連接當(dāng)用戶在 AcessPointDialog 中選擇好加密方式和輸入密鑰之后,再點(diǎn)擊連接按鈕,Android就會(huì)去連接這個(gè) AP。 private void handleConnect() String password = getEnt
15、eredPassword(); if (!TextUtils.isEmpty(password) mState.setPassword(password); mWifiLayer.connectToNetwork(mState); WifiLayer 會(huì)先檢測(cè)這個(gè) AP 是不是之前被配置過(guò),這個(gè)是通過(guò)向 wpa_supplicant 發(fā)送LIST_NETWORK 命令并且比較返回值來(lái)實(shí)現(xiàn)的, / Need WifiConfiguration for the AP WifiConfiguration config = findConfiguredNetwork(state);如果 wpa_sup
16、plicant 沒有這個(gè) AP 的配置信息, 則會(huì)向 wpa_supplicant 發(fā)送 ADD_NETWORK命令來(lái)添加該 AP, if (config = null) / Connecting for the first time, need to create it config = addConfiguration(state,ADD_CONFIGURATION_ENABLE|ADD_CONFIGURATION_SAVE); ADD_NETWORK 命 令 會(huì) 返 回 一 個(gè) ID , WifiLayer 再 用 這 個(gè) 返 回 的 ID 作 為 參 數(shù) 向wpa_supplicant
17、 發(fā)送 ENABLE_NETWORK 命令,從而讓 wpa_supplicant 去連接該 AP。 / Make sure that network is enabled, and disable others mReenableApsOnNetworkStateChange = true; if (!mWifiManager.enableNetwork(workId, true) Log.e(TAG, Could not enable network ID + workId); error(R.string.error_connecting); return false; 5. 配置 IP
18、地址當(dāng) wpa_supplicant 成功連接上 AP 之后,它會(huì)向控制通道發(fā)送事件通知連接上 AP 了,從而wifi_wait_for_event 函數(shù)會(huì)接收到該事件,由此 WifiMonitor 中的 MonitorThread 會(huì)被執(zhí)行來(lái)出來(lái)這個(gè)事件, void handleEvent(int event, String remainder) case CONNECTED: handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED,remainder); break;WifiMonitor 再調(diào)用 WifiStateTrac
19、ker 的 notifyStateChange,WifiStateTracker 則接著會(huì)往自身發(fā)送 EVENT_DHCP_START 消息來(lái)啟動(dòng) DHCP 去獲取 IP 地址, private void handleConnectedState() setPollTimer(); mLastSignalLevel = -1; if (!mHaveIPAddress & !mObtainingIPAddress) mObtainingIPAddress = true; mDhcpTarget.obtainMessage(EVENT_DHCP_START).sendToTarget(); 然后再
20、廣播發(fā)送 NETWORK_STATE_CHANGED_ACTION 這個(gè) Intent case EVENT_NETWORK_STATE_CHANGED: if (result.state != DetailedState.DISCONNECTED | !mDisconnectPending) intent = newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION); intent.putExtra(WifiManager.EXTRA_NETWORK_INFO,mNetworkInfo); if (result.BSSID != null) in
21、tent.putExtra(WifiManager.EXTRA_BSSID, result.BSSID); mContext.sendStickyBroadcast(intent); break;WifiLayer 注冊(cè)了接收 NETWORK_STATE_CHANGED_ACTION 這個(gè) Intent,所以它的相關(guān)處理函數(shù) handleNetworkStateChanged 會(huì)被調(diào)用,當(dāng) DHCP 拿到 IP 地址之后,會(huì)再發(fā)送 EVENT_DHCP_SUCCEEDED 消息, private class DhcpHandler extends Handler public void han
22、dleMessage(Message msg) switch (msg.what) case EVENT_DHCP_START: if (NetworkUtils.runDhcp(mInterfaceName, mDhcpInfo) event = EVENT_DHCP_SUCCEEDED; WifiLayer 處 理 EVENT_DHCP_SUCCEEDED 消 息 , 會(huì) 再 次 廣 播 發(fā) 送NETWORK_STATE_CHANGED_ACTION 這個(gè) Intent,這次帶上完整的 IP 地址信息。 case EVENT_DHCP_SUCCEEDED: mWifiInfo.setIpAddress(mDhcpInfo.ipAddress); setDetailedState(DetailedState.CONNECTED); intent = newIntent(WifiManager.NETWORK_STATE_CHANGED_ACTION); intent.putExtra(WifiManager.EXTRA_NETWORK_INFO, mNetworkInfo); mContext.sendStickyBroadcast(intent); break;至此為止,整個(gè)連接過(guò)程完成。問(wèn)題: 目前的實(shí)現(xiàn)不支持 Ad-hoc 方式。