Android -- Wifi启动流程分析

时间:2024-03-24 13:02:11
转自http://blog.csdn.net/csdn_of_coder/article/details/51541094
Android网络各个模式中,Wifi应该是目前最常用的一种网络方式了;下面就简单介绍下Android中Wifi的启动流程。
当我在Setting菜单里点击打开Wifi时,调用的入口函数是WifiManager::setWifiEnabled(boolean enabled):
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. /** 
  2.  * Enable or disable Wi-Fi. 
  3.  * @param enabled {@code true} to enable, {@code false} to disable. 
  4.  * @return {@code true} if the operation succeeds (or if the existing state 
  5.  *         is the same as the requested state). 
  6.  */  
  7. public boolean setWifiEnabled(boolean enabled) {  
  8.     try {  
  9.         return mService.setWifiEnabled(enabled);  
  10.     } catch (RemoteException e) {  
  11.         return false;  
  12.     }  
  13. }  
通过AIDL方式,在Android6.0中,实际调用的是WifiServiceImpl::setWifiEnabled(boolean enable):
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. /** 
  2.  * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)} 
  3.  * @param enable {@code true} to enable, {@code false} to disable. 
  4.  * @return {@code true} if the enable/disable operation was 
  5.  *         started or is already in the queue. 
  6.  */  
  7. public synchronized boolean setWifiEnabled(boolean enable) {  
  8.     enforceChangePermission();  
  9.     Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()  
  10.                 + ", uid=" + Binder.getCallingUid());  
  11.     if (DBG) {  
  12.         Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");  
  13.     }  
  14.   
  15.     /* 
  16.     * Caller might not have WRITE_SECURE_SETTINGS, 
  17.     * only CHANGE_WIFI_STATE is enforced 
  18.     */  
  19.   
  20.     long ident = Binder.clearCallingIdentity();  
  21.     try {  
  22.         if (! mSettingsStore.handleWifiToggled(enable)) {  
  23.             // Nothing to do if wifi cannot be toggled  
  24.             return true;  
  25.         }  
  26.     } finally {  
  27.         Binder.restoreCallingIdentity(ident);  
  28.     }  
  29.   
  30.     mWifiController.sendMessage(CMD_WIFI_TOGGLED);  
  31.     return true;  
  32. }  
从代码可以看出,这里主要的操作是将wifi是否enable的状态存入数据库、向WiFiController发送了CMD_WIFI_TOGGLED消息。WifiController实际上是一个状态机,相比WifiStateMachine,它的状态较少,结构也比较简单。WifiController的定义及构造函数:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. class WifiController extends StateMachine {  
  2.    ...  
  3.    WifiController(Context context, WifiServiceImpl service, Looper looper) {  
  4.         super(TAG, looper);  
  5.         ...    
  6.   
  7.         addState(mDefaultState);  
  8.             addState(mApStaDisabledState, mDefaultState);  
  9.             addState(mStaEnabledState, mDefaultState);  
  10.                 addState(mDeviceActiveState, mStaEnabledState);  
  11.                 addState(mDeviceInactiveState, mStaEnabledState);  
  12.                     addState(mScanOnlyLockHeldState, mDeviceInactiveState);  
  13.                     addState(mFullLockHeldState, mDeviceInactiveState);  
  14.                     addState(mFullHighPerfLockHeldState, mDeviceInactiveState);  
  15.                     addState(mNoLockHeldState, mDeviceInactiveState);  
  16.             addState(mStaDisabledWithScanState, mDefaultState);  
  17.             addState(mApEnabledState, mDefaultState);  
  18.             addState(mEcmState, mDefaultState);  
  19.   
  20.         boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();  
  21.         boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();  
  22.         boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();  
  23.   
  24.         log("isAirplaneModeOn = " + isAirplaneModeOn +  
  25.                 ", isWifiEnabled = " + isWifiEnabled +  
  26.                 ", isScanningAvailable = " + isScanningAlwaysAvailable);  
  27.   
  28.         if (isScanningAlwaysAvailable) {  
  29.             setInitialState(mStaDisabledWithScanState);  
  30.         } else {  
  31.             setInitialState(mApStaDisabledState);  
  32.         }  
  33.   
  34.         ...  
  35.     }  
  36.     ...  
  37. }  
