當SystemServer啟動后會加載一系列的Service其中init2啟動的就有ConnectivityService,這在我的前面《Android 啟動過程分析》中已經(jīng)提到過。ConnectivityService.java (frameworks\base\services\java\com\android\server) 會管理所有的Connectivity相關(guān)的比如APN,WiFi??纯词窃趺磫覹iFi Service的:
if (DBG) Log.v(TAG, "Starting Wifi Service.");
WifiStateTracker wst = new WifiStateTracker(context, mHandler);
WifiService wifiService = new WifiService(context, wst);
ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
WifiStateTracker會創(chuàng)建WifMonitor來接受來自底層的事件。WifiService和WifiMonitor是整個模塊的核心部分,WifiService負責啟動關(guān)閉wpa_supplicant,發(fā)命令給wpa_supplicant,WiFiMonitor負責從wpa_supplicant接收事件。
整個流程是
SystemServer -> ServerThread -> ConnectivityService -> ConnectivityThread -> WifiTracker->WifiService -> WifiMonitor
WiFi 的啟動過程
用戶在設(shè)置界面下開啟了WiFi,調(diào)用應(yīng)用程序Settings中的setWifiEnabler的onPerferenceChange,再由WifiEnable調(diào)用WifiService,發(fā)送MESSAGE_ENABLE_WIFI,首先裝載wifi內(nèi)核模塊wlan.ko然后啟動wpa_supplicant(用/data/misc/wifi/wpa_supplicant.conf配置),再通過WifiStateTracker來啟動WifiMonitor監(jiān)視線程。
WifiSettings.java (packages\apps\settings\src\com\android\settings\wifi)啟動
mWifiEnabled = (CheckBoxPreference) preferenceScreen.findPreference(KEY_WIFI_ENABLED);
mWifiEnabler = new WifiEnabler(this, (WifiManager) getSystemService(WIFI_SERVICE), mWifiEnabled);
這樣就啟動WifiEnabler
WifiEnabler.java (packages\apps\settings\src\com\android\settings\wifi)通過WifiManager調(diào)用WifiManager.java (frameworks\base\wifi\java\android\net\wifi) setWifiEnabled 中的IWifiManager來啟動wifiservice[mService.setWifiEnabled(enabled);]
WifiService.java (frameworks\base\services\java\com\android\server)又setWifiEnabled()這個里面的sendEnableMessage(enable, true, Binder.getCallingUid());來發(fā)送一則消息。
Message msg = Message.obtain(mWifiHandler,
(enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
(persist ? 1 : 0), uid);
msg.sendToTarget();發(fā)送給自身的消息。
通過WifiHandler的 handleMessage來維護這些消息,enable的時候會調(diào)用setWifiEnabledBlocking這個函數(shù),這個函數(shù)會做setWifiEnabledState 然后做兩件事: 1. 調(diào)用wifi 本地方法JNI的WifiNative.loadDriver。
下面說本地方法WifiNative.loadDriver函數(shù)WifiNative.java (frameworks\base\wifi\java\android\net\wifi) Android的WIFI系統(tǒng)的JNI的部分:
frameworks/base/core/jni/android_net_wifi_Wifi.cpp 中的android_net_wifi_loadDriver()可以把wifi驅(qū)動模塊裝載
Wifi.c (hardware\libhardware_legacy\wifi) 內(nèi)核模塊/system/lib/modules/wlan.ko中的wifi_load_driver()
設(shè)置wlan.driver.status屬性為ok,至此wifi模塊加載完畢。
2. 再來看看啟動,同樣是在WifiService 中的setWifiEnabledBlocking這個函數(shù)會調(diào)用startSupplicant 通過WifiNative.java (frameworks\base\wifi\java\android\net\wifi)的startSupplicant來啟動JNI:frameworks/base/core/jni/android_net_wifi_Wifi.cpp的android_net_wifi_startSupplicant調(diào)用驅(qū)動模塊Wifi.c (hardware\libhardware_legacy\wifi) wlan.ko中的wifi_start_supplicant, Wifi 啟動完畢。
成功啟動wifi之后setWifiEnabledBlocking運行mWifiStateTracker.startEventLoop();事件循環(huán),來監(jiān)視事件mWifiMonitor.startMonitoring(); à MonitorThread().start();一直在線程里循環(huán)調(diào)用WifiNative.waitForEvent();最后調(diào)用
setWifiEnabledState(eventualWifiState, uid);
intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
廣播消息向外界通知wifi已經(jīng)成功啟動了。
查找熱點AP
上面說了WifiManager發(fā)送廣播WIFI_STATE_CHANGED_ACTION,只要Android應(yīng)用注冊了接受該Action的就接受,我們的WifiLayer注冊了接收到該ActionWifiSettings.java (packages\apps\settings\src\com\android\settings\wifi)中有mWifiLayer.onCreate();(這個函數(shù)創(chuàng)建WifiLayer指定接受的Action)WifiLayer.java (packages\apps\settings\src\com\android\settings\wifi)中的BroadcastReceiver 有一句話else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));這個函數(shù)會調(diào)用loadConfiguredAccessPoints和attemptScan來開始掃描,調(diào)用WifiManager的mWifiManager.startScanActive,WifiManager.java中的mService.startScan通過WifiService中的startScan通過本地方法WifiNative.setScanResultHandlingCommand啟動JNI android_net_wifi_Wifi.cpp (frameworks\base\core\jni) 中的android_net_wifi_setScanResultHandlingCommand的命令“AP_SCAN 模式” Wifi.c ::wifi_command(cmd)開始掃描wifi_send_command發(fā)出SCAN命令調(diào)用wpa_supplicant開始掃描掃描完成之后會發(fā)送SCAN_RESULT 在WifiMonitor的HandleEvent里處理調(diào)用mWifiStateTracker.notifyScanResultsAvailable(); à sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE); mWifiStateTracker中的 handleMessage接收到case EVENT_SCAN_RESULTS_AVAILABLE:之后發(fā)送廣播mContext.sendBroadcast(new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));WiFiLayer接收到這個消息在mReceiver = new BroadcastReceiver()中處理handleScanResultsAvailable();
WiFi 連接流程
用戶在AccessPointDialog中輸入密碼之后點擊連接按鈕,Android調(diào)用順序如下:
AccessPointDialog.java (packages\apps\settings\src\com\android\settings\wifi) -> onClick -> handleConnect(); -> mWifiLayer.connectToNetwork ->通過WifiConfiguration config = findConfiguredNetwork(state);查看是不是配置過的,如果是就直接使用了,如果不是config = addConfiguration(state, 0); -> managerEnableNetwork -> mWifiManager.enableNetwork -> mService.enableNetwork -> WifiService. enableNetwork -> WifiNative.enableNetworkCommand -> JNI: android_net_wifi_Wifi.cpp android_net_wifi_enableNetworkCommand 調(diào)用wpa_suppcant發(fā)送相關(guān)命令返回之后由WiFiMonitor處理跟以前類似,連接的中間流程與查找AP的流程類似,都經(jīng)過了WifiMonitor對“CONNECTED”消息響應(yīng)的捕獲,以及WifiStateTracker對EVENT_SUPPLICANT_STATE_ CHANGED的處理。還有一個比較重
要的步驟是WifiStateTracker通過對DHCP服務(wù)器的申請進行了IP地址分配。最終會廣播NETWORK_STATE_CHANGED_ ACTION消息,由WifiLayer響應(yīng)。
IP地址分配
由上面繼續(xù)說IP地址分配,因為當wpa_supplicant鏈接AP成功之后,它會發(fā)出事件從而wifi_for_event函數(shù)會接收到該事件,由WifiMonitor中的MonitorThread執(zhí)行。
執(zhí)行這個事件handleEvent-> case CONNECTED: handleNetworkStateChange -> mWifiStateTracker.notifyStateChange -> EVENT_NETWORK_STATE_CHANGED -> handleMessage 下的:case EVENT_SUPPLICANT_STATE_CHANGED: -> intent = new Intent(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); Wi-Fi supplicant state changed:
SettingsObserver專門是觀察該類變化的
if (changed) {
resetInterface(true);
configureInterface();
if (mUseStaticIp) {
mTarget.sendEmptyMessage(EVENT_CONFIGURATION_CHANGED);
}
}
mDhcpTarget.sendEmptyMessage(EVENT_DHCP_START);
DhcpHandler的handleMessage函數(shù)case EVENT_DHCP_START: NetworkUtils.runDhcp獲取DHCP的IP地址,成功之后發(fā)送EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:
event通過WifiStateTracker的HandleMessage函數(shù)case EVENT_INTERFACE_CONFIGURATION_SUCCEEDED:會調(diào)用sendNetworkStateChangeBroadcast Intent intent = new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION);發(fā)送全局Intent Action 完成網(wǎng)絡(luò)切換。
上文中暗紅色的部分都是ICS Settings里面的內(nèi)容(也就是可以注意下android自帶的UI是如何使用wifi的)~~