android Wifi热点启动流程,[android]WIFI热点启动流程分析

WIFI热点是用软件实现AP的功能,让你的移动设备可以作为一个路由,让别的站点链接,事实上需要硬件以及驱动的支持才能真正的实现这个功能。

在android系统的设置中会有如下界面:

0818b9ca8b590ca3270a3433284dd417.png

主要的开关代码在设置模块中:

Packages/apps/Settings/src/com/android/settings/TetherSettings.java

|----private void startTethering()

|  |-----mWifiApEnabler.setSoftapEnabled(true);

Packages/apps/Settings/src/com/android/settings/wifi/WifiApEnabler.java

|----public void setSoftapEnabled (Booleanenable)

|  |-----mWifiManager.setWifiApEnabled(null,enable);

在WifiApEnabler.java中调用了WifiManager.java的setWifiApEnabled()函数,即代码走到了框架层。

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

|----public booleansetWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)

|    |----mService.setWifiApEnabled(wifiConfig, enabled);

IWifiManager.aidl

|----void setWifiApEnabled(WifiConfigurationwifiConfig, boolean enable);

frameworks/base/services/java/com/android/server/WifiService.java

|----public void setWifiApEnabled(WifiConfigurationwifiConfig, boolean enabled)

|  |----mWifiController.obtainMessage(CMD_SET_AP, enabled ? 1:0,0,wificonfig ).sendToTarget();

frameworks/base/services/java/com/android/server/wifi/WifiController.java

WifiController.java本身没有obtainMessage()函数,继承于StateMachine.java,使用StateMachine.java的obtainMessage()函数发送消息。

至此从WIFI热点被触发后,一直走到了状态机,由状态机进行相应处理,下面分析下状态机中的运作。

mWifiController调用了状态机的obtainMessage()函数,之后会将消息发送出去。状态机发送消息使用sendMessage()函数。

0818b9ca8b590ca3270a3433284dd417.png

StateMachine.java重写了很多sendMessage()函数以适应参数不同的消息发送。在sendMessage函数中定义了smh,类SmHandler继承于Handler类,Handler是大家熟悉的消息处理机制。首先通过smh发送消息,且SmHandler复写了Handler的handleMessage()、processMsg()函数用于对消息的处理。

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

processMsg()函数根据不同的状态进行处理,WifiController.java中有很多状态,每一个都有复写自己的processMessage方法,根据发送的命令进行判断处理。

0818b9ca8b590ca3270a3433284dd417.png

mWifiController.obtainMessage(CMD_SET_AP,enabled ? 1:0,0, wificonfig ).sendToTarget();发送的消息将会在ApStaDisabledState中被捕获并进行相应处理,

0818b9ca8b590ca3270a3433284dd417.png

根据发送的消息,Msg.arg1==1条件成立,因此执行WIFI状态机中的setHostApRunning()函数,该函数根据enable的值发送打开AP或者关闭AP命令,也即从现在开始转入了WIFI状态机进行处理。

WifiStateMachine.java同样继承于StateMachine.java,里面也有很多状态,如下:

0818b9ca8b590ca3270a3433284dd417.png

每个状态都复写有自己的processMessage方法,根据发送的命令进行判断处理。发送的CMD_START_AP命令首先会在InitialState状态被处理。通过mWifiNative.loadDriver()启动驱动,WifiNative.java是调用底层的loadDriver()函数加载驱动(底层不熟悉,这里不再往下深究)。

0818b9ca8b590ca3270a3433284dd417.png

若驱动加载成功则设置热点状态为WIFI_AP_STATE_ENABLING,然后将状态机的状态转到mSoftApStartingState。

setWifiApState()函数如下截图所示,首先获取前面WIFI AP的状态,根据传进来的状态若已经打开则电池状态开始记录Wifi相关,WIFI AP已经关闭,则电池状态对WIFI的记录关闭。更新WIFI AP的状态,并将状态消息发送至WifiManager进行进一步处理。

0818b9ca8b590ca3270a3433284dd417.png

在mSoftApStartingState状态,获取WIFI的配置信息,根据配置信息执行不同操作。

若config为null会发送获取配置信息命令mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG)。

在InitialState状态的时候对mWifiApConfigChannel设置了handler:

mWifiApConfigChannel.connectSync(mContext, getHandler(), wifiApConfigStore.getMessenger());

继而CMD_REQUEST_AP_CONFIG的消息处理是在WifiApConfigStore中处理的,

当前WIFI状态机状态为SoftApStartingState,所以回复消息在这里处理:如果配置文件存在就继续开启AP , 如果配置文件为空则开启失败,发送个消息CMD_START_AP_FAILURE卸载驱动,并更改状态为AP开启失败 。

配置文件是通过WifiManager的setWifiApConfiguration接口生成的,最后实现都交给了WIFI状态机,然后WIFI状态机将消息交给WifiApConfigStore处理。

WifiApConfigStore在构造的时候分mDefaultState分配了两个子状态mInactiveState, mActiveState,初始化状态为mInactiveState。

在ActiveState状态将配置信息写入文件,默认文件路径即为/misc/wifi/softap.conf,写好后发送CMD_SET_AP_CONFIG_COMPLETED命令。后续就使用该配置文件开启AP。

若config不为null

调用startSoftApWithConfig()函数根据配置信息打开SoftAp,startSoftApWithConfig()函数重开一个新线程用于打开SoftAp,最后发送CMD_START_AP_SUCCESS命令通知打开热点成功。

mNwService.startAccessPoint(config,mInterfaceName) config即为之前生成的配置文件,mInterfaceName为WifiStateMachine构造时传递下来的参数,而这个构造动作由WifiService构造的时候发起。

可见,这个mInterfaceName由prop wifi.interface控制,如我们经常能在build.prop中看到wifi.interface=eth0/wlan0等,如果没有会默认给wlan0。

接下来看startAccessPoint的实现(frameworks/base/services/java/com/android/server/NetworkManagementService.java):

最终都是通过mConnector.execute来执行命令,mConnector是在构造时生成的NativeDaemonConnector对象,查看一下NativeDaemonConnector的构造过程(frameworks/base/services/java/com/android/server/NativeDaemonConnector.java):

mSocket也就是在NetworkManagementService中始终监听的那个local socket,在这里

构造完成后,会new出一个线程,这个线程的工作就是调用listenToSocket。

最后WIFI状态机捕获到CMD_START_AP_SUCCESS命令,并进行相应的状态转换,如下,设置热点状态为WIFI_AP_STATE_ENABLED,然后将状态机的状态转到mSoftApStartedState。

上面简要的介绍了WIFI热点的打开流程,关于WIFI热点的关闭流程与打开流程差不多,只是上层发送的命令不同而已,在此不赘述。

旨在交流学习,大家轻拍~~

你可能感兴趣的:(android,Wifi热点启动流程)