WifiController状态机的创建、开启工作在WifiServiceImpl中完成:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. public WifiServiceImpl(Context context) {  
  2.     mContext = context;  
  3.   
  4.     mInterfaceName =  SystemProperties.get("wifi.interface""wlan0");  
  5.   
  6.     mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);  
  7.     mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);  
  8.     mWifiStateMachine.enableRssiPolling(true);  
  9.     mBatteryStats = BatteryStatsService.getService();  
  10.     mPowerManager = context.getSystemService(PowerManager.class);  
  11.     mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);  
  12.     mUserManager = UserManager.get(mContext);  
  13.   
  14.     mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);  
  15.     mSettingsStore = new WifiSettingsStore(mContext);  
  16.   
  17.     HandlerThread wifiThread = new HandlerThread("WifiService");  
  18.     wifiThread.start();  
  19.     mClientHandler = new ClientHandler(wifiThread.getLooper());  
  20.     mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());  
  21.     mWifiController = new WifiController(mContext, this, wifiThread.getLooper());  
  22. }  
WifiController中的各状态之间的关系如图:Android -- Wifi启动流程分析
WifiControlle状态机的初始状态由一些配置信息决定。当ApStaDisabledState为初始状态时,看对CMD_WIFI_TOGGLED消息的处理:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. class ApStaDisabledState extends State {  
  2.     ...  
  3.     @Override  
  4.     public boolean processMessage(Message msg) {  
  5.         switch (msg.what) {  
  6.             case CMD_WIFI_TOGGLED:  
  7.             case CMD_AIRPLANE_TOGGLED:  
  8.                 if (mSettingsStore.isWifiToggleEnabled()) {  
  9.                     if (doDeferEnable(msg)) {  
  10.                         if (mHaveDeferredEnable) {  
  11.                             //  have 2 toggles now, inc serial number an ignore both  
  12.                             mDeferredEnableSerialNumber++;  
  13.                         }  
  14.                         mHaveDeferredEnable = !mHaveDeferredEnable;  
  15.                         break;  
  16.                     }  
  17.                     if (mDeviceIdle == false) {  
  18.                         transitionTo(mDeviceActiveState);  
  19.                     } else {  
  20.                         checkLocksAndTransitionWhenDeviceIdle();  
  21.                     }  
  22.                 } else if (mSettingsStore.isScanAlwaysAvailable()) {  
  23.                     transitionTo(mStaDisabledWithScanState);  
  24.                 }  
  25.                 break;  
  26.             case CMD_SCAN_ALWAYS_MODE_CHANGED:  
  27.                 if (mSettingsStore.isScanAlwaysAvailable()) {  
  28.                     transitionTo(mStaDisabledWithScanState);  
  29.                 }  
  30.                 break;  
  31.             ...  
  32.             default:  
  33.                 return NOT_HANDLED;  
  34.         }  
  35.         return HANDLED;  
  36.     }  
  37.   
  38.     private boolean doDeferEnable(Message msg) {  
  39.         long delaySoFar = SystemClock.elapsedRealtime() - mDisabledTimestamp;  
  40.         if (delaySoFar >= mReEnableDelayMillis) {  
  41.             return false;  
  42.         }  
  43.   
  44.         log("WifiController msg " + msg + " deferred for " +  
  45.                 (mReEnableDelayMillis - delaySoFar) + "ms");  
  46.   
  47.         // need to defer this action.  
  48.         Message deferredMsg = obtainMessage(CMD_DEFERRED_TOGGLE);  
  49.         deferredMsg.obj = Message.obtain(msg);  
  50.         deferredMsg.arg1 = ++mDeferredEnableSerialNumber;  
  51.         sendMessageDelayed(deferredMsg, mReEnableDelayMillis - delaySoFar + DEFER_MARGIN_MS);  
  52.         return true;  
  53.     }  
  54.   
  55. }  
