wifi 鏈接&獲取IP 流程圖
- Android 每一次版本迭代與更新,對於設備開發商來講都是挺痛苦的一件事,不少的東西須要移植,須要適配,
- 年復一年,日復一日,bug不停,需求不停,儘管再累也是將一些重要的東西記錄下來,分享給到你們,
- 但願大家遇到相關問題,順着流程圖以及代碼主線,找到緣由(解決問題),
- 老三樣,先上流程圖
代碼流程
1、關聯階段
1. WifiSettings.submit – > WifiManager
- WifiSettings 乾的事情比較簡單,當在dialog完成ssid 以及密碼填充後,直接call WifiManager save 便可
- WifiManager 收到Save 以後,就開始了wifi 鏈接之旅
packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java
void submit(WifiConfigController configController){
...
mWifiManager.save(config, mSaveListener);
}
2. WifiSettings.submit – > WifiManager
- WifiManager 這裏至關於傳達室,信件到了,而後按個鈴鐺,把信息傳達給WifiSerivceImpl
- 主要是將SAVE_NETWORK 給到 WifiService(WifiServiceImpl 是真正幹活的)
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
public void save(WifiConfiguration config, ActionListener listener) {
getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}
3. WifiServiceImpl --> WifiStateMachine
- WifiServiceImpl又將 SAVE_NETWORK 送到中級cmd處理站: WifiStateMachine
- 這裏擴展一下,如咱們的移除熱點(其實也經過Settings 將remove cmd 送到WifiServieImpl進行下一步傳輸)
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java
private class ClientHandler extends WifiHandler {
case WifiManager.SAVE_NETWORK:
{
mWifiStateMachine.sendMessage(Message.obtain(msg));
}
}
4. WifiStateMachine–> WifiStateMachine
- 從save network 鏈接熱點
- 又一次轉化, 轉爲CMD_START_CONNECT送到內部狀態機(ConnectModeState )處理
- 送到WifiNative 進行處理Connect,回顧以上(Android 基本套路大框架仍是不變的: apps – services – native – drv(kernel))
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
public void startConnectToNetwork(int networkId, int uid, String bssid) {
sendMessage(CMD_START_CONNECT, networkId, uid, bssid);
}
class ConnectModeState extends State {
case WifiManager.SAVE_NETWORK:
startConnectToNetwork(netId, message.sendingUid, SUPPLICANT_BSSID_ANY);// 鏈接熱點
case CMD_START_CONNECT:
mWifiNative.connectToNetwork(mInterfaceName, config); // 轉到wifiNative 進行connect
}
5. WifiNative–> SupplicantStaIfaceHal --> WifMonitor
- SupplicantStaIfaceHal 添加網絡,select (實則將connect 傳給到 wpa_supplicant)
- wpa_supplicant完成一系列與路由器的之間的beacon幀(probe、assoc、4way-handshake 、group-handshake)後,再能取到路由器的頒發的承認證(既是拿到最後的compelted)
- 最後,經過wifiMonitor上報wpa_supplicant 任務已完成,既是完成鏈接的第一階段(關聯階段)
- WiFiMonitor上報的事件既是,NETWORK_CONNECTION_EVENT (又一次回到WifiStateMachine)
frameworks/opt/net/wifi/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
public boolean connectToNetwork(@NonNull String ifaceName, @NonNull WifiConfiguration config)
{
Pair<SupplicantStaNetworkHal, WifiConfiguration> pair =
addNetworkAndSaveConfig(ifaceName, config);
networkHandle.select();
}
public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,ArrayList<Byte> ssid) {
if (newSupplicantState == SupplicantState.COMPLETED){
mWifiMonitor.broadcastNetworkConnectionEvent(mIfaceName, getCurrentNetworkId(mIfaceName), bssidStr);
}
}
2、獲取IP 階段
6. WifMonitor --> WifiStateMachine
- 由5的NETWORK_CONNECTION_EVENT 事件上報,又一次回到了WifiStateMachine
- 並且仍是在ConnectModeState 狀態機裏,爲啥?(又回到這裏)
- 由於,1~5步只完成了關聯,還有最後一步(要獲取IP),拿到IP後才能算是一個有證的男人,
- 革命還沒有成功,苦逼仍要繼續(且看下面是如何獲取IP …)
- 先是,廣而告知(已取得真經),而後立馬切換到mObtainingIpState狀態機
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
class ConnectModeState extends State {
case WifiMonitor.NETWORK_CONNECTION_EVENT:
....
sendNetworkStateChangeBroadcast(mLastBssid);
transitionTo(mObtainingIpState);
}
7. WifiStateMachine.ObtainingIpState
- ObtainingIpState 獲取IP 的流程中規中矩,先是update 系統的State
- 停掉IpClient (自從Android N 後,獲取IP已廢棄了dhcpd,扶持了另外一位的IpClient 、IpManager來完成本身的事業 )
- 清掉bssid以免其影響到漫遊致使斷鏈
- Ipclient 開始接管舞臺(啓動獲取IP), 後面有空(將把這部分詳細講講的dhcp 協議以及常見的dhcp 問題),敬請期待
frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java
class ObtainingIpState extends State {
...
setNetworkDetailedState(DetailedState.OBTAINING_IPADDR);
clearTargetBssid("ObtainingIpAddress");
stopIpClient();
mIpClient.setHttpProxy(currentConfig.getHttpProxy());
IpClient.buildProvisioningConfiguration();
....
}