现在的位置: 首页 > 综合 > 正文

跟一下wpa_supplicant(2) wifi enable

2012年04月10日 ⁄ 综合 ⁄ 共 10753字 ⁄ 字号 评论关闭
1.  收到MESSAGE_ENABLE_WIFI

setWifiEnabledBlocking(wifiService.java)

  => mWifiStateTracker.loadDriver

  => mWifiStateTracker.startSupplicant() 

     ==> WifiNative.startSupplicant (WifiNative.java)

         ===> android_net_wifi_startSupplicant(android_net_wifi_Wifi.cpp JNI)

              ====> wifi_start_supplicant (wifi.c hardware wifi lib)

             就是去启动wpa_supplicant 命令行 

  => mWifiStateTracker.startEventLoop(); (WifiStateTracker.java)

     ==> mWifiMonitor.startMonitoring();

         Monitoring thread 中:

  ===>connectToSupplicant() 判断是否连上,该函数还打开两个wpa_cli的控制

    1. ctrl_conn ,用于JNI 通过wpa_cli往下发命令

    2. monitor_conn 在wifi_wait_for_event (call by JNI 

                           android_net_wifi_waitForEvent)

             接收event ,java 层就是通过call 该JNI 来获得wpa的event

             一来一去都有了,java 和 wpa 通讯建立成功

        ===>连接成功后,发消息 EVENT_SUPPLICANT_CONNECTION

     mWifiStateTracker.notifySupplicantConnection();

              接收处理 EVENT_SUPPLICANT_CONNECTION 部分见下面分支 4.

            接下来进入循环接收event

     String eventStr = WifiNative.waitForEvent();

             /* 就是监听上面connectToSupplicant 中的monitor_conn */

      然后将event string 转换成int,然后

      handleEvent(event, eventData);

      主要有下面event:

               event =CONNECTED;

               event = DISCONNECTED;

               event = STATE_CHANGE;

               event = SCAN_RESULTS;

               event = LINK_SPEED;

               event = TERMINATING;

               event = DRIVER_STATE;

               event = DRIVER_STATE

        event = LINK_SPEED 等等
     

  => setWifiEnabledState(eventualWifiState, uid);(wifiService.java)

     eventualWifiState 为 WIFI_STATE_ENABLED

     ==> mWifiStateTracker.setWifiState(WIFI_STATE_ENABLED);

         boardcast WIFI_STATE_CHANGED_ACTION  + WIFI_STATE_ENABLED

  处理接收该wifi 状态广播的分支见 3.


2. settings\wifi\WifiEnabler.java

   => class WifiEnabler

      BroadcastReceiver mReceiver = new BroadcastReceiver()

      if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {

         handleWifiStateChanged(intent.getIntExtra(

             WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_UNKNOWN));

    这部分就是处理wifi enable check  界面的 disable,和 打上勾的处理
 
3.packages\apps\Settings\src\com\android\settings\wifi\WifiSettings.java

  接收处理前面1.最后提到的

  boardcast WIFI_STATE_CHANGED_ACTION  + WIFI_STATE_ENABLED

  直接看代码:

  => 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));

         由 WIFI_STATE_ENABLED 走到下面

  ===> mScanner.resume(); ( sendEmptyMessage(0);)

       ====> handleMessage

             =====> mWifiManager.startScanActive() (wifiManager.java)

             ======> mService.startScan(true);

              MESSAGE_START_SCAN

       通过下面函数发出:

                   Message.obtain(mWifiHandler, MESSAGE_START_SCAN, 

                                     forceActive ? 1 : 0, 0).sendToTarget();

         ===> updateAccessPoints();  读conf network 配置,并设置到 java层的AP类
接收处理MESSAGE_START_SCAN的在 wifiService.java

    handleMessage(MESSAGE_START_SCAN)

      => mWifiStateTracker.scan(forceActive);  然后到下面的分支7.!!!

     

ESSAGE_START_SCAN 另外一条路是

   wifiService.java: updateWifiState 

         -> MESSAGE_UPDATE_STATE 

      -> doUpdateWifiState

          ->  sendStartMessage(MESSAGE_START_SCAN)

具体不展开了
 
4. 前面分支2.中 EVENT_SUPPLICANT_CONNECTION

     消息被WifiStateTracker处理

=> handleMessage(EVENT_SUPPLICANT_CONNECTION)

     ==> checkUseStaticIp 检测是否是static ip 连接
     ==> 发Intend :

         Intent(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);

       change 的内容为 EXTRA_SUPPLICANT_CONNECTED

     

     ==> dhcpThread.start(); 启动dhcp thread 并block 住,等待AP连上,在继续运行

     ==> 判断 complete 并 得到接入点的BSSID(MAC addr) 通过 GetBSSID()

                                     AP custom name   通过 GetSSID()

     ==> initializeMulticastFiltering (wifiService.java) 

         ===> startPacketFiltering ->JNI 可看到debug message :

  D/wpa_supplicant( 1468): nl80211_priv_driver_cmd RXFILTER-ADD 0 len = 4096

  D/wpa_supplicant( 1468): nl80211_priv_driver_cmd RXFILTER-ADD 1 len = 4096

  D/wpa_supplicant( 1468): nl80211_priv_driver_cmd RXFILTER-ADD 3 len = 4096

  D/wpa_supplicant( 1468): nl80211_priv_driver_cmd RXFILTER-START len = 4096

     ==> setBluetoothScanMode 

         ===> setBluetoothCoexistenceModeCommand 

     ==> setNumAllowedChannels 

     /*  Set the number of radio frequency channels that are allowed 

         to be used in the current regulatory domain */

      如果你有什么想法,就去动动Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS参数


