试谈android中WIFI源码

试谈android中WIFI源码

网上关于如何用代码设置wifi的文章一搜一大堆,小蒋在此就不再添乱了,我就试着给大家谈一谈wifi的源码吧。

首先,我还是得从代码入手,下面是设置打开wifi的相关代码:

01private WifiManager mWifiManager;  
02 
03 
04public WifiAdmin(Context context){  
05    //取得WifiManager对象  
06    mWifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);  
07    //取得WifiInfo对象  
08    mWifiInfo=mWifiManager.getConnectionInfo();  
09}  
10//打开wifi  
11public void openWifi(){  
12    if(!mWifiManager.isWifiEnabled()){  
13        mWifiManager.setWifiEnabled(true);  
14    }  
15}
很简单的一个函数--setWifiEnabled(ture),那我们开始分析吧!

首先找到WifiManager.java(frameworks/base/wifi/java/android/net/wifi),里面有

01public class WifiManager {
02  
03    IWifiManager mService;
04  
05     /**
06     * Enable or disable Wi-Fi.
07     * @param enabled {@code true} to enable, {@code false} to disable.
08     * @return {@code true} if the operation succeeds (or if the existing state
09     *         is the same as the requested state).
10     */
11    public boolean setWifiEnabled(boolean enabled) {
12        try {
13            return mService.setWifiEnabled(enabled);
14        } catch (RemoteException e) {
15            return false;
16        }
17    }
18  
19}

IWifiManager也是什么东西呢?在frameworks/base/wifi/java/android/net/wifi里面你会发现一个叫做IWifiManager.aidl的文件

1interface IWifiManager
2{
3  
4    boolean setWifiEnabled(boolean enable);
5  
6    
7}

这是一个aidl文件,如果有不懂的请看我的其他文章,这个interface会在WifiService.java里面实现(frameworks/base/services/java/com/android/server)

01/**
02 * WifiService handles remote WiFi operation requests by implementing
03 * the IWifiManager interface. It also creates a WifiMonitor to listen
04 * for Wifi-related events.
05 *
06 * @hide
07 */
08public class WifiService extends IWifiManager.Stub {
09  
10   private final  WifiHandler mWifiHandler;
11   private Context mContext;
12   private static PowerManager.WakeLock sWakeLock;
13    /**
14     * see {@link android.net.wifi.WifiManager#setWifiEnabled(boolean)}
15     * @param enable {@code true} to enable, {@code false} to disable.
16     * @return {@code true} if the enable/disable operation was
17     *         started or is already in the queue.
18     */
19    public boolean setWifiEnabled(boolean enable) {
20        enforceChangePermission();
21        if (mWifiHandler == null) return false;
22  
23        synchronized (mWifiHandler) {
24            // caller may not have WAKE_LOCK permission - it's not required here
25            long ident = Binder.clearCallingIdentity();
26            sWakeLock.acquire();
27            Binder.restoreCallingIdentity(ident);
28  
29            mLastEnableUid = Binder.getCallingUid();
30            // set a flag if the user is enabling Wifi while in airplane mode
31            mAirplaneModeOverwridden = (enable && isAirplaneModeOn() && isAirplaneToggleable());
32            sendEnableMessage(enable, true, Binder.getCallingUid());
33        }
34  
35        return true;
36    }
37  
38    private void enforceChangePermission() {
39        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CHANGE_WIFI_STATE,
40                                                "WifiService");
41  
42    }
43     

enforceCallingOrSelfPermission(..,..)函数就是检查是否具有权限,若没有则抛出异常。Binder.clearCallingIdentity()和Binder.restoreCallingIdentity()这两个方法,它的主要作用是暂时获得系统权限,acquire函数就是申请一把锁,以后释放。后面的sendEnableMessage函数

