5.4 WifiWatchdogStateMachine介绍

WifiWatchdogStateMachine用于监控无线网络的信号质量,在WifiService的checkAndStartWifi函数中被创建,其创建函数是makeWifiWatchdogStateMachine,代码如下所示。

[—>WifiWatchdogStateMachine.java::makeWifiWatchdogStateMachine]

  1. public static WifiWatchdogStateMachine makeWifiWatchdogStateMachine(Context context) {
  2. ContentResolver contentResolver = context.getContentResolver();
  3.  
  4. ConnectivityManager cm = (ConnectivityManager) context.getSystemService(
  5. Context.CONNECTIVITY_SERVICE);
  6. // 判断手机是否只支持Wi-Fi。对于大部分手机来说,sWifiOnly为false
  7. sWifiOnly = (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false);
  8. // WIFI_WATCHDOG_ON功能默认是打开的
  9. putSettingsGlobalBoolean(contentResolver, Settings.Global.WIFI_WATCHDOG_ON, true);
  10.  
  11. // 创建一个WifiWatchdogStateMachine对象,它也是一个HSM
  12. WifiWatchdogStateMachine wwsm = new WifiWatchdogStateMachine(context);
  13. wwsm.start();// 启动HSM
  14. return wwsm;
  15. }

1.WifiWatchdogStateMachine构造函数分析

先来看WifiWatchdogStateMachine的初始化流程。

[—>WifiWatchdogStateMachine.java::WifiWatchdogStateMachine]

  1. private WifiWatchdogStateMachine(Context context) {
  2. super(TAG);
  3. mContext = context; mContentResolver = context.getContentResolver();
  4. mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
  5. // mWsmChannel用于和WifiStateMachine交互
  6. mWsmChannel.connectSync(mContext, getHandler(),
  7. mWifiManager.getWifiStateMachineMessenger());
  8. /*
  9. 关键函数:setupNetworkReceiver将创建一个广播接收对象,用于接收NETWORK_STATE_CHANGED_ACTION、
  10. WIFI_STATE_CHANGED_ACTION、RSSI_CHANGED_ACTION、SUPPLICANT_STATE_CHANGED_
  11. ACTION等广播。
  12. */
  13. setupNetworkReceiver();
  14.  
  15. // 监控Wifi Watchdog设置的变化情况
  16. registerForSettingsChanges();
  17. registerForWatchdogToggle();
  18.  
  19. addState(mDefaultState);
  20. ......// 添加状态,一共有9个状态。如图5-7所示
  21. // Wifi Watchdog默认是开启的,故状态机转入NotConnectedState状态
  22. if (isWatchdogEnabled()) setInitialState(mNotConnectedState);
  23. else setInitialState(mWatchdogDisabledState);
  24.  
  25. updateSettings();
  26. }

上面代码中,WifiWatchdogStateMachine的初始状态是NotConnectedState。不过这个状态仅实现了enter函数,而且该函数中仅实现了一句打印输出的代码,所以NotConnectedState是一个象征意义远大于实际作用的类。

图5-7所示为WifiWatchdogStateMachine中的各个状态及层级关系。

5.4 WifiWatchdogStateMachine介绍 - 图1

图5-7 WifiWatchdogStateMachine状态及层级关系

WifiWatchdogStateMachine完全靠广播事件来驱动,相关代码在setupNetworkReceiver函数中。

[—>WifiWatchdogStateMachine.java::setupNetworkReceiver]

  1. private void setupNetworkReceiver() {
  2. mBroadcastReceiver = new BroadcastReceiver() {
  3. public void onReceive(Context context, Intent intent) {
  4. String action = intent.getAction();
  5. if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
  6. obtainMessage(EVENT_RSSI_CHANGE,
  7. intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, -200), 0).sendToTarget();
  8. } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
  9. sendMessage(EVENT_SUPPLICANT_STATE_CHANGE, intent);
  10. } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
  11. sendMessage(EVENT_NETWORK_STATE_CHANGE, intent);
  12. } ......
  13. else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION))
  14. sendMessage(EVENT_WIFI_RADIO_STATE_CHANGE,intent.getIntExtra(
  15. WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));
  16. }
  17. };
  18.  
  19. mIntentFilter = new IntentFilter();
  20. mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
  21. ......// 添加感兴趣的广播事件类型
  22. mContext.registerReceiver(mBroadcastReceiver, mIntentFilter);
  23. }

在前面介绍的WifiService工作流程中,SUPPLICANT_STATE_CHANGED_ACTION和NETWORK_STATE_CHANGED_ACTION广播发送的次数非常频繁。所以,WifiWatchdogStateMachine也不会太清闲。

下面,我们直接从WifiStateMachine在VerifyingLinkState的enter函数中发送的NETWORK_STATE_CHANGED_ACTION广播开始分析WifiWatchdogStateMachine的处理流程。

2.EVENT_NETWORK_STATE_CHANGE处理流程

该消息被NotConnectedState的父状态WatchdogEnabledState处理,相关代码如下所示。

