wifi direct/p2p流程分析 基于android 5.1

 转载自:http://blog.csdn.net/zjngogo/article/details/48299103


Wifi Direct流程分析

      Android平台中,P2P操作比较简单,用户只需要执行如下三个步骤:

      1)进入WifiP2pSettings界面

      2)搜索周围的P2P设备。搜索到的设备将显示在WifiP2pSettings

      3)用户选择其中的某个设备发起连接或者接受某设备发起的连接

     下面将根据这些步骤来分析WifiP2pSettingsWifiP2pService的流程,主要包括:P2P的使能、P2P的扫描、P2P的配对以及P2P的连接。


Wifi Direct环境的建立

WifiP2pSettings创建

android/apps/Settings/src/com/android/settings/wifi/p2p/WifiP2pSettings.java

      首先从WifiP2pSettings中的onActivityCreated()函数分析,代码如下:

[html]  view plain  copy
  1. <pre name="code" class="html">public void onActivityCreated(Bundle savedInstanceState) {  
  2.         addPreferencesFromResource(R.xml.wifi_p2p_settings);  
  3.   
  4.         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);  
  5.         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);  
  6.         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);  
  7.         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);  
  8.         mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);  
  9.         mIntentFilter.addAction(WifiP2pManager.  
  10.         WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);  
  11.         final Activity activity = getActivity();  
  12.         mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);  
  13.         if (mWifiP2pManager != null) {  
  14.            mChannel = mWifiP2pManager.initialize(activity, getActivity().getMainLooper(), null);  
  15.             if (mChannel == null) {  
  16.                 //Failure to set up connection  
  17.                 Log.e(TAG, "Failed to set up connection with wifi p2p service");  
  18.                 mWifiP2pManager = null;  
  19.             }  
  20.              ..............  
  21.         mRenameListener = new OnClickListener() {..............}  
  22.              ...............  
  23.         uper.onActivityCreated(savedInstanceState);  
  24.        }  


 

      onActivityCreated()函数主要的做了三件事:

      ①将P2P特有的Action添加到过滤器中。

      ②构造和初始化WifiP2pManager对象,并建立和WifiService联系。

      ③创建UI中按钮对应的OnClickListener

      WifiP2pSettings主要通过通过监听广播方式了解系统中Wifi P2p信息以及变化情况,下面简要介绍这几个属于P2P特有的广播:

      1)WIFI_P2P_STATE_CHANGED_ACTION-用于通知P2P功能的请用情况。

      2)WIFI_P2P_PEERS_CHANGED_ACTION-系统内部保存搜索到其他P2P设备信息的变化情况

      3)WIFI_P2P_CONNECTION_CHANGED_ACTION-用于通知P2P的连接情况

      4)WIFI_P2P_THIS_DEVICE_CHANGED_ACTION-用于通知本机设备信息变化情况

      5)WIFI_P2P_DISCOVERY_CHANGED_ACTION-用于通知P2P Discovery的工作状态

      6)WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION-用于通知persistent group信息的变化情况。

WifiP2pService的启动

android/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pService.java

android/opt/net/wifi/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java

     首先WifiP2pServicenew了一个WifiP2pServiceimpl对象,下面主要来看看WifiP2pServiceimpl的构造函数:

[html]  view plain  copy
  1. public WifiP2pServiceImpl(Context context) {  
  2.     mContext = context;  
  3.     //STOPSHIP: get this from native side  
  4. mInterface = "p2p0";  
  5. ..........  
  6. mP2pStateMachine = new P2pStateMachine(  
  7.     TAG, wifiP2pThread.getLooper(), mP2pSupported);  
  8.  mP2pStateMachine.start();  
  9. }  

      WifiP2pServiceimpl构造函数主要是创建一个NetworkInfo,然后调用getPackageManager判断本机设备是否支持P2P功能。通过创建一个P2pStateMachine并启动StateMachine

     下面进入P2pStateMachine函数分析