调试过程中发现,ApStaDisabledState会同时忽略两个时间间隔小于500ms的 CMD_WIFI_TOGGLED消息,接着转换到DeviceActiveState状态。StaEnabledState是它的父状态,由StateMachine的知识可知,转换到该状态时,会依次调用父、子状态的enter()函数。我们看两个状态的enter()函数:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. class StaEnabledState extends State {  
  2.     @Override  
  3.     public void enter() {  
  4.         mWifiStateMachine.setSupplicantRunning(true);  
  5.     }  
  6.     ...  
  7.     }  
  8. }  
  9. /* Parent: StaEnabledState */  
  10. class DeviceActiveState extends State {  
  11.     @Override  
  12.     public void enter() {  
  13.         mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);  
  14.         mWifiStateMachine.setDriverStart(true);  
  15.         mWifiStateMachine.setHighPerfModeEnabled(false);//此处分析忽略,关系不大  
  16.     }  
  17.   
  18.     ...  
  19. }  
这里依次会向WifiStateMachine发送三个消息,最后一个消息这里忽略:
  1. WifiStateMachine.setSupplicantRunning(true):发送CMD_START_SUPPLICANT消息
  2. WifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE):发送CMD_SET_OPERATIONAL_MODE消息,参数是CONNECT_MODE
  3. WifiStateMachine.setDriverStart(true):发送CMD_START_DRIVER消息
在此之前,我们先看下第二点中的参数CONNECT_MODE的含义。在WifiStateMachine中,已经有了如下定义:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. /* Wifi state machine modes of operation */  
  2. /* CONNECT_MODE - connect to any 'known' AP when it becomes available */  
  3. public static final int CONNECT_MODE = 1;  
  4. /* SCAN_ONLY_MODE - don't connect to any APs; scan, but only while apps hold lock */  
  5. public static final int SCAN_ONLY_MODE = 2;  
  6. /* SCAN_ONLY_WITH_WIFI_OFF - scan, but don't connect to any APs */  
  7. public static final int SCAN_ONLY_WITH_WIFI_OFF_MODE = 3;  
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. /* 3 operational states for STA operation: CONNECT_MODE, SCAN_ONLY_MODE, SCAN_ONLY_WIFI_OFF_MODE 
  2. * In CONNECT_MODE, the STA can scan and connect to an access point 
  3. * In SCAN_ONLY_MODE, the STA can only scan for access points 
  4. * In SCAN_ONLY_WIFI_OFF_MODE, the STA can only scan for access points with wifi toggle being off 
  5. */  
  6. private int mOperationalMode = CONNECT_MODE;  
可知Wifi状态机一共有三种处理模式:
  1. CONNECT_MODE:该状态下Wifi可以扫描AP,也可以连接AP
  2. SCAN_ONLY_MODE:该状态下Wifi尽可以扫描AP
  3. SCAN_ONLY_WIFI_OFF_MODE:该状态下,Wifi仅可以当Wifi toogle off时允许扫描AP
现在,我们将处理的过程转换到WifiStateMachine。WifiStateMachine是一个复杂的状态机,它维护了Wifi的启动、扫描、连接、断开等多个状态。它运行在自己独有的线程中,拥有自己的消息队列。WifiStateMachine中各状态的关系如图所示:Android -- Wifi启动流程分析

