系统启动时,会在SystemServer中创建一个WifiService的对象,并把这个对象保存在系统服务中
wifi = new WifiService(context);
ServiceManager.addService(Context.WIFI_SERVICE, wifi);
看看WiFiService的构造方法
public WifiService(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
<span style="color:#FF0000;">mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName);</span>
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
<span style="color:#FF0000;">mWifiController = new WifiController(mContext, this, wifiThread.getLooper());</span>
<span style="color:#FF0000;">mWifiController.start();</span>
mBatchedScanSupported = mContext.getResources().getBoolean(
R.bool.config_wifi_batched_scan_supported);
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);
if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
// Adding optimizations of only receiving broadcasts when wifi is enabled
// can result in race conditions when apps toggle wifi in the background
// without active user involvement. Always receive broadcasts.
registerForBroadcasts();
///M:
initializeExtra();
}
这里初始化了一个WifiStateMachine和一个WifiController,并且调用了WifiController 的start方法,WifiController 继承至StateMachine状态机,
class WifiController extends StateMachine {
我们先来看看WifiController这个状态机的构造方法
WifiController(Context context, <span style="color:#FF0000;">WifiService service</span>, Looper looper) {
super(TAG, looper);
mContext = context;
<span style="color:#FF0000;"> mWifiStateMachine = service.mWifiStateMachine;</span>
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
mWifiCsmClient = service.mWifiCsmClient;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
<span style="color:#FF0000;">
addState(mDefaultState);缩进的方式表示状态层次关系
addState(mApStaDisabledState, mDefaultState);
addState(mStaEnabledState, mDefaultState);
addState(mDeviceActiveState, mStaEnabledState);
addState(mDeviceInactiveState, mStaEnabledState);
addState(mScanOnlyLockHeldState, mDeviceInactiveState);
addState(mFullLockHeldState, mDeviceInactiveState);
addState(mFullHighPerfLockHeldState, mDeviceInactiveState);
addState(mNoLockHeldState, mDeviceInactiveState);
addState(mStaDisabledWithScanState, mDefaultState);
addState(mApEnabledState, mDefaultState);
addState(mEcmState, mDefaultState);</span>
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
log("isAirplaneModeOn = " + isAirplaneModeOn +
", isWifiEnabled = " + isWifiEnabled +
", isScanningAvailable = " + isScanningAlwaysAvailable);
if (isWifiEnabled && isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
<span style="color:#FF0000;"> setInitialState(mApStaDisabledState);</span>
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(ACTION_DEVICE_IDLE)) {
sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
mNetworkInfo = (NetworkInfo) intent.getParcelableExtra(
WifiManager.EXTRA_NETWORK_INFO);
}
}
},
new IntentFilter(filter));
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
ArrayList<String> active = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ACTIVE_TETHER);
if (active != null) updateTetherUsbState(active);
}
},new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED));
initializeAndRegisterForSettingsChange(looper);
}
这里参数service就是WifiService,并且通过service得到了WifiService中的WifiStateMachine对象,然后添加了一些状态对象,设置了初始状态,
这个start方法是父类的方法,表示启动一个状态机。
/**
* Start the state machine.
*/
public void start() {
// mSmHandler can be null if the state machine has quit.
SmHandler smh = mSmHandler;
if (smh == null) return;
/*Complete the construction of the state machine, Send the complete construction message */
smh.completeConstruction();
}
调用start方法后,WifiController首先进入mDefaultState状态,然后进入mApStaDisabledState状态(先父状态后子状态),此时,WifiController状态机的状态为mApStaDisabledState状态。
让我们回到WifiService的构造方法中,倒数第二行有个registerForBroadcasts方法
registerForBroadcasts();
private void registerForBroadcasts() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_SCREEN_ON);
intentFilter.addAction(Intent.ACTION_USER_PRESENT);
intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
intentFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
intentFilter.addAction(WifiStateMachine.SHUT_DOWN_WIFI_ACTION);
intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
mContext.registerReceiver(mReceiver, intentFilter);
}
这个方法注册了一个广播,那我们看看接收到注册的这些action后,会有哪些处理
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(<span style="color:#FF0000;">Intent.ACTION_SCREEN_ON</span>)) {
mWifiController.sendMessage(CMD_SCREEN_ON);
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
mWifiController.sendMessage(CMD_USER_PRESENT);
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
mWifiController.sendMessage(CMD_SCREEN_OFF);
} else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
int pluggedType = intent.getIntExtra("plugged", 0);
mWifiController.sendMessage(CMD_BATTERY_CHANGED, pluggedType, 0, null);
} else if (action.equals(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED)) {
int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE,
BluetoothAdapter.STATE_DISCONNECTED);
mWifiStateMachine.sendBluetoothAdapterStateChange(state);
} else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
boolean emergencyMode = intent.getBooleanExtra("phoneinECMState", false);
mWifiController.sendMessage(CMD_EMERGENCY_MODE_CHANGED, emergencyMode ? 1 : 0, 0);
} else if (action.equals(WifiStateMachine.SHUT_DOWN_WIFI_ACTION)) {
mWifiController.sendMessage(CMD_DEVICE_IDLE);
} else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
String stateExtra = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(stateExtra)) {
if (DBG) Slog.d(TAG, "SIM Card inserted");
updateIccNetworks(true);
} else if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)
|| IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(stateExtra)) {
if (DBG) Slog.d(TAG, "SIM Card removed or not ready");
updateIccNetworks(false);
}
}
}
};
当接收到的广播为ACTION_SCREEN_ON时,利用mWifiController对象发送一个CMD_SCREEN_ON消息,此时,mWifiController状态机的状态为mApStaDisabledState状态,我们看看这个状态实现类的processMessage方法子状态没处理的消息,将由父状态处理,mApStaDisabledState的父状态为mDefaultState状态,看看它的processMessage方法
class DefaultState extends State {
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_SCREEN_ON:
mAlarmManager.cancel(mIdleIntent);
mScreenOff = false;
mDeviceIdle = false;
updateBatteryWorkSource();
break;
case CMD_SCREEN_OFF:
mScreenOff = true;
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND the "stay on while plugged in" setting doesn't match the
* current power conditions (i.e, not plugged in, plugged in to USB,
* or plugged in to AC).
*/
if (!shouldWifiStayAwake(mPluggedType)) {
// Apply sleep policy only if usb tethering is disabled
if (!mTetherUsbOn) {
//Delayed shutdown if wifi is connected
if (mNetworkInfo.getDetailedState() ==
NetworkInfo.DetailedState.CONNECTED) {
if (DBG) Slog.d(TAG, "set idle timer: " + mIdleMillis + " ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + mIdleMillis, mIdleIntent);
} else {
sendMessage(CMD_DEVICE_IDLE);
}
}
}
break;
case CMD_DEVICE_IDLE:
mDeviceIdle = true;
updateBatteryWorkSource();
break;
case CMD_BATTERY_CHANGED:
/*
* Set a timer to put Wi-Fi to sleep, but only if the screen is off
* AND we are transitioning from a state in which the device was supposed
* to stay awake to a state in which it is not supposed to stay awake.
* If "stay awake" state is not changing, we do nothing, to avoid resetting
* the already-set timer.
*/
int pluggedType = msg.arg1;
if (DBG) Slog.d(TAG, "battery changed pluggedType: " + pluggedType);
if (mScreenOff && shouldWifiStayAwake(mPluggedType) &&
!shouldWifiStayAwake(pluggedType)) {
long triggerTime = System.currentTimeMillis() + mIdleMillis;
if (mNetworkInfo.getDetailedState() == DetailedState.CONNECTED
&& !mTetherUsbOn) {
if (DBG) Slog.d(TAG, "set idle timer for " + mIdleMillis + "ms");
mAlarmManager.set(AlarmManager.RTC_WAKEUP, triggerTime, mIdleIntent);
} else {
sendMessage(CMD_DEVICE_IDLE);
}
}
mPluggedType = pluggedType;
break;
case CMD_SET_AP:
case CMD_SCAN_ALWAYS_MODE_CHANGED:
case CMD_LOCKS_CHANGED:
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
case CMD_EMERGENCY_MODE_CHANGED:
break;
case CMD_USER_PRESENT:
mFirstUserSignOnSeen = true;
break;
case CMD_DEFERRED_TOGGLE:
log("DEFERRED_TOGGLE ignored due to state change");
break;
default:
throw new RuntimeException("WifiController.handleMessage " + msg.what);
}
return HANDLED;
}
}
再一次回到WifiService的构造方法,其中有这么一段代码
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
///M: modify for timing issue to access Settings.Global.AIRPLANE_MODE_ON
boolean isAirplaneModeOn = intent.getBooleanExtra("state", false);
SXlog.i(TAG, "ACTION_AIRPLANE_MODE_CHANGED isAirplaneModeOn="+isAirplaneModeOn);
if (mSettingsStore.handleAirplaneModeToggled(isAirplaneModeOn)) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
}
},
new IntentFilter(<span style="color:#FF0000;">Intent.ACTION_AIRPLANE_MODE_CHANGED</span>));
这里注册了一个捕捉ACTION_AIRPLANE_MODE_CHANGED的广播,接收到这个广播后,通过mWifiController发送一个CMD_AIRPLANE_TOGGLED的消息,来看看接收到这个消息的地方,还是在WifiController的当前状态mApStaDisabledState实现类的 processMessage方法中
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case <span style="color:#FF0000;">CMD_AIRPLANE_TOGGLED</span>:
if (mSettingsStore.isWifiToggleEnabled()) {
if (doDeferEnable(msg)) {
if (mHaveDeferredEnable) {
// have 2 toggles now, inc serial number an ignore both
mDeferredEnableSerialNumber++;
}
mHaveDeferredEnable = !mHaveDeferredEnable;
break;
}
<span style="color:#FF0000;"> if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);</span>
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
}
else{ // wifi is Off, check Scan state
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
}
}
break;
case CMD_SCAN_ALWAYS_MODE_CHANGED:
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
}
break;
case CMD_SET_AP:
if (msg.arg1 == 1) {
mWifiStateMachine.setHostApRunning((WifiConfiguration) msg.obj,
true);
transitionTo(mApEnabledState);
}
break;
case CMD_DEFERRED_TOGGLE:
if (msg.arg1 != mDeferredEnableSerialNumber) {
log("DEFERRED_TOGGLE ignored due to serial mismatch");
break;
}
log("DEFERRED_TOGGLE handled");
sendMessage((Message)(msg.obj));
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
当系统Wifi为开时,并且mDeviceIdle为false时,会把当前状态转换为mDeviceActiveState状态,mDeviceActiveState的父状态为mStaEnabledState状态,所以会先进入mStaEnabledState然后进入mDeviceActiveState状态,我们看看mStaEnabledState状态的实现类的enter方法
class StaEnabledState extends State {
@Override
public void enter() {
<span style="color:#FF0000;">mWifiStateMachine.setSupplicantRunning(true);</span>
}
这里调用了WifiService中的WifiStateMachine对象的setSupplicantRunning方法
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
当参数为true时,发送一个CMD_START_SUPPLICANT消息,那么WifiStateMachine当前的状态是什么呢?看看它的构造方法吧,其中添加状态和初始状态的代码为
addState(mDefaultState);
addState(mInitialState, mDefaultState);
addState(mSupplicantStartingState, mDefaultState);
addState(mSupplicantStartedState, mDefaultState);
addState(mDriverStartingState, mSupplicantStartedState);
addState(mDriverStartedState, mSupplicantStartedState);
addState(mScanModeState, mDriverStartedState);
addState(mConnectModeState, mDriverStartedState);
addState(mL2ConnectedState, mConnectModeState);
addState(mObtainingIpState, mL2ConnectedState);
addState(mVerifyingLinkState, mL2ConnectedState);
addState(mCaptivePortalCheckState, mL2ConnectedState);
addState(mConnectedState, mL2ConnectedState);
addState(mDisconnectingState, mConnectModeState);
addState(mDisconnectedState, mConnectModeState);
addState(mWpsRunningState, mConnectModeState);
addState(mWaitForP2pDisableState, mSupplicantStartedState);
addState(mDriverStoppingState, mSupplicantStartedState);
addState(mDriverStoppedState, mSupplicantStartedState);
addState(mSupplicantStoppingState, mDefaultState);
addState(mSoftApStartingState, mDefaultState);
addState(mSoftApStartedState, mDefaultState);
addState(mTetheringState, mSoftApStartedState);
addState(mTetheredState, mSoftApStartedState);
addState(mUntetheringState, mSoftApStartedState);
<span style="color:#FF0000;">setInitialState(mInitialState);</span>
初始状态为mInitialState,看看它的实现类的processMessage方法
public boolean processMessage(Message message) {
switch (message.what) {
case <span style="color:#FF0000;">CMD_START_SUPPLICANT</span>:
if (mWifiNative.<span style="color:#FF0000;">loadDriver</span>()) {
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
loge("Failed to reload STA firmware " + e);
// continue
}
try {
/* Stop a running supplicant after a runtime restart
* Avoids issues with drivers that do not handle interface down
* on a running supplicant properly.
*/
if (DBG) log("Kill any running supplicant");
mWifiNative.killSupplicant(mP2pSupported);
// A runtime crash can leave the interface up and
// this affects connectivity when supplicant starts up.
// Ensure interface is down before a supplicant start.
if (mP2pSupported) {
// Ensure p2p and p2p-p20-X interfaces are down
if (DBG) log("Set P2P interfaces down");
String[] ifaces = new String[0];
try {
ifaces = mNwService.listInterfaces();
} catch (Exception e) {
loge("Error listing Interfaces");
}
for (String iface : ifaces) {
if (isP2p(iface)) {
if (DBG) log("P2P group iface: " + iface);
mNwService.setInterfaceDown(iface);
}
}
mNwService.setInterfaceDown(mP2pInterfaceName);
}
mNwService.setInterfaceDown(mInterfaceName);
// Set privacy extensions
mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
// IPv6 is enabled only as long as access point is connected since:
// - IPv6 addresses and routes stick around after disconnection
// - kernel is unaware when connected and fails to start IPv6 negotiation
// - kernel can start autoconfiguration when 802.1x is not complete
mNwService.disableIpv6(mInterfaceName);
} catch (RemoteException re) {
loge("Unable to change interface settings: " + re);
} catch (IllegalStateException ie) {
loge("Unable to change interface settings: " + ie);
}
if(mWifiNative.startSupplicant(mP2pSupported)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
<span style="color:#FF0000;">mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);</span>
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
case CMD_START_AP:
if (mWifiNative.loadDriver()) {
setWifiApState(WIFI_AP_STATE_ENABLING);
transitionTo(mSoftApStartingState);
} else {
loge("Failed to load driver for softap");
if (mSoftApErrorDetected.get()) {
mSoftApErrorDetected.set(false);
if (mLastWifiApConfig != null &&
!mLastWifiApConfig.getWifiApConfigurationAdv().isRadioDefault())
{
if (DBG) log("Restart softAP with default radio configuration");
mLastWifiApConfig.getWifiApConfigurationAdv().resetRadioConfig();
setHostApRunning(mLastWifiApConfig, true);
}
}
}
default:
return NOT_HANDLED;
}
return HANDLED;
}
}
接收到CMD_START_SUPPLICANT消息后,首先会调用mWifiNative的loadDriver方法,loadDriver是一个本地方法,其作用是加载相应的Wifi驱动,如果驱动加载成功,会调用mWifiMonitor的startMonitoring方法,并且把当前的 状态转为mSupplicantStartingState状态。我们来看看mWifiMonitor这个对象,mWifiMonitor是一个WifiMonitor对象,它负责从wpa_supplicant接收消息,运行在一个独立的线程中。看看构造方法
public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) {
if (DBG) Log.d(TAG, "Creating WifiMonitor");
<span style="color:#FF0000;">mWifiNative = wifiNative;</span>
mInterfaceName = wifiNative.mInterfaceName;
<span style="color:#FF0000;">mWifiStateMachine = wifiStateMachine;</span>
mMonitoring = false;
WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this);
}
这里传入了StateMachine对象和WifiNative对象,接着我们看看startMonitoring方法
public void startMonitoring() {
WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName);
}
这里调用WifiMonitor内部类WifiMonitorSingleton的startMonitoring方法
public synchronized void startMonitoring(String iface) {
WifiMonitor m = mIfaceMap.get(iface);
if (m == null) {
Log.e(TAG, "startMonitor called with unknown iface=" + iface);
return;
}
Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);
if (mConnected) {
m.mMonitoring = true;
m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
} else {
if (DBG) Log.d(TAG, "connecting to supplicant");
int connectTries = 0;
while (true) {
if (mWifiNative.connectToSupplicant()) {
m.mMonitoring = true;
m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
<span style="color:#FF0000;">new MonitorThread(mWifiNative, this).start();</span>
mConnected = true;
break;
}
if (connectTries++ < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
} else {
mIfaceMap.remove(iface);
m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
Log.e(TAG, "startMonitoring(" + iface + ") failed!");
break;
}
}
}
}
这里会启动一个MonitorThread线程,看看这个线程的构造方法
private static class MonitorThread extends Thread {
private final WifiNative mWifiNative;
private final WifiMonitorSingleton mWifiMonitorSingleton;
private int mRecvErrors = 0;
private StateMachine mStateMachine = null;
public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
super("WifiMonitor");
mWifiNative = wifiNative;
mWifiMonitorSingleton = wifiMonitorSingleton;
}
没做什么,再看run方法
public void run() {
//noinspection InfiniteLoopStatement
for (;;) {
<span style="color:#FF0000;">String eventStr = mWifiNative.waitForEvent();</span>
// Skip logging the common but mostly uninteresting scan-results event
if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
Log.d(TAG, "Event [" + eventStr + "]");
}
String iface = "p2p0";
WifiMonitor m = null;
mStateMachine = null;
if (eventStr.startsWith("IFNAME=")) {
int space = eventStr.indexOf(' ');
if (space != -1) {
iface = eventStr.substring(7,space);
m = mWifiMonitorSingleton.getMonitor(iface);
if (m == null && iface.startsWith("p2p-")) {
// p2p interfaces are created dynamically, but we have
// only one P2p state machine monitoring all of them; look
// for it explicitly, and send messages there ..
m = mWifiMonitorSingleton.getMonitor("p2p0");
}
eventStr = eventStr.substring(space + 1);
}
} else {
// events without prefix belong to p2p0 monitor
m = mWifiMonitorSingleton.getMonitor("p2p0");
}
if (m != null) {
if (m.mMonitoring) {
mStateMachine = m.mWifiStateMachine;
} else {
if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
") is stopped");
continue;
}
}
if (mStateMachine != null) {
<span style="color:#FF0000;"> if (dispatchEvent(eventStr))</span> {
break;
}
} else {
if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id");
boolean done = false;
Iterator<Map.Entry<String, WifiMonitor>> it =
mWifiMonitorSingleton.mIfaceMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, WifiMonitor> e = it.next();
m = e.getValue();
mStateMachine = m.mWifiStateMachine;
if (dispatchEvent(eventStr)) {
done = true;
}
}
if (done) {
// After this thread terminates, we'll no longer
// be connected to the supplicant
if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
mWifiMonitorSingleton.mConnected = false;
break;
}
}
}
}
这里调用了mWifiNative的waitForEvent方法,这个方法通过jni调用本地方法读取wpa_supplicant的消息,接着转发出去。
看看dispatchEvent方法
private boolean dispatchEvent(String eventStr) {
if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
} else if (eventStr.startsWith(AUTH_TIMEOUT_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
} else if (eventStr.startsWith(SME_EVENT_PREFIX_STR) &&
0 < eventStr.indexOf(AUTH_REQ_FAILED_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
} else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
} else if (eventStr.startsWith(WPS_FAIL_STR)) {
handleWpsFailEvent(eventStr);
} else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
} else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
} else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
handleP2pEvents(eventStr);
} else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
handleHostApEvents(eventStr);
}
else {
if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
}
return false;
}
String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
int nameEnd = eventName.indexOf(' ');
if (nameEnd != -1)
eventName = eventName.substring(0, nameEnd);
if (eventName.length() == 0) {
if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");
return false;
}
/*
* Map event name into event enum
*/
int event;
if (eventName.equals(CONNECTED_STR))
event = CONNECTED;
else if (eventName.equals(DISCONNECTED_STR))
event = DISCONNECTED;
else if (eventName.equals(STATE_CHANGE_STR))
event = STATE_CHANGE;
else if (eventName.equals(SCAN_RESULTS_STR))
event = SCAN_RESULTS;
else if (eventName.equals(LINK_SPEED_STR))
event = LINK_SPEED;
else if (eventName.equals(TERMINATING_STR))
event = TERMINATING;
else if (eventName.equals(DRIVER_STATE_STR))
event = DRIVER_STATE;
else if (eventName.equals(EAP_FAILURE_STR))
event = EAP_FAILURE;
else if (eventName.equals(ASSOC_REJECT_STR))
event = ASSOC_REJECT;
else
event = UNKNOWN;
String eventData = eventStr;
if (event == DRIVER_STATE || event == LINK_SPEED)
eventData = eventData.split(" ")[1];
else if (event == STATE_CHANGE || event == EAP_FAILURE) {
int ind = eventStr.indexOf(" ");
if (ind != -1) {
eventData = eventStr.substring(ind + 1);
}
} else {
int ind = eventStr.indexOf(" - ");
if (ind != -1) {
eventData = eventStr.substring(ind + 3);
}
}
if (event == STATE_CHANGE) {
handleSupplicantStateChange(eventData);
} else if (event == DRIVER_STATE) {
handleDriverEvent(eventData);
} else if (event == TERMINATING) {
/**
* Close the supplicant connection if we see
* too many recv errors
*/
if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
if (++mRecvErrors > MAX_RECV_ERRORS) {
if (DBG) {
Log.d(TAG, "too many recv errors, closing connection");
}
} else {
return false;
}
}
// notify and exit
mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
return true;
} else if (event == EAP_FAILURE) {
if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
}
} else if (event == ASSOC_REJECT) {
mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
} else {
<span style="color:#FF0000;">handleEvent(event, eventData);</span>
}
mRecvErrors = 0;
return false;
}
经过一系列处理调用handleEvent方法
/**
* Handle all supplicant events except STATE-CHANGE
* @param event the event type
* @param remainder the rest of the string following the
* event name and " — "
*/
void handleEvent(int event, String remainder) {
switch (event) {
case DISCONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.DISCONNECTED, remainder);
break;
case CONNECTED:
handleNetworkStateChange(NetworkInfo.DetailedState.CONNECTED, remainder);
break;
case SCAN_RESULTS:
mStateMachine.sendMessage(SCAN_RESULTS_EVENT);
break;
case UNKNOWN:
break;
}
}
以SCAN_RESULTS_EVENT为例,状态机发送一个SCAN_RESULTS_EVENT消息,这个状态机是WifiStateMachine对象,WifiStateMachine当前的状态为SupplicantStartedState(中间的过程暂时忽略),看看processMessage方法相关代码
case WifiMonitor.SCAN_RESULTS_EVENT:
setScanResults();
sendScanResultsAvailableBroadcast();
mScanResultIsPending = false;
break;
这里会调用sendScanResultsAvailableBroadcast发送广播,把扫描到的Wifi热点信息发送给广播接收者
private void sendScanResultsAvailableBroadcast() {
noteScanEnd();
Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
至此,Wifi启动的一个大概流程就先分析到这里!