[html]  view plain  copy
  1. P2pStateMachine(String name, Looper looper, boolean p2pSupported) {  
  2.     super(name, looper);  
  3.       
  4. addState(mDefaultState);  
  5. addState(mP2pNotSupportedState, mDefaultState);  
  6.    ..............  
  7.  if (p2pSupported) {  
  8.                 setInitialState(mP2pDisabledState);  
  9.             } else {  
  10.                 setInitialState(mP2pNotSupportedState);  
  11.             }  
  12.             setLogRecSize(50);  
  13.             setLogOnlyTransitions(true);  

      分析构造函数,看出P2pStateMachine的各个State关系如下图:

     P2pStateMachineWifiP2pService的核心,P2pStateMachine的初始状态是P2pDisableState


Wifi Direct模块的初始化

Wifi Direct的主要数据结构

     下面来分析Wifi Direct的几个主要的数据结构,首先看的是p2p_configp2p_data,它们的成员如下图5所示:

      p2p_config定义了25个回调函数,这些回调函数定义了P2P模块与外界交互的接口,均指向p2p_supplicant.c.

p2p_data指向一个p2p_config对象。

     下面来看下其他几个重要的数据结构。如下图6


        p2p_device代表一个p2p设备。其中设备名等信息存放在类型为p2p_peer_info的对象中

         p2p_group代表一个p2p group的信息,其内包含一个p2p_group_config对象和一个p2p_group_member链表。p2p_group_config代表group的配置信息,p2p_group_member链表代表的是p2p client信息。


Wifi DirectWPAS中的初始化流程

       Wifi DirectWPAS中的初始化工作主要从wpas_p2p_init()函数开始,下面看看wpas_p2p_init()代码:

[plain]  view plain  copy
  1. int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)  
  2. {  
  3. struct p2p_config p2p;  
  4. int i;  
  5. if (wpa_s->conf->p2p_disabled)  
  6.    if (wpa_s->conf->p2p_disabled)  
  7. ..........  
  8. os_memset(&p2p, 0, sizeof(p2p));  
  9. p2p.cb_ctx = wpa_s;  
  10. p2p.debug_print = wpas_p2p_debug_print;  
  11. p2p.p2p_scan = wpas_p2p_scan;  
  12. p2p.send_action = wpas_send_action;  
  13. ..........  
  14. os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);  
  15. os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN);  
  16. p2p.dev_name = wpa_s->conf->device_name;  
  17. p2p.manufacturer = wpa_s->conf->manufacturer;  
  18. p2p.model_name = wpa_s->conf->model_name;  
  19. p2p.model_number = wpa_s->conf->model_number;  
  20. p2p.serial_number = wpa_s->conf->serial_number;  
  21. if (wpa_s->wps) {  
  22.         os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16);  
  23.         p2p.config_methods = wpa_s->wps->config_methods;  
  24.     }  
  25. .........  
  26.   
  27.     global->p2p = p2p_init(&p2p);  
  28.     if (global->p2p == NULL)  
  29.         return -1;  
  30.     global->p2p_init_wpa_s = wpa_s;  
  31.     for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) {  
  32.         if (wpa_s->conf->wps_vendor_ext[i] == NULL)  
  33.             continue;  
  34.         p2p_add_wps_vendor_extension(  
  35.             global->p2p, wpa_s->conf->wps_vendor_ext[i]);  
  36.     }  
  37.         ...........  
  38. }  

wpas_p2p_init()函数主要完成两件工作:

1)构造一个p2p_config对象并对p2p_config对象对象初始化,然后根据p2p_supplicant.conf文件的信息设置其中的内容。同时,为p2p模块设置回调函数。

2)调用p2p_init()函数初始化p2p模块

p2p_init()函数中主要构造了一个p2p_data结构体并设置相应的参数,p2p_init()函数代码比较简单感兴趣可以取分析。

 

3、注册Action

        本机设备和对端设备信息交互时候,Action帧扮演重要的角色。在P2P Device DiscovenryProvision Discovery流程以及Go Negotiation流程都涉及到Action帧的处理流程。因此,这边在初始化阶段对Action帧进行注册。