分别来看WifiStateMachine是怎么处理这三个消息的。InitialState首先接收到CMD_START_SUPPLICANT消息并处理:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. case CMD_START_SUPPLICANT:  
  2.          if (mWifiNative.loadDriver()) {//加载驱动  
  3.              try {  
  4.                  mNwService.wifiFirmwareReload(mInterfaceName, "STA");//加载wlan固件  
  5.              } catch (Exception e) {  
  6.                  loge("Failed to reload STA firmware " + e);  
  7.                  // Continue  
  8.              }  
  9.   
  10.              try {  
  11.                  // A runtime crash can leave the interface up and  
  12.                  // IP addresses configured, and this affects  
  13.                  // connectivity when supplicant starts up.  
  14.                  // Ensure interface is down and we have no IP  
  15.                  // addresses before a supplicant start.  
  16.                  mNwService.setInterfaceDown(mInterfaceName);  
  17.                  mNwService.clearInterfaceAddresses(mInterfaceName);  
  18.   
  19.                  // Set privacy extensions  
  20.                  mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);  
  21.   
  22.                  // IPv6 is enabled only as long as access point is connected since:  
  23.                  // - IPv6 addresses and routes stick around after disconnection  
  24.                  // - kernel is unaware when connected and fails to start IPv6 negotiation  
  25.                  // - kernel can start autoconfiguration when 802.1x is not complete  
  26.                  mNwService.disableIpv6(mInterfaceName);  
  27.              } catch (RemoteException re) {  
  28.                  loge("Unable to change interface settings: " + re);  
  29.              } catch (IllegalStateException ie) {  
  30.                  loge("Unable to change interface settings: " + ie);  
  31.              }  
  32.   
  33.             /* Stop a running supplicant after a runtime restart 
  34.              * Avoids issues with drivers that do not handle interface down 
  35.              * on a running supplicant properly. 
  36.              */  
  37.              mWifiMonitor.killSupplicant(mP2pSupported);  
  38.   
  39.              if (WifiNative.startHal() == false) {  
  40.                  /* starting HAL is optional */  
  41.                  loge("Failed to start HAL");  
  42.              }  
  43.   
  44.              if (mWifiNative.startSupplicant(mP2pSupported)) {//启动wpa_s  
  45.                  setWifiState(WIFI_STATE_ENABLING);  
  46.                  if (DBG) log("Supplicant start successful");  
  47.                  mWifiMonitor.startMonitoring();//建立与wpa_s之间的socket通信连接;开启线程,循环接收来自wpa_s的event,并分发处理  
  48.                  transitionTo(mSupplicantStartingState);  
  49.              } else {  
  50.                  loge("Failed to start supplicant!");  
  51.              }  
  52.          } else {  
  53.              loge("Failed to load driver");  
  54.          }  
  55.          break;  
主要的处理过程包括:
  1. WifiNative.loadDriver():加载Wifi驱动,实际的实现是在wifi.c中
  2. NetworkManagementService.wifiFirmwareReload(mInterfaceName, "STA"):加载wlan固件
  3. WifiNative.startSupplicant(mP2pSupported):启动wpa_supplicant
  4. WifiMonitor.startMonitoring():在前面一篇博文中已经介绍过WifiMonitor,这一步主要是在WifiMonitor中建立与wpa_supplicant通信的socket通道、创建一个线程接收底层事件并分发处理。这里会创建两个socket通道与wpa_s通信,一个用于下发指令,另一个用于接收事件。成功后WifiMonitor会向WifiStateMachine发送一个代表socket通信建立成功的消息:SUP_CONNECTION_EVENT;收到这个消息就表示Wifi已经启动成功了。
  5. 切换到SupplicantStartingState。
进入SupplicantStartingState后,第一个消息就处理完毕,这时消息队列中按处理先后顺序仍有三个消息:
  1. CMD_SET_OPERATIONAL_MODE,参数是CONNECT_MODE
  2. CMD_START_DRIVER
  3. SUP_CONNECTION_EVENT
