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

[android-wifi]开启,扫描与连接相关流程

2017-07-25 17:10 465 查看
[android-wifi]开启,扫描与连接相关流程

*重要知识点*:

<pre>

          mP0

         /          \

        mP1    mS0

       /         \

      mS2   mS1

     /        \          \

    mS3  mS4  mS5  ---> initial state

</pre>

 * <p>After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.

 * So the order of calling processMessage when a message is received is mS5,

 * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this

 * message by returning false or NOT_HANDLED.</p>

 *

 * <p>Now assume mS5.processMessage receives a message it can handle, and during

 * the handling determines the machine should change states. It could call

 * transitionTo(mS4) and return true or HANDLED. Immediately after returning from

 * processMessage the state machine runtime will find the common parent,

 * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then

 * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So

 * when the next message is received mS4.processMessage will be invoked.

解释如下:

假设目前的状态机是如上图所示.

1.当目前的状态机是mS5时,收到消息处理的顺序为mS5,mS1, mP1, mP0而且是当方法processMessage 返回的是NOT_HANDLED消息才能被上一层继续处理.

  而且处理的时候应该当改变相应的状态并返回真.比如mS5收到消息后转换相应的状态到mS4并返回HANDLED.

2.转换到mS4时,状态机将会发现mS5和mS4同样的父层级是mP1,接着状态机会调用mS5的exit方法,mS1的exit方法.调用mS2的enter和mS4的enter方法。

  这个时候新的激活状态结构为mP0,mP1,mS2,mS4,而接收消息会被mS4优先处理

举列说明:

Android-7.1(4.4基本一样)代码的WIFI模块中:

在WifiController文件中的的状态机 "部分结构" 如下[其中mApStaDisabledState为状态机初始状态]:

      mDefaultState.....................................................

           |                                                    |

   mApStaDisabledState       mStaEnabledState.....................

                                                                |

                                              mDeviceActiveState

                                                                 |

                                              DeviceActiveHighPerfState

简单表示如下:

                                    mP0(mDefaultState)

                                      /           \

(mStaEnabledState)mP1    mS0(mApStaDisabledState)

                                    /   \

                                        mS1(mDeviceActiveState)

当前状态为:mP0(mDefaultState),mS0(mApStaDisabledState)

经过下面操作后状态为:mP0,mP1(mStaEnabledState),mS1(mDeviceActiveState)而且会调用mP1(mStaEnabledState)的enter方法再调用mS1(mDeviceActiveState)的enter方法

