试谈android中WIFI源码

本文深入剖析Android系统中WiFi模块的源代码,从简单的setWifiEnabled方法入手,逐步揭示其内部实现机制,包括WifiManager类的具体作用及关键组件如WifiStateTracker的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >






              

    试谈android中WIFI源码

    原码下载:http://yxwojia.lingw.net/article-6510203-1.html
    发表于2年前(2013-01-09 20:52)   阅读( 4072) | 评论( 119人收藏此文章,我要收藏
    赞1

    慕课网,程序员升职加薪神器,点击免费学习


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

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    private WifiManager mWifiManager; 
     
     
    public WifiAdmin(Context context){ 
        //取得WifiManager对象 
        mWifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE); 
        //取得WifiInfo对象 
        mWifiInfo=mWifiManager.getConnectionInfo(); 
    //打开wifi 
    public void openWifi(){ 
        if(!mWifiManager.isWifiEnabled()){ 
            mWifiManager.setWifiEnabled(true); 
        
    很简单的一个函数--setWifiEnabled(ture),那我们开始分析吧!

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class WifiManager {
     
        IWifiManager mService;
     
        /**
         * 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;
            }
        }
     
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public void noteWifiOnLocked() {
        if (!mWifiOn) {
            mHistoryCur.states |= HistoryItem.STATE_WIFI_ON_FLAG;
            if (DEBUG_HISTORY) Slog.v(TAG,"WIFI on to: "
                    + Integer.toHexString(mHistoryCur.states));
            addHistoryRecordLocked(SystemClock.elapsedRealtime());
            mWifiOn = true;
            mWifiOnTimer.startRunningLocked(this);
        }
    }
    其中的mWifiOnTimer是个StopwatchTimer类型的对象,mWifiOn只是一个boolean类型。再看看代码段二
    ?
    1
    2
    3
    public void setWifiState(int wifiState) {
        mWifiState.set(wifiState);
    }
    而mWifistated的声明为
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
     * One of  {@link WifiManager#WIFI_STATE_DISABLED},
     *         {@link WifiManager#WIFI_STATE_DISABLING},
     *         {@link WifiManager#WIFI_STATE_ENABLED},
     *         {@link WifiManager#WIFI_STATE_ENABLING},
     *         {@link WifiManager#WIFI_STATE_UNKNOWN}
     *
     * getWifiState() is not synchronized to make sure it's always fast,
     * even when the instance lock is held on other slow operations.
     * Use a atomic variable for state.
     */
    private 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)里面会监听到此事件。

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

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    case MESSAGE_START_SCAN:
        boolean forceActive = (msg.arg1 ==1);
        switch (mWifiStateTracker.getSupplicantState()) {
            case DISCONNECTED:
            case INACTIVE:
            case SCANNING:
            case DORMANT:
                break;
            default:
                mWifiStateTracker.setScanResultHandling(
                        WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY);
                break;
        }
        mWifiStateTracker.scan(forceActive);
        break;
    首选根据supplicant的状态来执行不同的方法
    ?
    1
    2
    3
    public SupplicantState getSupplicantState() {
        return mWifiInfo.getSupplicantState();
    }
    从wifiInfo中获取supplicantState
    ?
    1
    2
    3
    public SupplicantState getSupplicantState() {
        return mSupplicantState;
    }

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

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

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

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    int wifi_send_command(struct wpa_ctrl *ctrl,const char *cmd,char *reply,size_t *reply_len)
    {
        int ret;
     
        if (ctrl_conn == NULL) {
            LOGV("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
            return -1;
        }
        ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), reply, reply_len, NULL);
        if (ret == -2) {
            LOGD("'%s' command timed out.\n", cmd);
            return -2;
        }else if (ret < 0 ||strncmp(reply,"FAIL", 4) == 0) {
            return -1;
        }
        if (strncmp(cmd,"PING", 4) == 0) {
            reply[*reply_len] = '\0';
        }
        return 0;
    }
    这里面有个struct,很重要
    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    struct wpa_ctrl {
    #ifdef CONFIG_CTRL_IFACE_UDP
        int s;
        struct sockaddr_in local;
        struct sockaddr_in dest;
        char *cookie;
    #endif /* CONFIG_CTRL_IFACE_UDP */
    #ifdef CONFIG_CTRL_IFACE_UNIX
        int s;
        struct sockaddr_un local;
        struct sockaddr_un dest;
    #endif /* CONFIG_CTRL_IFACE_UNIX */
    #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
        HANDLE pipe;
    #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
    };
    这个类中声明了两个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)

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    int wpa_ctrl_request(struct wpa_ctrl *ctrl,const char *cmd,size_t cmd_len,
                 char *reply,size_t *reply_len,
                 void (*msg_cb)(char *msg,size_t len))
    {
        struct timeval tv;
        int res;
        fd_set rfds;
        const char *_cmd;
        char *cmd_buf = NULL;
        size_t _cmd_len;
     
    #ifdef CONFIG_CTRL_IFACE_UDP
        if (ctrl->cookie) {
            char *pos;
            _cmd_len = strlen(ctrl->cookie) + 1 + cmd_len;
            cmd_buf = os_malloc(_cmd_len );
            if (cmd_buf == NULL)
                return -1;
            _cmd = cmd_buf;
            pos = cmd_buf;
            strcpy(pos, ctrl->cookie);
            pos += strlen(ctrl->cookie);
            *pos++ = ' ';
            memcpy(pos, cmd, cmd_len);
        }else
    #endif /* CONFIG_CTRL_IFACE_UDP */
        {
            _cmd = cmd;
            _cmd_len = cmd_len;
        }
     
        if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
            os_free(cmd_buf);
            return -1;
        }
        os_free(cmd_buf);
     
        for (;;) {
    #ifdef ANDROID
            tv.tv_sec = 10;
    #else
            tv.tv_sec = 2;
    #endif
            tv.tv_usec = 0;
            FD_ZERO(&rfds);
            FD_SET(ctrl->s, &rfds);
            res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
            if (FD_ISSET(ctrl->s, &rfds)) {
                res = recv(ctrl->s, reply, *reply_len, 0);
                if (res < 0)
                    return res;
                if (res > 0 && reply[0] =='<') {
                    /* This is an unsolicited message from
                     * wpa_supplicant, not the reply to the
                     * request. Use msg_cb to report this to the
                     * caller. */
                    if (msg_cb) {
                        /* Make sure the message is nul
                         * terminated. */
                        if ((size_t) res == *reply_len)
                            res = (*reply_len) - 1;
                        reply[res] = '\0';
                        msg_cb(reply, res);
                    }
                    continue;
                }
                *reply_len = res;
                break;
            }else {
                return -2;
            }
        }
        return 0;
    }
    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函数

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



    源码下载:http://yxwojia.lingw.net/article-6510203-1.html







                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

      评论
      添加红包

      请填写红包祝福语或标题

      红包个数最小为10个

      红包金额最低5元

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

      抵扣说明:

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

      余额充值