Android wifi源码分析(二) Wifi关闭流程

接着上一篇,这篇说一下Wifi的关闭流程。

由上一篇可以知道,framework层提供的wifi开关接口都是setWifiEnabled,只是参数不同而已。true表示开启wifi、false表示关闭wifi。

Wifi开关在WifiManager和WifiService中的流程一样,接着看WifiController。
wifi开启的时候,WifiController中状态为DeviceActiveState(其父状态为StaEnabledState)。
一下是StaEnabledState对CMD_WIFI_TOGGLED消息的处理。

case CMD_WIFI_TOGGLED:
   if (! mSettingsStore.isWifiToggleEnabled()) {
       if (mSettingsStore.isScanAlwaysAvailable()) {
           transitionTo(mStaDisabledWithScanState);
       } else {
           transitionTo(mApStaDisabledState);
       }
   }
   break;

isWifiToggleEnabled为false表示要关闭wifi,则将状态切换到StaDisabledWithScanState(如果可以一直扫描)或ApStaDisabledState。
我们这里主要看下切换到ApStaDisabledState状态。切换到ApStaDisabledState状态,会先走其enter函数。

class ApStaDisabledState extends State {
    private int mDeferredEnableSerialNumber = 0;
    private boolean mHaveDeferredEnable = false;
    private long mDisabledTimestamp;

    @Override
    public void enter() {
        mWifiStateMachine.setSupplicantRunning(false);
        // wpa_supplicant 不能立即重启,所以记录下关闭的时间。
        mDisabledTimestamp = SystemClock.elapsedRealtime();
        mDeferredEnableSerialNumber++;
        mHaveDeferredEnable = false;
    }
//.....

mWifiStateMachine.setSupplicantRunning(false)用来关闭wifi。

public void setSupplicantRunning(boolean enable) {
    if (enable) {
        sendMessage(CMD_START_SUPPLICANT);
    } else {
        sendMessage(CMD_STOP_SUPPLICANT);
    }
}

WifiStateMachine中发送CMD_STOP_SUPPLICANT消息。
由上一篇可知wifi开启后,WifiStateMachine状态可能是DriverStartedState(父状态是SupplicantStartedState)、DisconnectedState(父状态是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状态。否则切换到SupplicantStoppingState状态。

wifi直连的先不管,看下切换到SupplicantStoppingState状态。

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();
        }
        //关闭wpa_supplicant
        if (!mWifiNative.stopSupplicant()) {
            loge("Failed to stop supplicant");
        }

        /* 发送自己一个延迟的消息,指示等待时间后的失败 */
        sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED,
                ++mSupplicantStopFailureToken, 0), SUPPLICANT_RESTART_INTERVAL_MSECS);
        //发送广播,wifi状态改变(WIFI_STATE_DISABLING)
        setWifiState(WIFI_STATE_DISABLING);
        mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
    }
  1. handleNetworkDisconnect 通过清除任何状态,重新设置Wifi连接,使用该接口重置任何socket,停止DHCP和禁用接口。
  2. mDhcpStateMachine.doQuit(); 退出DhcpStateMachine。
  3. mWifiNative.stopSupplicant() 关闭wpa_supplicant。
  4. setWifiState 发送广播,wifi状态改变(WIFI_STATE_DISABLING)。
  5. CMD_RESET_SUPPLICANT_STATE 向SupplicantStateTracker发送消息,重置supplicant state tracker。

看一下handleNetworkDisconnect 函数。

/**
 * 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);
    }
    //设置network disconnect。
    setNetworkDetailedState(DetailedState.DISCONNECTED);
    mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.DISCONNECTED);

    /* send event to CM & network change broadcast */
    //发送广播、网络状态改变。
    sendNetworkStateChangeBroadcast(mLastBssid);

    /* 重置数据 */
    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();

    /* 如果网络使用DHCP,清除IP设置 */
    if (!mWifiConfigStore.isUsingStaticIp(mLastNetworkId)) {
        mWifiConfigStore.clearLinkProperties(mLastNetworkId);
    }

    mLastBssid= null;
    mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
}

mWifiNative.stopSupplicant() 关闭wpa_supplicant。向wpa_supplicant发送命令TERMINATE,wpa_supplicant终止并向java层返回状态TERMINATE,WifiMonitor中会循环从wpa_supplicant接收消息,此时会收到TERMINATE消息,其向WifiStateMachine发送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,则执行如下
                if (message.arg1 == mSupplicantStopFailureToken) {
                    loge("Timed out on a supplicant stop, kill and proceed");
                    handleSupplicantConnectionLoss();
                    transitionTo(mInitialState);
                }
                break;

handleSupplicantConnectionLoss 向supplicant发送kill信号、断开连接、发送wifi状态改变的广播(WIFI_STATE_DISABLED)。
看handleSupplicantConnectionLoss 函数如下:

private void handleSupplicantConnectionLoss() {
    //向supplicant发送kill信号。
    mWifiNative.killSupplicant(mP2pSupported);
    //断开连接。
    mWifiNative.closeSupplicantConnection();
    sendSupplicantConnectionChangedBroadcast(false);
    //发送wifi状态改变的广播(WIFI_STATE_DISABLED)
    setWifiState(WIFI_STATE_DISABLED);
}

mWifiNative.killSupplicant(mP2pSupported); 向supplicant发送kill信号,使wpa_supplicant进程退出。
mWifiNative.closeSupplicantConnection() 断开与wpa_supplicant连接。
setWifiState(WIFI_STATE_DISABLED) 向外发送广播(wifi状态改变,WIFI_STATE_DISABLED)。

transitionTo(mInitialState) 切换到InitialState状态。在InitialState的enter函数中调用mWifiNative.unloadDriver(),卸载驱动。此时wifi关闭完成。

有什么问题和意见,欢迎提问、交流
欢迎大家关注、评论、点赞
你们的支持是我坚持的动力。

你可能感兴趣的:(Android wifi源码分析(二) Wifi关闭流程)