1、狀態圖:java
2、代碼分析: \frameworks\opt\net\wifi\service\java\com\android\server\wifi\WifiStateMachine.javaandroid
1.建立WifiStateMachine的構造函數中添加各個狀態:ide
/*調用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消息:spa
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方法:code
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:server
// 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消息:blog
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方法。get
此狀態下收到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來實現相同消息的反覆發送。