1private void sendEnableMessage(boolean enable, boolean persist, int uid) {
2    Message msg = Message.obtain(mWifiHandler,
3                                 (enable ? MESSAGE_ENABLE_WIFI : MESSAGE_DISABLE_WIFI),
4                                 (persist ? 1 : 0), uid);
5    msg.sendToTarget();
6}
这个学android的人应该都知道是什么吧,看看handler
01/**
02   * Handler that allows posting to the WifiThread.
03   */
04  private class WifiHandler extends Handler {
05      public WifiHandler(Looper looper) {
06          super(looper);
07      }
08 
09      @Override
10      public void handleMessage(Message msg) {
11          switch (msg.what) {
12 
13              case MESSAGE_ENABLE_WIFI:
14                  setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);
15                  if (mWifiWatchdogService == null) {
16                      mWifiWatchdogService = new WifiWatchdogService(mContext, mWifiStateTracker);
17                  }
18                  sWakeLock.release();
19                  break;
20 
21          }
22      }
23  }

这里的msg.arg2就是uid,看下里面的setWifiEnabledBlocking函数,此代码段为代码段一

01/**
02 * Enables/disables Wi-Fi synchronously.
03 * @param enable {@code true} to turn Wi-Fi on, {@code false} to turn it off.
04 * @param persist {@code true} if the setting should be persisted.
05 * @param uid The UID of the process making the request.
06 * @return {@code true} if the operation succeeds (or if the existing state
07 *         is the same as the requested state)
08 */
09private boolean setWifiEnabledBlocking(boolean enable, boolean persist, int uid) {
10    final int eventualWifiState = enable ? WIFI_STATE_ENABLED : WIFI_STATE_DISABLED;
11    final int wifiState = mWifiStateTracker.getWifiState();
12 
13    if (wifiState == eventualWifiState) {
14        return true;
15    }
16    if (enable && isAirplaneModeOn() && !mAirplaneModeOverwridden) {
17        return false;
18    }
19 
20    /**
21     * Multiple calls to unregisterReceiver() cause exception and a system crash.
22     * This can happen if a supplicant is lost (or firmware crash occurs) and user indicates
23     * disable wifi at the same time.
24     * Avoid doing a disable when the current Wifi state is UNKNOWN
25     * TODO: Handle driver load fail and supplicant lost as seperate states
26     */
27    if ((wifiState == WIFI_STATE_UNKNOWN) && !enable) {
28        return false;
29    }
30 
31    /**
32     * Fail Wifi if AP is enabled
33     * TODO: Deprecate WIFI_STATE_UNKNOWN and rename it
34     * WIFI_STATE_FAILED
35     */
36    if ((mWifiApState == WIFI_AP_STATE_ENABLED) && enable) {
37        setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
38        return false;
39    }
40 
41    setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
42 
43    if (enable) {
44        if (!mWifiStateTracker.loadDriver()) {
45            Slog.e(TAG, "Failed to load Wi-Fi driver.");
46            setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
47            return false;
48        }
49        if (!mWifiStateTracker.startSupplicant()) {
50            mWifiStateTracker.unloadDriver();
51            Slog.e(TAG, "Failed to start supplicant daemon.");
52            setWifiEnabledState(WIFI_STATE_UNKNOWN, uid);
53            return false;
54        }
55 
56        registerForBroadcasts();
57        mWifiStateTracker.startEventLoop();
58 
59    }
60}
关键的就是从WifiStateTracker的loadDriver和startSupplicant开始(frameworks/base/wifi/java/android/net/wifi)
1public synchronized boolean loadDriver() {
2    return WifiNative.loadDriver();
3}
1public synchronized boolean startSupplicant() {
2    return WifiNative.startSupplicant();
3}

这调用了WifiNative的loadDriver与startSupplicant函数,注意,所有的WifiNative中的调用都需要发生在WifiStateTracker类中,除了waitForEvent()

1public class WifiNative {
2  
3    public native static boolean loadDriver();
4    public native static boolean startSupplicant();
5  
6}

