Android系统中的WIFI架构&工作流程分析
1. 前言
记录个人最近对Android wifi的了解和使用感受,并为想入门、学习Android wifi的人员提供一定的参考
2. Android系统中的WIFI架构
wifi在Android中的架构如下所示。
其中涉及到的代码:
Java应用层
----Settings应用
Java Framework层
----frameworks/base/wifi/java/android/net/wifi/
----frameworks/base/services/java/com/android/server/wifi/
JNI层
---frameworks/base/core/jni/android_net_wifi_WifiNative.cpp
HAL层
---hardware/libhardware_legacy/wifi/wifi.c
wpa_supplicant层
---external/wpa_supplicant_8/
Linux Kernel层(驱动、电源管理部分)
---linux-3.3/drivers/net/wireless/rtl8188eu/
---linux-3.3/arch/arm/mach-sun6i/rf/wifi_pm_rtl8188eu.c
---linux-3.3/arch/arm/mach-sun6i/rf/wifi_pm.c
3. wifi工作流程分析
下面以wifi toggle on为例对wifi的工作流程进行分析。
wifi toggle的工作是使能/失能wifi的,当在Settings应用里点击wifi的打开/关闭按钮时会触发packages/apps/Settings/src/com/android/settings/wifi/WifiEnabler.java里的onCheckedChanged()函数执行,所以这个文件是分析的入口点,首先看onCheckedChanged()函数:
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//Do nothing if called as a result of a state machine event
if (mStateMachineEvent) {
return;
}
// Show toast message if Wi-Fi is not allowed in airplane mode
if (isChecked && !WirelessSettings.isRadioAllowed(mContext, Settings.Global.RADIO_WIFI)) {
Toast.makeText(mContext, R.string.wifi_in_airplane_mode, Toast.LENGTH_SHORT).show();
// Reset switch to off. No infinite check/listenenr loop.
buttonView.setChecked(false);
return;
}
// Disable tethering if enabling Wifi
int wifiApState = mWifiManager.getWifiApState();
if (isChecked && ((wifiApState == WifiManager.WIFI_AP_STATE_ENABLING) ||
(wifiApState == WifiManager.WIFI_AP_STATE_ENABLED))) {
mWifiManager.setWifiApEnabled(null, false);
}
mSwitch.setEnabled(false);
if (!mWifiManager.setWifiEnabled(isChecked)) {
// Error
mSwitch.setEnabled(true);
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}
}
首先判断是否处于飞行模式,飞行模式下是不可以打开wifi的;
接着判断是否使能了softAP,如果是则关闭softAP;
最后调用mWifiManager.setWifiEnabled()函数。mWifiManager.setWifiEnabled()函数在frameworks/base/wifi/java/android/net/wifi/WifiManager.java中定义:
/**
* Enable or disable Wi-Fi.
* @param enabled {@code true} to enable, {@code false} to disable.
* @return {@code true} if the operation succeeds (or if the existing state
* is the same as the requested state).
*/
public boolean setWifiEnabled(boolean enabled) {
try {
return mService.setWifiEnabled(enabled);
} catch (RemoteException e) {
return false;
}
}
可以看到,实际上是调用WifiService类里的setWifiEnabled()函数,WifiManager类对WifiService类进行了大部分封装,WifiService.setWifiEnabled()函数在frameworks/base/services/java/com/android/server/wifi/WifiService.java中定义:
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;
}
在processMessage()函数里首先判断是否已经使能了wifi,接着判断两次使能的时间间隔,如果太短则跳出switch,否则执行transitionTo(mDeviceActiveState),将状态切换到mDeviceActiveState,而mDeviceActiveState的父状态是mStaEnabledState,由状态机的知识可以知道首先会调用mStaEnabledState的enter()函数:
class StaEnabledState extends State {
@Override
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
可以看到,调用的是frameworks/base/wifi/java/android/net/wifi/WifiStateMachine.java里的setSupplicantRunning()函数:
public void setSupplicantRunning(boolean enable) {
if (enable) {
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
在setSupplicantRunning()函数里发送CMD_START_SUPPLICANT消息。因为在WifiStateMachine构造函数里已经将状态设置为mInitialState,因此此消息由InitialState类处理,定义如下:
public boolean processMessage(Message message) {
switch (message.what) {
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
// this affects connectivity when supplicant starts up.
// Ensure interface is down before a supplicant start.
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);
}
/* 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(mWifiNative.startSupplicant(mP2pSupported)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
首先调用frameworks/base/wifi/java/android/net/wifi/WifiNative.java里定义的loadDriver()函数:
public native static boolean loadDriver();
loadDriver()是一个定义为本地实现的函数,在frameworks/base/core/jni/android_net_wifi_WifiNative.cpp里定义:
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
return (::wifi_load_driver() == 0);
}
这里实际上调用的是wifi_load_driver()函数,它在hardware/libhardware_legacy/wifi/wifi.c中定义:
#define TIME_COUNT 20 // 200ms*20 = 4 seconds for completion
#if defined(RTL_WIFI_VENDOR)
int wifi_load_driver()
{
char driver_status[PROPERTY_VALUE_MAX];
int count = 0;
char tmp_buf[512] = {0};
char *p_strstr_wlan = NULL;
char *p_strstr_p2p = NULL;
int ret = 0;
FILE *fp = NULL;
ALOGD("Start to insmod %s.ko\n", WIFI_DRIVER_MODULE_NAME);
if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0) {
ALOGE("insmod %s ko failed!", WIFI_DRIVER_MODULE_NAME);
rmmod(DRIVER_MODULE_NAME); //it may be load driver already,try remove it.
return -1;
}
do{
fp=fopen("/proc/net/wireless", "r");
if (!fp) {
ALOGE("failed to fopen file: /proc/net/wireless\n");
property_set(DRIVER_PROP_NAME, "failed");
rmmod(DRIVER_MODULE_NAME); //try remove it.
return -1;
}
ret = fread(tmp_buf, sizeof(tmp_buf), 1, fp);
if (ret==0){
ALOGD("faied to read proc/net/wireless");
}
fclose(fp);
ALOGD("loading wifi driver...");
p_strstr_wlan = strstr(tmp_buf, "wlan0");
p_strstr_p2p = strstr(tmp_buf, "p2p0");
if (p_strstr_wlan != NULL && p_strstr_p2p != NULL) {
property_set(DRIVER_PROP_NAME, "ok");
break;
}
usleep(200000);// 200ms
} while (count++ <= TIME_COUNT);
if(count > TIME_COUNT) {
ALOGE("timeout, register netdevice wlan0 failed.");
property_set(DRIVER_PROP_NAME, "timeout");
rmmod(DRIVER_MODULE_NAME);
return -1;
}
return 0;
}
首先调用insmod()函数加载驱动模块,然后读取/proc/net/wireless文件,判断驱动是否已经加载成功,在while循环里每隔200ms读取一次该文件,如果超时则退出循环。至此,mWifiNative.loadDriver()函数分析完毕。由于这里没有用到固件,因此mNwService.wifiFirmwareReload()函数就不分析了。继续看InitialState的processMessage()函数,
mWifiMonitor.killSupplicant(mP2pSupported);
if(mWifiNative.startSupplicant(mP2pSupported)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
mWifiMonitor.startMonitoring();
transitionTo(mSupplicantStartingState);
} else {
loge("Failed to start supplicant!");
}
} else {
loge("Failed to load driver");
}
break;
在启动wap_supplicant之前先停止,然后再启动。
在mWifiMonitor.startMonitoring()函数里会调用JNI中的connectToSupplicant()函数,进而调用wifi.c里的wifi_connect_to_supplicant()函数建立了两个socket连接,一个用于向内核发送消息,一个用于接收内核消息,并开启一个线程不断地接收内核传来的消息,在这里也可以知道wap_supplicant充当的是内核与android之间桥梁的作用,并且会发送一个SUP_CONNECTION_EVENT消息。最后将状态转换到mSupplicantStartingState。
然后再调用mDeviceActiveStat的enter()函数:
/* Parent: StaEnabledState */
class DeviceActiveState extends State {
@Override
public void enter() {
mWifiStateMachine.setOperationalMode(WifiStateMachine.CONNECT_MODE);
mWifiStateMachine.setDriverStart(true);
mWifiStateMachine.setHighPerfModeEnabled(false);
}
这三个函数分别在WifiStateMachine里发送三个消息:CMD_SET_OPERATIONAL_MODE、CMD_START_DRIVER和CMD_SET_HIGH_PERF_MODE。其中CMD_SET_OPERATIONAL_MODE和CMD_START_DRIVER消息会被SupplicantStartingState延迟处理,CMD_SET_HIGH_PERF_MODE消息会被DefaultState处理,此处不分析了。下面是SupplicantStartingState对SUP_CONNECTION_EVENT消息的处理:
public boolean processMessage(Message message) {
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
if (DBG) log("Supplicant connection established");
setWifiState(WIFI_STATE_ENABLED);
mSupplicantRestartCount = 0;
/* Reset the supplicant state to indicate the supplicant
* state is not known at this time */
mSupplicantStateTracker.sendMessage(CMD_RESET_SUPPLICANT_STATE);
/* Initialize data structures */
mLastBssid = null;
mLastNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
mLastSignalLevel = -1;
mWifiInfo.setMacAddress(mWifiNative.getMacAddress());
mWifiConfigStore.loadAndEnableAllNetworks();
initializeWpsDetails();
sendSupplicantConnectionChangedBroadcast(true);
transitionTo(mDriverStartedState);
break;
setWifiState()函数里做的其中一件事情就是在状态栏里显示wifi信号图标。在SUP_CONNECTION_EVENT的处理流程中,主要是调用WifiConfigStore的loadAndEnableAllNetworks函数来加载并enable用户之前连接过并保存的AP,然后会初始化一些Wps相关的信息,最后transition到DriverStartedState。下面看DriverStartedState的enter()函数,由于此函数代码较长,因此省略了后面一部分:
public void enter() {
mIsRunning = true;
mInDelayedStop = false;
mDelayedStopCounter++;
updateBatteryWorkSource(null);
/**
* Enable bluetooth coexistence scan mode when bluetooth connection is active.
* When this mode is on, some of the low-level scan parameters used by the
* driver are changed to reduce interference with bluetooth
*/
mWifiNative.setBluetoothCoexistenceScanMode(mBluetoothConnectionActive);
/* set country code */
setCountryCode();
/* set frequency band of operation */
setFrequencyBand();
/* initialize network state */
setNetworkDetailedState(DetailedState.DISCONNECTED);
/* Remove any filtering on Multicast v6 at start */
mWifiNative.stopFilteringMulticastV6Packets();
/* Reset Multicast v4 filtering state */
if (mFilteringMulticastV4Packets.get()) {
mWifiNative.startFilteringMulticastV4Packets();
} else {
mWifiNative.stopFilteringMulticastV4Packets();
}
mDhcpActive = false;
startBatchedScan();
if (mOperationalMode != CONNECT_MODE) {
mWifiNative.disconnect();
mWifiConfigStore.disableAllNetworks();
if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
setWifiState(WIFI_STATE_DISABLED);
}
transitionTo(mScanModeState);
} else {
/* Driver stop may have disabled networks, enable right after start */
mWifiConfigStore.enableAllNetworks();
if (DBG) log("Attempting to reconnect to wifi network ..");
mWifiNative.reconnect();
// Status pulls in the current supplicant state and network connection state
// events over the monitor connection. This helps framework sync up with
// current supplicant state
mWifiNative.status();
transitionTo(mDisconnectedState);
}
从注释上可以看出,主要是设置country code、工作频率和网络状态等。看mOperationalMode == CONNECT_MODE的分支,重新连接网络并将状态转换到mDisconnectedState。到这里,wifi toggle on的流程就分析完了。
- 分享
- 举报
-
浏览量:2318次2020-08-05 20:49:45
-
浏览量:2492次2019-06-21 14:24:27
-
浏览量:1411次2024-01-25 16:21:59
-
浏览量:8358次2021-03-10 17:32:13
-
浏览量:6060次2021-03-29 15:00:21
-
浏览量:3009次2019-11-09 19:10:44
-
浏览量:2655次2020-08-04 20:10:32
-
浏览量:1850次2022-05-30 09:56:07
-
浏览量:18366次2021-03-15 15:41:39
-
浏览量:1951次2020-07-28 17:27:40
-
浏览量:822次2023-08-30 10:00:35
-
浏览量:860次2023-03-15 10:03:25
-
浏览量:1171次2023-10-08 17:44:55
-
浏览量:5568次2021-04-12 16:15:46
-
浏览量:1165次2024-03-15 09:51:11
-
浏览量:2887次2020-11-10 14:23:32
-
浏览量:923次2023-12-11 11:01:31
-
浏览量:1975次2020-07-28 20:16:56
-
浏览量:1307次2023-01-11 12:36:23
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
free-jdx
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明