[objc]  view plain  copy
  1. tatic int wpa_driver_nl80211_set_mode_impl(  
  2.     struct i802_bss *bss,  
  3.     enum nl80211_iftype nlmode,  
  4.     struct hostapd_freq_params *desired_freq_params)  
  5. {  
  6. struct wpa_driver_nl80211_data *drv = bss->drv;  
  7. int ret = -1;  
  8.     int i;  
  9. int was_ap = is_ap_interface(drv->nlmode);  
  10. int res;  
  11. int mode_switch_res;  
  12. mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode);  
  13. if (mode_switch_res && nlmode == nl80211_get_ifmode(bss))  
  14. mode_switch_res = 0;  
  15. ......  
  16. if (is_ap_interface(nlmode)) {  
  17.         nl80211_mgmt_unsubscribe(bss, "start AP");  
  18.         /* Setup additional AP mode functionality if needed */  
  19.         if (nl80211_setup_ap(bss))  
  20.             return -1;  
  21.     } else if (was_ap) {  
  22.         /* Remove additional AP mode functionality */  
  23.         nl80211_teardown_ap(bss);  
  24.     } else {  
  25.         nl80211_mgmt_unsubscribe(bss, "mode change");  
  26.     }  
  27.     if (!bss->in_deinit && !is_ap_interface(nlmode) &&  
  28.         nl80211_mgmt_subscribe_non_ap(bss) < 0)  
  29.         wpa_printf(MSG_DEBUG, "nl80211: Failed to register Action "  
  30.                "frame processing - ignore for now");  
  31.     return 0;  
  32. }  

        wpa_driver_nl80211_set_mode_impl()函数中主要的是调用了nl80211_mgmt_subscribe_non_ap()函数,nl80211_mgmt_subscribe_non_ap()将注册对Action帧的监听时间,其作用就是当设备收到Action帧后,Wifi driver将发送相对应的netlink消息给WPAS.

nl80211_mgmt_subscribe_non_ap()注册了两种类型的帧监听事件。

         1P2P Public Action帧监听事件:根据P2P规范,目前适用的军事802.11 P2P Public Action帧(Category的值为0x04)。目前GONP2P InvitationProvision Discovery以及Device Discoverability都是适用P2P Public Action帧。

         2P2P Action帧监听事件:这种类型的帧属于802.11Action帧的一种(Category的值为0x7F),目前Notice of AbsenceP2P PresenceGO Discoverability适用P2P Action帧。

 

3.2.Wifi Direct的使能

       P2pStateMachine虽然属于WifiP2pService,但它也受WifiStateMachine影响。平台支持P2PWifiStateMachine中将创建一个名为mWifiP2pChannelAsyncChannelde 的对象用于向P2pStateMachine发消息。

如果用户打开WiFI功能,P2pStateMachine就会收到来自WifiStateMachine发送的消息CMD_ ENABLE_P2P

CMD_ ENABLE_P2P消息的处理过程主要在wifip2pserviceinpl.JavaP2pDisabledState函数中完成

[html]  view plain  copy
  1. class P2pDisabledState extends State {  
  2.  public boolean processMessage(Message message) {  
  3.      if (DBG) logd(getName() + message.toString());  
  4.      switch (message.what) {  
  5.      case WifiStateMachine.CMD_ENABLE_P2P:  
  6.          try {  
  7.              mNwService.setInterfaceUp(mInterface);  
  8.             } catch (RemoteException re) {  
  9.         ...............  
  10.                     }  
  11.                     mWifiMonitor.startMonitoring();  
  12.                     transitionTo(mP2pEnablingState);  
  13.                     break;  
  14.                 default:  
  15.                     return NOT_HANDLED;  
  16.             }  
  17.             return HANDLED;  
  18.         }  
  19.     }  

接收到CMD_ ENABLE_P2P消息后,P2pStateMachine主要做了两件工作:

1)创建一个WifiMonitor用于接收来自wpa_supplicant的消息

2)同时将状态机转入到P2pEnablingState状态

WifiMonitor连接连接wpa_supplicant之后,WifiMonitor会发送一个SUP_CONNECT_EVENT

消息给P2pStateMachine,该消息由P2pEnablingState处理。