这个native里面的调用是为了发送请求到supplicant daemon以及从获取异步事件。这个loadDriver实际上是通过JNI去实现的,实现于android_net_wifi_WIFI.cpp(frameworks/base/core/jni)
1static jboolean android_net_wifi_loadDriver(JNIEnv* env, jobject clazz)
2{
3    return (jboolean)(::wifi_load_driver() == 0);
4}
5static jboolean android_net_wifi_startSupplicant(JNIEnv* env, jobject clazz)
6{
7    return (jboolean)(::wifi_start_supplicant() == 0);
8}
而这两个系统级的函数实现于wifi.c(hardware/libhardware_legacy)
01int wifi_load_driver()
02{
03    char driver_status[PROPERTY_VALUE_MAX];
04    int count = 100; /* wait at most 20 seconds for completion */
05  
06    if (check_driver_loaded()) {
07        return 0;
08    }
09  
10    if (insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
11        return -1;
12  
13    if (strcmp(FIRMWARE_LOADER,"") == 0) {
14        usleep(WIFI_DRIVER_LOADER_DELAY);
15        property_set(DRIVER_PROP_NAME, "ok");
16    }
17    else {
18        property_set("ctl.start", FIRMWARE_LOADER);
19    }
20    sched_yield();
21    while (count-- > 0) {
22        if (property_get(DRIVER_PROP_NAME, driver_status, NULL)) {
23            if (strcmp(driver_status, "ok") == 0)
24                return 0;
25            else if (strcmp(DRIVER_PROP_NAME, "failed") == 0) {
26                wifi_unload_driver();
27                return -1;
28            }
29        }
30        usleep(200000);
31    }
32    property_set(DRIVER_PROP_NAME, "timeout");
33    wifi_unload_driver();
34    return -1;
35}
36  
37int wifi_unload_driver()
38{
39    int count = 20; /* wait at most 10 seconds for completion */
40  
41    if (rmmod(DRIVER_MODULE_NAME) == 0) {
42    while (count-- > 0) {
43        if (!check_driver_loaded())
44        break;
45            usleep(500000);
46    }
47    if (count) {
48            return 0;
49    }
50    return -1;
51    } else
52        return -1;
53}

这些都是驱动相关的信息,下面的是startSupplicant函数的实现

01int wifi_start_supplicant()
02{
03    char supp_status[PROPERTY_VALUE_MAX] = {'\0'};
04    int count = 200; /* wait at most 20 seconds for completion */
05#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
06    const prop_info *pi;
07    unsigned serial = 0;
08#endif
09  
10    /* Check whether already running */
11    if (property_get(SUPP_PROP_NAME, supp_status, NULL)
12            && strcmp(supp_status, "running") == 0) {
13        return 0;
14    }
15  
16    /* Before starting the daemon, make sure its config file exists */
17    if (ensure_config_file_exists() < 0) {
18        LOGE("Wi-Fi will not be enabled");
19        return -1;
20    }
21  
22    /* Clear out any stale socket files that might be left over. */
23    wpa_ctrl_cleanup();
24  
25#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
26    /*
27     * Get a reference to the status property, so we can distinguish
28     * the case where it goes stopped => running => stopped (i.e.,
29     * it start up, but fails right away) from the case in which
30     * it starts in the stopped state and never manages to start
31     * running at all.
32     */
33    pi = __system_property_find(SUPP_PROP_NAME);
34    if (pi != NULL) {
35        serial = pi->serial;
36    }
37#endif
38    property_set("ctl.start", SUPPLICANT_NAME);
39    sched_yield();
40  
41    while (count-- > 0) {
42#ifdef HAVE_LIBC_SYSTEM_PROPERTIES
43        if (pi == NULL) {
44            pi = __system_property_find(SUPP_PROP_NAME);
45        }
46        if (pi != NULL) {
47            __system_property_read(pi, NULL, supp_status);
48            if (strcmp(supp_status, "running") == 0) {
49                return 0;
50            } else if (pi->serial != serial &&
51                    strcmp(supp_status, "stopped") == 0) {
52                return -1;
53            }
54        }
55#else
56        if (property_get(SUPP_PROP_NAME, supp_status, NULL)) {
57            if (strcmp(supp_status, "running") == 0)
58                return 0;
59        }
60#endif
61        usleep(100000);
62    }
63    return -1;
64}

这段代码是属于启动supplicant服务。

现在继续回到代码段一,往下走是setWifiEnabledState函数,此处为代码段二!

01private void setWifiEnabledState(int wifiState, int uid) {
02    final int previousWifiState = mWifiStateTracker.getWifiState();
03 
04    long ident = Binder.clearCallingIdentity();
05    try {
06        if (wifiState == WIFI_STATE_ENABLED) {
07            mBatteryStats.noteWifiOn();
08        } else if (wifiState == WIFI_STATE_DISABLED) {
09            mBatteryStats.noteWifiOff();
10        }
11    } catch (RemoteException e) {
12    } finally {
13        Binder.restoreCallingIdentity(ident);
14    }
15 
16    // Update state
17    mWifiStateTracker.setWifiState(wifiState);
18 
19    // Broadcast
20    final Intent intent = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
21    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
22    intent.putExtra(WifiManager.EXTRA_WIFI_STATE, wifiState);
23    intent.putExtra(WifiManager.EXTRA_PREVIOUS_WIFI_STATE, previousWifiState);
24    mContext.sendStickyBroadcast(intent);
25}
try那一块的功能就是在获得系统权限后根据wifi状态更改,同样是通过stub,BatteryStatsService.java里面实现(frameworks/base/services/java/com/android/server/am)
01public final class BatteryStatsService extends IBatteryStats.Stub {
02  
03  
04    final BatteryStatsImpl mStats;
05  
06  
07    public void noteWifiOn() {
08        enforceCallingPermission();
09        synchronized (mStats) {
10            mStats.noteWifiOnLocked();
11        }
12    }
13  
14  
15}

查找BatteryStateImpl.java(freameworks/base/core/java/com/android/internal/os)

01public void noteWifiOnLocked() {
02    if (!mWifiOn) {
03        mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
04        if (DEBUG_HISTORY) Slog.v(TAG, "WIFI on to: "
05                + Integer.toHexString(mHistoryCur.states));
06        addHistoryRecordLocked(SystemClock.elapsedRealtime());
07        mWifiOn = true;
08        mWifiOnTimer.startRunningLocked(this);
09    }
10}
其中的mWifiOnTimer是个StopwatchTimer类型的对象,mWifiOn只是一个boolean类型。再看看代码段二
1public void setWifiState(int wifiState) {
2    mWifiState.set(wifiState);
3}
而mWifistated的声明为
01/**
02 * One of  {@link WifiManager#WIFI_STATE_DISABLED},
03 *         {@link WifiManager#WIFI_STATE_DISABLING},
04 *         {@link WifiManager#WIFI_STATE_ENABLED},
05 *         {@link WifiManager#WIFI_STATE_ENABLING},
06 *         {@link WifiManager#WIFI_STATE_UNKNOWN}
07 *
08 * getWifiState() is not synchronized to make sure it's always fast,
09 * even when the instance lock is held on other slow operations.
10 * Use a atomic variable for state.
11 */
12private final AtomicInteger mWifiState = new AtomicInteger(WIFI_STATE_UNKNOWN);

AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。再接着看代码段二,就是讲wifi事件广播出去,通知监听此事件的事务。然而在wifisettings.java(packages/apps/settings/src/com/android/settings/wifi)里面会监听到此事件。

1private void handleEvent(Intent intent) {
2    String action = intent.getAction();
3    if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
4        updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
5                WifiManager.WIFI_STATE_UNKNOWN));
6    } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
7        updateAccessPoints();
8    }
9}
监听到进行updateWifiState处理, 此处为代码段三!
1private void updateWifiState(int state) {
2    if (state == WifiManager.WIFI_STATE_ENABLED) {
3        mScanner.resume();
4        updateAccessPoints();
5    } else {
6        mScanner.pause();
7        mAccessPoints.removeAll();
8    }
9}
由于先前传入的就是WIFI_STATE_ENABLED,所以进行resume与updateAccessPoints函数处理。先看下Scanner吧
01private class Scanner extends Handler {
02    private int mRetry = 0;
03 
04    void resume() {
05        if (!hasMessages(0)) {
06            sendEmptyMessage(0);
07        }
08    }
09 
10    void pause() {
11        mRetry = 0;
12        mAccessPoints.setProgress(false);
13        removeMessages(0);
14    }
15 
16    @Override
17    public void handleMessage(Message message) {
18        if (mWifiManager.startScanActive()) {
19            mRetry = 0;
20        } else if (++mRetry >= 3) {
21            mRetry = 0;
22            Toast.makeText(WifiSettings.this, R.string.wifi_fail_to_scan,
23                    Toast.LENGTH_LONG).show();
24            return;
25        }
26        mAccessPoints.setProgress(mRetry != 0);
27        sendEmptyMessageDelayed(0, 6000);
28    }
startScanActive他会调用wifiManager.java里面的startScanActive函数
1public boolean startScanActive() {
2    try {
3        mService.startScan(true);
4        return true;
5    } catch (RemoteException e) {
6        return false;
7    }
8}
接着会调用wifiService.java里面的startScan函数
1public void startScan(boolean forceActive) {
2      enforceChangePermission();
3      if (mWifiHandler == null) return;
4 
5      Message.obtain(mWifiHandler, MESSAGE_START_SCAN, forceActive ? 1 : 0, 0).sendToTarget();
6  }

发送消息到wifiHandler,那么看下对应的响应,此处为代码段四!

01case MESSAGE_START_SCAN:
02    boolean forceActive = (msg.arg1 == 1);
03    switch (mWifiStateTracker.getSupplicantState()) {
04        case DISCONNECTED:
05        case INACTIVE:
06        case SCANNING:
07        case DORMANT:
08            break;
09        default:
10            mWifiStateTracker.setScanResultHandling(
11                    WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);
12            break;
13    }
14    mWifiStateTracker.scan(forceActive);
15    break;
首选根据supplicant的状态来执行不同的方法
1public SupplicantState getSupplicantState() {
2    return mWifiInfo.getSupplicantState();
3}
从wifiInfo中获取supplicantState
1public SupplicantState getSupplicantState() {
2    return mSupplicantState;
3}

这个返回的是supplicantState与AP协商后的详细状态。(Return the detailed state of the supplicant's negotiation with an access point)。接着看代码段四,下面遇到两个函数

01public synchronized boolean scan(boolean forceActive) {
02    if (mWifiState.get() != WIFI_STATE_ENABLED || isDriverStopped()) {
03        return false;
04    }
05    return WifiNative.scanCommand(forceActive);
06}
07 
08/**
09 * Specifies whether the supplicant or driver
10 * take care of initiating scan and doing AP selection
11 *
12 * @param mode
13 *    SUPPL_SCAN_HANDLING_NORMAL
14 *    SUPPL_SCAN_HANDLING_LIST_ONLY
15 * @return {@code true} if the operation succeeds, {@code false} otherwise
16 */
17public synchronized boolean setScanResultHandling(int mode) {
18    if (mWifiState.get() != WIFI_STATE_ENABLED) {
19        return false;
20    }
21    return WifiNative.setScanResultHandlingCommand(mode);
22}
这个又遇到wifiNative,于是又要运用JNI去调用底层代码,在android_net_wifi_WIFI.cpp里面       
01static jboolean android_net_wifi_scanCommand(JNIEnv* env, jobject clazz, jboolean forceActive)
02{
03    jboolean result;
04  
05    // Ignore any error from setting the scan mode.
06    // The scan will still work.
07    if (forceActive && !sScanModeActive)
08        doSetScanMode(true);
09    result = doBooleanCommand("SCAN", "OK");
10    if (forceActive && !sScanModeActive)
11        doSetScanMode(sScanModeActive);
12    return result;
13}
这里面的doSetScanMode其实也是调用的doBooleanCommand
1static jboolean doSetScanMode(jboolean setActive)
2{
3    return doBooleanCommand((setActive ? "DRIVER SCAN-ACTIVE" : "DRIVER SCAN-PASSIVE"), "OK");
4}
那么doBooleanCommand是什么呢
01static jboolean doBooleanCommand(const char *cmd, const char *expect)
02{
03    char reply[256];
04  
05    if (doCommand(cmd, reply, sizeof(reply)) != 0) {
06        return (jboolean)JNI_FALSE;
07    } else {
08        return (jboolean)(strcmp(reply, expect) == 0);
09    }
10}
11  
12static int doCommand(const char *cmd, char *replybuf, int replybuflen)
13{
14    size_t reply_len = replybuflen - 1;
15  
16    if (::wifi_command(cmd, replybuf, &reply_len) != 0)
17        return -1;
18    else {
19        // Strip off trailing newline
20        if (reply_len > 0 && replybuf[reply_len-1] == '\n')
21            replybuf[reply_len-1] = '\0';
22        else
23            replybuf[reply_len] = '\0';
24        return 0;
25    }
26}
而wifi_command在wifi.c中实现
1int wifi_command(const char *command, char *reply, size_t *reply_len)
2{
3    return wifi_send_command(ctrl_conn, command, reply, reply_len);
4}

接下来看看wifi_send_command函数,在wifi.c里面

01int wifi_send_command(struct wpa_ctrl *ctrl, const char *cmd, char *reply, size_t *reply_len)
02{
03    int ret;
04  
05    if (ctrl_conn == NULL) {
06        LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
07        return -1;
08    }
09    ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
10    if (ret == -2) {
11        LOGD("'%s' command timed out.\n", cmd);
12        return -2;
13    } else if (ret < 0 || strncmp(reply, "FAIL", 4) == 0) {
14        return -1;
15    }
16    if (strncmp(cmd, "PING", 4) == 0) {
17        reply[*reply_len] = '\0';
18    }
19    return 0;
20}
这里面有个struct,很重要
01struct wpa_ctrl {
02#ifdef CONFIG_CTRL_IFACE_UDP
03    int s;
04    struct sockaddr_in local;
05    struct sockaddr_in dest;
06    char *cookie;
07#endif /* CONFIG_CTRL_IFACE_UDP */
08#ifdef CONFIG_CTRL_IFACE_UNIX
09    int s;
10    struct sockaddr_un local;
11    struct sockaddr_un dest;
12#endif /* CONFIG_CTRL_IFACE_UNIX */
13#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
14    HANDLE pipe;
15#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
16};
这个类中声明了两个Socket套接口,一个是本地一个是要连接的套接 口,wpa_ctrl与wpa_supplicant的通信就需要socket来帮忙了,而wpa_supplicant就是通过调用 wpa_ctrl.h中定义的函数和wpa_supplicant进行通讯的,wpa_ctrl类(其实是其中的两个socket)就是他们之间的桥梁。

wpa_ctrl_request,这个函数存放在wpa_ctrl.c(external/wpa_supplicant)

01int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
02             char *reply, size_t *reply_len,
03             void (*msg_cb)(char *msg, size_t len))
04{
05    struct timeval tv;
06    int res;
07    fd_set rfds;
08    const char *_cmd;
09    char *cmd_buf = NULL;
10    size_t _cmd_len;
11  
12#ifdef CONFIG_CTRL_IFACE_UDP
13    if (ctrl->cookie) {
14        char *pos;
15        _cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
16        cmd_buf = os_malloc(_cmd_len );
17        if (cmd_buf == NULL)
18            return -1;
19        _cmd = cmd_buf;
20        pos = cmd_buf;
21        strcpy(pos, ctrl->cookie);
22        pos += strlen(ctrl->cookie);
23        *pos++ = ' ';
24        memcpy(pos, cmd, cmd_len);
25    } else
26#endif /* CONFIG_CTRL_IFACE_UDP */
27    {
28        _cmd = cmd;
29        _cmd_len = cmd_len;
30    }
31  
32    if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
33        os_free(cmd_buf);
34        return -1;
35    }
36    os_free(cmd_buf);
37  
38    for (;;) {
39#ifdef ANDROID
40        tv.tv_sec = 10;
41#else
42        tv.tv_sec = 2;
43#endif
44        tv.tv_usec = 0;
45        FD_ZERO(&rfds);
46        FD_SET(ctrl->s, &rfds);
47        res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
48        if (FD_ISSET(ctrl->s, &rfds)) {
49            res = recv(ctrl->s, reply, *reply_len, 0);
50            if (res < 0)
51                return res;
52            if (res > 0 && reply[0] == '<') {
53                /* This is an unsolicited message from
54                 * wpa_supplicant, not the reply to the
55                 * request. Use msg_cb to report this to the
56                 * caller. */
57                if (msg_cb) {
58                    /* Make sure the message is nul
59                     * terminated. */
60                    if ((size_t) res == *reply_len)
61                        res = (*reply_len) - 1;
62                    reply[res] = '\0';
63                    msg_cb(reply, res);
64                }
65                continue;
66            }
67            *reply_len = res;
68            break;
69        } else {
70            return -2;
71        }
72    }
73    return 0;
74}
This function is used to send commands to wpa_supplicant/hostapd. Received response will be written to reply and reply_len is set to the actual length of the reply. This function will block for up to two seconds while waiting for the reply. If unsolicited messages are received, the blocking time may be longer.

