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。

更多相关文章

  1. android failed to start daemon 问题
  2. Android(安卓)+ Axis2
  3. Android(安卓)8.1.0 SystemUI 修改之 - 系统锁屏状态下点击用户
  4. Android(安卓)5.1 启动有线网卡并为其分配静态IP地址
  5. [ZZ][Android]使用bindService启动服务
  6. OpenCV Android(安卓)通过 jni调用 使用opencv (Android(安卓)St
  7. Android(安卓)N调用系统安装APK方法报错原因整理及解决方案
  8. Linux/Android(安卓)NDK wchar_t 陷阱
  9. android 2.1 监听电话状态并自动接听来电

随机推荐

  1. Android(安卓)渐变色TextView
  2. do you know any crossplatform sound ef
  3. 一些 android 项目
  4. android 使用数据库事务提高操作效率
  5. Android工具包
  6. springmvc服务端+android客户端的文件上
  7. adb连接不上模拟器的问题
  8. Android中获取SQL Server中的数据
  9. android 音效
  10. android添加各种权限整理