基于rk3288平台android5.1系统的wifi流程分析 ---- 打开wifi,扫描热点

这里从安卓应用层开始着手分析:

// -------------- 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
回到上面的函数调用:
mWifiMonitor.startMonitoring();
其中mWifiMonitor是在WifiStateMachine类中的构造函数中定义的:
mWifiMonitor = new WifiMonitor(this, mWifiNative);

来看看WifiMonitor类:

// --------- 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:
m.mStateMachine.sendMessage(SUP_CONNECTION_EVENT);

同时状态切换到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。
     */
}



















你可能感兴趣的:(android)