android wifi p2p / wifi direct

版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/h784707460/article/details/81502574

 

一. wifi P2P协议相关

Wi-Fi Alliance(Wi-Fi联盟)推出的一项重要技术规范Wi-Fi P2P。该规范的商品名为Wi-Fi Direct,它支持多个Wi-Fi设备在没有AP的情况下相互连接。 借助P2P技术,Wi-Fi设备之间的直接相连将极大拓展Wi-Fi技术的使用场景。如智能终端设备之间的多屏共享和互动功能。

1.1 P2P架构

p2p架构中定义了两种角色,分别是:

  • P2P Group Owner:简称GO,其作用类似于Infrastructure BSS中的AP;
  • P2P Client:简称GC,其作用类似于Infrastructure BSS中的STA。

android wifi p2p / wifi direct_第1张图片

1.2 Device Discovery

Device Discovery使用Probe Request和Probe Response帧来交换设备信息。

P2P为Device Discovery定义了两个状态和两个阶段。

两个状态

  • Search State:在该状态中,P2P Device将在2.4GHz的1,6,11频段上分别发送Probe Request帧。这几个频段被称为Social Channels。
  • Listen State:在该状态下,P2P Device将随机选择在1,6,11频段中的一个频段(被选中的频段被称为Listen Channel)监听Probe Request帧并回复Probe Response帧。Listen Channel一旦选择好后,在整个P2P Discovery阶段就不能更改。

两个阶段

  • Scan Phase:扫描阶段。P2P Device会在其所支持的所有频段上发送Probe Request帧(主动扫描)。用于快速发现周围的Group。P2P Device在这一阶段中不会处理来自其他设备的Probe Request帧。(全信道扫描)
  • Find Phase:P2P Device将在Search State和Listen State之间来回切换。Search State中,P2P Device将发送Probe Request帧,而Listen State中,它将接收其他设备的Probe Request帧并回复Probe Response帧。

注:Operating Channel属性表示组建的P2P Group将在哪个频段上工作。并且其频段不限于Social Channels中指定的那三个频段。

android wifi p2p / wifi direct_第2张图片

1.3 GO Formation

GO Formation 包含两个阶段:

  • GO Negotiation:在这一阶段中,两个Device要协商好由谁来做GO。
  • Provisioning:GO和Client角色确定后,两个Device要借助WSC来交换安全配置信息。此后,Client就可以利用安全配置信息关联上GO。(Provision Discovery(PD)流程是为了确定交互双方使用的WSC方法,不属于GF流程)

GO协商包含一个三路握手过程,用于协商谁是GO以及P2P组的一些特征。 这三路握手过程主要主要交换如下一些信息:

  1.  Group Owner Intent Value
  2.  Acceptable Operating Channel the Group may use
  3.  Credentials for the P2P Group
  4.  Group Duration: Temporary or Persistent
  5.  Group support for other devices and optional capabilities

android wifi p2p / wifi direct_第3张图片

当一个P2P设备发送GO Negotiation Request后,100ms内没有接收到确认帧,则认为此次协商失败。GO Negotiation的一个主要目的就是交换GO Intent属性,以决定谁当GO。如果一个P2P设备只能当GO,则其GO Intent值必须设置为15。

第一个GO Negotiation Request帧的Tie Breaker位会被随机设置为0或1。在接下来的GO Negotiation Request帧中(该位会被置反,重传除外)。GO Negotiation Response帧的Tie breaker位将会根据相应的GO Negotiation Request帧的相应位置反。

android wifi p2p / wifi direct_第4张图片

wifi p2p工作流程

android wifi p2p / wifi direct_第5张图片

二. HSM和AsyncChannel介绍

HSM(对应的类是StateMachine)和AsyncChannel是Android Java Framework中两个重要的类。目前还仅由Framework内部使用,SDK中并没有包含它们。

2.1 HSM(Hierarchical State Machine,结构化状态机)

HSM在传统状态机对所有状态都一视同仁的基础上做了一些改变,使得状态和状态之间有了层级关系。在父状态中实现generic的功能,而在子状态中实现一些特定的处理。

State中重要函数:

  • enter, SM进入某状态时将调用其EA(Entry Action);
  • exit,退出某状态时将调用其EXA(Exit Action);
  • processMessage,在HSM中,外界和HSM交互的方式就是向其sendMessage。Message由当前State的processMessage函数来处理。如果当前State成功处理此message,则返回HANDLED。否则返回NOT_HANDLED。在Message处理中,如果子状态返回NOT_HANDLED,则其父状态的processMessage将被调用。如果当前状态及祖先状态都不能处理,则HSM的unhandledMessage将被调用。 

