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

来源:互联网 发布:android 仿淘宝分类 编辑:程序博客网 时间:2024/05/23 01:19
[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
--------------------------------------------------------------------------------------------------------------------------------