切换到SupplicantStartingState,消息队列中的前两个消息在该状态会被延迟处理,直接看SUP_CONNECTION_EVENT的处理过程:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. case WifiMonitor.SUP_CONNECTION_EVENT:  
  2.                     if (DBG) log("Supplicant connection established");  
  3.                     setWifiState(WIFI_STATE_ENABLED);  
  4.                     mSupplicantRestartCount = 0;  
  5.                     /* Reset the supplicant state to indicate the supplicant 
  6.                      * state is not known at this time */  
  7.                     mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);  
  8.                     /* Initialize data structures */  
  9.                     mLastBssid = null;  
  10.                     mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;  
  11.                     mLastSignalLevel = -1;  
  12.   
  13.                     mWifiInfo.setMacAddress(mWifiNative.getMacAddress());  
  14.                     /* set frequency band of operation */  
  15.                     setFrequencyBand();  
  16.                     mWifiNative.enableSaveConfig();  
  17.                     mWifiConfigStore.loadAndEnableAllNetworks();//加载并enable保存的AP  
  18.                     if (mWifiConfigStore.enableVerboseLogging.get() > 0) {  
  19.                         enableVerboseLogging(mWifiConfigStore.enableVerboseLogging.get());  
  20.                     }  
  21.                     initializeWpsDetails();  
  22.   
  23.                     sendSupplicantConnectionChangedBroadcast(true);//广播通知Wpa_s连接已建立,此时已经可以准备连接或扫描Wifi了  
  24.                     transitionTo(mDriverStartedState);  
  25.                     break;  
