从源代码角度去分析状态机的实现过程。

主要涉及到的文件有:

frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java

frameworks/base/core/java/com/android/internal/util/StateMachine.java

frameworks/base/core/java/com/android/internal/util/State.java

frameworks/base/core/java/com/android/internal/util/IState.java

其中IState是一个接口类:

上述的方法会由StateMachine来支配,决定何时调用,现有这个概念即可。

接着看StateMachine类中一些重要的内嵌类和函数。

[cpp] view plaincopy
  1. public static class ProcessedMessageInfo {//包含一个状态的所有信息
  2. private int what;
  3. private State state;//这个经常用到,表示当前处于那个状态
  4. private State orgState;//表示接收到消息的状态
  5. ........................................
  6. ProcessedMessageInfo(Message message, State state, State orgState) {
  7. update(message, state, orgState);//更新当前状态
  8. }
  9. ..........................................
  10. public void update(Message message, State state, State orgState) {
  11. this.what = message.what;
  12. this.state = state;
  13. this.orgState = orgState;
  14. }
  15. .......................................
  16. }
[cpp] view plaincopy
  1. private static class ProcessedMessages {//保存最近处理的20条消息,具体包括state,发送的message等
  2. private static final int DEFAULT_SIZE = 20;//默认的最大状态个数,这个不是指所有的状态,而是当前活动状态往父类追溯得到的所有类的状态
  3. private Vector<ProcessedMessageInfo> mMessages = new Vector<ProcessedMessageInfo>();
  4. private int mMaxSize = DEFAULT_SIZE;
  5. ....................................
  6. ProcessedMessageInfo get(int index) {//根据索引获取状态信息
  7. int nextIndex = mOldestIndex + index;
  8. if (nextIndex >= mMaxSize) {
  9. nextIndex -= mMaxSize;
  10. }
  11. if (nextIndex >= size()) {
  12. return null;
  13. } else {
  14. return mMessages.get(nextIndex);
  15. }
  16. }
  17. .........................................
  18. void add(Message message, State state, State orgState) {//orgState为最底层状态节点,state为有能力处理message的节点,他们可能相等,或则state为orgState的祖类节点
  19. mCount += 1;
  20. if (mMessages.size() < mMaxSize) {
  21. mMessages.add(new ProcessedMessageInfo(message, state, orgState));
  22. } else {
  23. ProcessedMessageInfo pmi = mMessages.get(mOldestIndex);
  24. mOldestIndex += 1;
  25. if (mOldestIndex >= mMaxSize) {
  26. mOldestIndex = 0;
  27. }
  28. pmi.update(message, state, orgState);
  29. }
  30. }
  31. }
[cpp] view plaincopy
  1. private static class SmHandler extends Handler {
  2. .................................
  3. private StateInfo mStateStack[];//这里存放的是当前state以及父类的state
  4. private int mStateStackTopIndex = -1;//mStateStack数组的下标索引
  5. private StateInfo mTempStateStack[];//状态信息缓存区
  6. private HaltingState mHaltingState = new HaltingState();//状态挂起时候才会用到,一般用不上
  7. private QuittingState mQuittingState = new QuittingState();//状态退出时候才会用上,一般用不上
  8. private StateMachine mSm;//全局的StateMachine引用,在构造函数中this指针赋的值
  9. private HashMap<State, StateInfo> mStateInfo =
  10. new HashMap<State, StateInfo>();//保存所有加入的state信息
  11. private State mInitialState;//初始化的状态
  12. private State mDestState;//切换时新的目标状态
  13. @Override
  14. public final void handleMessage(Message msg) {
  15. processMsg(msg);//处理接收到的消息
  16. performTransitions();//处理就状态到新状态的切换
  17. if (mDbg) Log.d(TAG, "handleMessage: X");
  18. }
  19. ..........................
  20. }

到这里,还是先把wifistatemachine的状态图写出来,以便好理解。

比如,如果当前状态为mDriverFailedState,则上面mStateStack存放的是[mDefaultState,mDriverUnloadedState,mDriverFailedState]三个状态的信息

StateMachine的构造函数做了些什么?

[cpp] view plaincopy
  1. protected StateMachine(String name) {
  2. mSmThread = new HandlerThread(name);
  3. mSmThread.start();
  4. Looper looper = mSmThread.getLooper();
  5. initStateMachine(name, looper);
  6. }

而在initStateMachine方法中:

[cpp] view plaincopy
  1. private void initStateMachine(String name, Looper looper) {
  2. mName = name;
  3. mSmHandler = new SmHandler(looper, this); //mSmHandler是一个全局的handler,后面常用到
  4. }
[cpp] view plaincopy
  1. private SmHandler(Looper looper, StateMachine sm) {
  2. super(looper);
  3. mSm = sm;//mSm是一个全局的变量,后面经常用到
  4. addState(mHaltingState, null);//状态挂起的时候调用
  5. addState(mQuittingState, null);//状态退出的时候调用
  6. }

WifiStateMachine的构造函数主要做了些什么?

主要是调用addState方法将wifi中创建的状态加入状态机中,最后setInitialState来设置初始化状态。具体过程如下:

[cpp] view plaincopy
  1. protected final void addState(State state, State parent) {//将state添加到父节点parent下,如果parent为null,则state作为父节点
  2. mSmHandler.addState(state, parent);
  3. }
[cpp] view plaincopy
  1. private final StateInfo addState(State state, State parent) {
  2. if (mDbg) {
  3. Log.d(TAG, "addStateInternal: E state=" + state.getName()
  4. + ",parent=" + ((parent == null) ? "" : parent.getName()));
  5. }
  6. StateInfo parentStateInfo = null;
  7. if (parent != null) {
  8. parentStateInfo = mStateInfo.get(parent);//取出父节点的parentStateInfo信息
  9. if (parentStateInfo == null) { //如果父节点为null,则递归调用,把当前节点作为父节点
  10. // Recursively add our parent as it's not been added yet.
  11. parentStateInfo = addState(parent, null);
  12. }
  13. }
  14. StateInfo stateInfo = mStateInfo.get(state);//新节点,肯定为null了
  15. if (stateInfo == null) {
  16. stateInfo = new StateInfo();
  17. mStateInfo.put(state, stateInfo);//将state和stateInfo放入哈系表中,以后根据state即可取出stateInfo信息,前面说过,全局变量mStateInfo哈系表保存了所有state信息
  18. }
  19. // Validate that we aren't adding the same state in two different hierarchies.
  20. if ((stateInfo.parentStateInfo != null) &&   //新创建还没有赋值,肯定为null啦,否则就抛出异常了
  21. (stateInfo.parentStateInfo != parentStateInfo)) {
  22. throw new RuntimeException("state already added");
  23. }
  24. stateInfo.state = state;
  25. stateInfo.parentStateInfo = parentStateInfo;//以后通过state可以找到父节点,一直递归,如果state的父节点为null,则表示到了顶部
  26. stateInfo.active = false; //时候是当前活动状态标志
  27. if (mDbg) Log.d(TAG, "addStateInternal: X stateInfo: " + stateInfo);
  28. return stateInfo;
  29. }

这样,通过上面的addState方法,最终形成了上图所示的树形结构。在使用之前,还要设置state的初始化状态:

[cpp] view plaincopy
  1. /**
  2. * Set the initial state. This must be invoked before
  3. * and messages are sent to the state machine.
  4. *
  5. * @param initialState is the state which will receive the first message.
  6. */
  7. protected final void setInitialState(State initialState) {
  8. mSmHandler.setInitialState(initialState);
  9. }

注释已经说的很清楚,这是第一次接收到消息时候进入的状态:

[cpp] view plaincopy
  1. private final void setInitialState(State initialState) {
  2. if (mDbg) Log.d(TAG, "setInitialState: initialState" + initialState.getName());
  3. mInitialState = initialState;//先简单的保存到全局变量中,后续才用到
  4. }

这样初始化工作完成,WifiStateMachine的构造函数最后调用start()来启动状态机,它的实现方法在父类StateMachine中:

[cpp] view plaincopy
  1. public void start() {
  2. // mSmHandler can be null if the state machine has quit.
  3. if (mSmHandler == null) return;//mSmHandler引用在前面构造函数中就赋值了,肯定不为null了
  4. /** Send the complete construction message */
  5. mSmHandler.completeConstruction();
  6. }
  7. }

来看completeConstruction方法的实现:

