android wifi应用层通信大致可由一图说明。
图中所调用的源文件如下,以本人的android6.0为准,其他版本可能会有不同
系统启动会开始调用SystemService,在上层的代码就不跟踪了,systemserver启动了众多server其中就有wifiservice,在我的android6.0的代码如下,其他版本有些许不同
mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
mSystemServiceManager.startService(
"com.android.server.wifi.WifiScanningService");
mSystemServiceManager.startService("com.android.server.wifi.RttService");
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
}
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);
} catch (Throwable e) {
reportWtf("starting Connectivity Service", e);
可以看到启动了wifiservice(),而wifiservice的类又很简单,只是为了实例化WifiServiceImpl类,代码如下。
public final class WifiService extends SystemService {
private static final String TAG = "WifiService";
final WifiServiceImpl mImpl;
public WifiService(Context context) {
super(context);
mImpl = new WifiServiceImpl(context);
}
@Override
public void onStart() {
Log.i(TAG, "Registering " + Context.WIFI_SERVICE);
publishBinderService(Context.WIFI_SERVICE, mImpl);
}
@Override
public void onBootPhase(int phase) {
if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
mImpl.checkAndStartWifi();
}
}
接下来具体看WifiServiceImpl实现,其中会实例化三个类如上图所示,其中WifiStateMachine是核心,WifiController也是一个状态机,主要接收从wifiManage传输过来从命令,最后还是调用WifiStateMachine,来控制wpa_supplicant,这里以setWifiEnabled()开启wifi命令为例简述WifiManage直接调用WifiServiceImpl过程,当app开始wifi,则调用WifiManage的setWifiEnabled()函数,代码如下
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
mservice及wifimanage构造函数实例化的WifiServiceImpl,所以直接调用WifiServiceImpl下的函数,
public synchronized boolean setWifiEnabled(boolean enable) {
enforceChangePermission();
Slog.d(TAG, "setWifiEnabled: " + enable + " pid=" + Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
if (DBG) {
Slog.e(TAG, "Invoking mWifiStateMachine.setWifiEnabled\n");
}
/*
* Caller might not have WRITE_SECURE_SETTINGS,
* only CHANGE_WIFI_STATE is enforced
*/
long ident = Binder.clearCallingIdentity();
try {
if (! mSettingsStore.handleWifiToggled(enable)) {
// Nothing to do if wifi cannot be toggled
return true;
}
} finally {
Binder.restoreCallingIdentity(ident);
}
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
return true;
mSettingsStore.handleWifiToggled(enable)会调用SettingsStore类的函数,给app传输wifion的值,之后发送message给WifiController状态机,handle的连接函数在WifiServiceImpl的构造函数里面完成,代码如下。
public WifiServiceImpl(Context context) {
mContext = context;
mInterfaceName = SystemProperties.get("wifi.interface", "wlan0");
mTrafficPoller = new WifiTrafficPoller(mContext, mInterfaceName);
mWifiStateMachine = new WifiStateMachine(mContext, mInterfaceName, mTrafficPoller);
mWifiStateMachine.enableRssiPolling(true);
mBatteryStats = BatteryStatsService.getService();
mPowerManager = context.getSystemService(PowerManager.class);
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
mUserManager = UserManager.get(mContext);
mNotificationController = new WifiNotificationController(mContext, mWifiStateMachine);
mSettingsStore = new WifiSettingsStore(mContext);
HandlerThread wifiThread = new HandlerThread("WifiService");
wifiThread.start();
//建立handle connect
mClientHandler = new ClientHandler(wifiThread.getLooper());
mWifiStateMachineHandler = new WifiStateMachineHandler(wifiThread.getLooper());
mWifiController = new WifiController(mContext, this, wifiThread.getLooper());
}
其中mClientHandler为接收wifimanage所发信息的handle函数。mWifiStateMachineHandler为接收WifiStateMachine所发信息的函数。
接下来看下WifiController构造函数。
WifiController(Context context, WifiServiceImpl service, Looper looper) {
super(TAG, looper);
mContext = context;
mWifiStateMachine = service.mWifiStateMachine;
mSettingsStore = service.mSettingsStore;
mLocks = service.mLocks;
mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE);
Intent idleIntent = new Intent(ACTION_DEVICE_IDLE, null);
mIdleIntent = PendingIntent.getBroadcast(mContext, IDLE_REQUEST, idleIntent, 0);
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);
boolean isAirplaneModeOn = mSettingsStore.isAirplaneModeOn();
boolean isWifiEnabled = mSettingsStore.isWifiToggleEnabled();
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
log("isAirplaneModeOn = " + isAirplaneModeOn +
", isWifiEnabled = " + isWifiEnabled +
", isScanningAvailable = " + isScanningAlwaysAvailable);
if (isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
setLogRecSize(100);
setLogOnlyTransitions(false);
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_DEVICE_IDLE);
filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
filter.addAction(WifiManager.WIFI_AP_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);
} else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
int state = intent.getIntExtra(
WifiManager.EXTRA_WIFI_AP_STATE,
WifiManager.WIFI_AP_STATE_FAILED);
if(state == WifiManager.WIFI_AP_STATE_FAILED) {
loge(TAG + "SoftAP start failed");
sendMessage(CMD_AP_START_FAILURE);
}
}
}
},
new IntentFilter(filter));
initializeAndRegisterForSettingsChange(looper);
}
实例化这两个类mWifiStateMachine ,mSettingsStore 并设置各个state,初始化起始状态为mApStaDisabledState,初始化代码如下。
synchronized boolean isScanAlwaysAvailable() {
return !mAirplaneModeOn && mScanAlwaysAvailable;
}
boolean isScanningAlwaysAvailable = mSettingsStore.isScanAlwaysAvailable();
if (isScanningAlwaysAvailable) {
setInitialState(mStaDisabledWithScanState);
} else {
setInitialState(mApStaDisabledState);
}
最终为false所以初始化为mApStaDisabledState,状态机开启函数在
WifiService的checkAndStartWifi()函数中开启。
public void checkAndStartWifi() {
/* Check if wi-fi needs to be enabled */
boolean wifiEnabled = mSettingsStore.isWifiToggleEnabled();
Slog.i(TAG, "WifiService starting up with Wi-Fi " +
(wifiEnabled ? "enabled" : "disabled"));
registerForScanModeChange();
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mSettingsStore.handleAirplaneModeToggled()) {
mWifiController.sendMessage(CMD_AIRPLANE_TOGGLED);
}
if (mSettingsStore.isAirplaneModeOn()) {
Log.d(TAG, "resetting country code because Airplane mode is ON");
mWifiStateMachine.resetCountryCode();
}
}
},
new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));
mContext.registerReceiver(
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
if (state.equals(IccCardConstants.INTENT_VALUE_ICC_ABSENT)) {
Log.d(TAG, "resetting networks because SIM was removed");
mWifiStateMachine.resetSimAuthNetworks();
Log.d(TAG, "resetting country code because SIM is removed");
mWifiStateMachine.resetCountryCode();
}
}
},
new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_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();
registerForPackageOrUserRemoval();
mInIdleMode = mPowerManager.isDeviceIdleMode();
//开启wificontrol ,启动状态机
mWifiController.start();
// If we are already disabled (could be due to airplane mode), avoid changing persist
// state here
if (wifiEnabled) setWifiEnabled(wifiEnabled);
mWifiWatchdogStateMachine = WifiWatchdogStateMachine.
makeWifiWatchdogStateMachine(mContext, mWifiStateMachine.getMessenger());
再来看下StaEnabledState state下的如何开始加载driver和开启wpa_supplicant。代码如下
class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
if (! mSettingsStore.isWifiToggleEnabled()) {
if (mSettingsStore.isScanAlwaysAvailable()) {
transitionTo(mStaDisabledWithScanState);
} else {
transitionTo(mApStaDisabledState);
}
}
break;
case CMD_AIRPLANE_TOGGLED:
/* When wi-fi is turned off due to airplane,
* disable entirely (including scan)
*/
if (! mSettingsStore.isWifiToggleEnabled()) {
transitionTo(mApStaDisabledState);
}
break;
case CMD_EMERGENCY_CALL_STATE_CHANGED:
case CMD_EMERGENCY_MODE_CHANGED:
if (msg.arg1 == 1) {
transitionTo(mEcmState);
break;
}
case CMD_SET_AP:
if (msg.arg1 == 1) {
// remeber that we were enabled
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.WIFI_SAVED_STATE, WIFI_ENABLED);
deferMessage(obtainMessage(msg.what, msg.arg1, 1, msg.obj));
transitionTo(mApStaDisabledState);
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
其中enter函数调用了mWifiStateMachine.setSupplicantRunning(true);
在看下代码
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
跳转到WifiStateMachine发送CMD_START_SUPPLICANT命令。此时再看下wifistatemachine的构造函数,由于代码较长,我只截取一些,读者可自行查看源码。
public WifiStateMachine(Context context, String wlanInterface,
WifiTrafficPoller trafficPoller) {
super("WifiStateMachine");
mContext = context;
mInterfaceName = wlanInterface;
mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, NETWORKTYPE, "");
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
mNwService = INetworkManagementService.Stub.asInterface(b);
mP2pSupported = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_WIFI_DIRECT);
mWifiNative = new WifiNative(mInterfaceName, mContext);
mWifiConfigStore = new WifiConfigStore(context,this, mWifiNative);
mWifiAutoJoinController = new WifiAutoJoinController(context, this,
mWifiConfigStore, mWifiConnectionStatistics, mWifiNative);
mWifiMonitor = new WifiMonitor(this, mWifiNative);
这里实例化了一些类,其中WifiMonitor作为监控读取wpa_supplicant传上来的event,
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(mConnectedState, mL2ConnectedState);
addState(mRoamingState, 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);
setInitialState(mInitialState);
setLogRecSize(ActivityManager.isLowRamDeviceStatic() ? 100 : 3000);
setLogOnlyTransitions(false);
if (VDBG) setDbg(true);
//start the state machine
start();
add许多状态最终初始化为mInitialState(),最后开启状态机,即CMD_START_SUPPLICANT命令会在mInitialState()中读取到,看下代码
class InitialState extends State {
@Override
public void enter() {
//关闭HAL,在unloader driver,如果已经load的情况下,其余为配置通信handle 函数
WifiNative.stopHal();
mWifiNative.unloadDriver();
if (mWifiP2pChannel == null) {
mWifiP2pChannel = new AsyncChannel();
mWifiP2pChannel.connect(mContext, getHandler(),
mWifiP2pServiceImpl.getP2pStateMachineMessenger());
}
if (mWifiApConfigChannel == null) {
mWifiApConfigChannel = new AsyncChannel();
mWifiApConfigStore = WifiApConfigStore.makeWifiApConfigStore(
mContext, getHandler());
mWifiApConfigStore.loadApConfiguration();
mWifiApConfigChannel.connectSync(mContext, getHandler(),
mWifiApConfigStore.getMessenger());
}
if (mWifiConfigStore.enableHalBasedPno.get()) {
// make sure developer Settings are in sync with the config option
mHalBasedPnoEnableInDevSettings = true;
}
}
@Override
public boolean processMessage(Message message) {
logStateAndMessage(message, this);
switch (message.what) {
//接收到命令,先loaddriver
case CMD_START_SUPPLICANT:
if (mWifiNative.loadDriver()) {
try {
mNwService.wifiFirmwareReload(mInterfaceName, "STA");
} catch (Exception e) {
loge("Failed to reload STA firmware " + e);
// Continue
}
try {
// A runtime crash can leave the interface up and
// IP addresses configured, and this affects
// connectivity when supplicant starts up.
// Ensure interface is down and we have no IP
// addresses before a supplicant start.
mNwService.setInterfaceDown(mInterfaceName);
mNwService.clearInterfaceAddresses(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);
}
/* Stop a running supplicant after a runtime restart
* Avoids issues with drivers that do not handle interface down
* on a running supplicant properly.
*/
mWifiMonitor.killSupplicant(mP2pSupported);
if (WifiNative.startHal() == false) {
/* starting HAL is optional */
loge("Failed to start HAL");
}
if (mWifiNative.startSupplicant(mP2pSupported)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
//开启wifi montor
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
case CMD_START_AP:
if (mWifiNative.loadDriver() == false) {
loge("Failed to load driver for softap");
} else {
if (enableSoftAp() == true) {
setWifiApState(WIFI_AP_STATE_ENABLING, 0);
transitionTo(mSoftApStartingState);
} else {
setWifiApState(WIFI_AP_STATE_FAILED,
WifiManager.SAP_START_FAILURE_GENERAL);
transitionTo(mInitialState);
}
}
break;
default:
return NOT_HANDLED;
}
return HANDLED;
}
先load driver 在开启wpa_supplicant,最后开启WIfiMonitor其中loaddriver和startSupplicant都是通过wifinative调用的,最终通过JNI调用,代码如下,在com_android_server_wifi_WifiNative.cpp中定义
/*
* JNI registration.
*/
static JNINativeMethod gWifiMethods[] = {
/* name, signature, funcPtr */
{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
{ "isDriverLoaded", "()Z", (void *)android_net_wifi_isDriverLoaded },
{ "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
{ "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant },
{ "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant },
{ "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant },
{ "closeSupplicantConnectionNative", "()V",
(void *)android_net_wifi_closeSupplicantConnection },
{ "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent },
{ "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
{ "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
{ "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) android_net_wifi_doStringCommand },
{ "startHalNative", "()Z", (void*) android_net_wifi_startHal },
{ "stopHalNative", "()V", (void*) android_net_wifi_stopHal },
{ "waitForHalEventNative", "()V", (void*) android_net_wifi_waitForHalEvents },
{ "getInterfacesNative", "()I", (void*) android_net_wifi_getInterfaces},
{ "getInterfaceNameNative", "(I)Ljava/lang/String;", (void*) android_net_wifi_getInterfaceName},
{ "getScanCapabilitiesNative", "(ILcom/android/server/wifi/WifiNative$ScanCapabilities;)Z",
(void *) android_net_wifi_getScanCapabilities},
{ "startScanNative", "(IILcom/android/server/wifi/WifiNative$ScanSettings;)Z",
(void*) android_net_wifi_startScan},
{ "stopScanNative", "(II)Z", (void*) android_net_wifi_stopScan},
{ "getScanResultsNative", "(IZ)[Landroid/net/wifi/WifiScanner$ScanData;",
(void *) android_net_wifi_getScanResults},
{ "setHotlistNative", "(IILandroid/net/wifi/WifiScanner$HotlistSettings;)Z",
(void*) android_net_wifi_setHotlist},
{ "resetHotlistNative", "(II)Z", (void*) android_net_wifi_resetHotlist},
{ "trackSignificantWifiChangeNative", "(IILandroid/net/wifi/WifiScanner$WifiChangeSettings;)Z",
(void*) android_net_wifi_trackSignificantWifiChange},
{ "untrackSignificantWifiChangeNative", "(II)Z",
(void*) android_net_wifi_untrackSignificantWifiChange},
{ "getWifiLinkLayerStatsNative", "(I)Landroid/net/wifi/WifiLinkLayerStats;",
(void*) android_net_wifi_getLinkLayerStats},
{ "setWifiLinkLayerStatsNative", "(II)V",
(void*) android_net_wifi_setLinkLayerStats},
{ "getSupportedFeatureSetNative", "(I)I",
(void*) android_net_wifi_getSupportedFeatures},
{ "requestRangeNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
(void*) android_net_wifi_requestRange},
{ "cancelRangeRequestNative", "(II[Landroid/net/wifi/RttManager$RttParams;)Z",
(void*) android_net_wifi_cancelRange},
{ "setScanningMacOuiNative", "(I[B)Z", (void*) android_net_wifi_setScanningMacOui},
{ "getChannelsForBandNative", "(II)[I", (void*) android_net_wifi_getValidChannels},
{ "setDfsFlagNative", "(IZ)Z", (void*) android_net_wifi_setDfsFlag},
{ "toggleInterfaceNative", "(I)Z", (void*) android_net_wifi_toggle_interface},
{ "getRttCapabilitiesNative", "(I)Landroid/net/wifi/RttManager$RttCapabilities;",
(void*) android_net_wifi_get_rtt_capabilities},
{"setCountryCodeHalNative", "(ILjava/lang/String;)Z",
(void*) android_net_wifi_set_Country_Code_Hal},
{ "setPnoListNative", "(II[Lcom/android/server/wifi/WifiNative$WifiPnoNetwork;)Z",
(void*) android_net_wifi_setPnoListNative},
{"enableDisableTdlsNative", "(IZLjava/lang/String;)Z",
(void*) android_net_wifi_enable_disable_tdls},
{"getTdlsStatusNative", "(ILjava/lang/String;)Lcom/android/server/wifi/WifiNative$TdlsStatus;",
(void*) android_net_wifi_get_tdls_status},
{"getTdlsCapabilitiesNative", "(I)Lcom/android/server/wifi/WifiNative$TdlsCapabilities;",
(void*) android_net_wifi_get_tdls_capabilities},
{"getSupportedLoggerFeatureSetNative","(I)I",
(void*) android_net_wifi_get_supported_logger_feature},
{"getDriverVersionNative", "(I)Ljava/lang/String;",
(void*) android_net_wifi_get_driver_version},
{"getFirmwareVersionNative", "(I)Ljava/lang/String;",
(void*) android_net_wifi_get_firmware_version},
{"getRingBufferStatusNative", "(I)[Lcom/android/server/wifi/WifiNative$RingBufferStatus;",
(void*) android_net_wifi_get_ring_buffer_status},
{"startLoggingRingBufferNative", "(IIIIILjava/lang/String;)Z",
(void*) android_net_wifi_start_logging_ring_buffer},
{"getRingBufferDataNative", "(ILjava/lang/String;)Z",
(void*) android_net_wifi_get_ring_buffer_data},
{"getFwMemoryDumpNative","(I)Z", (void*) android_net_wifi_get_fw_memory_dump},
{ "setLazyRoamNative", "(IIZLcom/android/server/wifi/WifiNative$WifiLazyRoamParams;)Z",
(void*) android_net_wifi_setLazyRoam},
{ "setBssidBlacklistNative", "(II[Ljava/lang/String;)Z",
(void*)android_net_wifi_setBssidBlacklist},
{ "setSsidWhitelistNative", "(II[Ljava/lang/String;)Z",
(void*)android_net_wifi_setSsidWhitelist},
{"setLoggingEventHandlerNative", "(II)Z", (void *) android_net_wifi_set_log_handler},
{"resetLogHandlerNative", "(II)Z", (void *) android_net_wifi_reset_log_handler},
{ "startSendingOffloadedPacketNative", "(II[B[B[BI)I",
(void*)android_net_wifi_start_sending_offloaded_packet},
{ "stopSendingOffloadedPacketNative", "(II)I",
(void*)android_net_wifi_stop_sending_offloaded_packet},
{"startRssiMonitoringNative", "(IIBB)I",
(void*)android_net_wifi_start_rssi_monitoring_native},
{"stopRssiMonitoringNative", "(II)I",
(void*)android_net_wifi_stop_rssi_monitoring_native},
{"isGetChannelsForBandSupportedNative", "()Z",
(void*)android_net_wifi_is_get_channels_for_band_supported}
};
int register_android_net_wifi_WifiNative(JNIEnv* env) {
return AndroidRuntime::registerNativeMethods(env,
"com/android/server/wifi/WifiNative", gWifiMethods, NELEM(gWifiMethods));
}
则最终调用(void *)android_net_wifi_loadDriver函数,代码如下,在wifi.c中定义
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
return (::wifi_load_driver() == 0);
}
最终会调用insmod通过加载.ko驱动的路径加载wifi,本人代码使修改过的,主体并未改变。
int wifi_load_driver()
{
FILE *fp = NULL;
DIR *d;
struct dirent *de;
#ifdef MULTI_WIFI_SUPPORT
set_wifi_power(SDIO_POWER_UP);
#else
#ifdef USB_WIFI_SUPPORT
set_wifi_power(USB_POWER_UP);
#endif
#endif
#ifdef WIFI_DRIVER_MODULE_PATH
char driver_status[PROPERTY_VALUE_MAX];
int count = 100; /* wait at most 20 seconds for completion */
if (is_wifi_driver_loaded()) {
return 0;
}
#ifdef MULTI_WIFI_SUPPORT
if (multi_wifi_load_driver() < 0)
{
set_wifi_power(SDIO_POWER_DOWN);
ALOGE("MULTI wifi load fail\n");
return -1;
}
#else
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
return -1;
#ifdef BCM_USB_WIFI
enable_bcmdl(1);
#endif
#endif
#define TIME_COUNT 200
count = 0;
ALOGD("check loading wifi driver is ok...");
do {
d = opendir("/sys/class/net");
if (d == 0) {
ALOGD("fail to open /sys/class/net");
wifi_unload_driver();
return -1;
}
while ((de = readdir(d))) {
if (strcmp(de->d_name, "wlan0")== 0) {
ALOGE("driver loaded");
property_set(DRIVER_PROP_NAME, "ok");
closedir(d);
return 0;
}
}
closedir(d);
usleep(200000);// 200ms
ALOGD("driver not ok ,wait\n");
} while (count++ <= TIME_COUNT);
property_set(DRIVER_PROP_NAME, "timeout");
wifi_unload_driver();
return -1;
#else
#ifdef WIFI_DRIVER_STATE_CTRL_PARAM
if (is_wifi_driver_loaded()) {
return 0;
}
if (wifi_change_driver_state(WIFI_DRIVER_STATE_ON) < 0)
return -1;
#endif
property_set(DRIVER_PROP_NAME, "ok");
return 0;
#endif
}
分析这么多简述了Wifimanage如何通过直接调用WIfiServiceImpl开启wifi,WifiManage还有通过message传递command的方式调用WIfiServiceImpl,
主要差别在于调用方式不同,最终都是发送命令给WifiStateMachine来处理,这里以Wifimanage的connect函数为例,
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
validateChannel();
sAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
}
最终会在WIfiServiceImpl的ClientHandler中接收数据,代码如下
/* Client commands are forwarded to state machine */
case WifiManager.CONNECT_NETWORK:
case WifiManager.SAVE_NETWORK: {
WifiConfiguration config = (WifiConfiguration) msg.obj;
int networkId = msg.arg1;
if (msg.what == WifiManager.SAVE_NETWORK) {
Slog.e("WiFiServiceImpl ", "SAVE"
+ " nid=" + Integer.toString(networkId)
+ " uid=" + msg.sendingUid
+ " name="
+ mContext.getPackageManager().getNameForUid(msg.sendingUid));
}
if (msg.what == WifiManager.CONNECT_NETWORK) {
Slog.e("WiFiServiceImpl ", "CONNECT "
+ " nid=" + Integer.toString(networkId)
+ " uid=" + msg.sendingUid
+ " name="
+ mContext.getPackageManager().getNameForUid(msg.sendingUid));
}
if (config != null && isValid(config)) {
if (DBG) Slog.d(TAG, "Connect with config" + config);
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else if (config == null
&& networkId != WifiConfiguration.INVALID_NETWORK_ID) {
if (DBG) Slog.d(TAG, "Connect with networkId" + networkId);
mWifiStateMachine.sendMessage(Message.obtain(msg));
} else {
Slog.e(TAG, "ClientHandler.handleMessage ignoring invalid msg=" + msg);
if (msg.what == WifiManager.CONNECT_NETWORK) {
replyFailed(msg, WifiManager.CONNECT_NETWORK_FAILED,
WifiManager.INVALID_ARGS);
} else {
replyFailed(msg, WifiManager.SAVE_NETWORK_FAILED,
WifiManager.INVALID_ARGS);
}
}
break;
}
最后会在WifistateMachine的ConnectModeState状态下读取connect命令
case WifiManager.CONNECT_NETWORK:
/**
* The connect message can contain a network id passed as arg1 on message or
* or a config passed as obj on message.
* For a new network, a config is passed to create and connect.
* For an existing network, a network id is passed
*/
netId = message.arg1;
config = (WifiConfiguration) message.obj;
mWifiConnectionStatistics.numWifiManagerJoinAttempt++;
boolean updatedExisting = false;
/* Save the network config */
代码较长。总之就是根据传入的wifi配置信息连接wifi,成功能reply一个成功的信息,否则回复失败。
到目前wifi整个流程以大致完成,还缺少wifiMonitor接收wpa_supplicant回传过来的信息。上面说到wifiMonitor在发送开启wifi命令时在WifiStateMachine的initstage中调用开启,看下构造函数,
public WifiMonitor(StateMachine stateMachine, WifiNative wifiNative) {
if (DBG) Log.d(TAG, "Creating WifiMonitor");
mWifiNative = wifiNative;
mInterfaceName = wifiNative.mInterfaceName;
mStateMachine = stateMachine;
mStateMachine2 = null;
mMonitoring = false;
WifiMonitorSingleton.sInstance.registerInterfaceMonitor(mInterfaceName, this);
}
,没干什么软事,直接看startMonitoring函数
public void startMonitoring() {
WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
}
再看下WifiMonitorSingleton.sInstance.startMonitoring(mInterfaceName);
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.mStateMachine.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.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
mConnected = true;
new MonitorThread(mWifiNative, this).start();
break;
}
if (connectTries++ < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
} else {
m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
Log.e(TAG, "startMonitoring(" + iface + ") failed!");
break;
}
}
}
}
像WifiStateMachine发送了wpa_supplicant连接的event并开启了WifiMonitor线程,看下线程构造函数
private static class MonitorThread extends Thread {
private final WifiNative mWifiNative;
private final WifiMonitorSingleton mWifiMonitorSingleton;
private final LocalLog mLocalLog = WifiNative.getLocalLog();
public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
super("WifiMonitor");
mWifiNative = wifiNative;
mWifiMonitorSingleton = wifiMonitorSingleton;
}
public void run() {
if (DBG) {
Log.d(TAG, "MonitorThread start with mConnected=" +
mWifiMonitorSingleton.mConnected);
}
//noinspection InfiniteLoopStatement
for (;;) {
if (!mWifiMonitorSingleton.mConnected) {
if (DBG) Log.d(TAG, "MonitorThread exit because mConnected is false");
break;
}
String eventStr = mWifiNative.waitForEvent();
// Skip logging the common but mostly uninteresting events
if (eventStr.indexOf(BSS_ADDED_STR) == -1
&& eventStr.indexOf(BSS_REMOVED_STR) == -1) {
if (DBG) Log.d(TAG, "Event [" + eventStr + "]");
mLocalLog.log("Event [" + eventStr + "]");
}
if (mWifiMonitorSingleton.dispatchEvent(eventStr)) {
if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
break;
}
}
}
}
在run里面先调用了 String eventStr = mWifiNative.waitForEvent();的native函数这个函数通过JNI在wifi.c里面,看下这个函数
int wifi_wait_on_socket(char *buf, size_t buflen)
{
size_t nread = buflen - 1;
int result;
char *match, *match2;
if (monitor_conn == NULL) {
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
primary_iface, WPA_EVENT_TERMINATING);
}
result = wifi_ctrl_recv(buf, &nread);
/* Terminate reception on exit socket */
if (result == -2) {
return snprintf(buf, buflen, "IFNAME=%s %s - connection closed",
primary_iface, WPA_EVENT_TERMINATING);
}
if (result < 0) {
ALOGD("wifi_ctrl_recv failed: %s\n", strerror(errno));
return snprintf(buf, buflen, "IFNAME=%s %s - recv error",
primary_iface, WPA_EVENT_TERMINATING);
}
buf[nread] = '\0';
/* Check for EOF on the socket */
if (result == 0 && nread == 0) {
/* Fabricate an event to pass up */
ALOGD("Received EOF on supplicant socket\n");
return snprintf(buf, buflen, "IFNAME=%s %s - signal 0 received",
primary_iface, WPA_EVENT_TERMINATING);
}
/*
* Events strings are in the format
*
* IFNAME=iface CTRL-EVENT-XXX
* or
* CTRL-EVENT-XXX
*
* where N is the message level in numerical form (0=VERBOSE, 1=DEBUG,
* etc.) and XXX is the event name. The level information is not useful
* to us, so strip it off.
*/
if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
match = strchr(buf, ' ');
if (match != NULL) {
if (match[1] == '<') {
match2 = strchr(match + 2, '>');
if (match2 != NULL) {
nread -= (match2 - match);
memmove(match + 1, match2 + 1, nread - (match - buf) + 1);
}
}
} else {
return snprintf(buf, buflen, "%s", WPA_EVENT_IGNORE);
}
} else if (buf[0] == '<') {
match = strchr(buf, '>');
if (match != NULL) {
nread -= (match + 1 - buf);
memmove(buf, match + 1, nread + 1);
ALOGV("supplicant generated event without interface - %s\n", buf);
}
} else {
/* let the event go as is! */
ALOGW("supplicant generated event without interface and without message level - %s\n", buf);
}
return nread;
}
一个 result = wifi_ctrl_recv(buf, &nread);和wpa_suplicant连接,这个反正具体分析wpa_suplicant后面详细说明。所以在接收到event后先判断是否有无用信息,在调用mWifiMonitorSingleton.dispatchEvent(eventStr)函数,看下这个函数
private synchronized boolean dispatchEvent(String eventStr) {
String iface;
// IFNAME=wlan0 ANQP-QUERY-DONE addr=18:cf:5e:26:a4:88 result=SUCCESS
if (eventStr.startsWith("IFNAME=")) {
int space = eventStr.indexOf(' ');
if (space != -1) {
iface = eventStr.substring(7, space);
if (!mIfaceMap.containsKey(iface) && 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 ..
iface = "p2p0";
}
eventStr = eventStr.substring(space + 1);
} else {
// No point dispatching this event to any interface, the dispatched
// event string will begin with "IFNAME=" which dispatchEvent can't really
// do anything about.
Log.e(TAG, "Dropping malformed event (unparsable iface): " + eventStr);
return false;
}
} else {
// events without prefix belong to p2p0 monitor
iface = "p2p0";
}
if (VDBG) Log.d(TAG, "Dispatching event to interface: " + iface);
WifiMonitor m = mIfaceMap.get(iface);
//确定event接收的接口。在下面接收event
if (m != null) {
if (m.mMonitoring) {
if (m.dispatchEvent(eventStr, iface)) {
mConnected = false;
return true;
}
return false;
} else {
if (DBG) Log.d(TAG, "Dropping event because (" + iface + ") is stopped");
return false;
}
} else {
if (DBG) Log.d(TAG, "Sending to all monitors because there's no matching iface");
boolean done = false;
boolean isMonitoring = false;
boolean isTerminating = false;
if (eventStr.startsWith(EVENT_PREFIX_STR)
&& eventStr.contains(TERMINATING_STR)) {
isTerminating = true;
}
for (WifiMonitor monitor : mIfaceMap.values()) {
if (monitor.mMonitoring) {
isMonitoring = true;
if (monitor.dispatchEvent(eventStr, iface)) {
done = true;
}
}
}
if (!isMonitoring && isTerminating) {
done = true;
}
if (done) {
mConnected = false;
}
return done;
}
}
}
先确定wifi接口后,在调用m.dispatchEvent(eventStr, iface)函数。再看下这个函数做了什么
/* @return true if the event was supplicant disconnection */
private boolean dispatchEvent(String eventStr, String iface) {
if (DBG) {
// Dont log CTRL-EVENT-BSS-ADDED which are too verbose and not handled
if (eventStr != null && !eventStr.contains("CTRL-EVENT-BSS-ADDED")) {
logDbg("WifiMonitor:" + iface + " cnt=" + Integer.toString(eventLogCounter)
+ " dispatchEvent: " + 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, eventLogCounter);
} 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 (eventStr.startsWith(ANQP_DONE_STR)) {
try {
handleAnqpResult(eventStr);
}
catch (IllegalArgumentException iae) {
Log.e(TAG, "Bad ANQP event string: '" + eventStr + "': " + iae);
}
} else if (eventStr.startsWith(GAS_QUERY_PREFIX_STR)) { // !!! clean >>End
handleGasQueryEvents(eventStr);
} else if (eventStr.startsWith(RX_HS20_ANQP_ICON_STR)) {
if (mStateMachine2 != null)
mStateMachine2.sendMessage(RX_HS20_ANQP_ICON_EVENT,
eventStr.substring(RX_HS20_ANQP_ICON_STR_LEN + 1));
} else if (eventStr.startsWith(HS20_PREFIX_STR)) { // !!! <
handleHs20Events(eventStr);
} else if (eventStr.startsWith(REQUEST_PREFIX_STR)) {
handleRequests(eventStr);
} else if (eventStr.startsWith(TARGET_BSSID_STR)) {
handleTargetBSSIDEvent(eventStr);
} else if (eventStr.startsWith(ASSOCIATED_WITH_STR)) {
handleAssociatedBSSIDEvent(eventStr);
} else if (eventStr.startsWith(AUTH_EVENT_PREFIX_STR) &&
eventStr.endsWith(AUTH_TIMEOUT_STR)) {
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
} else if (eventStr.startsWith(RSN_PMKID_STR)) {
mStateMachine.sendMessage(RSN_PMKID_MISMATCH_EVENT);
} else {
if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
}
eventLogCounter++;
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");
eventLogCounter++;
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(SCAN_FAILED_STR))
event = SCAN_FAILED;
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 if (eventName.equals(TEMP_DISABLED_STR)) {
event = SSID_TEMP_DISABLE;
} else if (eventName.equals(REENABLED_STR)) {
event = SSID_REENABLE;
} else if (eventName.equals(BSS_ADDED_STR)) {
event = BSS_ADDED;
} else if (eventName.equals(BSS_REMOVED_STR)) {
event = BSS_REMOVED;
} 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 == SSID_TEMP_DISABLE)||(event == SSID_REENABLE)) {
String substr = null;
int netId = -1;
int ind = eventStr.indexOf(" ");
if (ind != -1) {
substr = eventStr.substring(ind + 1);
}
if (substr != null) {
String status[] = substr.split(" ");
for (String key : status) {
if (key.regionMatches(0, "id=", 0, 3)) {
int idx = 3;
netId = 0;
while (idx < key.length()) {
char c = key.charAt(idx);
if ((c >= 0x30) && (c <= 0x39)) {
netId *= 10;
netId += c - 0x30;
idx++;
} else {
break;
}
}
}
}
}
mStateMachine.sendMessage((event == SSID_TEMP_DISABLE)?
SSID_TEMP_DISABLED:SSID_REENABLED, netId, 0, substr);
} else 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 (++sRecvErrors > MAX_RECV_ERRORS) {
if (DBG) {
Log.d(TAG, "too many recv errors, closing connection");
}
} else {
eventLogCounter++;
return false;
}
}
// Notify and exit
mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT, eventLogCounter);
return true;
} else if (event == EAP_FAILURE) {
if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
logDbg("WifiMonitor send auth failure (EAP_AUTH_FAILURE) ");
mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT, eventLogCounter);
}
} else if (event == ASSOC_REJECT) {
Matcher match = mAssocRejectEventPattern.matcher(eventData);
String BSSID = "";
int status = -1;
if (!match.find()) {
if (DBG) Log.d(TAG, "Assoc Reject: Could not parse assoc reject string");
} else {
BSSID = match.group(1);
try {
status = Integer.parseInt(match.group(2));
} catch (NumberFormatException e) {
status = -1;
}
}
mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT, eventLogCounter, status, BSSID);
} else if (event == BSS_ADDED && !VDBG) {
// Ignore that event - it is not handled, and dont log it as it is too verbose
} else if (event == BSS_REMOVED && !VDBG) {
// Ignore that event - it is not handled, and dont log it as it is too verbose
} else {
handleEvent(event, eventData);
}
sRecvErrors = 0;
eventLogCounter++;
return false;
}
原来就是处理接收上来不同wifi接口的event而已,先以不同的envet前导过滤一些,由函数!eventStr.startsWith(EVENT_PREFIX_STR),再将去掉前导过滤掉的保存在event中,再判断不同event的状态跳转到相应的handle中去,以handleEvent(event, eventData);为例看下代码
void handleEvent(int event, String remainder) {
if (DBG) {
logDbg("handleEvent " + Integer.toString(event) + " " + 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 SCAN_FAILED:
mStateMachine.sendMessage(SCAN_FAILED_EVENT);
break;
case UNKNOWN:
if (DBG) {
logDbg("handleEvent unknown: " + Integer.toString(event) + " " + remainder);
}
break;
default:
break;
}
}
在以SCAN_RESULTS为例看下WifiStateMachine如何处理event,在此函数中mStateMachine.sendMessage(SCAN_RESULTS_EVENT),发送信息
在SupplicantStartedState中
case WifiMonitor.SCAN_RESULTS_EVENT:
case WifiMonitor.SCAN_FAILED_EVENT:
maybeRegisterNetworkFactory(); // Make sure our NetworkFactory is registered
noteScanEnd();
setScanResults();
if (mIsFullScanOngoing || mSendScanResultsBroadcast) {
/* Just updated results from full scan, let apps know about this */
boolean scanSucceeded = message.what == WifiMonitor.SCAN_RESULTS_EVENT;
sendScanResultsAvailableBroadcast(scanSucceeded);
}
mSendScanResultsBroadcast = false;
mIsScanOngoing = false;
mIsFullScanOngoing = false;
if (mBufferedScanMsg.size() > 0)
sendMessage(mBufferedScanMsg.remove());
break;
其中 sendScanResultsAvailableBroadcast(scanSucceeded);通过广播发送接收结果
void sendScanResultsAvailableBroadcast(boolean scanSucceeded) {
Intent intent = new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
intent.putExtra(WifiManager.EXTRA_RESULTS_UPDATED, scanSucceeded);
mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
}
到此告一段落,下次分析wpa_suplicant源码,在结合此文章会有更清晰的思路