这里主要是调用WifiConfigStore.loadAndEnableAllNetworks()加载并enable所有保存在wpa_s中的AP,然后做一些其他的初始化工作,切换到DriverStartedState状态。关注其父状态和自身的enter()函数:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1.  class SupplicantStartedState extends State {  
  2.         @Override  
  3.         public void enter() {  
  4.             /* Wifi is available as long as we have a connection to supplicant */  
  5.             mNetworkInfo.setIsAvailable(true);  
  6.             if (mNetworkAgent != null) mNetworkAgent.sendNetworkInfo(mNetworkInfo);  
  7.   
  8.             int defaultInterval = mContext.getResources().getInteger(  
  9.                     R.integer.config_wifi_supplicant_scan_interval);  
  10.   
  11.             mSupplicantScanIntervalMs = Settings.Global.getLong(mContext.getContentResolver(),  
  12.                     Settings.Global.WIFI_SUPPLICANT_SCAN_INTERVAL_MS,  
  13.                     defaultInterval);  
  14.   
  15.             mWifiNative.setScanInterval((int)mSupplicantScanIntervalMs / 1000);//设置扫描时间间隔  
  16.             mWifiNative.setExternalSim(true);  
  17.   
  18.             /* turn on use of DFS channels */  
  19.             WifiNative.setDfsFlag(true);  
  20.   
  21.             /* set country code */  
  22.             setCountryCode();  
  23.   
  24.             setRandomMacOui();  
  25.             mWifiNative.enableAutoConnect(false); //可以事先注意该设置  
  26.         }  
  27. }  
  28.   class DriverStartedState extends State {  
  29.         @Override  
  30.         public void enter() {  
  31.   
  32.             if (PDBG) {  
  33.                 logd("DriverStartedState enter");  
  34.             }  
  35.   
  36.             mWifiLogger.startLogging(mVerboseLoggingLevel > 0);  
  37.             mIsRunning = true;  
  38.             mInDelayedStop = false;  
  39.             mDelayedStopCounter++;  
  40.             updateBatteryWorkSource(null);  
  41.             /** 
  42.              * Enable bluetooth coexistence scan mode when bluetooth connection is active. 
  43.              * When this mode is on, some of the low-level scan parameters used by the 
  44.              * driver are changed to reduce interference with bluetooth 
  45.              */  
  46.             mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);  
  47.             /* initialize network state */  
  48.             setNetworkDetailedState(DetailedState.DISCONNECTED);  
  49.   
  50.             /* Remove any filtering on Multicast v6 at start */  
  51.             mWifiNative.stopFilteringMulticastV6Packets();  
  52.   
  53.             /* Reset Multicast v4 filtering state */  
  54.             if (mFilteringMulticastV4Packets.get()) {  
  55.                 mWifiNative.startFilteringMulticastV4Packets();  
  56.             } else {  
  57.                 mWifiNative.stopFilteringMulticastV4Packets();  
  58.             }  
  59.   
  60.             mDhcpActive = false;  
  61.   
  62.             if (mOperationalMode != CONNECT_MODE) {  
  63.                 mWifiNative.disconnect();  
  64.                 mWifiConfigStore.disableAllNetworks();  
  65.                 if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {  
  66.                     setWifiState(WIFI_STATE_DISABLED);  
  67.                 }  
  68.                 transitionTo(mScanModeState);  
  69.             } else {  
  70.   
  71.                 // Status pulls in the current supplicant state and network connection state  
  72.                 // events over the monitor connection. This helps framework sync up with  
  73.                 // current supplicant state  
  74.                 // TODO: actually check th supplicant status string and make sure the supplicant  
  75.                 // is in disconnecte4d state.  
  76.                 mWifiNative.status();  
  77.                 // Transitioning to Disconnected state will trigger a scan and subsequently AutoJoin  
  78.                 transitionTo(mDisconnectedState);  
  79.                 transitionTo(mDisconnectedState);  
  80.             }  
  81.   
  82.             // We may have missed screen update at boot  
  83.             if (mScreenBroadcastReceived.get() == false) {  
  84.                 PowerManager powerManager = (PowerManager)mContext.getSystemService(  
  85.                         Context.POWER_SERVICE);  
  86.                 handleScreenStateChanged(powerManager.isScreenOn());  
  87.             } else {  
  88.                 // Set the right suspend mode settings  
  89.                 mWifiNative.setSuspendOptimizations(mSuspendOptNeedsDisabled == 0  
  90.                         && mUserWantsSuspendOpt.get());  
  91.             }  
  92.             mWifiNative.setPowerSave(true);  
  93.   
  94.             if (mP2pSupported) {  
  95.                 if (mOperationalMode == CONNECT_MODE) {  
  96.                     mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);//支持p2p,则会发送命令enbale p2p  
  97.                 } else {  
  98.                     // P2P statemachine starts in disabled state, and is not enabled until  
  99.                     // CMD_ENABLE_P2P is sent from here; so, nothing needs to be done to  
  100.                     // keep it disabled.  
  101.                 }  
  102.             }  
  103.   
  104.             final Intent intent = new Intent(WifiManager.WIFI_SCAN_AVAILABLE);  
  105.             intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);  
  106.             intent.putExtra(WifiManager.EXTRA_SCAN_AVAILABLE, WIFI_STATE_ENABLED);  
  107.             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);  
  108.   
  109.             mHalFeatureSet = WifiNative.getSupportedFeatureSet();  
  110.             if ((mHalFeatureSet & WifiManager.WIFI_FEATURE_HAL_EPNO)  
  111.                     == WifiManager.WIFI_FEATURE_HAL_EPNO) {  
  112.                 mHalBasedPnoDriverSupported = true;  
  113.             }  
  114.   
  115.             // Enable link layer stats gathering  
  116.             mWifiNative.setWifiLinkLayerStats("wlan0"1);  
  117.   
  118.             if (PDBG) {  
  119.                 logd("Driverstarted State enter done, epno=" + mHalBasedPnoDriverSupported  
  120.                      + " feature=" + mHalFeatureSet);  
  121.             }  
  122.         }  
  123. }  