[objc]  view plain  copy
  1. class P2pEnablingState extends State {  
  2.  public boolean processMessage(Message message) {  
  3.      if (DBG) logd(getName() + message.toString());  
  4.      switch (message.what) {  
  5.      case WifiMonitor.SUP_CONNECTION_EVENT:  
  6.          if (DBG) logd("P2p socket connection successful");  
  7.          transitionTo(mInactiveState);  
  8.          break;  
  9.      case WifiMonitor.SUP_DISCONNECTION_EVENT:  
  10.          loge("P2p socket connection failed");  
  11.          transitionTo(mP2pDisabledState);  
  12.          break;  
  13.          .......}  
  14.             return HANDLED;  
  15.         }  
  16.     }  

         P2pEnablingState这时会跳转到InactiveState中,由前面P2pStateMachineState关系图我们可以知道,P2pEnabledStateInactiveState状态,我们先到P2pEnabledStateenter函数去分析:

[javascript]  view plain  copy
  1. class P2pEnabledState extends State {  
  2.  @Override  
  3.   public void enter() {  
  4.   if (DBG) logd(getName());  
  5.      sendP2pStateChangedBroadcast(true);  
  6.      mNetworkInfo.setIsAvailable(true);  
  7.      sendP2pConnectionChangedBroadcast();  
  8.      initializeP2pSettings();  
  9.    }  

P2pEnabledState()函数主要工作如下:

1)通过sendP2pStateChangedBroadcast()发送WIFI_P2P_STATE_CHANGED_ACTION广播,它将携带WifiP2pInfoNetworkInfo信息,同时还将通过sendP2pConnectionChangedBroadcast()函数向WifiStateMachine发送WIFI_P2P_CONNECTION_CHANGED_ACTION广播。

调用函数initializeP2pSettings()初始化P2P的一些设,包括deviceNameDeviceTypeConfigMethods,并且获取以前persistent的相关device信息


3.3.Wifi Direct的扫描

           P2P的扫描还是从WifiP2psettings开始,当用户单击“SEARCH”按钮搜索P2P设备。该按钮对应的函数是WifiP2pSettingsstartSearch()函数。

           startSearch()函数调用WifiManagerdiscoverPeers搜索周围的P2P设备。discoverPeers()函数主要的工作是发布DISCOVER_PEERS消息,由WifiP2pServiceP2pEnabledState函数处理。

          下面来看下WifiP2pServicediscoverPeers处理流程。

[cpp]  view plain  copy
  1. class P2pEnabledState extends State {  
  2.            ..............  
  3.      public boolean processMessage(Message message) {  
  4.             if (DBG) logd(getName() + message.toString());  
  5.             switch (message.what) {  
  6.                   ....................  
  7.             case WifiP2pManager.DISCOVER_PEERS:  
  8.                     if (mDiscoveryBlocked) {  
  9.                     replyToMessage(  
  10.                        message,WifiP2pManager.DISCOVER_PEERS_FAILED,  
  11.                                 WifiP2pManager.BUSY);  
  12.                         break;  
  13.                     }  
  14.                     // do not send service discovery request while normal find operation.  
  15.                     clearSupplicantServiceRequest();  
  16.                     if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {  
  17.                         replyToMessage(  
  18.                          message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);  
  19.                         sendP2pDiscoveryChangedBroadcast(true);  
  20.                     } else {  
  21.                         replyToMessage(  
  22.                          message, WifiP2pManager.DISCOVER_PEERS_FAILED,  
  23.                                 WifiP2pManager.ERROR);  
  24.                     }  
  25.                     break;  
  26.                      ...........  
  27.                }  
  28. }  

P2pEnabledState()收到DISCOVER_PEERS主要做了三件事:

1通过clearSupplicantServiceRequest()取消Service Discovery请求。

2调用WifiNativep2pFind函数wpa_supplicant发送P2P_FIND命令。

 3)通过sendP2pDiscoveryChangedBroadcast()函数发送 

