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

// -------------- packages/apps/settings/src/com/android/settings/wifi/WifiSettings.java -------------- //private WifiEnabler mWifiEnabler;// 以下为WifiSettings界面处在Active的状态下创建的!!@Overridepublic 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。     */}



















更多相关文章

  1. GitHub 标星 2.5K+!教你通过玩游戏的方式学习 VIM!
  2. 如何在后台运行Linux命令?
  3. No.11 使用firewall配置的防火墙策略的生效模式
  4. Android之Handler的post注意事项
  5. Examples_06_02(android)DDMS的data文件中没有显示文件。
  6. 笔记之Android(安卓)Bluetooth OOP 传送文件流程小记
  7. adb devices ???????????? no permission
  8. Android源码编译开启ccache缓存
  9. Android中TextClock中的一个abc函数

随机推荐

  1. Umeng推送消息的坑,Android Service的andr
  2. 你到底懂Android吗?了解多少?
  3. Android仿人人客户端(v5.7.1)——项目框架
  4. Android(安卓)使用Intent传递数据的实现
  5. 基于NanoHttpd的Android视频服务器开发
  6. Android 获取android密钥哈希码(keytool -
  7. 苹果悄悄进入企业级市场,iOS起飞,Android折
  8. repo 和 git 管理源代码
  9. Android带进度条的下载图片示例(AsyncTask
  10. android不将apk包编译到系统里的方法