[cpp] view plaincopy
  1. private final void completeConstruction() {
  2. if (mDbg) Log.d(TAG, "completeConstruction: E");
  3. /**
  4. * Determine the maximum depth of the state hierarchy
  5. * so we can allocate the state stacks.
  6. */
  7. int maxDepth = 0;
  8. for (StateInfo si : mStateInfo.values()) {//这个for循环就是遍历前面添加到哈系表中的状态,找出树的最大深度,根据前面的树形表可以看出,最大深度为5
  9. int depth = 0;
  10. for (StateInfo i = si; i != null; depth++) {
  11. i = i.parentStateInfo;
  12. }
  13. if (maxDepth < depth) {
  14. maxDepth = depth;
  15. }
  16. }
  17. if (mDbg) Log.d(TAG, "completeConstruction: maxDepth=" + maxDepth);
  18. mStateStack = new StateInfo[maxDepth];//这个是最后存放当前活动state的,可以看到要得到最大深度的作用就是为了创建数组,因为当前活动state以及父类家族最多就为maxDepth
  19. mTempStateStack = new StateInfo[maxDepth];//这个是暂时存放state的
  20. setupInitialStateStack();
  21. /**
  22. * Construction is complete call all enter methods
  23. * starting at the first entry.
  24. */
  25. mIsConstructionCompleted = true;
  26. mMsg = obtainMessage(SM_INIT_CMD);
  27. invokeEnterMethods(0);
  28. /**
  29. * Perform any transitions requested by the enter methods
  30. */
  31. performTransitions();
  32. if (mDbg) Log.d(TAG, "completeConstruction: X");
  33. }

接着下一句是setupInitialStateStack方法:

[cpp] view plaincopy
  1. private final void setupInitialStateStack() {
  2. if (mDbg) {
  3. Log.d(TAG, "setupInitialStateStack: E mInitialState="
  4. + mInitialState.getName());
  5. }
  6. StateInfo curStateInfo = mStateInfo.get(mInitialState);//取出初始化state,前面已经赋值过,这里为WifiStateMachine中mInitialState对应的stateInfo
  7. for (mTempStateStackCount = 0; curStateInfo != null; mTempStateStackCount++) {
  8. mTempStateStack[mTempStateStackCount] = curStateInfo;//最后mTempStateStack存放的值为[mInitialState,mDefaultState]对应的stateInfo
  9. curStateInfo = curStateInfo.parentStateInfo;
  10. }
  11. // Empty the StateStack
  12. mStateStackTopIndex = -1;
  13. moveTempStateStackToStateStack();
  14. }

moveTempStateStackToStateStack方法就是将mTempStateStack的值倒序放到mStateStack中:

[cpp] view plaincopy
  1. private final int moveTempStateStackToStateStack() {
  2. int startingIndex = mStateStackTopIndex + 1;// -1 + 1 = 0;
  3. int i = mTempStateStackCount - 1;//第一次进入,2 - 1 = 1;
  4. int j = startingIndex;
  5. while (i >= 0) {
  6. if (mDbg) Log.d(TAG, "moveTempStackToStateStack: i=" + i + ",j=" + j);
  7. mStateStack[j] = mTempStateStack[i];
  8. j += 1;
  9. i -= 1;
  10. }
  11. mStateStackTopIndex = j - 1;// 2 - 1 = 1
  12. if (mDbg) {
  13. Log.d(TAG, "moveTempStackToStateStack: X mStateStackTop="
  14. + mStateStackTopIndex + ",startingIndex=" + startingIndex
  15. + ",Top=" + mStateStack[mStateStackTopIndex].state.getName());
  16. }
  17. return startingIndex; //0
  18. }

这样,当前状态信息就保存在mStateStack中,为[mDefaultState, mInitialState]对应的状态信息。

回到completeConstruction中,接着invokeEnterMethods方法:

[cpp] view plaincopy
  1. private final void invokeEnterMethods(int stateStackEnteringIndex) {
  2. for (int i = stateStackEnteringIndex; i <= mStateStackTopIndex; i++) {//前面分析可以,mStateStackTopIndex为1
  3. if (mDbg) Log.d(TAG, "invokeEnterMethods: " + mStateStack[i].state.getName());
  4. mStateStack[i].state.enter();//依次调用活动状态的enter方法,可以看到是从最顶层父类依次往下调用的
  5. mStateStack[i].active = true; //把当前state置为true
  6. }
  7. }

mDefaultState重写enter方法,父类State的enter方法什么也不做;InitialState有重写enter方法:

