GC-WB150 支持softap配置ics失败吗

当前位置:
→ TL-WN725N如何设置模拟AP TL-WN725N设置模拟AP教程
本类常用软件
下载量:358638
下载量:229067
下载量:209966
下载量:209618
下载量:209315
TL-WN725N如何设置模拟AP TL-WN725N设置模拟AP教程
18:05:04&&出处:&&&人气:229次&&&&字号:&&&&
东坡下载 & 分享互联网
Copyright(C)
All Rights Reserved! 网站备案/许可证号:鄂ICP备号-1分类:&&6454人阅读&&&
SoftAP 打开时调用的相关函数解析
Softap字面意思是用软件实现AP的功能,让你的移动设备可以作为一个路由,让别的站点链接。比如让别人的手机连上你的已经打开AP功能的手机,玩联机游戏或者上网等等
但事实上此功能是需要硬件以及驱动的支持才能真正的实现的。
Softap打开流程。
&&&&&&& 在Android系统的Setting界面的wireless配置项中会看到一个“Portable Wi-Fi hotspot” 跟一个&Configure Wi-Fi hotspot setting&选项,可以进入系统配置AP的名称,加密方式,密码等。 如下图
& & & & 当你做完这些设置,系统接受的AP设置界面变化打开的响应,从此开启了整个Android SoftAP的序幕。
首先./packages/apps/Settings/src/com/android/settings/TetherSettings.java 的onPreferenceChange 函数接收到Softap状态改变信息
&Softap开启时,enable 为真,因而执行startProvisioningIfNecessary(WIFI_TETHERING);
isProvisioningNeeded 用来检测是否需要进行一些准备工作
如果无需准备工作则执行startTethering& 大戏即将上演了 期待ing&
这里 mTetherChoice == WIFI_TETHERING 所以继而执行WiFiApEnable.java中的setSoftapEnabled(true)函数
也从此处也跳出了Setting的代码 跳入了Android WIFI 子系统的framework层
./packages/apps/Settings/src/com/android/settings/wifi/WifiApEnabler.java
上面的代码中我们看到了Google人的考虑事情的周全。首先检测Wifi当前状态如果正在打开或者已经打开则关闭WIFI并将此状态记录下来,以便关闭softap时它能自动恢复到之前打开wifi的状态。 Android代码不愧牛X,这些都能想到...& 崇拜那些大牛。
这里调用mWifiManager.setWifiApEnabled(null, enable)&&& &frameworks/base/wifi/java/android/net/wifi/WifiManager.java&
转向服务层的 setWifiApEnabled& &frameworks/base/services/java/com/android/server/WifiService.java&
从而调用到最基础的也是最重要的Wifi状态机中的&&&setWifiApEnabled&实例 其实我真搞不懂为什么Android代码要嵌套这么多层去调用,为了安全、方便... 哪个牛人解释一下。
&frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java&
&&&&&&& 发送CMD_LOAD_DRIVER状态迁移到mDriverLoadingState 加载AP对应的驱动 这里把WIFI的驱动跟 AP的驱动做了区分,可见SoftAP不仅仅是软件实现的,需要硬件驱动的相应支持。
加载驱动成功后 系统迁移到mDriverLoadedState 状态
接收到&CMD_START_AP消息 &状态又被迁移至mSoftApStartingState
&SoftApStartingState 会检测上层传下的参数的有效性并调用startSoftApWithConfig 配置、打开SoftAP
获取SoftAp的网络配置AP名称 加密方式密码....
进行系统驱动(硬件)的配置。
这里调用到了&frameworks/base/services/java/com/android/server/NetworkManagementService.java& 中的startAccessPoint函数
函数如下:
1、下载AP对应的&firmware
wifiFirmwareReload(wlanIface, &AP&);
2、设置ap的ssid 加密方式 以及密码
mConnector.execute(&softap&, &set&, wlanIface, wifiConfig.SSID, getSecurityType(wifiConfig), wifiConfig.preSharedKey);
3、运行softap
mConnector.execute(&softap&, &startap&);
&这里通过一个NativeDaemonConnector的实例mConnector 调用c++程序 具体的实现我是没看懂 但是知道最后实际调用的函数, 想深入了解可以找一些其他的资料看
实际调用到了 &./system/netd/CommandListener.cpp& 中的CommandListener::SoftapCmd::runCommand
首先是&set“ 命令, 调用到c = sSoftapCtrl-&setSoftap(argc, argv); 来配置网络
配置即将所有上层的网络设置写到HOSTAPD_CONF_FILE[]&&& = &/data/misc/wifi/hostapd.conf& 中
(&system/netd/SoftapController.cpp&)
然后是&startap&命令调用rc = sSoftapCtrl-&startSoftap(); 真正开启Softap&
在startSoftap函数中调用了
execl(&/system/bin/hostapd&, &/system/bin/hostapd&, &-e&, WIFI_ENTROPY_FILE, HOSTAPD_CONF_FILE, (char *) NULL)
这里hostapd就是softap的deamon 程序 类似于wifi的的wpa_supplicant
至此所有wifi子系统从界面打开softap 到如何运行调用到deamon程序打开Softap的流程就是这样的
之后会介绍到Setting 界面&Portable Wi-Fi&的开启 以及& Hostapd 的一些东东&
分类:&LINUX
=====================================================
安卓相关的网络配置
=====================================================
=====================================================
hostapd 配置命令
=====================================================
/system/bin/hostapd -e/data/misc/wifi/entropy.bin /data/misc/wifi/hostapd.conf &
=====================================================
wpa_supplicant -iwlan0 -Dwext -c/system/etc/wifi/wpa_supplicant.conf -dd -B
wpa_supplicant -iwlan0 -Dnl80211 -c/system/etc/wifi/wpa_supplicant.conf &-B
wpa_supplicant -iwlan0 -Dwext -c/data/misc/wifi/wpa_supplicant.conf -dd -B
wpa_supplicant -iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf -dd -B
=====================================================
=====================================================
wpa_cli -iwlan0 scan
wpa_cli -iwlan0 scan_results
wpa_cli -iwlan0 remove_network 0
wpa_cli -iwlan0 add_network
wpa_cli -iwlan0 set_network 0 ssid '&henryking&'
wpa_cli -iwlan0 set_network 0 key_mgmt WPA-PSK
wpa_cli -iwlan0 set_network 0 key_mgmt NONE
wpa_cli -iwlan0 set_network 0 psk '&&'
wpa_cli -iwlan0 set_network 0 wep_key0 123456
wpa_cli -iwlan0 set_network 0 wep_tx_keyidx 0
wpa_cli -iwlan0 select_network 0
wpa_cli -iwlan0 save_config
wpa_cli -iwlan0 list_networks
wpa_cli -iwlan0 add_wpa_cli -iwlan0 set_network 0 ssid '&&';wpa_cli -iwlan0 set_network 0 psk '&&';wpa_cli -iwlan0 select_network 0
=====================================================
wpa_cli -irausb0 scan
wpa_cli -irausb0 scan_results
wpa_cli -irausb0 add_network
wpa_cli -irausb0 set_network 0 ssid '&henry&'
wpa_cli -irausb0 set_network 0 psk '&&'
wpa_cli -irausb0 set_network 0 key_mgmt WPA-PSK
wpa_cli -irausb0 set_network 0 key_mgmt NONE
wpa_cli -irausb0 select_network 0
wpa_cli -irausb0 enable_network 0
wpa_cli -irausb0 ap_scan '&1&'
wpa_cli -irausb0 save_config
=====================================================
=====================================================
=====================================================
=====================================================
iwpriv 配置网络
=====================================================
=====================================================
iwpriv rausb0 set NetworkType=Infra
iwpriv rausb0 set AuthMode=WPA2PSK
iwpriv rausb0 set EncrypType=AES
iwpriv rausb0 set SSID=&sabre&
iwpriv rausb0 set WPAPSK=&&
iwpriv rausb0 set NetworkType=Iiwpriv rausb0 set AuthMode=WPA2PSK;iwpriv rausb0 set EncrypType=AES;iwpriv rausb0 set WPAPSK=&&;iwpriv rausb0 set SSID=&henryking&;
iwpriv rausb0 set NetworkType=Iiwpriv rausb0 set AuthMode=WPAPSK;iwpriv rausb0 set EncrypType=AES;iwpriv rausb0 set SSID=&&;iwpriv rausb0 set WPAPSK=&&
iwpriv rausb0 set NetworkType=Iiwpriv wlan0 set AuthMode=WPAPSK;iwpriv wlan0 set EncrypType=AES;iwpriv wlan0 set WPAPSK=&&;iwpriv wlan0 set SSID=&henryking&;
=====================================================
=====================================================
iwpriv rausb0 set AuthMode=SHARED
iwpriv rausb0 set EncrypType=WEP
iwpriv rausb0 set DefaultKeyID=1
iwpriv rausb0 set Key1=&&
iwpriv rausb0 set SSID=&sabre&
=====================================================
iwconfig wlan0 essid &sabre&
iwconfig wlan0 key
=====================================================
=====================================================
mstar wifi配置
=====================================================
wpa_supplicant -Dwext -iwlan0 -c /usr/bin/wpa_0_8.conf -B
ifconfig wlan0 up
wpa_cli -iwlan0 -p/var/run/wpa_supplicant scan
wpa_cli -iwlan0 -p/var/run/wpa_supplicant scan_results
wpa_cli -iwlan0 -p/var/run/wpa_supplicant ap_scan 1
wpa_cli -iwlan0 -p/var/run/wpa_supplicant add_network&
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 ssid '&henryking&'&
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 key_mgmt WPA-PSK
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 proto WPA2
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 pairwise CCMP
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 group CCMP
wpa_cli -iwlan0 -p/var/run/wpa_supplicant set_network 0 psk '&&'&
wpa_cli -iwlan0 -p/var/run/wpa_supplicant select_network 0
=====================================================
=====================================================
=====================================================
wpa_supplicant.conf
=====================================================
linux下格式:
=====================================================
update_config=1
ctrl_interface=/var/run/wpa_supplicant
& & & & ssid=&henry&
& & & & psk=&&
& & & & key_mgmt=WPA-PSK
=====================================================
Android下格式:
=====================================================
update_config=1
ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi
eapol_version=1
fast_reauth=1
=====================================================
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:1279213次
积分:12881
积分:12881
排名:第461名
原创:49篇
转载:690篇
评论:178条
(7)(3)(5)(11)(4)(5)(9)(6)(4)(8)(8)(10)(13)(10)(21)(24)(6)(4)(29)(19)(12)(24)(12)(4)(6)(5)(16)(27)(23)(17)(5)(15)(23)(50)(6)(5)(19)(11)(9)(2)(13)(15)(19)(1)(2)(2)(11)(8)(2)(14)(1)(9)(6)(8)(2)(2)(29)(41)(24)(36)当前访客身份:游客 [
:gpio-220 (gpio_kp_in ) in hi 这个 hi 是什么?...
:表达的很清晰,赞一个
:大牛,我没看懂。。。。 请问你是怎么分析的??...
:很好,支持
:引用来自“icyfox”的评论请教一下博主,4.2的手...
:架构分析
:请教一下博主,4.2的手机,可以在电脑上显示手机...
:请教博主,能获取到手机通过wifi display功能连接...
:这个是在android4.2以下才是这样开发的。现在都是...
今日访问:1
昨日访问:26
本周访问:1
本月访问:27
所有访问:44226
Softap热点原理分析
发表于2年前( 17:30)&&
阅读(617)&|&评论()
0人收藏此文章,
Softap 热点
Android4.1.2
设置中开关:
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(boolean enable)
| & & |----mWifiManager.setWifiApEnabled(null, enable)
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
|----public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
| & & |----mService.setWifiApEnabled(wifiConfig, enabled);
IWifiManager.aidl
|----void setWifiApEnabled(in WifiConfiguration wifiConfig, boolean enable);
frameworks/base/services/java/com/android/server/WifiService.java
|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled)
| & & |----mWifiStateMachine.setWifiApEnabled(wifiConfig, enabled);
frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java
|----public void setWifiApEnabled(WifiConfiguration wifiConfig, boolean enable)
| & & |----sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));
| & & |----sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
斗胆分析一下状态机的运作
WifiStateMachine 继承于StateMachine, 而在WifiStateMachine中未有对sendMessage方法的复写,所以实现是使用父类的实现:
&*&Enqueue&a&message&to&this&state&machine.&
public&final&void&sendMessage(int&what)&{&&
&&&&//&mSmHandler&can&be&null&if&the&state&machine&has&quit.&&
&&&&if&(mSmHandler&==&null)&&&
&&&&mSmHandler.sendMessage(obtainMessage(what));&&
&*&Enqueue&a&message&to&this&state&machine.&
public&final&void&sendMessage(int&what,&Object&obj)&{&&
&&&&//&mSmHandler&can&be&null&if&the&state&machine&has&quit.&&
&&&&if&(mSmHandler&==&null)&&&
&&&&mSmHandler.sendMessage(obtainMessage(what,obj));&&
&*&Enqueue&a&message&to&this&state&machine.&
public&final&void&sendMessage(Message&msg)&{&&
&&&&//&mSmHandler&can&be&null&if&the&state&machine&has&quit.&&
&&&&if&(mSmHandler&==&null)&&&
&&&&mSmHandler.sendMessage(msg);&&
可见,mSmHandler的定义是类SmHandler, 继承于Handler,&SmHandler对handleMessage进行了复写,所以对于消息的接收处理应该是在SmHandler的handleMessage中:
&*&Handle&messages&sent&to&the&state&machine&by&calling&
&*&the&current&state's&processMessage.&It&also&handles&
&*&the&enter/exit&calls&and&placing&any&deferred&messages&
&*&back&onto&the&queue&when&transitioning&to&a&new&state.&
@Override&&
public&final&void&handleMessage(Message&msg)&{&&
&&&&if&(mDbg)&Log.d(TAG,&"handleMessage:&E&msg.what="&+&msg.what);&&
&&&&/**&Save&the&current&message&*/&&
&&&&mMsg&=&&&
&&&&if&(mIsConstructionCompleted)&{&&&&//正常的操作&&
&&&&&&&&/**&Normal&path&*/&&
&&&&&&&&processMsg(msg);&&
&&&&}&else&if&(!mIsConstructionCompleted&&&&&
&&&&&&&&&&&&(mMsg.what&==&SM_INIT_CMD)&&&&(mMsg.obj&==&mSmHandlerObj))&{&&&&//初始化操作&&
&&&&&&&&/**&Initial&one&time&path.&*/&&
&&&&&&&&mIsConstructionCompleted&=&&&
&&&&&&&&invokeEnterMethods(0);&&
&&&&}&else&{&&
&&&&&&&&throw&new&RuntimeException("StateMachine.handleMessage:&"&+&&
&&&&&&&&&&&&&&&&&&&&"The&start&method&not&called,&received&msg:&"&+&msg);&&
&&&&performTransitions();&&&&//应用改变&&
&&&&if&(mDbg)&Log.d(TAG,&"handleMessage:&X");&&
processMsg(msg):
&*&Process&the&message.&If&the&current&state&doesn't&handle&
&*&it,&call&the&states&parent&and&so&on.&If&it&is&never&handled&then&
&*&call&the&state&machines&unhandledMessage&method.&
private&final&void&processMsg(Message&msg)&{&&
&&&&StateInfo&curStateInfo&=&mStateStack[mStateStackTopIndex];&&&&//获取当前状态&&
&&&&if&(mDbg)&{&&
&&&&&&&&Log.d(TAG,&"processMsg:&"&+&curStateInfo.state.getName());&&
&&&&}&&&&&&
&&&&while&(!curStateInfo.state.processMessage(msg))&{&&&&//判断该消息是否处理&&
&&&&&&&&/**&&&
&&&&&&&&&*&Not&processed&
&&&&&&&&&*/&&
&&&&&&&&curStateInfo&=&curStateInfo.parentStateI&&
&&&&&&&&if&(curStateInfo&==&null)&{&&
&&&&&&&&&&&&/**&&&
&&&&&&&&&&&&&*&No&parents&left&so&it's&not&handled&
&&&&&&&&&&&&&*/&&
&&&&&&&&&&&&mSm.unhandledMessage(msg);&&
&&&&&&&&&&&&if&(isQuit(msg))&{&&
&&&&&&&&&&&&&&&&transitionTo(mQuittingState);&&&&//设置状态&&
&&&&&&&&&&&&}&&&&&&
&&&&&&&&&&&&&&
&&&&&&&&}&&&&&&
&&&&&&&&if&(mDbg)&{&&
&&&&&&&&&&&&Log.d(TAG,&"processMsg:&"&+&curStateInfo.state.getName());&&
&&&&&&&&}&&&&&&
&&&&}&&&&&
在WifiStateMachine中有很多状态,截取几个来看:
/*&Loading&the&driver&*/&&
private&State&mDriverUnloadedState&=&new&DriverUnloadedState();&&
/*&Driver&load/unload&failed&*/&&
private&State&mDriverFailedState&=&new&DriverFailedState();&&
/*&Driver&loading&*/&&
private&State&mDriverLoadingState&=&new&DriverLoadingState();&&
/*&Driver&loaded&*/&&
private&State&mDriverLoadedState&=&new&DriverLoadedState();&&
以上4个都是关于Wifi驱动加载与卸载的相关状态,每一个都有复写自己的processMessage方法,比如DriverUnloadedState():
@Override&&
public&boolean&processMessage(Message&message)&{&&
&&&&if&(DBG)&log(getName()&+&message.toString()&+&"\n");&&
&&&&switch&(message.what)&{&&
&&&&&&&&case&CMD_LOAD_DRIVER:&&
&&&&&&&&&&&&transitionTo(mDriverLoadingState);&&
&&&&&&&&&&&&&&
&&&&&&&&default:&&
&&&&&&&&&&&&return&NOT_HANDLED;&&
&&&&return&HANDLED;&&
这说明,在状态是“Wifi驱动已经成功卸载”时,系统只响应(handle)CMD_LOAD_DRIVER的消息,也就是驱动加载命令,其他一概不管。很符合逻辑吧。
假设,在打开Wifi热点的时候,驱动就是卸载的(默认状态),那么 sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0));过后会来到这里,也就会将新的状态mDriverLoadingState加入状态栈。随后返回HANDLED,另一种NOT_HANDLED就 不做讨论了。那么现在的流程变成了processMsg(msg) --& transitionTo(mDriverLoadingState) --& performTransitions(),所以在分析performTransitions()之前要先看看transitionTo(实现在父类 StateMachine中):
/**&@see&StateMachine#transitionTo(IState)&*/&&
private&final&void&transitionTo(IState&destState)&{&&
&&&&mDestState&=&(State)&destS&&
&&&&if&(mDbg)&Log.d(TAG,&"transitionTo:&destState="&+&mDestState.getName());&&
由于State是IState的子类,所以这样的参数传递进去没有问题,mDestState目标状态变成了mDriverLoadingState,然后是performTransitions()(还是在父类StateMachine中):
&&&&&&&&/**&
&&&&&&&&&*&Do&any&transitions&
&&&&&&&&&*/&&
&&&&&&&&private&void&performTransitions()&{&&
&&&&&&&&&&&&/**&
&&&&&&&&&&&&&*&If&transitionTo&has&been&called,&exit&and&then&enter&
&&&&&&&&&&&&&*&the&appropriate&states.&We&loop&on&this&to&allow&
&&&&&&&&&&&&&*&enter&and&exit&methods&to&use&transitionTo.&
&&&&&&&&&&&&&*/&&
&&&&&&&&&&&&State&destState&=&&&
&&&&&&&&&&&&while&(mDestState&!=&null)&{&&//即transitionTo设置的新状态&mDriverLoadingState&&
&&&&&&&&&&&&&&&&if&(mDbg)&Log.d(TAG,&"handleMessage:&new&destination&call&exit");&&
&&&&&&&&&&&&&&&&/**&
&&&&&&&&&&&&&&&&&*&Save&mDestState&locally&and&set&to&null&
&&&&&&&&&&&&&&&&&*&to&know&if&enter/exit&use&transitionTo.&
&&&&&&&&&&&&&&&&&*/&&
&&&&&&&&&&&&&&&&destState&=&mDestS&&
&&&&&&&&&&&&&&&&mDestState&=&&&
&&&&&&&&&&&&&&&&/**&
&&&&&&&&&&&&&&&&&*&Determine&the&states&to&exit&and&enter&and&return&the&
&&&&&&&&&&&&&&&&&*&common&ancestor&state&of&the&enter/exit&states.&Then&
&&&&&&&&&&&&&&&&&*&invoke&the&exit&methods&then&the&enter&methods.&
&&&&&&&&&&&&&&&&&*/&&
&&&&&&&&&&&&&&&&StateInfo&commonStateInfo&=&setupTempStateStackWithStatesToEnter(destState);&&//将状态装入临时队列&&
&&&&&&&&&&&&&&&&invokeExitMethods(commonStateInfo);&&&&//将该状态之前的所有状态全部退出&&
&&&&&&&&&&&&&&&&int&stateStackEnteringIndex&=&moveTempStateStackToStateStack();&&&&//把临时队列合并至标准队列,并且返回界限值stateStaclEnteringIndex&&
&&&&&&&&&&&&&&&&invokeEnterMethods(stateStackEnteringIndex);&&&&//遍历执行自界限值到队列顶部的所有状态的enter方法,如下图所示:&&
&&&&|-------------|&
High|&&&stack_x&&&|&&mStateStackTopIndex&
&&&&|-------------|&
&&&&|&&&.....&&&&&|&
&&&&|-------------|&
&&&&|&&&stack_y&&&|&&stateStackEnteringIndex&&以上都是从Temp临时队列合并来的&
&&&&|-------------|&
&&&&|&&&.....&&&&&|&
&&&&|-------------|&
Low&|&&&stack_1&&&|&
&&&&|-------------|&
&*&Since&we&have&transitioned&to&a&new&state&we&need&to&have&
&*&any&deferred&messages&moved&to&the&front&of&the&message&queue&
&*&so&they&will&be&processed&before&any&other&messages&in&the&
&*&message&queue.&
&*/&moveDeferredMessageAtFrontOfQueue();&//将所有延迟消息再次发送到队列顶部,随后清除延迟消息队列。&}&&&
&*&After&processing&all&transitions&check&and&
&*&see&if&the&last&transition&was&to&quit&or&halt.&
&&&&&&&&&&&&if&(destState&!=&null)&{&&&&//以下检查状态是否是需求退出或挂起的,是则进行相应处理&&
&&&&&&&&&&&&&&&&if&(destState&==&mQuittingState)&{&&
&&&&&&&&&&&&&&&&&&&&cleanupAfterQuitting();&&
&&&&&&&&&&&&&&&&}&else&if&(destState&==&mHaltingState)&{&&
&&&&&&&&&&&&&&&&&&&&/**&
&&&&&&&&&&&&&&&&&&&&&*&Call&halting()&if&we've&transitioned&to&the&halting&
&&&&&&&&&&&&&&&&&&&&&*&state.&All&subsequent&messages&will&be&processed&in&
&&&&&&&&&&&&&&&&&&&&&*&in&the&halting&state&which&invokes&haltedProcessMessage(msg);&
&&&&&&&&&&&&&&&&&&&&&*/&&
&&&&&&&&&&&&&&&&&&&&mSm.halting();&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
看了好多子函数,有点晕晕的。看得出来这个performTransitions()是对所有状态进行处理的关键节点,可能同一时间会受到很多 Message,而这些Message所携带的不同状态会被加入到一个临时队列中,然后会将标准队列顶端到此状态之前的所有状态都退出(也就是触发 exit()),并设置为非活跃,然后剔除。之后会将临时队列合并入标准队列,取得一个界限值,从界限值到队列顶端依次激活(触发enter())。其实 在sendMessage的同时,还有一种消息处理方式就是deferMessage,是对消息的延迟发送,最终会将消息加入到一个延迟消息队列 mDeferredMessages中,每次的performTransitions()都会对延迟消息队列进行重新发送并且清空它的队列。最后,还会检 测一下是否有特殊的状态需要处理,如退出和挂起。
WifiStateMachine.java
应该关注一下mDriverLoadingState了,前边看到这是一个DriverLoadingState(),enter()的主要内容是一个工作线程:
&&&&new&Thread(new&Runnable()&{&&
&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&mWakeLock.acquire();&&&&//整个过程需要wakelock保护&&
&&&&&&&&&&&&//enabling&state&&
&&&&&&&&&&&&switch(message.arg1)&{&&
&&&&&&&&&&&&&&&&case&WIFI_STATE_ENABLING:&&&&//打开WIFI&&
&&&&&&&&&&&&&&&&&&&&setWifiState(WIFI_STATE_ENABLING);&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&case&WIFI_AP_STATE_ENABLING:&&&&//打开WIFI&AP&&
&&&&&&&&&&&&&&&&&&&&setWifiApState(WIFI_AP_STATE_ENABLING);&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if(mWifiNative.loadDriver())&{&&&&// 加载Wifi驱动,WifiNative.java&--&&core/jni /android_net_wifi_Wifi.cpp&--&&hardware/libhardware_legacy/wifi.c&就是 insmod&xxx.ko,也许带参数blablabla&&
&&&&&&&&&&&&&&&&if&(DBG)&log("Driver&load&successful");&&
&&&&&&&&&&&&&&&&sendMessage(CMD_LOAD_DRIVER_SUCCESS);&&
&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&loge("Failed&to&load&driver!");&&
&&&&&&&&&&&&&&&&switch(message.arg1)&{&&
&&&&&&&&&&&&&&&&&&&&case&WIFI_STATE_ENABLING:&&
&&&&&&&&&&&&&&&&&&&&&&&&setWifiState(WIFI_STATE_UNKNOWN);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&case&WIFI_AP_STATE_ENABLING:&&
&&&&&&&&&&&&&&&&&&&&&&&&setWifiApState(WIFI_AP_STATE_FAILED);&&
&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&&&sendMessage(CMD_LOAD_DRIVER_FAILURE);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&mWakeLock.release();&&
&&&&&&&&}&&
&&&&}).start();&&
而这里可以快速的复习一下前边的流程,加载成功后会sendMessage(CMD_LOAD_DRIVER_SUCCESS),失败了就会发送 CMD_LOAD_DRIVER_FAILURE。当前的状态就是mDriverLoadingState,所以是DriverLoadingState 的processMessage来处理这两个消息了:
@Override&&
public&boolean&processMessage(Message&message)&{&&
&&&&if&(DBG)&log(getName()&+&message.toString()&+&"\n");&&
&&&&switch&(message.what)&{&&
&&&&&&&&case&CMD_LOAD_DRIVER_SUCCESS:&&
&&&&&&&&&&&&transitionTo(mDriverLoadedState);&&
&&&&&&&&&&&&&&
&&&&&&&&case&CMD_LOAD_DRIVER_FAILURE:&&
&&&&&&&&&&&&transitionTo(mDriverFailedState);&&
&&&&&&&&&&&&&&
&&&&&&&&case&CMD_LOAD_DRIVER:&&
&&&&&&&&case&CMD_UNLOAD_DRIVER:&&
&&&&&&&&case&CMD_START_SUPPLICANT:&&
&&&&&&&&case&CMD_STOP_SUPPLICANT:&&
&&&&&&&&case&CMD_START_AP:&&
&&&&&&&&case&CMD_STOP_AP:&&
&&&&&&&&case&CMD_START_DRIVER:&&
&&&&&&&&case&CMD_STOP_DRIVER:&&
&&&&&&&&case&CMD_SET_SCAN_MODE:&&
&&&&&&&&case&CMD_SET_SCAN_TYPE:&&
&&&&&&&&case&CMD_SET_COUNTRY_CODE:&&
&&&&&&&&case&CMD_SET_FREQUENCY_BAND:&&
&&&&&&&&case&CMD_START_PACKET_FILTERING:&&
&&&&&&&&case&CMD_STOP_PACKET_FILTERING:&&
&&&&&&&&&&&&deferMessage(message);&&
&&&&&&&&&&&&&&
&&&&&&&&default:&&
&&&&&&&&&&&&return&NOT_HANDLED;&&
&&&&return&HANDLED;&&
由此可见,加载成功后状态就变为mDriverLoadedState,失败了状态就是mDriverFailedState。回到DriverLoadingState的enter,setWifiApState:
private&void&setWifiApState(int&wifiApState)&{&&
&&&&final&int&previousWifiApState&=&mWifiApState.get();&&
&&&&try&{&&
&&&&&&&&if&(wifiApState&==&WIFI_AP_STATE_ENABLED)&{&&&&//WIFI&AP已经打开,则电池状态开始记录Wifi相关&&
&&&&&&&&&&&&mBatteryStats.noteWifiOn();&&
&&&&&&&&}&else&if&(wifiApState&==&WIFI_AP_STATE_DISABLED)&{&&&&//WIFI&AP已经关闭,则电池状态对WIFI的记录关闭&&
&&&&&&&&&&&&mBatteryStats.noteWifiOff();&&
&&&&&&&&}&&
&&&&}&catch&(RemoteException&e)&{&&
&&&&&&&&loge("Failed&to&note&battery&stats&in&wifi");&&
&&&&//&Update&state&&
&&&&mWifiApState.set(wifiApState);&&&&//设置WIFI&AP的状态,原子状态&&
&&&&if&(DBG)&log("setWifiApState:&"&+&syncGetWifiApStateByName());&&
&&&&//将状态消息发送至WifiManager进行进一步处理。终于脱离了状态机,回到WifiManager了。&&
&&&&final&Intent&intent&=&new&Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);&&
&&&&intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);&&
&&&&intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE,&wifiApState);&&
&&&&intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE,&previousWifiApState);&&
&&&&mContext.sendStickyBroadcast(intent);&&
PS:通过sendBroadcast中发出的intent在Reciever注册后才能正确收到,未注册的时候不能被接收,即使后面再次注册上也无法接受到。而sendStickyBroadcast发出的Intent当Reciever注册后就能收到Intent,即使注册发生在广播之后。也就是说sendStickyBroadcast安全性更高,能够保证广播不会丢失,而sendBroadcast有一定危险。
好 的,分析了这么久,只是有一条sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_AP_STATE_ENABLING, 0)),发送出状态广播给别人获取,在系统中一个很好的例子是桌面电源控件对这个状态进行接收,可以直观的理解为当ing的状态时某按钮是不可用的。
然后才是真正的开启动作:
sendMessage(obtainMessage(CMD_START_AP, wifiConfig));
假设加载成功,当前状态变成了mDriverLoadedState,那么去DriverLoadedState的processMessage寻找这个Message的处理方法:
case&CMD_START_AP:&&
&&&&transitionTo(mSoftApStartingState);&&
新的状态,mSoftApStartingState:
/*&Soft&ap&is&starting&up&*/&&
private&State&mSoftApStartingState&=&new&SoftApStartingState();&&
@Override&&
public&void&enter()&{&&
&&&&if&(DBG)&log(getName()&+&"\n");&&
&&&&EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED,&getName());&&
&&&&final&Message&message&=&getCurrentMessage();&&
&&&&if&(message.what&==&CMD_START_AP)&{&&&&//如果进入这个状态而不是打开AP,那么就直接抛出runtime异常,一般来说就是重启了。又一次验证了:不以结婚为目的的谈恋爱都是耍流氓。&&
&&&&&&&&final&WifiConfiguration&config&=&(WifiConfiguration)&message.&&
&&&&&&&&if&(config&==&null)&{&&
&&&&&&&&&&&&mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG,&config);&&
&&&&&&&&&&&&startSoftApWithConfig(config);&&
&&&&&&&&}&&
&&&&}&else&{&&
&&&&&&&&throw&new&RuntimeException("Illegal&transition&to&SoftApStartingState:&"&+&message);&&
OK, config为NULL,又是一个Message:
mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);&&
在WifiStateMachine构造的时候对mWifiApConfigChannel设置了handler:
mWifiApConfigChannel.connectSync(mContext,&getHandler(),&wifiApConfigStore.getMessenger());&&
WifiApConfigStore.java
CMD_REQUEST_AP_CONFIG的消息处理是在WifiApConfigStore中处理的:
class&DefaultState&extends&State&{&&
&&&&public&boolean&processMessage(Message&message)&{&&
&&&&&&&&switch&(message.what)&{&&
&&&&&&&&&&&&case&WifiStateMachine.CMD_SET_AP_CONFIG:&&
&&&&&&&&&&&&case&WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:&&
&&&&&&&&&&&&&&&&Log.e(TAG,&"Unexpected&message:&"&+&message);&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&case&WifiStateMachine.CMD_REQUEST_AP_CONFIG:&&
&&&&&&&&&&&&&&&&mReplyChannel.replyToMessage(message,&&
&&&&&&&&&&&&&&&&&&&&&&&&WifiStateMachine.CMD_RESPONSE_AP_CONFIG,&mWifiApConfig);&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&default:&&
&&&&&&&&&&&&&&&&Log.e(TAG,&"Failed&to&handle&"&+&message);&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&}&&&&&
&&&&&&&&return&HANDLED;&&
&&&&}&&&&&
当前WIFI状态机状态为SoftApStartingState,所以回复消息在这里处理:
@Override&&&&&
public&boolean&processMessage(Message&message)&{&&
&&&&if&(DBG)&log(getName()&+&message.toString()&+&"\n");&&
&&&&switch(message.what)&{&&
&&&&&&&&case&CMD_LOAD_DRIVER:&&
&&&&&&&&case&CMD_UNLOAD_DRIVER:&&
&&&&&&&&case&CMD_START_SUPPLICANT:&&
&&&&&&&&case&CMD_STOP_SUPPLICANT:&&
&&&&&&&&case&CMD_START_AP:&&&
&&&&&&&&case&CMD_STOP_AP:&&
&&&&&&&&case&CMD_START_DRIVER:&&
&&&&&&&&case&CMD_STOP_DRIVER:&&
&&&&&&&&case&CMD_SET_SCAN_MODE:&&
&&&&&&&&case&CMD_SET_SCAN_TYPE:&&
&&&&&&&&case&CMD_SET_COUNTRY_CODE:&&
&&&&&&&&case&CMD_SET_FREQUENCY_BAND:&&
&&&&&&&&case&CMD_START_PACKET_FILTERING:&&
&&&&&&&&case&CMD_STOP_PACKET_FILTERING:&&
&&&&&&&&case&CMD_TETHER_STATE_CHANGE:&&
&&&&&&&&&&&&deferMessage(message);&&
&&&&&&&&&&&&&&
&&&&&&&&case&WifiStateMachine.CMD_RESPONSE_AP_CONFIG:&&
&&&&&&&&&&&&WifiConfiguration&config&=&(WifiConfiguration)&message.&&&&//设置文件就是WifiApConfigStore中的mWifiApConfig&&
&&&&&&&&&&&&if&(config&!=&null)&{&&
&&&&&&&&&&&&&&&&startSoftApWithConfig(config);&&&&//如果配置文件存在就继续开启AP&&
&&&&&&&&&&&&}&else&{&&
&&&&&&&&&&&&&&&&loge("Softap&config&is&null!");&&&&//如果配置文件为空则开启失败,发送个消息CMD_START_AP_FAILURE,还是在本状态中处理&&
&&&&&&&&&&&&&&&&sendMessage(CMD_START_AP_FAILURE);&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&&&
&&&&&&&&case&CMD_START_AP_SUCCESS:&&
&&&&&&&&&&&&setWifiApState(WIFI_AP_STATE_ENABLED);&&
&&&&&&&&&&&&transitionTo(mSoftApStartedState);&&
&&&&&&&&&&&&&&
&&&&&&&&case&CMD_START_AP_FAILURE:&&
&&&&&&&&&&&&//&initiate&driver&unload&&
&&&&&&&&&&&&sendMessage(obtainMessage(CMD_UNLOAD_DRIVER,&WIFI_AP_STATE_FAILED,&0));&&//卸载驱动,并更改状态为AP开启失败&&
&&&&&&&&&&&&&&
&&&&&&&&default:&&
&&&&&&&&&&&&return&NOT_HANDLED;&&
&&&&}&&&&&
&&&&return&HANDLED;&&
这里的配置文件是通过WifiManager的setWifiApConfiguration接口生成的:
frameworks/base/wifi/java/android/net/wifi/WifiManager.java
&*&Sets&the&Wi-Fi&AP&Configuration.&
&*&@return&{@code&true}&if&the&operation&succeeded,&{@code&false}&otherwise&
&*&@hide&Dont&open&yet&
public&boolean&setWifiApConfiguration(WifiConfiguration&wifiConfig)&{&&
&&&&try&{&&
&&&&&&&&mService.setWifiApConfiguration(wifiConfig);&&
&&&&&&&&return&&&
&&&&}&catch&(RemoteException&e)&{&&&
&&&&&&&&return&&&
&&&&}&&&&&&
mService为IWifiManager,该接口定义如下:
void&setWifiApConfiguration(in&WifiConfiguration&wifiConfig);&&
而实现为WifiService
public&class&WifiService&extends&IWifiManager.Stub&&
&*&see&{@link&WifiManager#setWifiApConfiguration(WifiConfiguration)}&
&*&@param&wifiConfig&WifiConfiguration&details&for&soft&access&point&
public&void&setWifiApConfiguration(WifiConfiguration&wifiConfig)&{&&
&&&&enforceChangePermission();&&
&&&&if&(wifiConfig&==&null)&&
&&&&&&&&&&
&&&&mWifiStateMachine.setWifiApConfiguration(wifiConfig);&&
真是的实现有抛给了WifiStateMachine:
public&void&setWifiApConfiguration(WifiConfiguration&config)&{&&
&&&&mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG,&config);&&
消息交给WifiApConfigStore处理,而
WifiApConfigStore(Context&context,&Handler&target)&{&&
&&&&super(TAG,&target.getLooper());&&
&&&&mContext&=&&&
&&&&addState(mDefaultState);&&
&&&&&&&&addState(mInactiveState,&mDefaultState);&&
&&&&&&&&addState(mActiveState,&mDefaultState);&&
&&&&setInitialState(mInactiveState);&&
WifiApConfigStore在构造的时候分mDefaultState分配了两个子状态mInactiveState, mActiveState, 初始化状态为mInactiveState。
class&InactiveState&extends&State&{&&
&&&&public&boolean&processMessage(Message&message)&{&&
&&&&&&&&switch&(message.what)&{&&
&&&&&&&&&&&&case&WifiStateMachine.CMD_SET_AP_CONFIG:&&
&&&&&&&&&&&&&&&&mWifiApConfig&=&(WifiConfiguration)&message.&&
&&&&&&&&&&&&&&&&transitionTo(mActiveState);&&&&//触发ActiveState.enter()&&
&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&default:&&
&&&&&&&&&&&&&&&&return&NOT_HANDLED;&&
&&&&&&&&}&&&&&
&&&&&&&&return&HANDLED;&&
class&ActiveState&extends&State&{&&
&&&&public&void&enter()&{&&
&&&&&&&&new&Thread(new&Runnable()&{&&
&&&&&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&&&&&writeApConfiguration(mWifiApConfig);&&
&&&&&&&&&&&&&&&&sendMessage(WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED);&&
&&&&&&&&&&&&}&&
&&&&&&&&}).start();&&
writeApConfiguration实现:
private&void&writeApConfiguration(final&WifiConfiguration&config)&{&&
&&&&DataOutputStream&out&=&&&
&&&&try&{&&
&&&&&&&&out&=&new&DataOutputStream(new&BufferedOutputStream(&&
&&&&&&&&&&&&&&&&&&&&new&FileOutputStream(AP_CONFIG_FILE)));&&
&&&&&&&&out.writeInt(AP_CONFIG_FILE_VERSION);&&
&&&&&&&&out.writeUTF(config.SSID);&&
&&&&&&&&int&authType&=&config.getAuthType();&&
&&&&&&&&out.writeInt(authType);&&
&&&&&&&&if(authType&!=&KeyMgmt.NONE)&{&&
&&&&&&&&&&&&out.writeUTF(config.preSharedKey);&&
&&&&&&&&}&&
&&&&}&catch&(IOException&e)&{&&
&&&&&&&&Log.e(TAG,&"Error&writing&hotspot&configuration"&+&e);&&
&&&&}&finally&{&&
&&&&&&&&if&(out&!=&null)&{&&
&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&out.close();&&
&&&&&&&&&&&&}&catch&(IOException&e)&{}&&
&&&&&&&&}&&
默认文件路径即为/misc/wifi/softap.conf,写好配置文件后发送WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED,自己发自己收了:
public&boolean&processMessage(Message&message)&{&&
&&&&switch&(message.what)&{&&
&&&&&&&&//TODO:&have&feedback&to&the&user&when&we&do&this&&
&&&&&&&&//to&indicate&the&write&is&currently&in&progress&&
&&&&&&&&case&WifiStateMachine.CMD_SET_AP_CONFIG:&&
&&&&&&&&&&&&deferMessage(message);&&
&&&&&&&&&&&&&&
&&&&&&&&case&WifiStateMachine.CMD_SET_AP_CONFIG_COMPLETED:&&&&//修改完后切换状态到InactiveState&&
&&&&&&&&&&&&transitionTo(mInactiveState);&&
&&&&&&&&&&&&&&
&&&&&&&&default:&&
&&&&&&&&&&&&return&NOT_HANDLED;&&
&&&&return&HANDLED;&&
这样配置文件就配置完了,结果是保存在mWifiConfig中的。
带着配置文件开启AP
frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java & & &startSoftApWithConfig
/*&Current&design&is&to&not&set&the&config&on&a&running&hostapd&but&instead&
&*&stop&and&start&tethering&when&user&changes&config&on&a&running&access&point&
&*&TODO:&Add&control&channel&setup&through&hostapd&that&allows&changing&config&
&*&on&a&running&daemon&
private&void&startSoftApWithConfig(final&WifiConfiguration&config)&{&&
&&&&//&start&hostapd&on&a&seperate&thread&&
&&&&new&Thread(new&Runnable()&{&&
&&&&&&&&public&void&run()&{&&
&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&mNwService.startAccessPoint(config,&mInterfaceName,&SOFTAP_IFACE);&&
&&&&&&&&&&&&}&catch&(Exception&e)&{&&
&&&&&&&&&&&&&&&&loge("Exception&in&softap&start&"&+&e);&&
&&&&&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&&&&&mNwService.stopAccessPoint(mInterfaceName);&&
&&&&&&&&&&&&&&&&&&&&mNwService.startAccessPoint(config,&mInterfaceName,&SOFTAP_IFACE);&&
&&&&&&&&&&&&&&&&}&catch&(Exception&e1)&{&&
&&&&&&&&&&&&&&&&&&&&loge("Exception&in&softap&re-start&"&+&e1);&&
&&&&&&&&&&&&&&&&&&&&sendMessage(CMD_START_AP_FAILURE);&&
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&}&&
&&&&&&&&&&&&}&&
&&&&&&&&&&&&if&(DBG)&log("Soft&AP&start&successful");&&
&&&&&&&&&&&&sendMessage(CMD_START_AP_SUCCESS);&&
&&&&&&&&}&&
&&&&}).start();&&
逻辑就是尝试开启,如果发生错误就尝试重启,如果再错误就承认失败,发送失败状态,如果没错误就发送成功的消息。关键在mNwService的startAccessPoint方法中。
config, mInterfaceName, SOFTAP_IFACE
这三个参数:config为传递下来的配置文件,SOFTAP_IFACE为字符串wl0.1,mInterfaceName为WifiStateMachine构造时传递下来的参数,而这个构造动作由WifiService构造的时候发起:
&&&&WifiService(Context&context)&{&&
&&&&&&&&mContext&=&&&
&&&&&&&&mInterfaceName&=&&SystemProperties.get("wifi.interface",&"wlan0");&&
&&&&&&&&mWifiStateMachine&=&new&WifiStateMachine(mContext,&mInterfaceName);&&
&&&&&&&&mWifiStateMachine.enableRssiPolling(true);&&
可见,这个mInterfaceName由prop wifi.interface控制,如我们经常能在build.prop中看到wifi.interface=eth0/wlan0等,如果没有会默认给wlan0。
接下来看startAccessPoint的实现(frameworks/base/services/java/com/android/server/NetworkManagementService.java):
@Override&&
public&void&startAccessPoint(&&
&&&&&&&&WifiConfiguration&wifiConfig,&String&wlanIface,&String&softapIface)&{&&
&&&&mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL,&TAG);&&
&&&&try&{&&
&&&&&&&&Resources&resources&=&mContext.getResources();&&
&&&&&&&&if&(resources.getBoolean(com.android.internal.R.bool.config_wifiApFirmwareReload))&&
&&&&&&&&&&&&wifiFirmwareReload(wlanIface,&"AP");&&
&&&&&&&&if&(resources.getBoolean(com.android.internal.R.bool.config_wifiApStartInterface))&&
&&&&&&&&&&&&mConnector.execute("softap",&"start",&wlanIface);&&
&&&&&&&&if&(wifiConfig&==&null)&{&&
&&&&&&&&&&&&mConnector.execute("softap",&"set",&wlanIface,&softapIface);&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&mConnector.execute("softap",&"set",&wlanIface,&softapIface,&wifiConfig.SSID,&&
&&&&&&&&&&&&&&&&&&&&getSecurityType(wifiConfig),&wifiConfig.preSharedKey);&&
&&&&&&&&}&&&&&&
&&&&&&&&mConnector.execute("softap",&"startap");&&
&&&&}&catch&(NativeDaemonConnectorException&e)&{&&&
&&&&&&&&throw&e.rethrowAsParcelableException();&&
&&&&}&&&&&&
config_wifiApFirmwareReload、config_wifiApStartInterface都是可以用户自定义的xml配置接口,默认在frameworks/base/core/res/res/values/config.xml中,默认如:
&!--&Boolean&indicating&whether&Softap&requires&reloading&AP&firmware&--&&&
&bool&name="config_wifiApFirmwareReload"&true&/bool&&&
&!--&Boolean&indicating&whether&the&start&command&should&be&called&on&the&wireless&interface&&
&&&&&when&starting&the&SoftAp&--&&&
&bool&name="config_wifiApStartInterface"&false&/bool&&&
想关联的几个函数有:
private&static&String&getSecurityType(WifiConfiguration&wifiConfig)&{&&&&//获取网络安全类型&&
&&&&switch&(wifiConfig.getAuthType())&{&&
&&&&&&&&case&KeyMgmt.WPA_PSK:&&
&&&&&&&&&&&&return&"wpa-psk";&&
&&&&&&&&case&KeyMgmt.WPA2_PSK:&&
&&&&&&&&&&&&return&"wpa2-psk";&&
&&&&&&&&default:&&
&&&&&&&&&&&&return&"open";&&
&&&&}&&&&&&
/*&@param&mode&can&be&"AP",&"STA"&or&"P2P"&*/&&
@Override&&
public&void&wifiFirmwareReload(String&wlanIface,&String&mode)&{&&&&//根据不同模式装在不同的固件(如果有需要的话)&&
&&&&mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL,&TAG);&&
&&&&try&{&&
&&&&&&&&mConnector.execute("softap",&"fwreload",&wlanIface,&mode);&&
&&&&}&catch&(NativeDaemonConnectorException&e)&{&&&
&&&&&&&&throw&e.rethrowAsParcelableException();&&
&&&&}&&&&&&
通过以上不难看出,最终都是通过mConnector.execute来执行命令。
&*&Constructs&a&new&NetworkManagementService&instance&
&*&@param&context&&Binder&context&for&this&service&
private&NetworkManagementService(Context&context)&{&&
&&&&mContext&=&&&
&&&&if&("simulator".equals(SystemProperties.get("ro.product.device")))&{&&
&&&&&&&&&&
&&&&mConnector&=&new&NativeDaemonConnector(&&
&&&&&&&&&&&&new&NetdCallbackReceiver(),&"netd",&10,&NETD_TAG,&160);&&
&&&&mThread&=&new&Thread(mConnector,&NETD_TAG);&&
&&&&//&Add&ourself&to&the&Watchdog&monitors.&&
&&&&Watchdog.getInstance().addMonitor(this);&&
mConnector是在构造时生成的NativeDaemonConnector对象,查看一下NativeDaemonConnector的构造过程 (frameworks/base/services/java/com/android/server /NativeDaemonConnector.java):
NativeDaemonConnector(INativeDaemonConnectorCallbacks&callbacks,&String&socket,&&
&&&&&&&&int&responseQueueSize,&String&logTag,&int&maxLogSize)&{&&
&&&&mCallbacks&=&&&
&&&&mSocket&=&&&
&&&&mResponseQueue&=&new&ResponseQueue(responseQueueSize);&&
&&&&mSequenceNumber&=&new&AtomicInteger(0);&&
&&&&TAG&=&logTag&!=&null&?&logTag&:&"NativeDaemonConnector";&&
&&&&mLocalLog&=&new&LocalLog(maxLogSize);&&
1.分别在handleMessage和listenToSocket的时候调用回调对象的onEvent和onDaemonConnected方法。而 监听socket的服务被创建后就已经开出一个线程始终监听了。在这里为new NetdCallbackReceiver();
2.mSocket也就是在NetworkManagementService中始终监听的那个local socket。在这里为netd(/dev/socket/netd);
3.mResponseQueue是新建了一个命令队列ResponseQueue,传递金的参数responseQueuesize就是这个队列的容量上限。这个子类算上构造在内总共4个方法:& & a.构造
& & b.添加命令
& & c.移除命令
& & d.打印队列信息
4.mSequeueceNumber作为指令执行计数器,是个原子量, 防止线程操作混乱;
5.日志标签
6.日志容量
构造完成后,会new出一个线程,这个线程的工作就是调用listenToSocket。最后会使用看门狗来保护这个服务。
回到主线,默认情况下,并有有效的配置文件,打开WIFI AP需要执行两条命令:
mConnector.execute("softap",&"fwreload",&wlanIface,&mode);&&
mConnector.execute("softap",&"set",&wlanIface,&softapIface,&wifiConfig.SSID,&&
&&&&&&&&&&&&&&&&&&&&&&&&getSecurityType(wifiConfig),&wifiConfig.preSharedKey);&&
逐个分析一下:
wlanIface就是prop指定的wifi.interface,默认为wlan0,mode为"AP",共计四个参数。
这两条命令都会最终执行到这里:
public&NativeDaemonEvent[]&execute(int&timeout,&String&cmd,&Object...&args)&&
&&&&&&&&throws&NativeDaemonConnectorException&{&&
&&&&final&ArrayList&NativeDaemonEvent&&events&=&Lists.newArrayList();&&
&&&&final&int&sequenceNumber&=&mSequenceNumber.incrementAndGet();&&&&//命令计数器加一并返回&&
&&&&final&StringBuilder&cmdBuilder&=&&
&&&&&&&&&&&&new&StringBuilder(Integer.toString(sequenceNumber)).append('&');&&
&&&&final&long&startTime&=&SystemClock.elapsedRealtime();&&//返回的是自从系统启动到当前的时间&&
&&&&makeCommand(cmdBuilder,&cmd,&args);&&&&//将所有参数整合成一条命令,放置在cmdBuilder中&&
&&&&final&String&logCmd&=&cmdBuilder.toString();&/*&includes&cmdNum,&cmd,&args&*/&&
&&&&log("SND&-&&{"&+&logCmd&+&"}");&&
&&&&cmdBuilder.append('\0');&&&&//给字符串来个尾巴,然后化作真正的字符串sentCmd&&
&&&&final&String&sentCmd&=&cmdBuilder.toString();&/*&logCmd&+&\0&*/&&
&&&&synchronized&(mDaemonLock)&{&&
&&&&&&&&if&(mOutputStream&==&null)&{&&&&//mOutputStraem是netd的输出通道&&
&&&&&&&&&&&&throw&new&NativeDaemonConnectorException("missing&output&stream");&&
&&&&&&&&}&else&{&&
&&&&&&&&&&&&try&{&&
&&&&&&&&&&&&&&&&mOutputStream.write(sentCmd.getBytes(Charsets.UTF_8));&&&&//将命令发送出去&&netd&socket&&
&&&&&&&&&&&&}&catch&(IOException&e)&{&&
&&&&&&&&&&&&&&&&throw&new&NativeDaemonConnectorException("problem&sending&command",&e);&&
&&&&&&&&&&&&}&&
&&&&&&&&}&&
&&&&NativeDaemonEvent&event&=&&&
&&&&do&{&&
&&&&&&&&event&=&mResponseQueue.remove(sequenceNumber,&timeout,&sentCmd);&&//从命令队列中删除已经发送出去的命令&&
&&&&&&&&if&(event&==&null)&{&&
&&&&&&&&&&&&loge("timed-out&waiting&for&response&to&"&+&logCmd);&&
&&&&&&&&&&&&throw&new&NativeDaemonFailureException(logCmd,&event);&&
&&&&&&&&}&&
&&&&&&&&log("RMV&&-&{"&+&event&+&"}");&&
&&&&&&&&events.add(event);&&
&&&&}&while&(event.isClassContinue());&&
&&&&final&long&endTime&=&SystemClock.elapsedRealtime();&&
&&&&if&(endTime&-&startTime&&&WARN_EXECUTE_DELAY_MS)&{&&
&&&&&&&&loge("NDC&Command&{"&+&logCmd&+&"}&took&too&long&("&+&(endTime&-&startTime)&+&"ms)");&&
&&&&if&(event.isClassClientError())&{&&
&&&&&&&&throw&new&NativeDaemonArgumentException(logCmd,&event);&&
&&&&if&(event.isClassServerError())&{&&
&&&&&&&&throw&new&NativeDaemonFailureException(logCmd,&event);&&
&&&&return&events.toArray(new&NativeDaemonEvent[events.size()]);&&
现在看来,所有命令都是通过netd socket发送出去。但是这个socket是谁来接收呢?
netd Socket
system/netd
[to be continued...]
更多开发者职位上
1)">1)">1" ng-class="{current:{{currentPage==page}}}" ng-repeat="page in pages"><li class='page' ng-if="(endIndex<li class='page next' ng-if="(currentPage
相关文章阅读

我要回帖

更多关于 softap配置ics失败 的文章

 

随机推荐