接著上一篇,這篇說一下Wifi的關(guān)閉流程。
由上一篇可以知道,framework層提供的wifi開關(guān)接口都是setWifiEnabled,只是參數(shù)不同而已。true表示開啟wifi、false表示關(guān)閉wifi。
Wifi開關(guān)在WifiManager和WifiService中的流程一樣,接著看WifiController。
wifi開啟的時候,WifiController中狀態(tài)為DeviceActiveState(其父狀態(tài)為StaEnabledState)。
一下是StaEnabledState對CMD_WIFI_TOGGLED消息的處理。
case CMD_WIFI_TOGGLED:
if (! mSettingsStore.isWifiToggleEnabled()) {
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
} else {
transitionTo(mApStaDisabledState);
}
}
break;
isWifiToggleEnabled為false表示要關(guān)閉wifi,則將狀態(tài)切換到StaDisabledWithScanState(如果可以一直掃描)或ApStaDisabledState。
我們這里主要看下切換到ApStaDisabledState狀態(tài)。切換到ApStaDisabledState狀態(tài),會先走其enter函數(shù)。
class ApStaDisabledState extends State {
private int mDeferredEnableSerialNumber = 0;
private boolean mHaveDeferredEnable = false;
private long mDisabledTimestamp;
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(false);
// wpa_supplicant 不能立即重啟,所以記錄下關(guān)閉的時間。
mDisabledTimestamp = SystemClock.elapsedRealtime();
mDeferredEnableSerialNumber++;
mHaveDeferredEnable = false;
}
//.....
mWifiStateMachine.setSupplicantRunning(false)用來關(guān)閉wifi。
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
WifiStateMachine中發(fā)送CMD_STOP_SUPPLICANT消息。
由上一篇可知wifi開啟后,WifiStateMachine狀態(tài)可能是DriverStartedState(父狀態(tài)是SupplicantStartedState)、DisconnectedState(父狀態(tài)是DriverStartedState)。
class SupplicantStartedState extends State {
@Override
public boolean processMessage(Message message) {
switch(message.what) {
case CMD_STOP_SUPPLICANT: /* Supplicant stopped by user */
if (mP2pSupported) {
transitionTo(mWaitForP2pDisableState);
} else {
transitionTo(mSupplicantStoppingState);
}
break;
//。。。
mP2pSupported表示是否支持wifi直連。支持wifi直連,則WifiStateMachine切換到WaitForP2pDisableState狀態(tài)。否則切換到SupplicantStoppingState狀態(tài)。
wifi直連的先不管,看下切換到SupplicantStoppingState狀態(tài)。
class SupplicantStoppingState extends State {
@Override
public void enter() {
/* Send any reset commands to supplicant before shutting it down */
handleNetworkDisconnect();
if (mDhcpStateMachine != null) {
//退出DhcpStateMachine
mDhcpStateMachine.doQuit();
}
//關(guān)閉wpa_supplicant
if (!mWifiNative.stopSupplicant()) {
loge("Failed to stop supplicant");
}
/* 發(fā)送自己一個延遲的消息,指示等待時間后的失敗 */
sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED,
++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS);
//發(fā)送廣播,wifi狀態(tài)改變(WIFI_STATE_DISABLING)
setWifiState(WIFI_STATE_DISABLING);
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
}
- handleNetworkDisconnect 通過清除任何狀態(tài),重新設(shè)置Wifi連接,使用該接口重置任何socket,停止DHCP和禁用接口。
- mDhcpStateMachine.doQuit(); 退出DhcpStateMachine。
- mWifiNative.stopSupplicant() 關(guān)閉wpa_supplicant。
- setWifiState 發(fā)送廣播,wifi狀態(tài)改變(WIFI_STATE_DISABLING)。
- CMD_RESET_SUPPLICANT_STATE 向SupplicantStateTracker發(fā)送消息,重置supplicant state tracker。
看一下handleNetworkDisconnect 函數(shù)。
/**
* Resets the Wi-Fi Connections by clearing any state, resetting any sockets
* using the interface, stopping DHCP & disabling interface
*/
private void handleNetworkDisconnect() {
//停止dhcp
stopDhcp();
try {//清除ip地址
mNwService.clearInterfaceAddresses(mInterfaceName);
mNwService.disableIpv6(mInterfaceName);
} catch (Exception e) {
loge("Failed to clear addresses or disable ipv6" + e);
}
//設(shè)置network disconnect。
setNetworkDetailedState(DetailedState.DISCONNECTED);
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);
/* send event to CM & network change broadcast */
//發(fā)送廣播、網(wǎng)絡(luò)狀態(tài)改變。
sendNetworkStateChangeBroadcast(mLastBssid);
/* 重置數(shù)據(jù) */
mWifiInfo.setInetAddress(null);
mWifiInfo.setBSSID(null);
mWifiInfo.setSSID(null);
mWifiInfo.setNetworkId(WifiConfiguration.INVALID_NETWORK_ID);
mWifiInfo.setRssi(MIN_RSSI);
mWifiInfo.setLinkSpeed(-1);
mWifiInfo.setMeteredHint(false);
mWifiInfo.setReason(-1);
/* Clear network properties */
mLinkProperties.clear();
/* 如果網(wǎng)絡(luò)使用DHCP,清除IP設(shè)置 */
if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
mWifiConfigStore.clearLinkProperties(mLastNetworkId);
}
mLastBssid= null;
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
}
mWifiNative.stopSupplicant() 關(guān)閉wpa_supplicant。向wpa_supplicant發(fā)送命令TERMINATE,wpa_supplicant終止并向java層返回狀態(tài)TERMINATE,WifiMonitor中會循環(huán)從wpa_supplicant接收消息,此時會收到TERMINATE消息,其向WifiStateMachine發(fā)送SUP_DISCONNECTION_EVENT消息。
看看WifiStateMachine是如何處理該消息的。
class SupplicantStoppingState extends State {
@Override
public boolean processMessage(Message message) {
switch(message.what) {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
handleSupplicantConnectionLoss();
transitionTo(mInitialState);
break;
case CMD_STOP_SUPPLICANT_FAILED:
//超時未收到supplicant disconnect event,則執(zhí)行如下
if (message.arg1 == mSupplicantStopFailureToken) {
loge("Timed out on a supplicant stop, kill and proceed");
handleSupplicantConnectionLoss();
transitionTo(mInitialState);
}
break;
handleSupplicantConnectionLoss 向supplicant發(fā)送kill信號、斷開連接、發(fā)送wifi狀態(tài)改變的廣播(WIFI_STATE_DISABLED)。
看handleSupplicantConnectionLoss 函數(shù)如下:
private void handleSupplicantConnectionLoss() {
//向supplicant發(fā)送kill信號。
mWifiNative.killSupplicant(mP2pSupported);
//斷開連接。
mWifiNative.closeSupplicantConnection();
sendSupplicantConnectionChangedBroadcast(false);
//發(fā)送wifi狀態(tài)改變的廣播(WIFI_STATE_DISABLED)
setWifiState(WIFI_STATE_DISABLED);
}
mWifiNative.killSupplicant(mP2pSupported); 向supplicant發(fā)送kill信號,使wpa_supplicant進(jìn)程退出。
mWifiNative.closeSupplicantConnection() 斷開與wpa_supplicant連接。
setWifiState(WIFI_STATE_DISABLED) 向外發(fā)送廣播(wifi狀態(tài)改變,WIFI_STATE_DISABLED)。
transitionTo(mInitialState) 切換到InitialState狀態(tài)。在InitialState的enter函數(shù)中調(diào)用mWifiNative.unloadDriver(),卸載驅(qū)動。此時wifi關(guān)閉完成。
有什么問題和意見,歡迎提問、交流。
歡迎大家關(guān)注、評論、點(diǎn)贊。
你們的支持是我堅(jiān)持的動力。