SupplicantStartedState的enter()函数设置了Wifi扫描间隔;DriverStartedState的enter()函数主要进行了一些相关的设置工作,根据配置启动p2p。最后在enter()函数中会将状态切换到DisconnectedState。消息队列中被延迟的两条消息此时会被处理:
  1. CMD_SET_OPERATIONAL_MODE消息在DisconnectedState被处理,将mOperationalMode设置为CONNECT_MODE;Wifi状态机中该字段的默认值也是该值。
  2. CMD_START_DRIVER消息则在DriverStartedState中被处理。
最后转换到DisconnectedState状态,关注enter()函数:
[java] view plain copy Android -- Wifi启动流程分析Android -- Wifi启动流程分析
  1. public void enter() {  
  2.             // We dont scan frequently if this is a temporary disconnect  
  3.             // due to p2p  
  4.             if (mTemporarilyDisconnectWifi) {  
  5.                 mWifiP2pChannel.sendMessage(WifiP2pServiceImpl.DISCONNECT_WIFI_RESPONSE);  
  6.                 return;  
  7.             }  
  8.   
  9.             if (PDBG) {  
  10.                 logd(" Enter DisconnectedState scan interval "  
  11.                         + mWifiConfigStore.wifiDisconnectedShortScanIntervalMilli.get()  
  12.                         + " mLegacyPnoEnabled= " + mLegacyPnoEnabled  
  13.                         + " screenOn=" + mScreenOn  
  14.                         + " useGscan=" + mHalBasedPnoDriverSupported + "/"  
  15.                         + mWifiConfigStore.enableHalBasedPno.get());  
  16.             }  
  17.   
  18.             /** clear the roaming state, if we were roaming, we failed */  
  19.             mAutoRoaming = WifiAutoJoinController.AUTO_JOIN_IDLE;  
  20.   
  21.             if (useHalBasedAutoJoinOffload()) {  
  22.                 startGScanDisconnectedModeOffload("disconnectedEnter");  
  23.             } else {  
  24.                 if (mScreenOn) {  
  25.                     /** 
  26.                      * screen lit and => delayed timer 
  27.                      */  
  28.                     startDelayedScan(500nullnull);  
  29.                 } else {  
  30.                     /** 
  31.                      * screen dark and PNO supported => scan alarm disabled 
  32.                      */  
  33.                     if (mBackgroundScanSupported) {  
  34.                         /* If a regular scan result is pending, do not initiate background 
  35.                          * scan until the scan results are returned. This is needed because 
  36.                         * initiating a background scan will cancel the regular scan and 
  37.                         * scan results will not be returned until background scanning is 
  38.                         * cleared 
  39.                         */  
  40.                         if (!mIsScanOngoing) {  
  41.                             enableBackgroundScan(true);//启动wifi扫描,随后会触发autojoin,进行连接操作  
  42.                         }  
  43.                     } else {  
  44.                         setScanAlarm(true);//启动一个扫描定时器  
  45.                     }  
  46.                 }  
  47.             }  
  48.   
  49.             /** 
  50.              * If we have no networks saved, the supplicant stops doing the periodic scan. 
  51.              * The scans are useful to notify the user of the presence of an open network. 
  52.              * Note that these are not wake up scans. 
  53.              */  
  54.             if (mNoNetworksPeriodicScan != 0 && !mP2pConnected.get()  
  55.                     && mWifiConfigStore.getConfiguredNetworks().size() == 0) {  
  56.                 sendMessageDelayed(obtainMessage(CMD_NO_NETWORKS_PERIODIC_SCAN,  
  57.                         ++mPeriodicScanToken, 0), mNoNetworksPeriodicScan);  
  58.             }  
  59.   
  60.             mDisconnectedTimeStamp = System.currentTimeMillis();  
  61.             mDisconnectedPnoAlarmCount = 0;  
  62.         }  
在enter()函数中,会进行scan动作;WifiStateMachine处理SCAN_RESULTS_EVENT消息时,就会进入autojoin流程,尝试AP重连。