WIFI_P2P_DISCOVERY_CHANGE_ACTION广播通知P2P Device Discovery已经启动。

          其中,wpa_supplicant收到P2P_FIND命令开始搜索周边的P2P设备,如果找到就会向WifiMonitor发送P2P-DEVICE-FOUND这样的EVENT这个event会带有对方设备的信息,包括MAC地址、device type、设备名字以及config methodsWifiMonitor收到这样的event后,会将P2P-DEVICE-FOUND后面的data数据封装成为一个WifiP2pDevice对象,然后发送P2P_DEVICE_FOUND_EVENT消息给WIfiStateMachine处理。

          下面来看下WifiP2pServiceP2P_DEVICE_FOUND_EVENT处理流程。

[objc]  view plain  copy
  1. class P2pEnabledState extends State {  
  2.            ..............  
  3.      public boolean processMessage(Message message) {  
  4.             if (DBG) logd(getName() + message.toString());  
  5.             switch (message.what) {  
  6.                   ....................  
  7.             case WifiMonitor.P2P_DEVICE_FOUND_EVENT:  
  8.                     WifiP2pDevice device = (WifiP2pDevice) message.obj;  
  9.                     if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;  
  10.                     mPeers.updateSupplicantDetails(device);  
  11.                     sendPeersChangedBroadcast();  
  12.                     break;  
  13.                   }.................  
  14. }  

P2pEnabledState()收到P2P_DEVICE_FOUND_EVENT,在构造函数中主要做了两件事:

①通过WPAS反馈的信息构建一个WifiP2pDevice对象

②发送WIFI_P2P_PEERS_CHANGED_ACTION广播

下面来看看WifiP2pSetting收到WIFI_P2P_PEERS_CHANGED_ACTION广播以及

WIFI_P2P_DISCOVERY_CHANGE_ACTION广播后的处理过程。

[javascript]  view plain  copy
  1. private final BroadcastReceiver mReceiver = new BroadcastReceiver() {  
  2.         @Override  
  3.         public void onReceive(Context context, Intent intent) {  
  4.             String action = intent.getAction();  
  5.             ............  
  6.             }else if  
  7.                  WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action))    
  8.                 {  
  9.                         mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(  
  10.                                   WifiP2pManager.EXTRA_P2P_DEVICE_LIST);  
  11.                         handlePeersChanged();  
  12.              }............  
  13.              else if(  
  14.             WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action))      
  15.              {  
  16.                     ...............  
  17.                     updateSearchMenu(true);  
  18.                     .. ........  
  19.                 }  
  20. }  

            WifiP2pSetting收到WIFI_P2P_PEERS_CHANGED_ACTION广播后,通过WifiManagerhandlepeerschanged()函数获取P2P Device信息。收到WIFI_P2P_DISCOVERY_CHANGED_ACTION调用updateSearchMenu()函数显示所有的设备。至此,P2P扫描的全部过程已经完成。P2P扫描的时序图如图3


            由前面可知,P2pStateMachine将通过发送P2P_FIND命令给WPAS触发P2P Device Discovery流程。下面来看下P2P Device Discovery扫描过程,如下图4


P2P Device Discovery扫描过程主要做了三件工作:

1)接受来之P2pStateMachine的命令,设置搜索方式。

2)调用wpas_p2p_scan()函数设置SSIDProbe Request帧中的WSC IE信息、P2P IE以及其他扫描参数。

3)调用wpa_driver_nl80211_scan()函数开始扫描以及设置P2P扫描结果处理指针函数主要调用wpas_p2p_scan_res_handle()函数。

其中,搜索方式主要有三种:

P2P_FIND_ONLY_WITH_FULL:默认设置。表示先扫描所有频段,然后再扫描social channels.

P2P_FIND_ONLY_SOCIAL:只扫描social channels

    P2P_FIND_PROGRESSIVE:P2P_FIND_ONLY_WITH_FULL扫描过程相类似,只不过Search

State阶段将逐个扫描所有的频段。

对扫描结果的处理主要从wpas_p2p_scan_res_handle()开始。数据结构wpa_scan_results用于存储扫描结果,如图5为扫描结果的时序图:


wpas_p2p_scan_res_handler()函数中主要存在两个关键函数p2p_scan_res_handler()和p2p_scan_res_handled()。