5. WPA_SUPPLICANT 部分开始蠢蠢欲动了:

   可以看到这样的debug message:

       RTM_NEWLINK: operstate=0 ifi_flags=0x1043 ([UP][RUNNING])

 =>wpa_driver_nl80211_event_rtm_newlink 被event 驱动,看代码:

   /* 如果上次 disable 本次enable 发这个event! */

   if (drv->if_disabled && (ifi->ifi_flags & IFF_UP)) {

   ==> wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_ENABLED, NULL); 

   ==> wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);

       ==> wpa_supplicant_req_scan(wpa_s, 0, 0);

      if_disabled 不满足所以没走到这里,所以发起scan 不在这里开始的.小插曲
6. 同时可以看到这样的消息 :Event 5 received on interface wlan0

   在下面函数打出

   => wpa_driver_nl80211_event_link ==> 

      ==> wpa_supplicant_event(drv->ctx, EVENT_INTERFACE_STATUS, &event);

               event =EVENT_INTERFACE_ADDED

           ===> wpa_supplicant_event_interface_status

                if (!wpa_s->interface_removed)

   break; 什么也没做      

   (new link 部分处理没有启动scan,还是由java部分启动的,就是前面3.分支中的)
    mWifiStateTracker.scan


7. 前面3.分支最后 开始mWifiStateTracker.scan(forceActive)

 到WifiStateTracker.java,找到全名如下:

=> public synchronized boolean scan(boolean forceActive)

   ==> WifiNative.scanCommand 

       ===> doSetScanMode(true); 

         从debug message (Unsupported command: SCAN-ACTIVE) 看来

 主动扫描不支持???

                    

 ===> doBooleanCommand("SCAN", "OK");

      ====> doCommand 

                   =====> wifi_command(wifi.c)

                  执行到(wpa_supplicant中的ctrl_iface.c)代码如下:

                  else if (os_strcmp(buf, "SCAN") == 0) 

         ======> wpa_supplicant_req_scan(wpa_s, 0, 0);

                 马上调度一个 scan => 

           eloop_register_timeout(sec, usec, 

         wpa_supplicant_scan, wpa_s, NULL);

         接下来到分支8.就在下面

                         

8.

 下面是eloop 部分,因为前面分支7.中eloop timeout 为0,

马上执行下面部分:

=> wpa_supplicant_scan:

   ==> wpa_supplicant_set_state(wpa_s, WPA_SCANNING); 

    从 debugmsage: State: INACTIVE -> SCANNING可以看出从inactive 进入scanning

    该函数会调用wpas_notify_state_changed,往下又调用了wpas_notify_state_changed

    然后再到 wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE

    最后到 wpa_msg_cb,一函数指针,指向那个函数呢,请望下看:

    wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);  

    该函数 msg debug call back func 通过前面monitor_conn,发给java的 WifiMonior

    如果有时看到WifiMonitor的消息:

    Event [CTRL-EVENT-STATE-CHANGE id=-1 state=2 BSSID=00:00:00:00:00:00]

    就是这么一层一层然后发出来的
  ==> wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard SSID");

  ==> wpa_supplicant_extra_ies 

      ===> wps_build_probe_req_ie

          关联参数到 request probe ie (构建一个主动探测IE 的帧)

     上面说的Unsupported command: SCAN-ACTIVE,和这里描述矛盾吗?

      ===> params->extra_ies = wpabuf_head(wps_ie);

      ===> params->extra_ies_len = wpabuf_len(wps_ie);

  ==> params.freqs = wpa_s->next_scan_freqs;  设置scan channel 到 params

  ==> wpa_supplicant_build_filter_ssids 设置过滤的ap到params
  ==> wpa_supplicant_trigger_scan(params)终于到了真正的带参数扫描了!

       ===> wpa_drv_scan(wpa_s, params);  具体到nl80211 driver的

           wpa_driver_nl80211_scan,终于潜到wpa_supplicant 的最底了

           ====> 在wpa_driver_nl80211_scan 最后有如下调用:

          =====> eloop_register_timeout(timeout, 0, 

         wpa_driver_nl80211_scan_timeout,drv, drv->ctx);

接下来干什么,网撒出去了,该等着收网的时候了

10秒后timeout ,应该不会等到timeout 时间到,wifi compat driver

就会发event 来通知 scan result,eloop call back下面函数

