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();
....
}