现在回到代码段三,后面有个update函数

01private void updateAccessPoints() {
02    List<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
03 
04    List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
05    if (configs != null) {
06        mLastPriority = 0;
07        for (WifiConfiguration config : configs) {
08            if (config.priority > mLastPriority) {
09                mLastPriority = config.priority;
10            }
11 
12            // Shift the status to make enableNetworks() more efficient.
13            if (config.status == Status.CURRENT) {
14                config.status = Status.ENABLED;
15            } else if (mResetNetworks && config.status == Status.DISABLED) {
16                config.status = Status.CURRENT;
17            }
18 
19            AccessPoint accessPoint = new AccessPoint(this, config);
20            accessPoint.update(mLastInfo, mLastState);
21            accessPoints.add(accessPoint);
22        }
23    }
24 
25    List<ScanResult> results = mWifiManager.getScanResults();
26    if (results != null) {
27        for (ScanResult result : results) {
28            // Ignore hidden and ad-hoc networks.
29            if (result.SSID == null || result.SSID.length() == 0 ||
30                    result.capabilities.contains("[IBSS]")) {
31                continue;
32            }
33 
34            boolean found = false;
35            for (AccessPoint accessPoint : accessPoints) {
36                if (accessPoint.update(result)) {
37                    found = true;
38                }
39            }
40            if (!found) {
41                accessPoints.add(new AccessPoint(this, result));
42            }
43        }
44    }
45 
46    mAccessPoints.removeAll();
47    for (AccessPoint accessPoint : accessPoints) {
48        mAccessPoints.addPreference(accessPoint);
49    }
50}
这个就是更新AP并通过GUI的形式列出来。  

引用自:http://my.oschina.net/JumpLong/blog/101147
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值