Android:StateMachine 之 WifiStateMachine
一、状态图:
二、代码分析: \frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachine.java
1.创建WifiStateMachine的构造函数中添加各个状态:
/*调用stateMachine类的构造方法完成状态机的构造,名字为WifiStateMachine*/
super("WifiStateMachine"); /*添加状态*/
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mVerifyingLinkState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mRoamingState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mUntetheringState, mSoftApStartedState); /*设置初始状态*/
setInitialState(mInitialState); /*设置状态日志记录*/
setLogRecSize(2000);
setLogOnlyTransitions(false); /*开始状态机*/
start();
2.状态切换-开启AP (access point:热点)
(1)TetheredState监听中收到CMD_TETHER_STATE_CHANGE消息后调用setHostApRunning() 开启AP功能,此方法发送CMD_START_AP消息:
public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
if (enable) {
sendMessage(CMD_START_AP, wifiConfig);
} else {
sendMessage(CMD_STOP_AP);
}
}
(2)状态机启动后处于InitialState状态,processMessage()中处理CMD_START_AP消息:
case CMD_START_AP: if (enableSoftAp() == true) {
/*设置AP状态*/
setWifiApState(WIFI_AP_STATE_ENABLING, 0);
/*状态切换mSoftApStartingState*/
transitionTo(mSoftApStartingState);
} else {
setWifiApState(WIFI_AP_STATE_FAILED,
WifiManager.SAP_START_FAILURE_GENERAL);
transitionTo(mInitialState);
}
break;
(3)CMD_START_AP消息处理完后,跳转到mSoftApStartingState进入mSoftApStartingState的enter方法:
class SoftApStartingState extends State {
@Override
public void enter() {
final Message message = getCurrentMessage();
if (message.what == CMD_START_AP) {
final WifiConfiguration config = (WifiConfiguration) message.obj; if (config == null) {
mWifiApConfigChannel.sendMessage(CMD_REQUEST_AP_CONFIG);
} else {
mWifiApConfigChannel.sendMessage(CMD_SET_AP_CONFIG, config);
/*开启AP*/
startSoftApWithConfig(config);
}
} else {
throw new RuntimeException("Illegal transition to SoftApStartingState: " + message);
}
}
......
}
(4)startSoftApWithConfig开启AP成功后,会发送CMD_START_AP_SUCCESS:
// Start hostapd on a separate thread
new Thread(new Runnable() {
public void run() {
try {
mNwService.startAccessPoint(config, mInterfaceName);
} catch (Exception e) {
loge("Exception in softap start " + e);
try {
// 重置热点
mNwService.stopAccessPoint(mInterfaceName);
mNwService.startAccessPoint(config, mInterfaceName);
} catch (Exception e1) {
loge("Exception in softap re-start " + e1);
sendMessage(CMD_START_AP_FAILURE, WifiManager.SAP_START_FAILURE_GENERAL);
return;
}
}
if (DBG) log("Soft AP start successful");
// 发送消息
sendMessage(CMD_START_AP_SUCCESS);
}
}).start();
}
SoftApStartingState中处理CMD_START_AP_SUCCESS消息:
public boolean processMessage(Message message) {
switch(message.what) { case CMD_START_AP_SUCCESS:
/*设置AP状态*/
setWifiApState(WIFI_AP_STATE_ENABLED);
/*跳转到mSoftApStartedState*/
transitionTo(mSoftApStartedState);
break; case CMD_START_AP_FAILURE:
setWifiApState(WIFI_AP_STATE_FAILED, message.arg1);
transitionTo(mInitialState);
break;
default:
return NOT_HANDLED;
}
}
(5)CMD_START_AP_SUCCESS消息处理完后,跳转到mSoftApStartedState状态,执行该状态的enter方法。
此状态下收到CMD_TETHER_STATE_CHANGE消息后做进一步处理:
public boolean processMessage(Message message) {
switch(message.what) {
//
case CMD_TETHER_STATE_CHANGE:
TetherStateChange stateChange = (TetherStateChange) message.obj;
/*开启tethering*/
if (startTethering(stateChange.available)) {
transitionTo(mTetheringState);
}
break;
}
}
(6)开启startTethering成功后,跳转到mTetheringState状态,执行其enter方法:
public void enter() {
/*发送延时消息,超时时间5s*/
sendMessageDelayed(obtainMessage(CMD_TETHER_NOTIFICATION_TIMED_OUT,
++mTetherToken, 0), TETHER_NOTIFICATION_TIME_OUT_MSECS);
}
mTetheringState状态下,收到CMD_TETHER_NOTIFICATION_TIMED_OUT超时消息,则启动tether失败,一步步切回到init状态。
switch(message.what) {
case CMD_TETHER_STATE_CHANGE:
TetherStateChange stateChange = (TetherStateChange) message.obj;
if (isWifiTethered(stateChange.active)) {
transitionTo(mTetheredState);
}
return HANDLED;
case CMD_TETHER_NOTIFICATION_TIMED_OUT:
if (message.arg1 == mTetherToken) {
loge("Failed to get tether update, shutdown soft access point");
transitionTo(mSoftApStartedState);
// Needs to be first thing handled
sendMessageAtFrontOfQueue(CMD_STOP_AP);
}
break;
......
}
如果在超时消息之前收到CMD_TETHER_STATE_CHANGE消息,则跳转到 TetheredState 中:
class TetheredState extends State {
@Override
public boolean processMessage(Message message) {
logStateAndMessage(message, getClass().getSimpleName()); switch(message.what) {
case CMD_TETHER_STATE_CHANGE:
TetherStateChange stateChange = (TetherStateChange) message.obj;
if (!isWifiTethered(stateChange.active)) {
loge("Tethering reports wifi as untethered!, shut down soft Ap");
// 开启热点
setHostApRunning(null, false);
setHostApRunning(null, true);
}
return HANDLED;
......
}
}
其中setHostApRunning方法中发送CMD_START_AP消息:
public void setHostApRunning(WifiConfiguration wifiConfig, boolean enable) {
if (enable) {
sendMessage(CMD_START_AP, wifiConfig);
} else {
sendMessage(CMD_STOP_AP);
}
}
上面发送的CMD_START_AP消息会传到DefaultState中处理。
至此整个状态机的状态历经如下切换,稳定在mThertheredState:
mInitialState->mSoftApStartingState->mSoftApStartedState->mThetheringState->mThertheredState
若在mThertheredState状态下关闭AP,则按照如下流程切换:
mThertheredState->mUntetheringState->mSoftApStartedState->mInitialState
这个流程中用到了deferMessage来实现相同消息的反复发送。
Android:StateMachine 之 WifiStateMachine的更多相关文章
- Android stateMachine分析
StateMachine与State模式的详细介绍可以参考文章:Android学习 StateMachine与State模式 下面是我对于StateMachine的理解: 先了解下消息处理.看下Sta ...
- android源码中修改wifi热点默认始终开启
在项目\frameworks\base\wifi\java\android\net\wifi\WifiStateMachine.java里面,有如下的代码,是设置wifi热点保持状态的:如下: pri ...
- android 5.1 WIFI图标上的感叹号及其解决办法
转自:http://blog.csdn.net/w6980112/article/details/45843129 第一次调试android5.1的 WIFI更改小功能 Wifi 源码的相关路径目录 ...
- android WiFi ASSOC_REJECT 流程跟踪
Android设备在于AP关联时,如果AP返回关联拒绝帧,Android设别会把AP加入黑名单中. 黑名单中的设备将会在扫描时,延时一段时间放在后面处理. 代码以及log基于SDM450, Andro ...
- Android 8 Wifi 初始化过程
记录一下wifi初始化过程. packages/apps/Settings/src/com/android/settings/wifi/WifiSettings.java public void on ...
- Android 8.0/9.0 wifi 自动连接评分机制
前言 Android N wifi auto connect流程分析 Android N selectQualifiedNetwork分析 Wifi自动连接时的评分机制 今天了解了一下Wifi自动连接 ...
- 解决不能打开wifi问题
使用 命令svc wifi来调试,避免使用GUI 相关资料 https://community.freescale.com/thread/319407 D/WifiService( 313): se ...
- rk3288 usb无线网卡支持 8188eu
第一部分是kernel 内核配置参考rk文档,把device driver 下wireless相关的先勾选上. 编译到buildin有问题,识别不到,所以打算编译成ko cd kernel/driv ...
- Android状态机StateMachine使用举例及源码解析
Android frameworks源码StateMachine使用举例及源码解析 工作中有一同事说到Android状态机StateMachine.作为一名Android资深工程师,我居然没有听说过S ...
随机推荐
- 【HCIA Gauss】学习汇总-数据库管理(数据库设计 范式 索引 分区)-7
zsql user/pasword@ip:port -c "show databases" # 展示一条sql语句 spool file_path 指定输出文件 可以为相对路径 s ...
- Error: EACCES: permission denied when trying to install ESLint using npm
https://stackoverflow.com/questions/35954725/error-eacces-permission-denied-when-trying-to-install-e ...
- Maximum Subarray II
Given an array of integers, find two non-overlapping subarrays which have the largest sum. The numbe ...
- mongodb 开发规范
一.命名规则 1.数据库命名规则 数据库名可以是满足以下条件的任意UTF-8字符串: (1)不能是空字符串(”") : (2)不能含有”(空格)...$./..和(空字符): (3)应全部小 ...
- MySQL数据库卸载有残留, windows10 sc delete 拒绝访问 失败5
sc delete 拒绝访问,原因是当前用户的权限不足,需要做的是在注册表 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\P ...
- django项目部署上线 nginx + uwsgi
一.安装python3 安装步骤:https://www.cnblogs.com/zhangqigao/p/11661875.html 二.修改django中的配置文件 修改settings.py ( ...
- Storage Port Drivers
为了学习存储知识,我也是拼了,来,翻译一下下面这篇微软的文章(如果有谁翻译过了,或者微软有中文翻译,请绕路): Storage Port Drivers Last Updated: 4/20/2017 ...
- python中如何给散点图上面的特定点做标记
今天想在散点图的某些特定的点外面画圆圈标记,从下面的文章找到一些灵感,只要在原来的散点图上面给指点添加相应的标志,设置其透明度就可以实现该想法. 顺便复习下散点图的用法. 大家平时为了直观地显示数据的 ...
- 二分算法题目训练(四)——Robin Hood详解
codeforces672D——Robin Hood详解 Robin Hood 问题描述(google翻译) 我们都知道罗宾汉令人印象深刻的故事.罗宾汉利用他的射箭技巧和他的智慧从富人那里偷钱,然后把 ...
- 30行左右代码实现一个类似httprunner的接口框架
框架的最终归宿往往是领域语言+模板解析. 首先先约定一种所要执行操作的表述格式.然后通过模板解析将描述语言转化为代码进行执行.例如,我们可以使用以下yaml文件描述多个步骤并且需要关联的接口: api ...