您的位置:首页 > 移动开发 > Android开发

安卓StateMachine分析举例---WifiStateMachine

2016-01-03 17:31 519 查看

WifiStateMachine创建:

创建在构造方法WifiStateMachine(Context context, String wlanInterface) 中实施:

public WifiStateMachine(Context context, String wlanInterface) {
/*调用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(mCaptivePortalCheckState, mL2ConnectedState);
addState(mConnectedState, 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();

}


在start方法中,调用completeConstruction方法完成构造,这个方法之前已经分析过,主要是完成状态机棧的搭建,并发送启动完成的消息,将状态机运行起来。状态机起来后,分别运行mDefaultState和mInitialState的状态的enter方法,在mDefaultState的方法中do nothing,在mInitialState的enter方法中,进行了wifi相关的初始化,这里不做关注:

public void enter() {
mWifiNative.unloadDriver();
if (mWifiP2pChannel == null) {
mWifiP2pChannel = new AsyncChannel();
mWifiP2pChannel.connect(mContext, getHandler(), mWifiP2pManager.getMessenger());
}

if (mWifiApConfigChannel == null) {
mWifiApConfigChannel = new AsyncChannel();
WifiApConfigStore wifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
mContext, getHandler());
wifiApConfigStore.loadApConfiguration();
mWifiApConfigChannel.connectSync(mContext, getHandler(),wifiApConfigStore.getMessenger());
}
}


至此WifiStateMachine创建成功,运行在InitialState状态,罗列一下各个状态之间的关系:



WifiStateMachine状态切换举例–开启AP:

调用setHostApRunning方法,开启AP功能,此方法发送CMD_START_AP消息

状态机启动后处于InitialState状态,收到CMD_START_AP消息后:

public boolean processMessage(Message message) {
switch (message.what) {
/*省略代码*/
case CMD_START_AP:
if (mWifiNative.loadDriver()) {
/*设置AP状态*/
setWifiApState(WIFI_AP_STATE_ENABLING);
/*状态切换mSoftApStartingState*/
transitionTo(mSoftApStartingState);
} else {
loge("Failed to load driver for softap");
}
/*省略代码*/
}
}


此消息处理函数处理完后,跳转到mSoftApStartingState

进入mSoftApStartingState的enter方法:

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);
}
}


startSoftApWithConfig开启AP成功后,会发送CMD_START_AP_SUCCESS消息,

SoftApStartingState状态下,处理此消息:

public boolean processMessage(Message message) {
switch(message.what) {
//
case CMD_START_AP_SUCCESS:
/*设置AP状态*/
setWifiApState(WIFI_AP_STATE_ENABLED);
/*跳转到mSoftApStartedState*/
transitionTo(mSoftApStartedState);
break;
}
}


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;
}
}


开启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状态。如果在超时消息之前收到CMD_TETHER_STATE_CHANGE消息,则走如下 处理:

public boolean processMessage(Message message) {

switch(message.what) {
/*省略代码*/
case CMD_TETHER_STATE_CHANGE:
TetherStateChange stateChange = (TetherStateChange) message.obj;
if (isWifiTethered(stateChange.active)) {
transitionTo(mTetheredState);
}
return HANDLED;
/*省略代码*/
}


如果isWifiTethered返回成功则跳转到mTetheredState状态,并执行其enter方法。否则,超时消息到达后关闭ap。

至此整个状态机的状态历经如下切换,稳定在mThertheredState

mInitialState->mSoftApStartingState->mSoftApStartedState->mThetheringState->mThertheredState

若在mThertheredState状态下关闭AP,则按照如下流程切换

mThertheredState->mUntetheringState->mSoftApStartedState->mInitialState

这个流程中用到了deferMessage来实现相同消息的反复发送。在StateMachine章节已论述。

根据源码分析,弄清一个状态机代码流程的关键点是根据源码画出状态关系图,再根据状态逐个进行推演。如果是定位问题,可以重点使用dump功能,将状态迁徙的过程dump出来,再结合logcat进行分析。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android wifi state