Android Wifi 启动过程分析

Wifi系统框图

Android Wifi 启动过程分析_第1张图片

WifiService的启动

Android中的Service启动都是从SystemServer中启动的。WifiService也不例外。
在开机时,如果Wifi的状态是on的话,是如何启动的,下面进行分析
首先看WifiService在SystemServer中是怎么启动的

private static final String WIFI_SERVICE_CLASS =
            "com.android.server.wifi.WifiService";
private void startOtherServices() {
···
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
···
}

WifiService启动是有SystemServiceManager启动的,所以猜测WifiService是一个SystemService。所以看一下WifiService的结构

public final class WifiService extends SystemService {
    public WifiService(Context context) {
        super(context);
        mImpl = new WifiServiceImpl(context);
    }

    @Override
    public void onStart() {
        Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
        publishBinderService(Context.WIFI_SERVICE, mImpl);
    }

    @Override
    public void onBootPhase(int phase) {
        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
            mImpl.checkAndStartWifi();
        }
    }
}

SystemServiceManager.startService()之后WifiService启动起来了。之后WifiManager就可以调用WifiService进行操作了。
在SystemServer状态变为PHASE_SYSTEM_SERVICES_READY之后就会调用WifiServiceImpl。WifiServiceImpl是WifiService中Action的实际实现对象。
d调用checkAndStartWifi就是根据数据库中的设置项看是否要打开Wifi.

Wifi开机自启动过程分析

public void checkAndStartWifi() {
···
        /* Check if wi-fi needs to be enabled */
        boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
        // Add by Skysoft start
        boolean softapEnabled = mSettingsStore.isSoftapToggleEnabled();
···
		mWifiController.start();
···
        if (wifiEnabled)
            setWifiEnabled(wifiEnabled);
        // Add by Skysoft start
        else if(softapEnabled)
            setWifiApEnabled(null, softapEnabled);

}

这个函数里面主要进行了一下几个动作:
1.从数据库中获取Wifi或者softap的状态
2.启动WifiController,这个类继承StateMachine。用来维护Wifi的状态。与WifiStateMachine比较紧密
3.根据状态去启动Wifi或者AP。这里面就是调用WifiController的接口
这就是Android系统启动之后是如何自动启动WifiService,如何打开Wifi的。
下面就开始分析Wifi是如何打开的

Wifi打开

WifiController分析

上面已经提到WifiController是继承自StateMachine。至于StateMachine是如何工作的这里不详细介绍。下图描述了各个state的关系:
Android Wifi 启动过程分析_第2张图片
根据WifiController初始化函数,初始化状态是ApStaDisabledState。所以CMD_WIFI_TOGGLED是ApStaDisabledState来处理的。

 WifiController(Context context, WifiServiceImpl service, Looper looper) {
 ···
         if (isScanningAlwaysAvailable) {
            setInitialState(mStaDisabledWithScanState);
        } else {
            setInitialState(mApStaDisabledState);
        }
 ···
 }

那么收到CMD_WIFI_TOGGLED后做了什么,继续分析

class ApStaDisabledState extends State {
···
	public boolean processMessage(Message msg) {
	··
		switch (msg.what) {
		case CMD_WIFI_TOGGLED:
		case CMD_AIRPLANE_TOGGLED:
		···
			transitionTo(mDeviceActiveState);
			break;
		···
		}
	···
	}
···
}

这里面就是跳转到DeviceActiveState。
根据StateMachine的规则,状态的切换顺序为ApStaDisabledState->StaEnabledState->DeviceActiveState
因此在切换的过程当中会进入StaEnabledState.enter()中

class StaEnabledState extends State {
	@Override
	public void enter() {
		mWifiStateMachine.setSupplicantRunning(true);
	}
···	
}

在这里会启动supplicant,这里先不分析,到分析WifiStateMachine时再一起分析。之后就会切换到DeviceActiveState,进行Wifi Driver的加载。

class DeviceActiveState extends State {
        @Override
        public void enter() {
            mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
            mWifiStateMachine.setDriverStart(true);
            mWifiStateMachine.setHighPerfModeEnabled(false);
        }
···
}

在这里进行了两个设置:
1.设置当前的模式为CONNECT_MODE。也就是如果之前连接过Wifi,那么准备完成之后就开始连接Wifi。
2.设置Wifi Driver的状态为启动状态。
下面就是在WifiStateMachine中实现的了。

WifiStateMachine分析

WifiStateMachine相当于Wifi的大脑,维护着wifi的状态。同WifiController一样,WifiStateMachine也是继承自StateMachine。
Android Wifi 启动过程分析_第3张图片
在WifiStateMachine的构造函数里面设置了WifiStateMachine的初始状态

public WifiStateMachine(Context context, String wlanInterface,
                            WifiTrafficPoller trafficPoller){
···
	setInitialState(mInitialState);	
···
}

根据WifiController的分析可以知道,1.启动supplicant;2.加载Wifi驱动
先看启动Supplicant是怎么进行的

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

由初始化函数可知初始状态为InitialState。所以在InitialState中会处理CMD_START_SUPPLICANT

class InitialState extends State {
···
public boolean processMessage(Message message) {
	switch (message.what) {
                case CMD_START_SUPPLICANT:
                    if (mWifiNative.loadDriver()) {
                       ···
                        if (mWifiNative.startSupplicant(mP2pSupported)) {
							···
                            transitionTo(mSupplicantStartingState);
                        } else {
                        }
                    } else {
                    }
}
···
}

在这里面就会进行加载驱动,并且启动supplicant,完成之后就会切换到SupplicantStartingState。之后就会调用JNI的接口,进行驱动的加载,启动supplicant
具体实现是在wifi.c中。
1.Wifi驱动的加载
调用流程为:WifiNative.loadDriver->com_android_server_WifiNative.loadDriver->wifi.wifi_load_driver

int wifi_load_driver()
{
···
    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
        return -1;
···
}

这里面的DRIVER_MODULE_PATH对应/system/lib/modules/wlan.ko
2.启动supplicant
supplicant的启动流程为:WifiNative.startSupplicant->com_android_server_WifiNative.android_net_wifi_startSupplicant->wifi.wifi_start_supplicant

int wifi_start_supplicant(int p2p_supported)
{
···
	property_get("wifi.interface", primary_iface, WIFI_TEST_INTERFACE);
    property_set("ctl.start", supplicant_name);
···
}

接下来就是调用启动supplicant的service.这个service是在init.rc中注册的。
下面看一下init.rc中是如何注册这个service的

···
service wpa_supplicant /system/bin/wpa_supplicant \
    -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf \
    -I/system/etc/wifi/wpa_supplicant_overlay.conf \
    -O/data/misc/wifi/sockets -dd \
    -e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
    #   we will start as root and wpa_supplicant will switch to user wifi 
    #   after setting up the capabilities required for WEXT 
    #   user wifi 
    #   group wifi inet keystore
    class main 
    socket wpa_wlan0 dgram 660 wifi wifi 
    disabled
    oneshot
···

这里面就是启动supplicant。

supplicant启动完之后就是启动driver。
WifiController驱动启动的函数实现如下:

    public void setDriverStart(boolean enable) {
        if (enable) {
            sendMessage(CMD_START_DRIVER);
        } else {
            sendMessage(CMD_STOP_DRIVER);
        }
    }

这个命令之后就会自动的去连接之前连接过的Wifi。

你可能感兴趣的:(Wifi)