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.
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是如何打开的
上面已经提到WifiController是继承自StateMachine。至于StateMachine是如何工作的这里不详细介绍。下图描述了各个state的关系:
根据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相当于Wifi的大脑,维护着wifi的状态。同WifiController一样,WifiStateMachine也是继承自StateMachine。
在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。