每一个存储在wpa_scan_results结构体中的扫描结果,都会调用p2p_scan_res_handler()进行处理。p2p_scan_res_handler()函数主要的工作有两方面:

1)p2p_add_device()函数构造一个p2p Device对象加入到devices链表并获取对端设备的P2P DEVICE信息。

2)设置一个dev_found指针指向wpas_dev_found()函数,wpas_dev_found()将向WifiMonitor发送消息P2P DEVICE FOUND告知上层对端设备找到。

处理完扫描结果将调用第二个关键函数p2p_scan_res_handled()进入listen state状态。这边需要注意的是:

1)p2p_build_probe_resp_ies()函数为wifi driver设置P2P IE消息,如果wifi driver自己处理Probe Request帧,则wifi driver将把此处设置的P2P IE信息填写到Probe Response帧中。

2) wpa_drv_set_ap_wps_ie()要求wifi driver收到Probe Request帧后,发送EVENT_RX_PROBE_REQWPAS

3)wpa_drv_remain_on_channel()函数要求wifi driver在指定的频段工作一段时间,若切换到某一频段,wifi driver会发送EVENT_REMAIN_ON_CHANNAL消息给WPAS.

 

3.4.Wifi Direct的连接

3.4.1Wifi Direct的连接

               Wifi P2P连接主要分为:主动连接 、被动连接、主动invite以及被动invite,本文主要分析主动连接。

Wifi P2P扫描完成后,用户可以在界面中选择某个P2P设备并与之连接,Wifi P2P连接也是有WifiP2pSettings.java开始。先来看看WifiP2pSettingsonPreferenceTreeClick函数:

[javascript]  view plain  copy
  1. public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {  
  2.         if (preference instanceof WifiP2pPeer) {  
  3.             mSelectedWifiPeer = (WifiP2pPeer) preference;  
  4.             if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) {  
  5.                 showDialog(DIALOG_DISCONNECT);  
  6.             } else if (mSelectedWifiPeer.device.status == WifiP2pDevice.INVITED) {  
  7.                 showDialog(DIALOG_CANCEL_CONNECT);  
  8.             } else {  
  9.                 WifiP2pConfig config = new WifiP2pConfig();  
  10.                 config.deviceAddress = mSelectedWifiPeer.device.deviceAddress;  
  11.   
  12.                 int forceWps = SystemProperties.getInt("wifidirect.wps", -1);  
  13.   
  14.                 if (forceWps != -1) {  
  15.                     config.wps.setup = forceWps;  
  16.                 } else {  
  17.                     if (mSelectedWifiPeer.device.wpsPbcSupported()) {  
  18.                         config.wps.setup = WpsInfo.PBC;  
  19.                     } else if (mSelectedWifiPeer.device.wpsKeypadSupported()) {  
  20.                         config.wps.setup = WpsInfo.KEYPAD;  
  21.                     } else {  
  22.                         config.wps.setup = WpsInfo.DISPLAY;  
  23.                     }  
  24.                 }  
  25.   
  26.                 mWifiP2pManager.connect(mChannel, config,  
  27.                         new WifiP2pManager.ActionListener() {...................}  
  28.                     }..............  
  29.             }  
  30.      }  

onPreferenceTreeClick()主要做了三件事:

①获取用户指定的WifiP2pPeer项。

②获取对端设备的WSC的配置方法。

③构造WifiP2pConfig对象存储对端设备信息并调用WifiP2pManagerconnect函数向该对端设备发起连接。

connect函数的工作主要是通过ChannelAsyncChannelP2pStatuesMachine发送CONNECT消息。

下面来看下CONNECT消息的处理流程。

