Copyright Statement: This article is the original article of the blogger. It can not be reproduced without the permission of the blogger. https://blog.csdn.net/h784707460/article/details/81502574
I. wifi P2P Protocol Relevance
Wi-Fi Alliance (Wi-Fi Alliance) introduced an important technical specification, Wi-Fi P2P. The product name of the specification is Wi-Fi Direct, which supports multiple Wi-Fi devices to connect without AP. With the help of P2P technology, the direct connection between Wi-Fi devices will greatly expand the use scenarios of Wi-Fi technology. For example, multi-screen sharing and interaction between intelligent terminal devices.
1.1 P2P Architecture
Two roles are defined in the p2p architecture, namely:
- P2P Group Owner: referred to as GO, its role is similar to that of AP in Infrastructure BSS;
- P2P Client: abbreviated as GC, its function is similar to STA in Infrastructure BSS.
1.2 Device Discovery
Device Discovery uses Probe Request and Probe Response frames to exchange device information.
P2P defines two states and two stages for Device Discovery.
Two states:
- Search State: In this state, P2P Device will send Probe Request frames on 1, 6, 11 bands of 2.4 GHz, respectively. These bands are called Social Channels.
- Listen State: In this state, P2P Device will randomly select a band in the 1,6,11 band (the selected band is called Listen Channel) to listen for the Probe Request frame and reply to the Probe Response frame. Once Listen Channel is selected, it cannot be changed during the entire P2P Discovery phase.
Two stages:
- Scan Phase: Scan phase. P2P Device sends Probe Request frames (active scanning) over all the bands it supports. Used to quickly discover surrounding groups. P2P Device does not process Probe Request frames from other devices at this stage. (Full Channel Scanning)
- Find Phase: P2P Device will switch back and forth between Search State and Listen State. In Search State, P2P Device sends Probe Request frames, while in Listen State, it receives Probe Request frames from other devices and replies to Probe Response frames.
Note: The Operating Channel attribute indicates which band the formed P2P Group will work on. And its frequency band is not limited to those three bands specified in Social Channels.
1.3 GO Formation
GO Formation consists of two stages:
- GO Negotiation: At this stage, the two devices will negotiate who will do GO.
- Provisioning: After the roles of GO and Client are determined, the two Device s exchange security configuration information with WSC. Client can then use security configuration information to associate GO. (Provision Discovery(PD) process is to determine the WSC method used by both sides of the interaction, not the GF process)
GO negotiation includes a three-way handshake process for negotiating who is GO and some features of the P2P group. The three-way handshake process mainly exchanges the following information:
- Group Owner Intent Value
- Acceptable Operating Channel the Group may use
- Credentials for the P2P Group
- Group Duration: Temporary or Persistent
- Group support for other devices and optional capabilities
When a P2P device sends GO Negotiation Request, no confirmation frame is received within 100ms, then the negotiation is considered to be a failure. One of the main purposes of GO Negotiation is to exchange GO Intent attributes to determine who should be GO. If a P2P device can only be GO, its GO Intent value must be set to 15.
The Tie Breaker bit of the first GO Negotiation Request frame is randomly set to 0 or 1. In the next GO Negotiation Request frame (this bit will be reversed, except for retransmissions). The Tie breaker bit of the GO Negotiation Response frame will be reversed according to the corresponding position of the corresponding GO Negotiation Request frame.
wifi p2p workflow
Introduction to HSM and Async Channel
HSM (corresponding classes are StateMachine) and syncChannel are two important classes in Android Java Framework. At present, they are only used internally by Framework, and they are not included in SDK.
2.1 HSM(Hierarchical State Machine, Structured State Machine)
HSM makes some changes on the basis of the traditional state machine which treats all States equally, so that there is a hierarchical relationship between States and states. The function of generic is implemented in the parent state, while some specific processing is implemented in the child state.
Important functions in State:
- enter, SM will call its EA(Entry Action) when it enters a certain state.
- exit, which calls its EXA(Exit Action) when it exits a state;
- ProceMessage, in HSM, the way the outside world interacts with HSM is to send message to it. Message is handled by the processMessage function of the current State. If the current State successfully processes this message, it returns HANDLED. Otherwise return NOT_HANDLED. In Message processing, if the child state returns NOT_HANDLED, the processMessage of its parent state will be invoked. If the current state and ancestor state cannot be processed, the unhandled message of HSM will be invoked.
Some important API s in HSM:
- addState: Add a state. You can also specify the parent state.
- TransiionTo: Switch the state machine to a state.
- ObtainMessage: Since HSM works around a Handler internally, the outside world can only call the obtainMessage of HSM to get a Message.
- sendMessage: Send a message to HSM. Handler in HSM handles it.
- start: start the state machine.
- Stop state machines can use quit or quitNow functions.
The hierarchical relationship between States and states in HSM embodies:
- After SM is started, the EA of the initial state will be executed in the order of derivation. That is, the EA of its ancestral state is executed first, and the EA of its sub-state is executed later.
- When the State is switched, the exit of the old State is executed first, the enter of the new State is executed later, and the corresponding State of the new and old State derived tree also needs to execute the exit or enter function. But EXA and EA of the common ancestral State will not be executed. The execution order of EA is from ancestor class to descendant class, while that of EXA is from descendant class to ancestor class.
- When State processes a Message, if the child state cannot be processed (returning NOT_HANDLED), it is handed over to the parent state for processing.
2.2 AsyncChannel
Async Channel is used for communication between two handlers. The specific communication mode is that the source Handler sends messages to the target Handler through sendMessage, while the target Handler replies to the source Handler through replyToMessage to process the results. These two handlers can be located in the same process, or they can belong to two different processes.
Usage includes two different usage models.
- Under the simple request/response mode (one-to-many communication mode), the Server does not need to maintain the information of the Client, but only processes the requests from the Client. Before communication, the two sides do not need to display to establish a connection. The client (sender) sends the request to the Server (receiver), and the Server sends the reply message to the client through the replayToMessage method.
- One-to-one communication mode, this application mode is the server side to maintain Client information. In this way, Server can send its status or other meaningful information to Client.
WifiService related modules, the second application mode is used more.
Introduction to WifiP2p Settings and WifiP2p Service
WifiP2p Settings is the main class in Settings applications that handles P2P-related UI/UE logic, and it interacts with WifiP2p Service in the System Server process.
3.1 relates to the source file name and location (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
Loading interface elements
By monitoring the broadcasting, we can understand the information and changes related to Wi-Fi P2P in the system, and deal with them accordingly.
- WIFI_P2P_STATE_CHANGED_ACTION: Used to notify the system of the enablement of the P2P function, such as enable or disable.
- WIFI_P2P_PEERS_CHANGED_ACTION: The search information of other P2P devices will be saved within the system, and if the information changes, the system will send the broadcast. Receivers need to retrieve the information of these P2P devices through the requestPeers function of WifiP2P Manager.
- WIFI_P2P_CONNECTION_CHANGED_ACTION: Used to notify the P2P connection, the broadcast can carry two objects, Wifi P2pInfo and NetworkInfo. Relevant information can be obtained from these two objects.
- WIFI_P2P_THIS_DEVICE_CHANGED_ACTION: Used to notify local P2P devices that information has changed.
- WIFI_P2P_DISCOVERY_CHANGED_ACTION: Used to notify P2P Device Discovery of its working status, such as start or stop.
- WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION: The persistent group information for notification has changed.
Wifi P2p Settings will interact with Wifi P2p Manager and Wifi P2p Service in the system. WifiP2pSettings mainly use several important functions of WifiP2pManager:
- initialize: initialize WifiP2pManager. Channel, which will interact with WifiP2pService through AsyncChannel.
- Discovery Peers: Triggers WifiP2pService to initiate P2P Device scanning.
- RequPeers: Get the P2P Device information stored in the system.
- connect: To initiate a connection with a designated P2P Device, that is, to negotiate with each other to create or join a P2P network, a Group.
- Request GroupInfo: Gets Group information on the current connection.
3.3 WifiP2pService
WifiP2pService is the core module of Java layer of P2P function in Android system. The family class diagram is as follows.
- IWifiP2pManager, IWifiP2pManager.Stub and IWifiP2pManager.Stub.Proxy classes are converted from IWifiP2pManager.aidl files by aidl tools at compilation time.
- WifiP2pService is derived from the IWifiP2pManager.Stub class, which is the Binder server.
- WifiP2pManager is the client of WifiP2pService. It interacts with Binder through member variables mService and WifiSP2pervice.
P2pStateMachine is an internal class defined by WifiP2pService, and P2pStateMachine is the core of WifiP2pService. The States and hierarchical relationships defined in the P2pState Machine are shown as follows:
3.4 WifiP2pService workflow
The initial state of the P2pState Machine is P2pDisabled State, and then:
1) The P2pStateMachine receives a CMD_ENABLE_P2P message from the WifiStateMachine. In the processing logic of the message, the P2pStateMachine will create a WifiMonitor object to interact with the wpa_supplicant process. P2pState Machine is transferred to P2pEnabling State.
2) In P2p Enabling State, the SUP_CONNECT_EVENT message is processed, which represents the successful connection of WifiMonitor to wpa_supplicant. P2pStateMachine will be transferred to Inactive State.
3) The parent state of InactiveState is P2pEnabledState, and the EA of P2pEnabledState will initialize the P2P settings. This part of the code logic is in the initializeP2pSettings function. In addition, WifiP2p Settings will receive some P2P broadcasts, at which time the P2P function will start normally.
4) When searching for devices, the P2pState Machine will receive DISCVOER_PEERS messages. It is processed in the P2p Enabled State, and wpas_supplicant will initiate the P2P Device Discovery process to search for the surrounding P2P devices.
5) If a P2P device is found, the P2P State Machine will receive a P2P_DEVICE_FOUND_EVENT message. The message is processed by its parent state, P2pEnabledState. At the same time, WifiP2p Settings will receive information to update the UI accordingly.
6) When connected, WifiP2pSettings will send CONNECT messages to P2pStateMachine. The message is processed by Inactive State. In most cases (except in the case of Persistent Group or GO for the opposite device), the P2pState Machine will be transferred to Provision Discovery State.
7) In Provision Discovery State, the P2pState Machine will notify WPAS to implement the Provision Discovery process. After that, the P2P State Machine will receive the P2P_PROV_DISC_PBC_RSP_EVENT message. During the processing of this message, the P2pState Machine will notify WPAS and the end device to start the Group Formation process through the p2pConnect WithPinDisplay function. Since then, the P2pState Machine has been transferred to Group Negotiation State.
8) When the Group Formation is completed, a Group is created successfully, and the P2P State Machine will receive the P2P_GROUP_STARTED_EVENT message. The message is processed by Group Negotiation State. If this machine acts as GO, it will start a Dhcp server
9) When the peer-to-peer P2P Client(Group is established, the role is determined) is associated with the local GO, the AP_STA_CONNECTED_EVENT message will be sent to the P2pState Machine for processing.
IV. P2P process
Introduction to related documents:
1. WifiP2pSettings belongs to the application layer and is a visual presentation of the results of related operations. Mainly responsible for interface initialization, receiving bottom event messages for interface updates, issuing corresponding commands, etc.
2. WifiP2pManager: It is the external interface of Wi-Fi P2P, through which the core functions of Wi-Fi P2P can be accessed.
3. Wifi P2p Service: It is the core of Wi-Fi P2p, responsible for the control of the whole process of Wi-Fi.
4. P2pStateMachine: Inherited StateMachine. WifiMonitor was launched by issuing the loading driver and starting the supplicant command.
5. WifiMonitor: Open a MonitorThread to poll events, and the key function of polling is WifiNative.waitForEvent(). WifiMonitor converts the received underlying events into messages recognized by the WifiStateMachine and sends them to the WifiStateMachine.
6. WifiNative: It encapsulates a series of interface functions called locally and calls C++ code through JNI.
4.1 P2P Scanning Process
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 is empty, if empty, throw an Illegal ArgumentException exception c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener)); } WifiP2pService: P2pStateMachine Currently in InactiveState,However DISCOVER_PEERS The message is in its father's state. P2pEnabledState To deal with. 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)) {//Send P2P_FIND command to WPAS replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED); sendP2pDiscoveryChangedBroadcast(true); } else { replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED, WifiP2pManager.ERROR); } break; WifiP2pService: //The above process mainly calls the p2pFind function of WifiNative, which sends the P2P_FIND command to wpa_supplicant. If this command is successfully sent, the Application will be notified of its success through ActionListener, the second parameter of discoverPeers in WifiManager; if it fails, it will also be notified of its Application, except that it calls back different methods, one is onSuccess(), the other is onFailure(). wpa_supplicant Received P2P_FIND After that, start searching for the surrounding ones. P2P Equipment, if found, to WifiMonitor Send out P2P-DEVICE-FOUND In this way event,WifiMonitor Upon receipt, the P2P-DEVICE-FOUND Hinder data Data encapsulation becomes WifiP2pDevice Object, and then send P2P_DEVICE_FOUND_EVENT Message to WIfiStateMachine Handle. P2P_DEVICE_FOUND_EVENT Also from InactiveState Parent state P2pEnabledState To deal with: 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 Connection Flow
There are four situations of P2P device connection: active connection, passive connection, active invite and passive invite. This paper introduces the process of P2P connection by active connection.
APP: mContentView.findViewById(R.id.btn_connect).setOnClickListener(new View.OnClickListener() { public void onClick(View v) { WifiP2pConfig config = new WifiP2pConfig(); config.deviceAddress = device.deviceAddress; // Setting the WSC configuration method of peer-to-peer P2P Device to 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 Of connect The function will be sent CONNECT Message to P2pStateMachine,The message from InactiveState The state handles itself 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)) {//Determine whether persisten connection is used transitionTo(mGroupNegotiationState); } else { transitionTo(mProvisionDiscoveryState);} mSavedPeerConfig = config; mPeers.updateStatus(mSavedPeerConfig.deviceAddress, WifiP2pDevice.INVITED); sendPeersChangedBroadcast(); replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED); break; WifiP2pService: Group Divided into persistent and Temporary Two, for persistent Connection. After a successful connection, the connection information does not change, including credential,GO MAC Address, Ssid And other information. If adopted persisten Connecting is going. wpa_supplicant Take this information and match it. about temporary,Use negotiate Mode, then jump to ProvisionDiscoveryState,Its father state is 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 Of p2pProvisionDiscovery Send to each other Provision discovery Packet. When the other party receives Provision discovery After encapsulation, it will reply provision response,wpa_supplicant After treatment, it will give WifiMonitor Send out P2P-PROV-DISC-PBC-RESP(When WPS The way is PBC When) WifiMonitor Would give P2pStateMachine Send out 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());//Send P2P_CONNECT command to wpa_supplicant try { Integer.parseInt(pin); notifyInvitationSent(pin, config.deviceAddress); } catch (NumberFormatException ignore) {} } WifiP2pService: //After group negotiation, wpa_supplicant sends several event s to WifiMonitor, including P2P-GO-NEG-SUCCESS, WPS-SUCCESS, P2P-GROUP-FORMATION-SUCCESS, P2P-GROUP-STARTED, etc. //The most important one is the event of P2P-GROUP-STARTED. When WifiMonitor receives this event, it sends P2P_GROUP_STARTED_EVENT to the P2pStateMachine. After receiving this message, the Group Negotiation State mainly calls the DHCP-related StateMachine to allocate IP on both ends, then updates the owner group information, and finally jumps to the Group CreatedState to indicate that the connection is complete. //After the DhcpStateMachine gets the IP address, it sends the DhcpStateMachine.CMD_POST_DHCP_ACTION message to the 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;
Three other connections
PS:
Recently, we are testing wifi p2p correlation. We found that some processes are not very clear. We found that the data we compiled two years ago is far higher than the current level.
If you sail against the current, if you don't advance, you will retreat.