这里从安卓应用层开始着手分析:
// -------------- packages/apps/settings/src/com/android/settings/wifi/WifiSettings.java -------------- //
private WifiEnabler mWifiEnabler;
// 以下为WifiSettings界面处在Active的状态下创建的!!
@Override
public void onStart() {
super.onStart();
// 创建了 WifiEnabler 对象,用于打开/关闭 wifi
mWifiEnabler = createWifiEnabler();
}
// -------------- packages/apps/settings/src/com/android/settings/wifi/WifiEnabler.java -------------- //
private final WifiManager mWifiManager;
public void onSwitchChanged(Switch switchView, boolean isChecked) {
mSwitchBar.setEnabled(false);
// 这里就调用WifiManager的打开/关闭wifi功能
if (!mWifiManager.setWifiEnabled(isChecked)) {
// Error
mSwitchBar.setEnabled(true);
Toast.makeText(mContext, R.string.wifi_error, Toast.LENGTH_SHORT).show();
}
}
// ---------------- frameworks/base/wifi/java/android/net/wifi/WifiManager.java ------------------ //
IWifiManager mService;
public boolean setWifiEnabled(boolean enabled) {
return mService.setWifiEnabled(enabled);
}
// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java --------- //
public final class WifiServiceImpl extends IWifiManager.Stub {
public synchronized boolean setWifiEnabled(boolean enable) {
mWifiController.sendMessage(CMD_WIFI_TOGGLED);
}
}
默认情况下,在WifiController类的构造函数中已经将状态机的初始状态设置为mApStaDisabledState, 故上面发送的CMD_WIFI_TOGGLED应该由mApStaDisabledState类来接收!
// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiController.java --------- //
class ApStaDisabledState extends State {
class ApStaDisabledState extends State {
public boolean processMessage(Message msg) {
switch (msg.what) {
case CMD_WIFI_TOGGLED:
case CMD_AIRPLANE_TOGGLED:
if (mDeviceIdle == false) {
transitionTo(mDeviceActiveState);
} else {
checkLocksAndTransitionWhenDeviceIdle();
}
}
}
}
}
由于之前WifiController构造函数中有如下定义:addState(mDeviceActiveState, mStaEnabledState); 根据状态机原理,transitionTo(mDeviceActiveState);会先调用父类mStaEnabledState的Enter函数。
class StaEnabledState extends State {
public void enter() {
mWifiStateMachine.setSupplicantRunning(true);
}
}
setSupplicantRunning定义如下:
// ---------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java ---------- //
public void setSupplicantRunning(boolean enable) {
if (enable)
sendMessage(CMD_START_SUPPLICANT);
} else {
sendMessage(CMD_STOP_SUPPLICANT);
}
}
WifiStateMachine状态机的初始化状态是InitialState, 则此时的由InitialState状态来接收CMD_START_SUPPLICANT命令:
// ---------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java ---------- //
class InitialState extends State {
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_START_SUPPLICANT:
// 在这里insmod 对应的ko文件
if (mWifiNative.loadDriver()) {
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!");
}
}
}
}
}
// ---------- frameworks/opt/net/wifi/service/jni/com_android_server_wifi_WifiNative.cpp ---------- //
static JNINativeMethod gWifiMethods[] = {
{ "loadDriver", "()Z", (void *)android_net_wifi_loadDriver },
}
static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject)
{
return (::wifi_load_driver() == 0);
}
// ---------------------- hardware/libhardware_legacy/wifi/Wifi.c ------------------------ //
int wifi_load_driver() {
if (rk_wifi_load_driver(1) < 0)
return -1;
}
// -------------- hardware/libhardware_legacy/wifi/Rk_wifi_ctrl.c ----------------- //
#define WIFI_DRIVER_INF "/sys/class/rkwifi/driver"
int rk_wifi_load_driver(int enable) {
switch(enable)
{
case 0:
buffer = '0';
break;
case 1:
buffer = '1';
break;
}
fd = open(WIFI_DRIVER_INF, O_WRONLY);
sz = write(fd, &buffer, 1);
}
上面使用的"/sys/class/rkwifi/driver"是Rkwifi_sys_iface.c定义的:
// ------------- drivers/net/wireless/rockchip_wlan/wifi_sys/Rkwifi_sys_iface.c --------------- //
static CLASS_ATTR(driver, 0660, NULL, wifi_driver_write);
int rkwifi_sysif_init(void) {
rkwifi_class = class_create(THIS_MODULE, "rkwifi");
ret = class_create_file(rkwifi_class, &class_attr_driver);
}
所以上面调用write函数, 其实就是调用wifi_driver_write函数:
static ssize_t wifi_driver_write(struct class *cls, struct class_attribute *attr, const char *_buf, size_t _count) {
if(enable > 0) {
ret = wifi_init_exit_module(enable);
if (ret >= 0)
wifi_driver_insmod = enable;
} else {
wifi_init_exit_module(enable);
wifi_driver_insmod = enable;
}
}
static int wifi_init_exit_module(int enable) {
int type = get_wifi_chip_type();
if (enable > 0)
ret = rockchip_wifi_init_module_rkwifi();
else
rockchip_wifi_exit_module_rkwifi();
}
// ----------- drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/Dhd_linux.c ----------- //
int rockchip_wifi_init_module_rkwifi(void) {
return dhd_module_init();
}
这样就加载了wifi驱动 !!!
继续来看上面执行loadDriver之后的动作: mWifiNative.startSupplicant(mP2pSupported) , 启动 wpa_supplicant
// ------------------- hardware/libhardware_legacy/wifi/Wifi.c ---------------------- //
static const char BCM_SUPPLICANT_NAME[] = "wpa_supplicant";
static const char BCM_PROP_NAME[] = "init.svc.wpa_supplicant";
int wifi_start_supplicant(int p2p_supported) {
property_set("ctl.start", supplicant_name); // 这里就会启动init.connectivity.rc中的wpa_supplicant服务
while(count-- > 0) {
if (property_get(supplicant_prop_name, supp_status, NULL)) { // 判断是否init.svc.wpa_supplicant处于running状态
if (strcmp(supp_status, "running") == 0)
return 0; // 正常则返回0
}
}
return -1; // 其他情况返回-1
}
wpa_supplicant 服务定义:
// -------------------- device/rockchip/common/init.connectivity.rc -------------------- //
########## kernel version >= 3.10.x ##########
service wpa_supplicant /system/bin/wpa_supplicant /
-iwlan0 -Dnl80211 -c/data/misc/wifi/wpa_supplicant.conf /
-I/system/etc/wifi/wpa_supplicant_overlay.conf /
-e/data/misc/wifi/entropy.bin -g@android:wpa_wlan0
class main
socket wpa_wlan0 dgram 660 wifi wifi
disabled
oneshot
回到上面的函数调用:
// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMonitor.java -------- //
public synchronized void startMonitoring(String iface) {
while (true) {
if (mWifiNative.connectToSupplicant()) {
m.mMonitoring = true;
m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT); // 连接成功后就会向WifiStateMachine发送SUP_CONNECT_EVENT
new MonitorThread(mWifiNative, this).start(); // 启动MonitorThread线程监听底层的消息
mConnected = true;
break;
}
if (connectTries++ < 5) {
try {
Thread.sleep(1000);
} catch (InterruptedException ignore) {
}
} else {
//mIfaceMap.remove(iface);
m.mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
Log.e(TAG, "startMonitoring(" + iface + ") failed!");
break;
}
}
}
private static class MonitorThread extends Thread {
private final WifiNative mWifiNative;
private final WifiMonitorSingleton mWifiMonitorSingleton;
public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
super("WifiMonitor");
mWifiNative = wifiNative;
mWifiMonitorSingleton = wifiMonitorSingleton;
}
public void run() {
for (;;) {
String eventStr = mWifiNative.waitForEvent();
// Skip logging the common but mostly uninteresting scan-results event
if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
Log.d(TAG, "Event [" + eventStr + "]");
}
if (mWifiMonitorSingleton.dispatchEvent(eventStr)) {
if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
break;
}
}
}
}
可以看到, 上面首先调用connectToSupplicant 和 wpa_supplicant 建立联系,并创建了一个Monitor Thread, 调用 waiForEvent 用于接收wpa_supplicant 上发的消息, 并调用dispatchEvent分发处理消息!!
// ------------ hardware/libhardware_legacy/wifi/Wifi.c ----------- //
int wifi_connect_to_supplicant()
{
static char path[PATH_MAX];
if (access(IFACE_DIR, F_OK) == 0) {
snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, primary_iface);
} else {
snprintf(path, sizeof(path), "@android:wpa_%s", primary_iface);
}
ALOGD("open connection to supplicant on /"%s/"", path); // @android:wpa_wlan0
return wifi_connect_on_socket_path(path);
}
int wifi_connect_on_socket_path(const char *path) {
ctrl_conn = wpa_ctrl_open(path); // 创建了两个套接字,ctrl_conn用于发送,monitor_conn用于接收
monitor_conn = wpa_ctrl_open(path);
wpa_ctrl_attach(monitor_conn);
}
上面讲到startMonitoring调用wifi_connect_to_supplicant之后, 紧接着会发送一个SUP_CONNECTION_EVENT的消息给到WifiStateMachine:
同时状态切换到transitionTo(mSupplicantStartingState);
// --------- frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiStateMachine.java --------- //
class SupplicantStartingState extends State {
public boolean processMessage(Message message) {
switch(message.what) {
case WifiMonitor.SUP_CONNECTION_EVENT:
sendSupplicantConnectionChangedBroadcast(true);
transitionTo(mDriverStartedState);
break;
case CMD_START_DRIVER:
case CMD_SET_OPERATIONAL_MODE:
messageHandlingStatus = MESSAGE_HANDLING_STATUS_DEFERRED;
deferMessage(message); // 上面发送的这两个命令,都延迟处理!!!
break;
}
}
}
class DriverStartedState extends State {
public void enter() {
if (mOperationalMode != CONNECT_MODE)
transitionTo(mScanModeState);
else
transitionTo(mDisconnectedState);
if (mP2pSupported) { //注意这里, 如果是支持wifi direct的话会在这里发送CMD_ENABLE_P2P命令!!
if (mOperationalMode == CONNECT_MODE) {
mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_ENABLE_P2P);
}
}
}
}
class DisconnectedState extends State {
public void enter() {
startDelayedScan(mDisconnectedScanPeriodMs, null, null); // 开始扫描
}
public boolean processMessage(Message message) {
switch (message.what) {
case WifiMonitor.SCAN_RESULTS_EVENT:
ret = NOT_HANDLED; // 不处理,抛给父类
break;
case CMD_START_SCAN:
handleScanRequest(WifiNative.SCAN_WITHOUT_CONNECTION_SETUP, message);
break;
case CMD_SET_OPERATIONAL_MODE: // 在这里处理CMD_SET_OPERATIONAL_MODE消息
if (message.arg1 != CONNECT_MODE) {
mOperationalMode = message.arg1;
mWifiConfigStore.disableAllNetworks();
if (mOperationalMode == SCAN_ONLY_WITH_WIFI_OFF_MODE) {
mWifiP2pChannel.sendMessage(CMD_DISABLE_P2P_REQ);
setWifiState(WIFI_STATE_DISABLED);
}
transitionTo(mScanModeState);
}
break;
}
}
}
private void handleScanRequest(int type, Message message) {
startScanNative(type, freqs);
}
private boolean startScanNative(int type, String freqs) {
mWifiNative.scan(type, freqs);
}
startScanNative会向wpa_supplicant发送SCAN的命令:
// ------------ frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java ------------ //
public boolean scan(int type, String freqList) {
if (type == SCAN_WITHOUT_CONNECTION_SETUP) {
if (freqList == null) return doBooleanCommand("SCAN TYPE=ONLY");
else return doBooleanCommand("SCAN TYPE=ONLY freq=" + freqList);
} else if (type == SCAN_WITH_CONNECTION_SETUP) {
if (freqList == null) return doBooleanCommand("SCAN");
else return doBooleanCommand("SCAN freq=" + freqList);
}
}
private boolean doBooleanCommand(String command) {
synchronized (mLock) {
int cmdId = getNewCmdIdLocked();
String toLog = Integer.toString(cmdId) + ":" + mInterfacePrefix + command;
boolean result = doBooleanCommandNative(mInterfacePrefix + command);
localLog(toLog + " -> " + result);
if (DBG) Log.d(mTAG, command + ": returned " + result);
return result;
}
}
// ------------ frameworks/opt/net/wifi/service/jni/com_android_server_wifi_WifiNative.cpp ---------------- //
static JNINativeMethod gWifiMethods[] = {
{ "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
}
static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring javaCommand) {
return doBooleanCommand(env, javaCommand);
}
static jboolean doBooleanCommand(JNIEnv* env, jstring javaCommand) {
char reply[REPLY_BUF_SIZE];
if (!doCommand(env, javaCommand, reply, sizeof(reply))) {
return JNI_FALSE;
}
return (strcmp(reply, "OK") == 0);
}
static bool doCommand(JNIEnv* env, jstring javaCommand, char* reply, size_t reply_len) {
ScopedUtfChars command(env, javaCommand);
if (command.c_str() == NULL) {
return false; // ScopedUtfChars already threw on error.
}
if (DBG) {
ALOGD("doCommand: %s", command.c_str());
}
--reply_len; // Ensure we have room to add NUL termination.
if (::wifi_command(command.c_str(), reply, &reply_len) != 0) {
return false;
}
// Strip off trailing newline.
if (reply_len > 0 && reply[reply_len-1] == '/n') {
reply[reply_len-1] = '/0';
} else {
reply[reply_len] = '/0';
}
return true;
}
最终就会调用wifi.c的wifi_command函数,从而通过ctrl_conn给wpa_supplicant发送SCAN TYPE=ONLY命令。
当wpa_suppliant执行完SCAN并成功找到一些AP后,就会给WifiMonitor发送CTRL-EVENT-SCAN-RESULTS的event,
WifiMonitor会parse出这个event,并向WifiStateMachine发送SCAN_RESULTS_EVENT消息,
由于DisconnectedState类不处理, 一直往上抛到父类,
WifiStateMachine的SupplicantStartedState会处理这个消息,如下:class SupplicantStartedState extends State {
public boolean processMessage(Message message) {
switch(message.what) {
// 这里主要做了两件事,一是去获取scanResults,另外会发送一个广播信息出去,
// 如果有检测这个广播的receive收到这个广播后,就可以调用函数去获取到scanResults并显示到listview上面,例如WifiSettings
case WifiMonitor.SCAN_RESULTS_EVENT:
setScanResults();
sendScanResultsAvailableBroadcast();
}
}
}
private void setScanResults() {
/*
这个函数看起来比较复杂,其实仔细分析,它只是循环的parse从WifiNative获取到AP列表信息,
WifiNative.scanResut的返回结果如下,每个AP之间用"===="分割,末尾以“####”来表示结束。
id=1
bssid=68:7f:76:d7:1a:6e
freq=2412
level=-44
tsf=1344626243700342
flags=[WPA2-PSK-CCMP][WPS][ESS]
ssid=zfdy
====
id=2
bssid=68:5f:74:d7:1a:6f
req=5180
level=-73
tsf=1344626243700373
flags=[WPA2-PSK-CCMP][WPS][ESS]
ssid=zuby
####
当所有的结果都被parse出来后,会被存到mScanResults这个ArrayList当中,
另外会用bssid+ssid做key值,将这个scanResult存到mScanResultCache这个LRU(最近最少使用) cache当中。
当然随着wifi driver不断的scan,发现新的AP,mScanResults和mScanResultCache中的数据也在不断的变化。
当应用程序收到sendScanResultsAvailableBroadcast发送的WifiManager.SCAN_RESULTS_AVAILABLE_ACTION这个broadcast后,
就可以去获取上面提供的mScanResults信息了,获取过程很简单,直接复制mScanResults这个ArrayList里面的成员,然后返回。
值得注意的是!!!sendScanResultsAvailableBroadcast设置了Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT这个属性,
所以只有动态注册的broadcastReceive才会收到这个broadcast。
*/
}