[—>WifiWatchdogStateMachine.java::WatchdogEnabledState:processMessage]

  1. public boolean processMessage(Message msg) {
  2. Intent intent;
  3. switch (msg.what) {
  4. ......
  5. case EVENT_NETWORK_STATE_CHANGE:
  6. intent = (Intent) msg.obj;
  7. NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
  8. WifiManager.EXTRA_NETWORK_INFO);
  9. mWifiInfo = (WifiInfo) intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO);
  10. // 更新bssid信息
  11. updateCurrentBssid(mWifiInfo != null ? mWifiInfo.getBSSID() : null);
  12.  
  13. switch (networkInfo.getDetailedState()) {
  14. case VERIFYING_POOR_LINK:
  15. // WifiStateMachine在VerifyingLinkState中设置的状态
  16. mLinkProperties = (LinkProperties) intent.getParcelableExtra(
  17. WifiManager.EXTRA_LINK_PROPERTIES);
  18. // mPoorNetworkDetectionEnabled用于判断是否需要监控AP的信号质量
  19. if (mPoorNetworkDetectionEnabled) {
  20. if (mWifiInfo == null || mCurrentBssid == null) {
  21. // 下面这个函数将通过mWsmChannel向WifiStateMachine发送
  22. // GOOD_LINK_DETECTED消息
  23. sendLinkStatusNotification(true);
  24. }
  25. else transitionTo(mVerifyingLinkState);
  26. // 进入VerifyingLinkState
  27. } else sendLinkStatusNotification(true);
  28. break;
  29. case CONNECTED:// WifiStateMachine在ConnectedState中设置的状态
  30. // 请读者自行分析OnlineWatchState的处理流程
  31. transitionTo(mOnlineWatchState);
  32. }
  33. ......
  34. }
  35. return HANDLED;
  36. }

如果WifiWatchdogStateMachine开启无线网络信号质量监控,将转入VerifyingLinkState,其enter函数如下所示。

[—>WifiWatchdogStateMachine.java::VerifyingLinkState:enter]

  1. public void enter() {
  2. mSampleCount = 0;
  3. mCurrentBssid.newLinkDetected();
  4. // 向自己发送CMD_RSSI_FETCH消息
  5. sendMessage(obtainMessage(CMD_RSSI_FETCH, ++mRssiFetchToken, 0));
  6. }

3.CMD_RSSI_FETCH处理流程

来看CMD_RSSI_FETCH消息的处理。

[—>WifiWatchdogStateMachine.java::VerifyingLinkState:processMessage]

  1. public boolean processMessage(Message msg) {
  2. switch (msg.what) {
  3. ......
  4. case CMD_RSSI_FETCH:
  5. if (msg.arg1 == mRssiFetchToken) {
  6. /*
  7. 向WifiStateMachine发送RSSI_PKTCNT_FETCH消息,WifiStateMachine
  8. 的处理过程就是调用WifiNative的signalPoll和pktcntPoll以获取RSSI、
  9. LinkSpeed、发送Packet的总个数、发送失败的Packet总个数。注意,4.2中
  10. 的WPAS才支持pktcntPoll。
  11. WifiStateMachine处理完RSSI_PKTCNT_FETCH后将回复RSSI_PKTCNT_FETCH_
  12. SUCCEEDED消息给WifiWatchdogStateMachine。
  13. */
  14. mWsmChannel.sendMessage(WifiManager.RSSI_PKTCNT_FETCH);
  15. // LINK_SAMPLING_INTERVAL_MS值为1000ms
  16. sendMessageDelayed(obtainMessage(CMD_RSSI_FETCH,
  17. ++mRssiFetchToken, 0), LINK_SAMPLING_INTERVAL_MS);
  18. }
  19. break;
  20. case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
  21. // WifiStateMachine回复的消息中携带一个RssiPacketCountInfo对象
  22. RssiPacketCountInfo info = (RssiPacketCountInfo) msg.obj;
  23. int rssi = info.rssi;
  24. /*
  25. WifiWatchdog用了一个名为指数加权移动平均算法(Volume-weighted Exponential
  26. Moving Average)的方法来辨别网络信号质量的好坏。本书不对它进行讨论,感兴趣的
  27. 读者不妨自行研究。
  28. */
  29. long time = mCurrentBssid.mBssidAvoidTimeMax -
  30. SystemClock.elapsedRealtime();
  31. // 假设网络质量很好,则调用sendLinkStateNotification
  32. // 以发送GOOD_LINK_DETECT消息给WifiStateMachine
  33. if (time <= 0) sendLinkStatusNotification(true);
  34. else {
  35. // 此时的rssi等某个阈值。mGoodLinkTargetRssi由算法计算得来
  36. if (rssi >= mCurrentBssid.mGoodLinkTargetRssi) {
  37. // 当采样次数大于一定值时,才认为网络状态变好
  38. // mGoodLinkTargetCount也是通过相关方法计算得来
  39. if (++mSampleCount >= mCurrentBssid.mGoodLinkTargetCount) {
  40. mCurrentBssid.mBssidAvoidTimeMax = 0;
  41. sendLinkStatusNotification(true);
  42. }
  43. } else mSampleCount = 0;
  44. }
  45. break;
  46. ......
  47. }
  48. return HANDLED;
  49. }

当WifiWatchdogStateMachine检测到Pool link时,它将发送POOL_LINK_DETECT消息给WifiStateMachine去处理。相关流程请感兴趣的读者自行研究。

WifiWatchdogStateMachine是一个比较有趣的模块。其目的很简单,就是监测无线网络的信号质量,然后做相应动作。另外,WifiWatchdogStateMachine还使用了一些比较高级的算法来判断网络信号质量的好坏,感兴趣的读者不妨进行深入研究。