=> wpa_driver_nl80211_scan_timeout:

   ==> wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);

       其中代码:

       case EVENT_SCAN_RESULTS:

       ===> wpa_supplicant_event_scan_results(wpa_s, data);

           ====> _wpa_supplicant_event_scan_results 

          这时你该能看到如下wpa_supplicant message:

   看不到的话,要不是设备坏了的话,那就是进入无人区了

 Received scan results (9 BSSes)  

 BSS: Start scan result update 1

 BSS: Add new id 0 BSSID 00:1f:33:b9:5d:e0 SSID 'RD-test'

 BSS: Add new id 1 BSSID 04:21:b0:e0:20:20 SSID 'xxxxx1'

 BSS: Add new id 2 BSSID 00:22:b0:e0:20:20 SSID 'xxxxx2'

 BSS: Add new id 3 BSSID 00:22:b0:e0:20:e8 SSID 'xxxx3'

 BSS: Add new id 4 BSSID 00:22:b0:e0:20:1d SSID 'xxxx4'

 BSS: Add new id 5 BSSID 04:21:b0:e0:20:1d SSID 'G-B-U-5'

 BSS: Add new id 6 BSSID 0e:4c:39:78:01:94 SSID 'ChinaNet-WGEc'

 BSS: Add new id 7 BSSID 5c:63:bf:a6:e4:50 SSID 'xxxxx'

 BSS: Add new id 8 BSSID 04:27:b0:e0:20:20 SSID 'xxxxx'

 New scan results available


另外还有下面这条分支也会接收扫描结果,可能是driver 主动发上来的

貌似如下:

这个 event 由eloops 中 注册的:

    eloop_register_read_sock(nl_socket_get_fd(drv->nl_handle_event), 

               wpa_driver_nl80211_event_receive, drv, drv->nl_handle_event);
=> wpa_driver_nl80211_event_receive

  通过process_event callback 来继续处理 NL80211_CMD_NEW_SCAN_RESULTS 如下:

  这时会: eloop_cancel_timeout(wpa_driver_nl80211_scan_timeout, 

          取消前面的10s scan timeout eloop 

   ==> send_scan_event 

       ===> wpa_supplicant_event(drv->ctx, EVENT_SCAN_RESULTS, &event); 

            ===> wpa_supplicant_event_scan_results

  ====> _wpa_supplicant_event_scan_results

        如果driver 没有横插1杠,前面也会走到下面:

        =====> wpa_supplicant_get_scan_results 获得ap info

                           ======> wpa_bss_update_scan_res 

                                     =======> wpa_bss_add

                      =====> wpa_msg_ctrl(wpa_s, MSG_INFO, 

                   WPA_EVENT_SCAN_RESULTS);

                      =====> wpas_notify_scan_results(wpa_s); 

               ======> wpas_wps_notify_scan_results 

                =======> wpas_wps_notify_scan_results

        到这里wpa_supplicant_event(EVENT_SCAN_RESULTS)  处理结束
下面这段messsage是由上面 wpa_bss_add 

                         => wpas_notify_bss_added 

       ==> wpa_msg_ctrl(wpa_s, MSG_INFO, 

                       WPA_EVENT_BSS_ADDED "%u " MACSTR,

引发monitor 接收 scan result 前的消息

D/wpa_supplicant( 1468): Event 5 received on interface wlan0

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 0 00:1f:33:b9:5d:e0]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 1 04:21:b0:e0:20:20]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 2 00:22:b0:e0:20:20]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 3 00:22:b0:e0:20:e8]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 4 00:22:b0:e0:20:1d]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 5 04:21:b0:e0:20:1d]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 6 0e:4c:39:78:01:94]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 7 5c:63:bf:a6:e4:50]

V/WifiMonitor( 1172): Event [CTRL-EVENT-BSS-ADDED 8 04:27:b0:e0:20:20]

                                               
接下来还有收到这样1条msg:

V/WifiMonitor( 1172): Event [WPS-AP-AVAILABLE ]

再跟下:

=> wpa_supplicant_event_scan_results

   ==> _wpa_supplicant_event_scan_results =>

       wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available");

       wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS);

    
马上结束,最后再回到java部分,上面发的WPA_EVENT_SCAN_RESULTS 被monitor接收:

=> handleEvent(int event, String remainder)(WifiMonitor.java)

    case SCAN_RESULTS

    ==>mWifiStateTracker.notifyScanResultsAvailable();

       ===>  setScanResultHandling(SUPPL_SCAN_HANDLING_NORMAL);

             ====> wifiStateTracker.setScanResultHandling

       ===>  sendEmptyMessage(EVENT_SCAN_RESULTS_AVAILABLE);

       接下来WifiStateTracker中的handleMessage会处理该消息
wpa_supplicant_get_scan_results中有对scan result排序,

一般按RSSI 强度来排, 如果有什么想法,可以动下

另外还有network group priority ,后面会提到

enable 部分基本就这样了,结束

抱歉!评论已关闭.