HSM中一些重要的API:

  • addState:添加一个状态。同时还可指定父状态。
  • transitionTo:将状态机切换到某个状态。
  • obtainMessage:由于HSM内部是围绕一个Handler来工作的,所以外界只能调用HSM的obtainMessage以获取一个Message。
  • sendMessage:发送消息给HSM。HSM中的Handler会处理它。
  • start:启动状态机。
  • 停止状态机可使用quit或quitNow函数。

HSM中状态和状态之间的层级关系体现:

  • SM启动后,初始状态的EA将按派生顺序执行。即其祖先状态的EA先执行,子状态的 EA后执行。
  • 当State发生切换时,旧State的exit先执行,新State的enter后执行,并且新旧State派生树上对应的State也需要执行exit或enter函数。但公共祖先状态的EXA和EA不会执行。EA执行顺序由祖先类开始直至子孙类,而EXA执行先从子孙类开始,直到祖先类。
  • State处理Message时,如果子状态不能处理(返回NOT_HANDLED),则交给父状态去 处理。

2.2 AsyncChannel

AsyncChannel用于两个Handler之间的通信。具体的通信方式为源Handler通过sendMessage向目标Handler发送消息,而目标Handler通过replyToMessage回复源Handler处理结果。这两个Handler可位于同一个进程,也可分属两个不同的进程.

用法包含两种不同的应用模式(usage model)。

  • 简单的request/response模式(一对多的通信方式)下,Server端无须维护Client的信息,它只要处理来自Client的请求即可。通信前双方不需要显示建立连接。客户端(发送方)将请求发送给服务器(接收方),服务器则通过replayToMessage方法向客户端发送应答消息。

android wifi p2p / wifi direct_第6张图片

  • 一对一的通信方式,这种应用模式就是Server端维护Client的信息。这样,Server可以向Client发送自己的状态或者其他一些有意义的信息。

android wifi p2p / wifi direct_第7张图片

WifiService相关模块中,第二种应用模式使用得较多。

三. WifiP2pSettings和WifiP2pService介绍

WifiP2pSettings是Settings应用中负责处理P2P相关UI/UE逻辑的主要类,与之交互的则是位于SystemServer进程中的WifiP2pService。

3.1 涉及源码文件名及位置(Marshmallow - 6.0.1_r10)

WifiP2pManager /frameworks/base/wifi/java/android/net/wifi/p2p/WifiP2pManager.java 

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

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

WifiNative /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiNative.java

WifiMonitor /frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiMonitor.java

3.2 WifiP2pSettings

加载界面元素

通过监听广播的方式来了解系统中Wi-Fi P2P相关的信息及变化情况,进行相应的处理:

  • WIFI_P2P_STATE_CHANGED_ACTION:用于通知系统中P2P功能的启用情况,如该功能是enable还是disable。
  • WIFI_P2P_PEERS_CHANGED_ACTION:系统内部将保存搜索到的其他P2P设备信息,如果这些信息有变化,则系统将发送该广播。接收者需要通过WifiP2pManager的requestPeers函数重新获取这些P2P设备的信息。
  • WIFI_P2P_CONNECTION_CHANGED_ACTION:用于通知P2P连接情况,该广播可携带WifiP2pInfo和NetworkInfo两个对象。相关信息可从这两个对象中获取。
  • WIFI_P2P_THIS_DEVICE_CHANGED_ACTION:用于通知本机P2P设备信息发生了变化。
  • WIFI_P2P_DISCOVERY_CHANGED_ACTION:用于通知P2P Device Discovery的工作状态,如启动或停止。
  • WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION:用于通知之persistent group信息发生了变化。

WifiP2pSettings将借助WifiP2pManager和系统中的WifiP2pService交互。WifiP2pSettings主要使用WifiP2pManager的几个重要函数:

  • initialize:初始化WifiP2pManager.Channel ,WifiP2pManager内部将和WifiP2pService通过AsyncChannel建立交互关系。
  • discoverPeers:触发WifiP2pService发起P2P Device扫描工作。
  • requestPeers:获取系统中保存的P2P Device信息。
  • connect:和指定P2P Device发起连接,也就是相互协商以创建或加入一个P2P网络,即一个Group。
  • requestGroupInfo:获取当前连接上的Group信息。

3.3 WifiP2pService