操作步骤:打开设置中的wifi开关在WifiController文件中的状态机会发生变化如下(因为mApStaDisabledState状态机是初始状态首先收到信息并进行相应的逻辑处理):

   

      mApStaDisabledState状态机优先处理消息

      {

        @Override

        public boolean processMessage(Message msg) {

            switch (msg.what) {

                case CMD_WIFI_TOGGLED:

                      if (mDeviceIdle == false) {

                            checkLocksAndTransitionWhenDeviceActive();//假设走个方法"当前设备是活动使用状态"

                        } else {

                            checkLocksAndTransitionWhenDeviceIdle();

                        }

                break;

             return HANDLED

       }

      private void checkLocksAndTransitionWhenDeviceActive() {

        if (mWifiLockManager.getStrongestLockMode() == WIFI_MODE_FULL_HIGH_PERF) {

            // It is possible for the screen to be off while the device is

            // is active (mIdleMillis), so we need the high-perf mode

            // otherwise powersaving mode will be turned on.

            transitionTo(mDeviceActiveHighPerfState);//为mDeviceActiveState的子层级

        } else {

            transitionTo(mDeviceActiveState);//假设走这个方法

        }

      }

 说明:这个时候mApStaDisabledState状态会处理完消息并转换成mDeviceActiveState状态

      根据状态机原理会调用mDeviceActiveState的父级mStaEnabledState的enter方法和mDeviceActiveState的enter方法

     mStaEnabledState

     {

         @Override

        public void enter() {

            mWifiStateMachine.setSupplicantRunning(true);

            //上面这个方法会调用sendMessage(CMD_START_SUPPLICANT)在WifiStateMachine的状态机内部进行消息传递

            //而WifiStateMachine的默认初始状态为InitialState处理此消息调用wifiNative.loadDriver

            //继续调用mWifiNative.startHal方法和mWifiNative.startSupplicant 就把wifi驱动和hal层和wpa_supplicant建立起来可以进行下一步连接wifi

            //而WifiStateMachine从InitialState状态变为transitionTo(mSupplicantStartingState)状态

        }

     }

 说明:这样通过状态机有效的管理Wifi的驱动被加载,HAL层和关键模块wpa_supplicant也被启动.下一步wifi的连接动作就可以进行了

*在WifiController的状态机变为*:

mDefaultState---mStaEnabledState---mDeviceActiveState

这样状态机的例子就结束了.应该可以看出状态机如果理解对代码就比较好梳理.

不过上面逻辑已经到WifiStateMachine的setSupplicantRunning了趁热继续详细分析一下

 WifiStateMachine::setSupplicantRunning

   public void setSupplicantRunning(boolean enable) {

        if (enable) {

            WifiNative.setApMode(false);

            sendMessage(CMD_START_SUPPLICANT);//发送消息 此时WifiStateMachine的初始状态机InitialState会处理此消息

        }

   }

     InitialState{

       @Override

        public boolean processMessage(Message message) {

            logStateAndMessage(message, this);

            switch (message.what) {

                case CMD_START_SUPPLICANT:

                     //见上面简单描述

                     mWifiNative.loadDriver()

                     mNwService.wifiFirmwareReload(mInterfaceName, "STA");

                     mWifiNative.startHal()

                     mWifiNative.startSupplicant(mP2pSupported)

                     mWifiMonitor.startMonitoring(mInterfaceName);//启动监听器状态机

                     transitionTo(mSupplicantStartingState)//转换状态

 

     }

*在WifiStateMachine的状态机变为*:

mDefaultState---mSupplicantStartingState

看下关键代码:

 WifiMonitor::startMonitoring

 {

       mWifiNative.connectToSupplicant();//启动supplicant后会接着启动MonitorThread线程调用WifiNative.waitForEvent 来监听事件

       //事件调用方法比如handleSupplicantStateChange或者handleDriverEvent

       sendMessage(iface, SUP_CONNECTION_EVENT)

 }

又因为在WifiStateMachine中通过如下方法注册了

mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SUP_CONNECTION_EVENT, getHandler())

所以WifiStateMachine的mSupplicantStartingState会处理此消息

   mSupplicantStartingState

   {

        @Override

        public boolean processMessage(Message message) {

          switch(message.what) {

                case WifiMonitor.SUP_CONNECTION_EVENT:

                setWifiState(WIFI_STATE_ENABLED);

                mWifiInfo.setMacAddress(mWifiNative.getMacAddress());//设置MAC地址

                transitionTo(mDriverStartedState);//转换状态到mDriverStartedState

        }

    }

*在WifiStateMachine的状态机又变为*

mDefaultState---mSupplicantStartedState(因为是mDriverStartedState的父层级)---mDriverStartedState

继续趁热分析

   mSupplicantStartedState

   {

        @Override

        public void enter() {

           mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000)//设置扫描周期会保存到wpa_supplicant相应的结构体中

        }

   }

  mDriverStartedState

  {

        @Override

        public void enter() {

          transitionTo(mDisconnectedState);/转换到mDisconnectedState状态

        }

   }

*在WifiStateMachine的状态机又变为*

mDefaultState---mSupplicantStartedState---mDriverStartedState---mConnectModeState(因为是父层级)---mDisconnectedState

  mDisconnectedState

  {

        @Override

        public void enter() {

            //执行300S后周期搜索无线网络

            //<integer translatable="false" name="config_wifi_no_network_periodic_scan_interval">300000</integer>

            if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get()

                    && mWifiConfigManager.getSavedNetworks().size() == 0) {

                sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,

                        ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);

            }

        }

        @Override

        public boolean processMessage(Message message) {

            boolean ret = HANDLED;

            switch (message.what) {

                case CMD_NO_NETWORKS_PERIODIC_SCAN:

                    if (mP2pConnected.get()) break;

                    if (mNoNetworksPeriodicScan != 0 && message.arg1 == mPeriodicScanToken &&

                            mWifiConfigManager.getSavedNetworks().size() == 0) {

                        startScan(UNKNOWN_SCAN_SOURCE, -1, null, WIFI_WORK_SOURCE);//开始搜索网络

                        sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,

                                    ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);//重新执行搜索网络

                    }

                    break;

   }

----------------"以上逻辑4.4与7.1代码 大同小异 相差不是很大 状态机基本一样"-----------

----------------"开启supplicant后要进行扫描网络接入点"----------------

1.余下为搜索网络相关逻辑

由于7.1针对搜索网络添加了新的状态机机制所以这部分和4.4有比较大的区别

packages.SettingsLib.wifi.WifiTracker::mReceiver监听到此广播

{

 WifiManager.WIFI_STATE_CHANGED_ACTION//此状态是由mSupplicantStartingState传过来

 mWifiManager.startScan//最终调用接口启动扫描

}

而界面上的更新接入点是在WifiTracker::updateAccessPoints实现

由上面可知当前状态是由mDriverStartedState启动扫描

 WifiStateMachine.DriverStartedState

 {

     case CMD_START_SCAN:

     handleScanRequest(message);

     break;

  }

接着调用WifiStateMachine.startScanNative

{

   mWifiScanner.startScan

}

在frameowkrs.base.wifi.WifiScanner.startScan

{

  mAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, key, scanParams)

}

     -------扫描服务介绍----

    1.WifiScanningServiceImpl extends IWifiScanner.Stub

    2.在FrameworkFacade.makeWifiScanner{

        new WifiScanner(context, IWifiScanner.Stub.asInterface(

                        getService(Context.WIFI_SCANNING_SERVICE)), looper)

    }

    //把WifiScanningServiceImpl保存到WifiScanner的内部通过AsyncChannel将两者的ServiceHandler和ClientHandler连接起来

    //所以WifiScanner.startScan(CMD_START_SINGLE_SCAN)消息将在WifiScanningServiceImpl实现

    WifiScanningServiceImpl

    {

          case WifiScanner.CMD_START_SINGLE_SCAN:

          case WifiScanner.CMD_STOP_SINGLE_SCAN:

            mSingleScanStateMachine.sendMessage(Message.obtain(msg));

    }

    WifiScanningServiceImpl.SingleScanStateMachine.DriverStartedState

    {

        case WifiScanner.CMD_START_SINGLE_SCAN:

             mWifiMetrics.incrementOneshotScanCount();

             tryToStartNewScan

     }

        WifiScanningServiceImpl的tryToStartNewScan方法

    {

         mScannerImpl.startSingleScan//通过WifiScannerImpl去执行搜索

         transitionTo(mScanningState);//转换状态

    }

   而WifiScanningService的构造方法传递WifiScannerImpl的实现类

   {

         mImpl = new WifiScanningServiceImpl(getContext(), mHandlerThread.getLooper(),

                WifiScannerImpl.DEFAULT_FACTORY, BatteryStatsService.getService(),

                WifiInjector.getInstance());

         //工厂类是HalWifiScannerImpl或者SupplicantWifiScannerImpl这里走SupplicantWifiScannerImpl

   }

   最终会调用SupplicantWifiScannerImpl类 并调用mWifiNative.scan进行扫描网络热入点

  而在WifiMonitor.handleEvent

  {

       case SCAN_RESULTS:

             sendMessage(iface, SCAN_RESULTS_EVENT);

             break;

   }

  又在SupplicantWifiScannerImpl.SupplicantWifiScannerImpl中进行注册

  {

    WifiMonitor.getInstance().registerHandler(mWifiNative.getInterfaceName(),

                WifiMonitor.SCAN_RESULTS_EVENT, mEventHandler);

  }

  又在WifiStateMachine中进行注册

  {

    mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.SCAN_RESULTS_EVENT, getHandler());

  }

  SupplicantWifiScannerImpl

  {

    case WifiMonitor.SCAN_RESULTS_EVENT:

         mAlarmManager.cancel(mScanTimeoutListener);

         pollLatestScanData();

         processPendingScans();

         break;

   }

  会执行SupplicantWifiScannerImpl.pollLatestScanData方法

  {

     mWifiNative.getScanResults

   }

  而WifiScanningServiceImpl:onScanStatus

  {

    sendMessage(CMD_SCAN_RESULTS_AVAILABLE)

  }

  //由前面而知在扫描之后会入ScanningState状态所以事件消息将会由此处理

  在WifiScanningServiceImpl.WifiSingleScanStateMachine.ScanningState

  {

     @Override

     public boolean processMessage(Message msg) {

             switch (msg.what) {

               case CMD_SCAN_RESULTS_AVAILABLE:

                reportScanResults(mScannerImpl.getLatestSingleScanResults());//调用SupplicantWifiScannerImpl

                mActiveScans.clear();

                transitionTo(mIdleState);//转换状态

  }

  回调到WifiScanner

  {

     case CMD_SCAN_RESULT :

          ((ScanListener) listener).onResults(((ParcelableScanData) msg.obj).getResults());

          return;

  }

  在看WifiStateMachine.SupplicantStartedState中对事件的处理

  {

      case WifiMonitor.SCAN_RESULTS_EVENT:

      case WifiMonitor.SCAN_FAILED_EVENT:

           maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered

           setScanResults();

           //如上方法会调用ArrayList<ScanDetail> scanResults = mWifiNative.getScanResults()供WifiServiceImpl调用

           if (mIsFullScanOngoing || mSendScanResultsBroadcast) {

                        /* Just updated results from full scan, let apps know about this */

                        boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT;

                        sendScanResultsAvailableBroadcast(scanSucceeded);//发送广播

           }

   }

2.------------4.4的扫描流程--------------------

packages.apps.Settings.WifiSettings文件

{

   mReceiver = new BroadcastReceiver() {

            @Override

            public void onReceive(Context context, Intent intent) {

            //监听广播如mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)

                handleEvent(context, intent);

            }

   };

   状态上来后会调用WifiManager.startScan

}

 WifiStateMachine.DriverStartedState

 {

     startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP)

 }

 WifiStateMachine.startScanNative

 {

   mWifiNative.scan(type)

 }

事件上传WifiMonitor.handleEvent

 {

     case SCAN_RESULTS:

          mStateMachine.sendMessage(SCAN_RESULTS_EVENT);

          break;

 }

 在WifiStateMachine.SupplicantStartedState

   {

         case WifiMonitor.SCAN_RESULTS_EVENT:

              setScanResults();

              sendScanResultsAvailableBroadcast();

              mScanResultIsPending = false;

              break;

    }

 在WifiStateMachine.setScanResults

   {

        mWifiNative.scanResults并保存在mScanResults中

    }

 而WifiStateMachine的syncGetScanResultsList可以提供给wifiManager使用

至此4.4和7.1搜索网络逻辑分析完毕其中7.1逻辑较为复杂而4.4比较简洁

-----------------------------------------------------------------------

2.搜索完网络 通过wifiManager.connect进行网络连接

注意:连接网络消息CONNECT_NETWORK将在mConnectModeState中进行处理

-----7.1----连接逻辑

  WifiServiceImpl.ClientHandler

  {

        @Override

        public void handleMessage(Message msg) {

            switch (msg.what) {

             case WifiManager.CONNECT_NETWORK:

                mWifiStateMachine.sendMessage(Message.obtain(msg));

            }

        }

  }

 由上可知状态为ConnectModeState

             {

              case WifiManager.CONNECT_NETWORK:

                   mWifiConfigManager.selectNetwork(config, /* updatePriorities = */ true,

                            message.sendingUid) && mWifiNative.reconnect()

             }

连接事件在ConnectModeState

          {

             case WifiMonitor.NETWORK_CONNECTION_EVENT:

                    sendNetworkStateChangeBroadcast(mLastBssid);

                    transitionTo(mObtainingIpState);//转换状态

          }

:此时WifiStateMachine状态为

mDefaultState---mSupplicantStartedState---mDriverStartedState---mL2ConnectedState---mObtainingIpState

    在mObtainingIpState.enter

      {

            final IpManager.ProvisioningConfiguration prov =

                        mIpManager.buildProvisioningConfiguration()

                            .withPreDhcpAction()

                            .withApfCapabilities(mWifiNative.getApfCapabilities())

                            .build();

            mIpManager.startProvisioning(prov)

      }

     //又WifiStateMachine里面对IpManager实例化的时候有相应的回调类IpManagerCallback将被IpManager回调相应的方法并发送消息.

     //相应的状态机会拦截相应的消息

      在IpManager的RunningState.enter方法内

     {

       startIPv6();

       startIPv4();

     }

在L2ConnectedState的状态的处理消息方法中

{

           case CMD_IP_CONFIGURATION_SUCCESSFUL:

                    handleSuccessfulIpConfiguration();

                    reportConnectionAttemptEnd(

                            WifiMetrics.ConnectionEvent.FAILURE_NONE,

                            WifiMetricsProto.ConnectionEvent.HLF_NONE);

                    sendConnectedState();

                    transitionTo(mConnectedState);

                    break;

 }

此时进入连接状态

mDefaultState---mSupplicantStartedState---mDriverStartedState---mConnectModeState---mL2ConnectedState---mConnectedState

-----------------------------------------------------------------------------------------------------------------------------------

----4.4---连接逻辑

  ConnectModeState.

  {

   case WifiManager.CONNECT_NETWORK

        if (mWifiConfigStore.selectNetwork(netId) && mWifiNative.reconnect()) {

             transitionTo(mDisconnectingState);

        }

  }

 ObtainingIpState.enter

  {

    startDhcp();

  }

//接着到VerifyingLinkState状态最后到CaptivePortalCheckState认证状态

//在此状态根据CMD_CAPTIVE_CHECK_COMPLETE消息调整到连接状态transitionTo(mConnectedState)

此时进入连接状态

mDefaultState---mSupplicantStartedState---mDriverStartedState---mConnectModeState---mL2ConnectedState---mConnectedState

--------------------------------------------------------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  wifi android androidn