[objc]  view plain  copy
  1. class InactiveState extends State {  
  2.            ..............  
  3.      public boolean processMessage(Message message) {  
  4.              
  5.             if (DBG) logd(getName() + message.toString());  
  6.             switch (message.what) {  
  7.                 case WifiP2pManager.CONNECT:  
  8.                     if (DBG) logd(getName() + " sending connect");  
  9.                     WifiP2pConfig config = (WifiP2pConfig) message.obj;  
  10.                     if (isConfigInvalid(config)) {  
  11.                         loge("Dropping connect requeset " + config);  
  12.                         replyToMessage(message, WifiP2pManager.CONNECT_FAILED);  
  13.                         break;  
  14.                     }  
  15.   
  16.                     mAutonomousGroup = false;  
  17.                     mWifiNative.p2pStopFind();  
  18.                     if (reinvokePersistentGroup(config)) {  
  19.                         transitionTo(mGroupNegotiationState);  
  20.                     } else {  
  21.                         transitionTo(mProvisionDiscoveryState);  
  22.                     }  
  23.                     ...................  
  24.                }.................  
  25.           }  

                  这里分为persistent的连接方式和非persistent的连接,对于persistent连接,如果第一次连接成功wpa_supplicant会记录连接的记录,包括credentialGO MAC地址、ssid等信息。采用非persistent的连接(即negotiate方式)则跳转到ProvisionDiscoveryState函数,调用WifiNativep2pProvisionDiscovery向对端设备发送Provision discovery封包。对端设备处理Provision discovery封包后就会回复provision response,经wpa_supplicant处理WifiMonitor会收到P2P-PROV-DISC-PBC-RESP(WPS方式为PBC方式时), WifiMonitor就会向P2pStateMachine发送P2P_PROV_DISC_PBC_RSP_EVENT

下面来看看P2P_PROV_DISC_PBC_RSP_EVENT消息的处理过程,主要做两件事

①调用p2pConnectWithPinDisplay函数插法WPAS发送GON Request(调用WifinativeP2pconnect函数有兴趣可以看看)

②跳转到GroupNegotiationState,开始Group negotiate

[javascript]  view plain  copy
  1. class ProvisionDiscoveryState extends State {  
  2.            ..............  
  3.      public boolean processMessage(Message message) {  
  4.            ..............  
  5.            switch (message.what) {  
  6.                 case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:  
  7.                     provDisc = (WifiP2pProvDiscEvent) message.obj;  
  8.                     device = provDisc.device;  
  9.                     if (!device.deviceAddress.equals(  
  10.                     mSavedPeerConfig.deviceAddress))   
  11.                     break;  
  12.                      if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {  
  13.                      if (DBG) logd("Found a match " + mSavedPeerConfig);  
  14.                      p2pConnectWithPinDisplay(mSavedPeerConfig);  
  15.                      transitionTo(mGroupNegotiationState);  
  16.                     }  
  17.             ...................  
  18.           }  

下面来看下Group negotiate过程:

[javascript]  view plain  copy
  1. class GroupNegotiationState extends State {  
  2.            ..............  
  3.      public boolean processMessage(Message message) {  
  4.            ..............  
  5.            switch (message.what) {                 
  6.                 case WifiMonitor.P2P_GO_NEGOTIATION_SUCCESS_EVENT:  
  7.                 case WifiMonitor.P2P_GROUP_FORMATION_SUCCESS_EVENT:  
  8.                     if (DBG) logd(getName() + " go success");  
  9.                     break;  
  10.                 case WifiMonitor.P2P_GROUP_STARTED_EVENT:  
  11.                     mGroup = (WifiP2pGroup) message.obj;  
  12.                     if (DBG) logd(getName() + " group started");   
  13.                    if (mGroup.getNetworkId()=WifiP2pGroup.PERSISTENT_NET_ID)  {  
  14.                     updatePersistentNetworks(NO_RELOAD);  
  15.                     String devAddr = mGroup.getOwner().deviceAddress;  
  16.                     mGroup.setNetworkId(mGroups.getNetworkId(devAddr,  
  17.                     mGroup.getNetworkName()));  
  18.                    }  
  19.                    if (mGroup.isGroupOwner()) {  
  20.                      if (!mAutonomousGroup) {  
  21.                          mWifiNative.setP2pGroupIdle(  
  22.                          mGroup.getInterface(), GROUP_IDLE_TIME_S);   
  23.                          }  
  24.                         startDhcpServer(mGroup.getInterface());  
  25.                      } else {.............}  
  26.                     transitionTo(mGroupCreatedState);  
  27.                               }  
  28.           }  

             开始group negotiate后,wpa_supplicant会发多个eventWifiMonitorWifiMonitor处理后也会发送多个event消息给P2pStateMachine。其中比较重要的是P2P_GROUP_STARTED_EVENT

GroupNegotiationState()接收到P2P_GROUP_STARTED_EVENT主要做了四件事:

①更新和设置mgroup的信息。

②调用DHCP为两端设备分配IP地址。

③向wifiP2pSettings发送广播。

④更新Group owner信息,跳转到GroupCreatedState连接完成。

GroupCreatedState函数主要调用sendP2pConnectionChangedBroadcast()广播当前连接状态的改变,WifiP2pSettings会捕获这个WIFI_P2P_CONNECTION_CHANGED_ACTION这个消息并且更新UI为已连接状态。GroupCreatedState代码比较简单,感兴趣可以自行分析,到此P2P的主动连接已经结束。

P2P主动连接的时序图如图6


3.4.2Wifi DirectProvision Discovery流程

                  P2P规范定义Provision Discovery流程,为了是确定两个P2P Device交互双方适用的WSC方法,只有在双方适用相同的WSC配置方法才能建立P2P Group

前文分析知道,当P2pStateMachineProvisionDiscoveryState发送P2P_PROV_DISC命令给WPAS时便启动了Provision Discovery流程。

Provision Discovery流程可以分为三个步骤:PD Request帧的发送流程(时序图19)、Action帧的接收流程(时序图1019)以及PD Response帧的处理流程。Provision Discovery流程时序图如下图7所示:


          PD Request帧最终通过p2p_send_action()函数发送出去,p2p_send_action()将涉及off channel发送以及处理对应的netlink消息的过程。

           PD Response帧属于Public Action帧的一种,PD Response帧主要有两种帧:对端设备发来的PD Response帧以及本机设备发送的管理帧TX Report,详细请分析process_bss_event()函数。无论是代表由本机发送的管理帧TX Report帧(NL80211_CMD_FRME_TX_STATUS)还是代表本机接收到的对端神杯发来的管理时间的帧(NL80211_CMD_FRME)最终都会调用mlme_event()函数。

PD Response帧处理流程主要做的工作:

1)解析PD Response帧,判断PD Response帧返回的WSC方法是否与所要求的WSC方法一致。

2)调用wpas_prov_disc_resp()发消息给客户端。对于前面提到的WSC PBC方式而言,wpas将发送P2P_EVENT_PROV_DISC_PBC_RESP消息给客户端。

 

3.4.3Wifi DirectGO Negotiation流程

               由3.3.1节分析知道P2pStateMachine收到P2P_PROV_DISC_PBC_RSP_EVENT消息后,将会通过ProvisionDiscoveryState中调用p2pConnectWithPinDisplay()函数,该函数内部将发送命令P2P_CONNECTWPAS开始GO Negotiation流程。

GO Negotiation流程主要有四个过程:P2P_CONNECT处理流程、GON Request帧发送流程、GON Request帧处理流程以及EVENT_TX_STATUS处理流程。

8P2P_CONNECT处理和GON Request帧的发送流程。


              对端设备设备根据接收到的GON Request帧回复GON Response帧,由前文分析知道GON Request帧将在p2p_process_go_neg_resp()函数负责处理。这段代码比较复杂暂且不进行分析,如果感兴趣自行分析。

              当GON Confirmation帧发送出去后,wifi driver将向WPAS发送一个NL80211_CMD_FRAME _TX_STATUS,该消息直接导致driver wrapper发送EVENT_TX_STATUS消息给WPAS。图9EVENT_TX_STATUS消息的处理流程:


                      当Group Negotiation完成后,WPAS将创建一个wpa_supplicant对象,它将用于管理和操作专门用于P2P Groupvirtual interface(GON Request帧发送过程创建)。一个interface对应一个wpa _supplicant对象,如果wpa_supplicant对象为GO角色,其MAC地址为P2P interface address;如果wpa_supplicant对象用于非P2P Group操作,其MAC地址为P2P Device address.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值