WifiP2pService是Android系统中P2P功能的Java层核心模块。其家族类图如下。

  • IWifiP2pManager、IWifiP2pManager.Stub和IWifiP2pManager.Stub.Proxy类均由IWifiP2pManager.aidl文件在编译时通过aidl工具转换而来。
  • WifiP2pService派生自IWifiP2pManager.Stub类,它是Binder服务端。
  • WifiP2pManager是WifiP2pService的客户端。它通过成员变量mService和WifiSP2pervice进行Binder交互。

android wifi p2p / wifi direct_第8张图片

P2pStateMachine是WifiP2pService定义的内部类,P2pStateMachine是WifiP2pService的核心。P2pStateMachine中定义的各个状态及层级关系如图:

android wifi p2p / wifi direct_第9张图片

3.4 WifiP2pService工作流程

P2pStateMachine初始状态为P2pDisabledState,然后:

1)P2pStateMachine收到来自WifiStateMachine的CMD_ENABLE_P2P消息,在该消息的处理逻辑中,P2pStateMachine将创建一个WifiMonitor对象以和wpa_supplicant进程交互。P2pStateMachine转入P2pEnablingState。

2)在P2pEnablingState中,处理SUP_CONNECT_EVENT消息,它代表WifiMonitor成功连接上了wpa_supplicant。P2pStateMachine将转入InactiveState。

3)InactiveState的父状态是P2pEnabledState,P2pEnabledState的EA将初始化P2P设置,这部分代码逻辑在initializeP2pSettings函数中。另外,WifiP2pSettings将收到一些P2P广播,此时P2P功能正常启动。

4)搜索设备时,P2pStateMachine将收到DISCVOER_PEERS消息。它在P2pEnabledState中被处理,wpas_supplicant将发起P2P DeviceDiscovery流程以搜索周围的P2P设备。

5)若有P2P设备被发现,P2pStateMachine将收到P2P_DEVICE_FOUND_EVENT消息。该消息由其父状态P2pEnabledState来处理。同时,WifiP2pSettings也会相应收到信息以更新UI。

6)连接时,WifiP2pSettings将发送CONNECT消息给P2pStateMachine。该消息由InactiveState来处理。大部分情况下(除了Persistent Group或者对端设备是GO的情况下),P2pStateMachine将转入ProvisionDiscoveryState。

7)ProvisionDiscoveryState中,P2pStateMachine将通知WPAS以开展ProvisioningDiscovery流程。之后,P2pStateMachine将收到P2P_PROV_DISC_PBC_RSP_EVENT消息。在该消息的处理过程中,P2pStateMachine将通过p2pConnectWithPinDisplay函数通知WPAS和对端设备启动Group Formation流程。此后,P2pStateMachine转入GroupNegotiationState。

8)Group Formation完成,一个Group也就创建成功,P2pStateMachine将收到P2P_GROUP_STARTED_EVENT消息。该消息由GroupNegotiationState处理。如果本机扮演GO的话,它将启动一个Dhcp服务器

9)当对端P2P Client(Group建立后,角色也就确定了)关联上本机的GO后, AP_STA_CONNECTED_EVENT消息将被发送给P2pStateMachine处理。

四. P2P流程

android wifi p2p / wifi direct_第10张图片

相关文件简介: 

1、WifiP2pSettings 属于应用程序层,是对相关操作结果的一个视觉呈现。主要负责界面初始化、接收底层事件消息进行界面更新、发出相应命令等。

2、WifiP2pManager:是Wi-Fi P2P部分对外的接口,通过它来访问Wi-Fi P2p的核心功能。

3、WifiP2pService:是Wi-Fi P2p部分的核心,负责Wi-Fi整个流程的控制。

4、P2pStateMachine:继承了StateMachine。下发了加载驱动和启动supplicant命令,启动了WifiMonitor。

5、WifiMonitor:开启一个MonitorThread来实现事件的轮询,而轮询的关键函数是WifiNative.waitForEvent()。WifiMonitor将接收到的底层事件转换成WifiStateMachine所能识别的消息,然后将消息发送给WifiStateMachine。

6、WifiNative:封装了一系列本地调用的接口函数,通过JNI调用C++代码。

android wifi p2p / wifi direct_第11张图片

4.1 P2P扫描流程 

APP 

WifiP2pManager manager;

manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE); 


WifiP2pManager.Channel

channel; channel = manager.initialize(this, getMainLooper(), null); 


