小博士wifiap是什么设置详细操作

如意云路由Web认证配置教程(wifiap) - 联想NBD社区 - Powered by Discuz!
联想NBD社区
标题: 如意云路由Web认证配置教程(wifiap)
作者: liouyi& & 时间:
标题: 如意云路由Web认证配置教程(wifiap) 本帖最后由 liouyi 于
16:26 编辑
ps:有的 朋友不知道web认证是什么。简单的说呢,就跟CMCC的认证方式,连接热点会弹出一个窗口要求输入帐号及密码,然后才能上网。
首先需要安装两个插件
wget_1.13.4-1_ralink.ipk
wifidog__ralink.ipk
(文章后面附件中已经打包)
插件安装方法:
1.打开192.168.99.1,进入路由后台,高级设置——系统菜单——软件包——配置,修改配置文件,把插件安装在路由器里面
将默认配置文件覆盖成如下配置src/gz attitude_adjustment http://r.xcloud.cc/router/Public/upload/plugins
dest root /
dest ram /tmp
lists_dir ext /var/opkg-lists
option overlay_root /overlay复制代码
111.jpg (86.11 KB, 下载次数: 27)
21:04 上传
2.然后用winscp将附件中的两个插件上传到/tmp/目录中
打开winSCP,登陆路由器
保存后登陆。
然后把附件中的wget_1.13.4-1_ralink.ipk和wifidog__ralink.ipk拖到图示位置,将插件上传至路由器
3.打开 putty或者自带telnet 登陆路由器,运行命令安装插件
(这里用的windows自带的telnet)
打开 开始-运行.输入telnet 192.168.99.1点确定,
登陆路由器输入路由器帐号密码.
然后输入cd /tmp复制代码再输入opkg install wget_1.13.4-1_ralink.ipk复制代码再输入opkg install wifidog__ralink.ipk复制代码插件安装完成后,将软件包配置文件还原,
打开192.168.99.1,进入路由后台,高级设置——系统菜单——软件包——配置,修改配置文件,
将配置文件覆盖成如下配置(下面的是代码是默认配置)src/gz attitude_adjustment http://r.xcloud.cc/router/Public/upload/plugins
dest root /opt
dest ram /tmp
lists_dir ext /var/opkg-lists
option overlay_root /opt
复制代码
下面开始安装Wifiap
一、注册Wifiap中央管理平台账号
1)访问wifiap官方网站
2)点击右下角的“商家登录|后台管理”,并进行注册
3)填写注册相关资料,提交免费注册(请牢记你的登录账号和密码)
二、创建云端AP并更新标识
1)登录官方网站的管理后台
2)从顶部导航进入“热点管理》【新增】”
3)热点名称:热点的唯一标识名称(脚本中的hotspotname)
4)热点类型:选择“认证路由器”
5)机器码:输入一段字符串,如wifiapkey,(随便输入)
6)点击“添加”,成功添加此热
7)在“热点管理”页面找到新增的热点,在“操作”中点击“生成启动脚本”
8)填写路由系统(open-WRT)、热点名称(刚新增的热点)、机器码(刚新增的机器码),然后点击“自动生成脚本”,在文本框中复制脚本
搜狗截图14年03月13日2014_1.jpg (181.98 KB, 下载次数: 18)
20:24 上传
三、配置路由器认证模块
进入wifiap路由器web管理界面
1)打开192.168.99.1,进入路由后台,高级设置——系统菜单——启动项
2)在exit 0之前,粘贴(添加)脚本参数中生成的脚本.如下图示:
222.jpg (68.82 KB, 下载次数: 18)
20:21 上传
3)编辑完成后,点击“提交”,然后重启路由器生效。联网一分钟左右,web认证完全开启(刚开机可能会出现不用验证即可上网,等待wifiap完全启动后,现象消失)。
这个插件个人玩玩还不错。免费版支持10个并发用户。如果商用的话,10个用户就可能有点不够了。
附上成功的配置后图片.
333.jpg (67.7 KB, 下载次数: 24)
20:28 上传
附件回复后可见↓↓↓↓
作者: liouyi& & 时间:
本帖最后由 liouyi 于
20:35 编辑
待会补图,现在有点卡
附上参考文章
作者: tulipa001& & 时间:
前排,凑凑热闹。
作者: ldd1231& & 时间:
不错,教程浅显易懂~~支持一下~~~
作者: guide6& & 时间:
不错,学生党也这么关注云路由。
作者: cox& & 时间:
没有wifi 收费系统吗?
比如1小时几毛钱,这样可以卖热点了~
作者: liouyi& & 时间:
没有wifi 收费系统吗?
后台可以设置收费...
作者: pq& & 时间:
本帖最后由 pq 于
14:56 编辑
重新刷机后,再按照楼主发的教程设置,就变成永久VIP了.谢谢楼主哈
作者: liouyi& & 时间:
怎么不是同时在线用户10个,我这里人流量比较大。
并发10用户。不是同时在线10用户吗?
作者: pq& & 时间:
本帖最后由 pq 于
09:20 编辑
不错,好像能用。我来试试
作者: a& & 时间:
不错已经设置成成功了很给力的系统
作者: ghast2005& & 时间:
2.然后用winscp将附件中的两个插件上传到/tmp/目录中
3.打开 putty或者自带telnet 登陆路由器,运行命令安装插件
&&新手求教这两步的具体操作方法
作者: gujunver99& & 时间:
不错,教程浅显易懂~~支持一下~~~
作者: liouyi& & 时间:
ghast2005 发表于
<font color="#.然后用winscp将附件中的两个插件上传到/tmp/目录中
3.打开 putty或者自带telnet 登陆路由器,运行命令安 ...
参考这个帖子。
http://bbs.xcloud.cc/forum.php?mod=viewthread&tid=4276
作者: yuhaaitao& & 时间:
这个插件有什么用?远程登录路由器?
作者: ghast2005& & 时间:
这个插件有什么用?远程登录路由器?
用这个可以不用设置无线密码,需要验证用户账户才能上网。& &就像电信的公共WIFI那样,理论上能防蹭网。& & 只是这样好像对网速稍微有点影响吧。&&晚点做个测试。
作者: 小云客服-六月& & 时间:
等下折腾折腾····
作者: & & 时间:
这个看起来挺不错的
就是不知道会不会给路由器带来太大压力
作者: zhang8981& & 时间:
这么牛逼?
作者: ak& & 时间:
作者: jiangxinjie& & 时间:
作者: ycruyiyunluyou& & 时间:
不错不错,简单易懂。顶一个!
作者: seasickness& & 时间:
很好的感觉
作者: 祯木头& & 时间:
不错,正想学呢,顶你
作者: atrong& & 时间:
收藏了。谢谢楼主分享
作者: yuhaaitao& & 时间:
这是好东西呀,不过每次连接都需要输入密码吧
作者: mickeywaley& & 时间:
不错不错不错不错不错不错不错不错不错不错不错不错不错
作者: 幸福灬约定& & 时间:
不是吧?????????还要恢复?
作者: guide6& & 时间:
Wiwiz 也可以,不过只有3个免费的
作者: websfx& & 时间:
不错,好像能用。我来试试
作者: zhangjijian& & 时间:
今天试一下。
作者: pq& & 时间:
今天不能重新刷机后不能用了
作者: zhangjijian& & 时间:
我没有成功啊,不知哪里不对?
作者: qilin3321& & 时间:
作者: & & 时间:
作者: cjkall& & 时间:
如意云路由Web认证配置教程
作者: sylxb& & 时间:
这个很强大,非常实用,给自己做点小广告
作者: shongz1001& & 时间:
大力支持& && && && && && && && && && && && && && &&&
作者: 蕊爸& & 时间:
作者: leevvlan& & 时间:
好高端的技术,问下校园网络认证的插件安装也是这样子吗?
作者: slinbo& & 时间:
你好 非常实用
作者: wadecheung& & 时间:
好好,好好,好啊
作者: & & 时间:
好东西。。哈哈哈哈哈哈哈
作者: @189& & 时间:
za研究研究
作者: steven_nx& & 时间:
谢谢分享。支持了
作者: jeromeli& & 时间:
鼓风管发的是
作者: 小叶& & 时间:
不错,教程浅显易懂
作者: jinyanlei& & 时间:
不错,教程浅显易懂~~支持一下~~~
作者: suwubee& & 时间:
官方就不能搞个wayos那样简单的?
作者: yusheng& & 时间:
作者: xo813& & 时间:
3q.................................
作者: benbenmore& & 时间:
哇塞。楼主威武
作者: xiao5& & 时间:
Transmission Remote
作者: 大健健& & 时间:
弄一个玩玩 HOHO~!
作者: & & 时间:
提示: 作者被禁止或删除 内容自动屏蔽
作者: chao& & 时间:
好贴必顶。
作者: haitao& & 时间:
什么意思 学习
作者: CQS& & 时间:
yao 要保存下来学习
作者: 江中望月& & 时间:
说明东西哦,好神秘的样子。
作者: qzyzlgy& & 时间:
作者: wuyuzai& & 时间:
哟哟 努力赚钱
作者: 迪克水手& & 时间:
这个教程发的好,长知识了。顶用。
作者: ANG丶huage& & 时间:
作者: xyixyixyi& & 时间:
好东西我来下载个
作者: wangxiao13611& & 时间:
看看,支持一下!
作者: 快意人生& & 时间:
这个可以试一下的。
作者: xxtting& & 时间:
好东西啊。。。期待更好的
作者: AiYaJing& & 时间:
修改软件包配置文件那部分,&&提供的代码 到底是要替换的 还是原始的?&&没看懂
作者: bright_boy& & 时间:
这都要隐藏啊……
作者: bobo21& & 时间:
如果如意云能把这个固化在固件里就爽了!
作者: bobo21& & 时间:
请问一下楼主,我按照楼主的方法安装了wifidog ,用wiwiz做认证,也按照wiwiz官网的去安装了,但每次都是安装时可以到认证网,重启后就不行了,该怎么弄呢?楼主可以放个教程出来吗?
作者: 漫步时光& & 时间:
赞一个。。。。。。
作者: iChen6& & 时间:
果您要查看本帖隐藏内容请回复
作者: richeml& & 时间:
这个还不错
作者: fgpgy& & 时间:
作者: le45tx1m& & 时间:
支持Web认证功能
作者: @qq.c& & 时间:
谢谢分享!
作者: bees678& & 时间:
这个插件个人玩玩还不错。免费版支持10个并发用户。如果商用的话,10个用户就可能有点不够了。
作者: skl520& & 时间:
作者: dim37962& & 时间:
设置了头像,终于可以回复了
作者: fengtong& & 时间:
ZHEGEG BIXUDING
作者: haitao& & 时间:
凑凑热闹。
作者: 无线梦想& & 时间:
x学习下& &
作者: jsj11zcl& & 时间:
ip学习学习
作者: kmshanren& & 时间:
感谢发布!!!!!!!!!!
作者: & & 时间:
有那么一点复杂
作者: wyi6999& & 时间:
顶顶顶顶顶
作者: cdh1122& & 时间:
我来安装试试看
作者: 屁民一个& & 时间:
商用的话,那个软件多少钱一个?
作者: chiyan& & 时间:
凑凑热闹。
作者: nongwo& & 时间:
作者: qinweihai& & 时间:
很不错啊。。。。。
作者: Neil& & 时间:
好东西啊,谢谢楼主分享
作者: hnxyhcwdl1003& & 时间:
正在安装进行中。。。
作者: root@kiss.lc& & 时间:
来看看......
作者: shangwl& & 时间:
谢谢!~~~~~~~~~~~~``
作者: Zero& & 时间:
顶上,正好需要这个
作者: sooma& & 时间:
这才能叫智能。
作者: qq& & 时间:
我要学习啊!!!!!!!!!!
作者: hnraysir& & 时间:
终于找到这个了,转发中。
欢迎光临 联想NBD社区 (/)
Powered by Discuz! X3.2wifiap模式苹果6无法连接是什么原因_百度知道
wifiap模式苹果6无法连接是什么原因
等待设备重新连接网络,接下来再关闭飞行模式、首先将你的iphone6手机设置为飞行模式,也希望你能采纳你好1.2,谢谢。希望这样可以帮到你,Wi-Fi 质量差的现象有很大几率就能得到解决、还原完成之后。这一套步骤执行完毕之后,重启你的无线路由器,接着选择“设置”→“通用”→“还原”→“还原网络设置”
其他类似问题
为您推荐:
苹果的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁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...]

我要回帖

更多关于 wifiap 的文章

 

随机推荐