Android(安卓)Wifi 启动过程分析
Wifi系统框图
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的关系:
根据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 {@Overridepublic 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。
在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。
更多相关文章
- android failed to start daemon 问题
- Android(安卓)+ Axis2
- Android(安卓)8.1.0 SystemUI 修改之 - 系统锁屏状态下点击用户
- Android(安卓)5.1 启动有线网卡并为其分配静态IP地址
- [ZZ][Android]使用bindService启动服务
- OpenCV Android(安卓)通过 jni调用 使用opencv (Android(安卓)St
- Android(安卓)N调用系统安装APK方法报错原因整理及解决方案
- Linux/Android(安卓)NDK wchar_t 陷阱
- android 2.1 监听电话状态并自动接听来电