manager.discoverPeers(channel, new WifiP2pManager.ActionListener() { 

     @Override
     public void onSuccess() {;}

     @Override
     public void onFailure(int reasonCode) {;}
}

WifiP2pManager:

public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {return initalizeChannel(srcContext, srcLooper, listener, getMessenger());}

private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,Messenger messenger) {
        if (messenger == null) return null;
        Channel c = new Channel(srcContext, srcLooper, listener);
        if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
                == AsyncChannel.STATUS_SUCCESSFUL) {
            return c;
        } else {return null;}
    }

public void discoverPeers(Channel c, ActionListener listener) {
    checkChannel(c);//void,c是否为空,若空,抛出IllegalArgumentException异常
    c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));
}

WifiP2pService:
P2pStateMachine当前处于InactiveState,不过DISCOVER_PEERS消息却是由其父状态
P2pEnabledState来处理的.
case WifiP2pManager.DISCOVER_PEERS:
    if (mDiscoveryBlocked) {
        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                                WifiP2pManager.BUSY);
        break;
    }
      // do not send service discovery request while normal find operation.
     clearSupplicantServiceRequest();
    if (mWifiNative.p2pFind(DISCOVER_TIMEOUT_S)) {//向WPAS发送P2P_FIND命令
        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);
                        sendP2pDiscoveryChangedBroadcast(true);
    } else {
        replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,
                                WifiP2pManager.ERROR);
    }
    break;


WifiP2pService:
上述处理流程主要调用WifiNative的p2pFind函数,它会向wpa_supplicant发送P2P_FIND命令。若成功发送这个命令,就会通过WifiManager中discoverPeers的第二个参数ActionListener来告知Application执行成功;若执行失败,也会通知Application,只是回调不同的方法,一个是onSuccess(),一个是onFailure()。
wpa_supplicant收到P2P_FIND后,开始搜索周边的P2P设备,若找到,给WifiMonitor发送P2P-DEVICE-FOUND这样的event,WifiMonitor收到后,会将P2P-DEVICE-FOUND后面的data数据封装成为WifiP2pDevice对象,然后发送P2P_DEVICE_FOUND_EVENT消息给WIfiStateMachine处理。
P2P_DEVICE_FOUND_EVENT也由InactiveState的父状态P2pEnabledState来处理:
case WifiMonitor.P2P_DEVICE_FOUND_EVENT:
    WifiP2pDevice device = (WifiP2pDevice) message.obj;
    if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;
    mPeers.updateSupplicantDetails(device);
    sendPeersChangedBroadcast();
    break;


APP:
public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {
            if (manager != null) {
                manager.requestPeers(channel, (WifiP2pManager.PeerListListener) activity.getFragmentManager().findFragmentById(R.id.frag_list));
            }
}

WifiP2pManager:
public void requestPeers(Channel c, PeerListListener listener) {
        checkChannel(c);
        c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener));
    } 

4.2 P2P连接流程

P2P设备连接有四种情况:主动连接、被动连接、主动invite和被动invite 这里以主动连接介绍P2P连接流程。

APP:
mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                WifiP2pConfig config = new WifiP2pConfig();
                config.deviceAddress = device.deviceAddress;
            // 设置对端P2P Device的WSC配置方法为PBC
                config.wps.setup = WpsInfo.PBC;
                ((DeviceListFragment.DeviceActionListener) getActivity()).connect(config);
            }
        });
public void connect(WifiP2pConfig config) {
        manager.connect(channel, config, new WifiP2pManager.ActionListener() {
            public void onSuccess() {}
            public void onFailure(int reason) {}
        });
    }


WifiP2pManager:
public void connect(Channel c, WifiP2pConfig config, ActionListener listener) {
        checkChannel(c);
        checkP2pConfig(config);
        c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config);
    }
private static void checkP2pConfig(WifiP2pConfig c) {
        if (c == null) throw new IllegalArgumentException("config cannot be null");
        if (TextUtils.isEmpty(c.deviceAddress)) {
            throw new IllegalArgumentException("deviceAddress cannot be empty");
        }
    }

WifiP2pManager的connect函数将发送CONNECT消息给P2pStateMachine,该消息由
InactiveState状态自己来处理


WifiP2pService:
case WifiP2pManager.CONNECT:
    if (DBG) logd(getName() + " sending connect");
    WifiP2pConfig config = (WifiP2pConfig) message.obj;
    if (isConfigInvalid(config)) {
        loge("Dropping connect requeset " + config);
        replyToMessage(message, WifiP2pManager.CONNECT_FAILED);
        break;
    }
     mAutonomousGroup = false;
     mWifiNative.p2pStopFind();
     if (reinvokePersistentGroup(config)) {//判断是否采用persisten连接
         transitionTo(mGroupNegotiationState);
     } else {        transitionTo(mProvisionDiscoveryState);}
     mSavedPeerConfig = config;
     mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED);
     sendPeersChangedBroadcast();
     replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);
     break;