[cpp] view plaincopy
  1. class InitialState extends State {
  2. @Override
  3. //TODO: could move logging into a common class
  4. public void enter() {
  5. ......................................
  6. if (WifiNative.isDriverLoaded()) {
  7. transitionTo(mDriverLoadedState);//如果我们打开过wifi,状态就会切换到mDriverLoadedState去了
  8. }
  9. else {
  10. transitionTo(mDriverUnloadedState);//第一次打开是没有load过的,所以进入unload状态
  11. }
  12. .................................
  13. }
  14. }
[cpp] view plaincopy
  1. protected final void transitionTo(IState destState) {//IState是所有state的接口类
  2. mSmHandler.transitionTo(destState);调用handler方法来处理
  3. }
[cpp] view plaincopy
  1. private final void transitionTo(IState destState) {
  2. mDestState = (State) destState;//先保存到变量中,后续真正状态切换时候才用到
  3. if (mDbg) Log.d(TAG, "StateMachine.transitionTo EX destState" + mDestState.getName());
  4. }

这样invokeEnterMethods方法就完成了,接着是performTransitions方法,这是真正处理状态切换的方法了:

[cpp] view plaincopy
  1. private void performTransitions() {
  2. .....................
  3. State destState = null;
  4. while (mDestState != null) {
  5. ......................................
  6. destState = mDestState;//destState为mDriverUnLoadedState
  7. mDestState = null;
  8. ..............................
  9. StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
  10. invokeExitMethods(commonStateInfo);
  11. int stateStackEnteringIndex = moveTempStateStackToStateStack();
  12. invokeEnterMethods(stateStackEnteringIndex);
  13. moveDeferredMessageAtFrontOfQueue();
  14. }
  15. if (destState != null) {
  16. if (destState == mQuittingState) {
  17. cleanupAfterQuitting();
  18. } else if (destState == mHaltingState) {
  19. mSm.halting();
  20. }
  21. }
  22. }

setupTempStateStackWithStatesToEnter方法主要是把当前活动state家族放入mTempStateStack中,并且返回顶层节点的信息,这样,mTempStateStack保存信息为[mDriverUnLoadedState, mDefaultState]的信息;

invokeExitMethods方法则是从当前活动state顶层节点一次调用exit方法,并且设置state的active标记为false;这里要注意当前活动的还是是mStateStack中的信息,即[mDefaultState, mInitialState]对应的状态信息,exit方法一般是做一些善后工作。处理完成后

mStateStackTopIndex又自减为-1。

moveTempStateStackToStateStack和invokeEnterMethods方法前面已经分析过。完成后mStateStack的状态信息变为[mDefaultState,mDriverUnLoadedState]

最后一个函数moveDeferredMessageAtFrontOfQueue刷新消息队列的排序。该方法就是将mDeferredMessages容器中的消息按先后顺序发送出去,然后清空容器。至于消息是如何加入容器的,后面遇到再分析。

这样start方法就完成,整个WifiStateMachine构造函数也建立完成了。

如果我们打开wifi,会在WifiService中调用setWifiEnabled - >mWifiStateMachine.setWifiEnabled来启动。setWifiEnabled的状态切换过程为:

[cpp] view plaincopy
  1. public void setWifiEnabled(boolean enable) {
  2. mLastEnableUid.set(Binder.getCallingUid());
  3. if (enable) {
  4. /* Argument is the state that is entered prior to load */
  5. sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
  6. sendMessage(CMD_START_SUPPLICANT);
  7. } else {
  8. sendMessage(CMD_STOP_SUPPLICANT);
  9. /* Argument is the state that is entered upon success */
  10. sendMessage(obtainMessage(CMD_UNLOAD_DRIVER, WIFI_STATE_DISABLED, 0));
  11. }
  12. }

sendMessage方法是StateMachine实现的,它封装了Handler类的sendMessage方法,会被SmHandler类的handleMessage来接收处理。而它是调用一下两个方法来处理消息的:

[cpp] view plaincopy
  1. processMsg(msg);
  2. performTransitions();

先看第一个:

[cpp] view plaincopy
  1. private final void processMsg(Message msg) {
  2. StateInfo curStateInfo = mStateStack[mStateStackTopIndex];//mStateStack保存信息的顺序为顶层节点->底层节点,mStateStackTopIndex为数组个数,这里取出的就为最底层节点的状态信息
  3. if (mDbg) {
  4. Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
  5. }
  6. while (!curStateInfo.state.processMessage(msg)) {//所以从底层节点开始往上遍历,调用processMessage来处理消息,直到找到一个可以处理的节点后返回HANDLED(true),条件退出
  7. /**
  8. * Not processed
  9. */
  10. curStateInfo = curStateInfo.parentStateInfo;
  11. if (curStateInfo == null) {//找到顶层节点了,才用unhandledMessage,它不做什么事情,打印一句LOG信息而已
  12. /**
  13. * No parents left so it's not handled
  14. */
  15. mSm.unhandledMessage(msg);
  16. if (isQuit(msg)) {//如果命令是SM_QUIT_CMD才会退出,一般情况下是不会退出的
  17. transitionTo(mQuittingState);
  18. }
  19. break;
  20. }
  21. if (mDbg) {
  22. Log.d(TAG, "processMsg: " + curStateInfo.state.getName());
  23. }
  24. }
  25. /**
  26. * Record that we processed the message
  27. */
  28. if (curStateInfo != null) {
  29. State orgState = mStateStack[mStateStackTopIndex].state;
  30. mProcessedMessages.add(msg, curStateInfo.state, orgState);//保存处理processMessage的消息到mProcessedMessages中,作为一个记录,一般保存最近的20条,这个最大值可以自己定义
  31. } else {
  32. mProcessedMessages.add(msg, null, null);
  33. }
  34. }

这时mStateStack的状态信息变为[mDefaultState, mDriverUnLoadedState],先所以调用mDriverUnLoadedState的processMessage方法,而前面发送的消息为:

[cpp] view plaincopy
  1. sendMessage(obtainMessage(CMD_LOAD_DRIVER, WIFI_STATE_ENABLING, 0));
  2. sendMessage(CMD_START_SUPPLICANT);

第一句的CMD_LOAD_DRIVER,发送给应用层的消息为WIFI_STATE_ENABLING:

[cpp] view plaincopy
  1. class DriverUnloadedState extends State {
  2. @Override
  3. public void enter() {
  4. if (DBG) log(getName() + "\n");
  5. EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
  6. }
  7. @Override
  8. public boolean processMessage(Message message) {
  9. if (DBG) log(getName() + message.toString() + "\n");
  10. switch (message.what) {
  11. case CMD_LOAD_DRIVER:
  12. mWifiP2pChannel.sendMessage(WIFI_ENABLE_PENDING);//这是发送消息给WifiP2pService,WifiP2pService会响应并返回消息WIFI_ENABLE_PROCEED,其中过程有点复杂,后续再分析
  13. transitionTo(mWaitForP2pDisableState);//状态切换到了mWaitForP2pDisableState,其他好像没有做什么
  14. break;
  15. case WifiP2pService.P2P_ENABLE_PENDING:
  16. mReplyChannel.replyToMessage(message, P2P_ENABLE_PROCEED);
  17. break;
  18. default:
  19. return NOT_HANDLED;
  20. }
  21. EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
  22. return HANDLED;
  23. }
  24. }

WaitForP2pDisableState的enter做什么了?

状态已经进入mWaitForP2pDisableState中了:

[cpp] view plaincopy
  1. class WaitForP2pDisableState extends State {
  2. .............................
  3. @Override
  4. public boolean processMessage(Message message) {
  5. case WifiP2pService.WIFI_ENABLE_PROCEED: //响应WifiP2pService消息
  6. //restore argument from original message (CMD_LOAD_DRIVER)
  7. message.arg1 = mSavedArg;
  8. transitionTo(mDriverLoadingState);
  9. break;
  10. case CMD_LOAD_DRIVER:
  11. case CMD_UNLOAD_DRIVER:
  12. case CMD_START_SUPPLICANT:
  13. ..........................
  14. deferMessage(message);
  15. .............................

deferMessage将消息放入mDeferredMessages容器中,前面有提及过,作用是要把消息保存起来,等切换到下一个状态后,再将消息发送出去,让下一个状态接收;接下来的performTransitions方法中会将消息发送出去,并且在切换下一个状态前清空容器。

这时候状态在WaitForP2pDisableState中,WifiP2pService接收到消息WIFI_ENABLE_PENDING后,返回WIFI_ENABLE_PROCEED作为响应;

所以执行transitionTo(mDriverLoadingState)进入下一个状态。

processMsg就处理完成了,接着的performTransitions前面已经分析过,主要工作为调用当前状态的exit方法;切换新状态到mSupplicantStartingState,并调用新状态的enter方法,静等下一个消息的到来。

根据前面的分析可知,这时候先执行的是mDriverLoadingState的enter方法:

[cpp] view plaincopy
  1. class DriverLoadingState extends State {
  2. @Override
  3. public void enter() {
  4. if (DBG) log(getName() + "\n");
  5. EventLog.writeEvent(EVENTLOG_WIFI_STATE_CHANGED, getName());
  6. final Message message = new Message();
  7. message.copyFrom(getCurrentMessage());
  8. /* TODO: add a timeout to fail when driver load is hung.
  9. * Similarly for driver unload.
  10. */
  11. new Thread(new Runnable() {
  12. public void run() {
  13. mWakeLock.acquire();
  14. //enabling state
  15. switch(message.arg1) {
  16. case WIFI_STATE_ENABLING:
  17. setWifiState(WIFI_STATE_ENABLING);
  18. break;
  19. if(WifiNative.loadDriver()) {
  20. if (DBG) log("Driver load successful");
  21. sendMessage(CMD_LOAD_DRIVER_SUCCESS);
  22. } else {
  23. loge("Failed to load driver!");
  24. switch(message.arg1) {
  25. case WIFI_STATE_ENABLING:
  26. setWifiState(WIFI_STATE_UNKNOWN);
  27. break;
  28. case WIFI_AP_STATE_ENABLING:
  29. setWifiApState(WIFI_AP_STATE_FAILED);
  30. break;
  31. }
  32. sendMessage(CMD_LOAD_DRIVER_FAILURE);
  33. }
  34. mWakeLock.release();
  35. }
  36. }).start();
  37. @Override
  38. public boolean processMessage(Message message) {
  39. if (DBG) log(getName() + message.toString() + "\n");
  40. switch (message.what) {
  41. case CMD_LOAD_DRIVER_SUCCESS:
  42. transitionTo(mDriverLoadedState);
  43. break;
  44. case CMD_LOAD_DRIVER_FAILURE:
  45. transitionTo(mDriverFailedState);
  46. break;
  47. case CMD_LOAD_DRIVER:
  48. case CMD_UNLOAD_DRIVER:
  49. case CMD_START_SUPPLICANT:
  50. case CMD_STOP_SUPPLICANT:
  51. case CMD_START_AP:
  52. case CMD_STOP_AP:
  53. case CMD_START_DRIVER:
  54. case CMD_STOP_DRIVER:
  55. case CMD_SET_SCAN_MODE:
  56. case CMD_SET_SCAN_TYPE:
  57. case CMD_SET_HIGH_PERF_MODE:
  58. case CMD_SET_COUNTRY_CODE:
  59. case CMD_SET_FREQUENCY_BAND:
  60. case CMD_START_PACKET_FILTERING:
  61. case CMD_STOP_PACKET_FILTERING:
  62. deferMessage(message);
  63. break;
  64. default:
  65. return NOT_HANDLED;
  66. }
  67. EventLog.writeEvent(EVENTLOG_WIFI_EVENT_HANDLED, message.what);
  68. return HANDLED;
  69. }

enter线程中的消息为前面发送的WIFI_STATE_ENABLING,setWifiState的作用是发送广播通知应用层wifi状态的改变,并且加载JNI的wifi驱动,成功后还发送CMD_LOAD_DRIVER_SUCCESS消息。

接着第二句命令CMD_START_SUPPLICANT,状态在mDriverLoadingState中,执行processMessage方法,这时候会先接收前面的延时消息CMD_LOAD_DRIVER_SUCCESS,接着接收CMD_LOAD_DRIVER,CMD_START_SUPPLICANT

状态就切换到了mDriverLoadedState,并且将其他两条消息延后再传给下一个状态。

后续WifiService会根据逻辑需求,发送各种命令过来进行状态的切换,但流程都和上述分析的一样,状态机能确保各种状态有条不紊的切换并保持控制流程的清晰明了。

最后画一幅流程图如下:

android状态机实现原理相关推荐

  1. 状态模式/Android状态机/微信多人语音

    最近在做类似微信多人语音,视频聊天功能,用到了Android的状态机,借此写写自己的理解 状态模式 对状态模式的理解: 不同的状态对应不同的行为,当一个对象的状态改变了,那么该对象的行为也随之改变!通 ...

  2. Android Touch事件原理加实例分析

    Android中有各种各样的事件,以响应用户的操作.这些事件可以分为按键事件和触屏事件.而Touch事件是触屏事件的基础事件,在进行Android开发时经常会用到,所以非常有必要深入理解它的原理机制. ...

  3. Android 插件化原理学习 —— Hook 机制之动态代理

    前言 为了实现 App 的快速迭代更新,基于 H5 Hybrid 的解决方案有很多,由于 webview 本身的性能问题,也随之出现了很多基于 JS 引擎实现的原生渲染的方案,例如 React Nat ...

  4. 【Android 安全】DEX 加密 ( Application 替换 | Android 应用启动原理 | ActivityThread 后续分析 | Application 替换位置 )

    文章目录 一.ActivityThread 后续分析 二.ActivityThread 相关源码 三.Application 替换位置 dex 解密时 , 需要将 代理 Application 替换为 ...

  5. 手机内存解读以及android刷机原理

    手机内存分为:机身内存.RAM.ROM 机身内存:相当于 电脑的硬盘 这个一般可以外加SD卡扩充: RAM:相当于 电脑的内存条 可读写,掉电清空 ROM:相当于 电脑的 BIOS ROM 原则上只读 ...

  6. Android 插件化原理解析——Activity生命周期管理

    之前的 Android插件化原理解析 系列文章揭开了Hook机制的神秘面纱,现在我们手握倚天屠龙,那么如何通过这种技术完成插件化方案呢?具体来说,插件中的Activity,Service等组件如何在A ...

  7. Android代码入侵原理解析(一)

    Original 2017-05-06 付超红 滴滴安全应急响应中心 2017年初,在滴滴安全沙龙上,滴滴出行安全专家--付超红,针对App的攻与防进行了分享.会后大家对这个议题反响热烈,纷纷求详情求 ...

  8. Android 插件化原理解析——Hook机制之AMSPMS

    在前面的文章中我们介绍了DroidPlugin的Hook机制,也就是代理方式和Binder Hook:插件框架通过AOP实现了插件使用和开发的透明性.在讲述DroidPlugin如何实现四大组件的插件 ...

  9. android r.java 原理,深入理解Android消息处理系统原理

    Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制.实际上谷歌参考了Windows的消息循环机制,也在Android系统中实现了消息循环机制. Android通过Looper.Ha ...

最新文章

  1. MongoDB 标准连接字符串
  2. WISMO模块GPRS上网设置的过程
  3. 程序可以在硬件之间发送吗_你知道硬件、软件工程师之间,还有一个固件工程师吗?...
  4. FFT C语言 修改了matlab
  5. 用数学方法分析哪类游戏中的AI难度最大
  6. 辽宁活跃ip段_有泰国女排影子!激情辽宁女排,打出快乐排球,输了比赛赢了球迷...
  7. CMake 使用笔记
  8. C51编程在不同内存空间(data xdata bdata)定义变量的注意事项
  9. 3. 说清 Observable
  10. 两个app应用之间的跳转
  11. android之自定义弹框
  12. 年终盘点丨2021边缘计算大事记
  13. 团队项目绩效考核方案表
  14. 【华人学者风采】刘小平 中山大学
  15. Mac快速创建文件、文件夹
  16. 杭电多校第七场 1011 Kejin Player HDU(6656)
  17. m35c android 4.4,手机实时动态:评测:索尼M35c的整体性能简介及性价比如何
  18. 《论语》全译——先进篇第十一
  19. 16秋计算机科学与技术鲁嘉华第七章
  20. Densely Connected Convolutional Networks(论文解读三)

热门文章

  1. 【Google Play】正式版上架流程 ( 创建版本 | 设置国家地区 | 发布正式版 )
  2. 【错误记录】Android 编译时技术版本警告 ( 注解处理器与主应用支持的 Java 版本不匹配 )
  3. 【计算理论】可判定性 ( 丘奇-图灵论题 | 可判定性引入 | 图灵机语言 | 图灵机结果 | 判定机 | 部分函数与全部函数 | 可判定性定义 )
  4. Hadoop-2.8.5的HA集群搭建
  5. 求不同字母全排列两种递归模板
  6. MYSQL 5.7 主从复制 -----GTID说明与限制 原创
  7. Item 14: 如果函数不会抛出异常就把它们声明为noexcept
  8. Hadoop 资源列表
  9. CodeDom 笔记整理
  10. 优化内存中DataTable搜索速度,IP区域汇总