WifiP2pService:
Group分为persistent和Temporary两种,对于persistent的连接,一次连接成功后,连接信息不在变化,包含credential、GO MAC地址、Ssid等信息。若采用persisten连接,就是去wpa_supplicant拿这些信息,并进行匹配。对于temporary,采用negotiate方式,则跳转到ProvisionDiscoveryState,其父状态是GroupCreatingState。
class GroupCreatingState extends State {
        public void enter() {
        if (DBG) logd(getName());
        sendMessageDelayed(obtainMessage(GROUP_CREATING_TIMED_OUT,
             ++mGroupCreatingTimeoutIndex, 0), GROUP_CREATING_WAIT_TIME_MS);
      }
class ProvisionDiscoveryState extends State {
    public void enter() {
    if (DBG) logd(getName());
    mWifiNative.p2pProvisionDiscovery(mSavedPeerConfig);
   }
WifiNative的p2pProvisionDiscovery向对方发送Provision discovery封包。当对方收到Provision discovery封包后,会回复provision response,wpa_supplicant处理后,会给WifiMonitor发送P2P-PROV-DISC-PBC-RESP(当WPS方式为PBC时),WifiMonitor就会给P2pStateMachine发送P2P_PROV_DISC_PBC_RSP_EVNET。


WifiP2pService:
case WifiMonitor.P2P_PROV_DISC_PBC_RSP_EVENT:
    provDisc = (WifiP2pProvDiscEvent) message.obj;
    device = provDisc.device;
    if (!device.deviceAddress.equals(mSavedPeerConfig.deviceAddress)) break;
    if (mSavedPeerConfig.wps.setup == WpsInfo.PBC) {
        if (DBG) logd("Found a match " + mSavedPeerConfig);
        p2pConnectWithPinDisplay(mSavedPeerConfig);
        transitionTo(mGroupNegotiationState);
   }
   break;
private void p2pConnectWithPinDisplay(WifiP2pConfig config) {
     WifiP2pDevice dev = fetchCurrentDeviceDetails(config);
    String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner());//向wpa_supplicant发送P2P_CONNECT命令
    try {
        Integer.parseInt(pin);
        notifyInvitationSent(pin, config.deviceAddress);
    } catch (NumberFormatException ignore) {}
}


WifiP2pService:
开始Group negotiate后,wpa_supplicant会发送多个event给WifiMonitor,包括P2P-GO-NEG-SUCCESS、WPS-SUCCESS、P2P-GROUP-FORMATION-SUCCESS、P2P-GROUP-STARTED等.
其中比较重要的是P2P-GROUP-STARTED这个event,WifiMonitor收到这个event后会给P2pStateMachine发送P2P_GROUP_STARTED_EVENT,收到这个消息后,GroupNegotiationState主要调用DHCP相关的StateMachine开始会两端分配IP,然后更新group owner的相关信息,最后跳转至GroupCreatedState就表示连接完成了。
在DhcpStateMachine获取到IP地址以后,就会发送DhcpStateMachine.CMD_POST_DHCP_ACTION消息给P2pStateMachine
 case DhcpStateMachine.CMD_POST_DHCP_ACTION:
    DhcpResults dhcpResults = (DhcpResults) message.obj;
    if (message.arg1 == DhcpStateMachine.DHCP_SUCCESS && dhcpResults != null) {
        if (DBG) logd("DhcpResults: " + dhcpResults);
        setWifiP2pInfoOnGroupFormation(dhcpResults.serverAddress);
        sendP2pConnectionChangedBroadcast();
        //Turn on power save on client
        mWifiNative.setP2pPowerSave(mGroup.getInterface(), true);
        try {    String iface = mGroup.getInterface();
            mNwService.addInterfaceToLocalNetwork(iface, dhcpResults.getRoutes(iface));
       } catch (RemoteException e) { }
   } else {  loge("DHCP failed"); mWifiNative.p2pGroupRemove(mGroup.getInterface()); }
   break;


其他三种连接

android wifi p2p / wifi direct_第12张图片

android wifi p2p / wifi direct_第13张图片

android wifi p2p / wifi direct_第14张图片

 

 

PS:

最近在测试wifi p2p相关. 发现一些流程已经不是很清楚了, 翻出来两年前自己整理的资料, 发现远超现在的水平.

逆水行舟, 不进则退.

你可能感兴趣的:(协议相关,wifi)