(七十三)WifiP2pSettings学习

2023-12-19 07:48

本文主要是介绍(七十三)WifiP2pSettings学习,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言:最近在看WiFi相关的知识,发现WiFi direct是一种连接方式,WiFi直连(一种类似于蓝牙的传输应用)和WFD(Wifi Display)都会用到,先学习一下设置里比较熟悉的WifiP2pSettings。

 

1. WiFi p2p

WiFi P2P是Wi-Fi联盟推出的一项重要技术规范。 该规范的商品名为Wi-Fi Direct, 它支持多个Wi-Fi设备在没有AP的情况下相互连接。相对应的在连接同一个AP的情况下互相连接的叫做TDLS。WiFi联盟推出了名为TDLS(Tunneled Direct Link Setup,通道直接链路建立)的无线标准,这项标准允许两款设备通过WiFi网络进行点对点直连,与早起提倡的WiFi Direct相似,不过功能则更加完善。

 

2. Setting代码梳理

Settings里对应WiFi p2p主要就是WifiP2pSettings

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

wifi p2p 时序图

2.1 onActivityCreated

WifiP2pSettings是个fragment,内部最先调用的是onActivityCreated。

    @Overridepublic void onActivityCreated(Bundle savedInstanceState) {final Activity activity = getActivity();mWifiP2pManager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);if (mWifiP2pManager != null) {mChannel = mWifiP2pManager.initialize(activity.getApplicationContext(),getActivity().getMainLooper(), null);if (mChannel == null) {//Failure to set up connectionLog.e(TAG, "Failed to set up connection with wifi p2p service");mWifiP2pManager = null;}} else {Log.e(TAG, "mWifiP2pManager is null !");}if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DIALOG_PEER)) {WifiP2pDevice device = savedInstanceState.getParcelable(SAVE_DIALOG_PEER);mSelectedWifiPeer = new WifiP2pPeer(getPrefContext(), device);}if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_DEVICE_NAME)) {mSavedDeviceName = savedInstanceState.getString(SAVE_DEVICE_NAME);}if (savedInstanceState != null && savedInstanceState.containsKey(SAVE_SELECTED_GROUP)) {mSelectedGroupName = savedInstanceState.getString(SAVE_SELECTED_GROUP);}mRenameListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {String name = mDeviceNameText.getText().toString();if (name != null) {for (int i = 0; i < name.length(); i++) {char cur = name.charAt(i);if(!Character.isDigit(cur) && !Character.isLetter(cur)&& cur != '-' && cur != '_' && cur != ' ') {Toast.makeText(getActivity(),R.string.wifi_p2p_failed_rename_message,Toast.LENGTH_LONG).show();return;}}}mWifiP2pManager.setDeviceName(mChannel,mDeviceNameText.getText().toString(),new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " device rename success");}public void onFailure(int reason) {Toast.makeText(getActivity(),R.string.wifi_p2p_failed_rename_message,Toast.LENGTH_LONG).show();}});}}}};//disconnect dialog listenermDisconnectListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {mWifiP2pManager.removeGroup(mChannel, new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " remove group success");}public void onFailure(int reason) {if (DBG) Log.d(TAG, " remove group fail " + reason);}});}}}};//cancel connect dialog listenermCancelConnectListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {mWifiP2pManager.cancelConnect(mChannel,new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " cancel connect success");}public void onFailure(int reason) {if (DBG) Log.d(TAG, " cancel connect fail " + reason);}});}}}};//delete persistent group dialog listenermDeleteGroupListener = new OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {if (which == DialogInterface.BUTTON_POSITIVE) {if (mWifiP2pManager != null) {if (mSelectedGroup != null) {if (DBG) Log.d(TAG, " deleting group " + mSelectedGroup.getGroupName());mWifiP2pManager.deletePersistentGroup(mChannel,mSelectedGroup.getNetworkId(),new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " delete group success");}public void onFailure(int reason) {if (DBG) Log.d(TAG, " delete group fail " + reason);}});mSelectedGroup = null;} else {if (DBG) Log.w(TAG, " No selected group to delete!");}}} else if (which == DialogInterface.BUTTON_NEGATIVE) {if (DBG) {Log.d(TAG, " forgetting selected group " + mSelectedGroup.getGroupName());}mSelectedGroup = null;}}};super.onActivityCreated(savedInstanceState);}

主要干了两个事:

1.初始化了

            mChannel = mWifiP2pManager.initialize(activity.getApplicationContext(),getActivity().getMainLooper(), null);

2.初始化了四个listener,分别是mRenameListener mDisconnectListener mCancelConnectListener mDeleteGroupListener

 

这里主要继续看下WifiP2pManager.initialize的方法做了什么操作。

WifiP2pManager

    /*** Registers the application with the Wi-Fi framework. This function* must be the first to be called before any p2p operations are performed.** @param srcContext is the context of the source* @param srcLooper is the Looper on which the callbacks are receivied* @param listener for callback at loss of framework communication. Can be null.* @return Channel instance that is necessary for performing any further p2p operations*/public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {Binder binder = new Binder();Channel channel = initalizeChannel(srcContext, srcLooper, listener, getMessenger(binder),binder);return channel;}
    private Channel initalizeChannel(Context srcContext, Looper srcLooper, ChannelListener listener,Messenger messenger, Binder binder) {if (messenger == null) return null;Channel c = new Channel(srcContext, srcLooper, listener, binder, this);if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)== AsyncChannel.STATUS_SUCCESSFUL) {return c;} else {c.close();return null;}}
    /*** Get a reference to WifiP2pService handler. This is used to establish* an AsyncChannel communication with WifiService** @param binder A binder for the service to associate with this client.** @return Messenger pointing to the WifiP2pService handler* @hide*/public Messenger getMessenger(Binder binder) {try {return mService.getMessenger(binder);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}}

这里用到了AsyncChannel,简单来说就是将WifiP2pManager$Channel$P2pHandler和WifiP2pServiceImpl$ClientHandler连接上,以便后续的message通讯。

 

2.2 onResume

    @Overridepublic void onResume() {super.onResume();mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION);mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION);mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION);mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION);mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION);mIntentFilter.addAction(WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION);final PreferenceScreen preferenceScreen = getPreferenceScreen();getActivity().registerReceiver(mReceiver, mIntentFilter);if (mWifiP2pManager != null) {mWifiP2pManager.requestPeers(mChannel, WifiP2pSettings.this);}}

做了两件事情

1.注册了6个广播的监听器

2.调用WifiP2pManager.requestPeers来获取周围可连接设备,填充UI。

2.2.1 startSearch

广播接收器代码如下:

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if (WifiP2pManager.WIFI_P2P_STATE_CHANGED_ACTION.equals(action)) {mWifiP2pEnabled = intent.getIntExtra(WifiP2pManager.EXTRA_WIFI_STATE,WifiP2pManager.WIFI_P2P_STATE_DISABLED) == WifiP2pManager.WIFI_P2P_STATE_ENABLED;handleP2pStateChanged();} else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST);handlePeersChanged();} else if (WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION.equals(action)) {if (mWifiP2pManager == null) return;NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_NETWORK_INFO);WifiP2pInfo wifip2pinfo = (WifiP2pInfo) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_INFO);if (networkInfo.isConnected()) {if (DBG) Log.d(TAG, "Connected");} else if (mLastGroupFormed != true) {//start a search when we are disconnected//but not on group removed broadcast eventstartSearch();}mLastGroupFormed = wifip2pinfo.groupFormed;} else if (WifiP2pManager.WIFI_P2P_THIS_DEVICE_CHANGED_ACTION.equals(action)) {mThisDevice = (WifiP2pDevice) intent.getParcelableExtra(WifiP2pManager.EXTRA_WIFI_P2P_DEVICE);if (DBG) Log.d(TAG, "Update device info: " + mThisDevice);mThisDevicePreferenceController.updateDeviceName(mThisDevice);} else if (WifiP2pManager.WIFI_P2P_DISCOVERY_CHANGED_ACTION.equals(action)) {int discoveryState = intent.getIntExtra(WifiP2pManager.EXTRA_DISCOVERY_STATE,WifiP2pManager.WIFI_P2P_DISCOVERY_STOPPED);if (DBG) Log.d(TAG, "Discovery state changed: " + discoveryState);if (discoveryState == WifiP2pManager.WIFI_P2P_DISCOVERY_STARTED) {updateSearchMenu(true);} else {updateSearchMenu(false);}} else if (WifiP2pManager.WIFI_P2P_PERSISTENT_GROUPS_CHANGED_ACTION.equals(action)) {if (mWifiP2pManager != null) {mWifiP2pManager.requestPersistentGroupInfo(mChannel, WifiP2pSettings.this);}}}};

发现在接收到WifiP2pManager.WIFI_P2P_CONNECTION_CHANGED_ACTION消息的时候会调用startSearch方法

    private void startSearch() {if (mWifiP2pManager != null && !mWifiP2pSearching) {mWifiP2pManager.discoverPeers(mChannel, new WifiP2pManager.ActionListener() {public void onSuccess() {}public void onFailure(int reason) {if (DBG) Log.d(TAG, " discover fail " + reason);}});}}

WifiP2pManager

    /*** Initiate peer discovery. A discovery process involves scanning for available Wi-Fi peers* for the purpose of establishing a connection.** <p> The function call immediately returns after sending a discovery request* to the framework. The application is notified of a success or failure to initiate* discovery through listener callbacks {@link ActionListener#onSuccess} or* {@link ActionListener#onFailure}.** <p> The discovery remains active until a connection is initiated or* a p2p group is formed. Register for {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent to* determine when the framework notifies of a change as peers are discovered.** <p> Upon receiving a {@link #WIFI_P2P_PEERS_CHANGED_ACTION} intent, an application* can request for the list of peers using {@link #requestPeers}.** @param c is the channel created at {@link #initialize}* @param listener for callbacks on success or failure. Can be null.*/public void discoverPeers(Channel c, ActionListener listener) {checkChannel(c);c.mAsyncChannel.sendMessage(DISCOVER_PEERS, 0, c.putListener(listener));}

看API注释里讲

  1. 搜索会持续到连接或者p2p group 建立
  2. 当监听到WIFI_P2P_PEERS_CHANGED_ACTION消息时,应用可以通过requestPeers请求peers列表。

观察到WifiP2pSettings里有监听这个消息做mPeers和界面的刷新处理。

WifiP2pSettings:

            } else if (WifiP2pManager.WIFI_P2P_PEERS_CHANGED_ACTION.equals(action)) {mPeers = (WifiP2pDeviceList) intent.getParcelableExtra(WifiP2pManager.EXTRA_P2P_DEVICE_LIST);handlePeersChanged();

之前梳理过了这个DISCOVER_PEERS消息会发送给WifiP2pServiceImpl来继续处理。

WifiP2pServiceImpl:

    /*** Handles client connections*/private class ClientHandler extends WifiHandler {ClientHandler(String tag, android.os.Looper looper) {super(tag, looper);}@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case WifiP2pManager.SET_DEVICE_NAME:case WifiP2pManager.SET_WFD_INFO:case WifiP2pManager.DISCOVER_PEERS:case WifiP2pManager.STOP_DISCOVERY:case WifiP2pManager.CONNECT:case WifiP2pManager.CANCEL_CONNECT:case WifiP2pManager.CREATE_GROUP:case WifiP2pManager.REMOVE_GROUP:case WifiP2pManager.START_LISTEN:case WifiP2pManager.STOP_LISTEN:case WifiP2pManager.SET_CHANNEL:case WifiP2pManager.START_WPS:case WifiP2pManager.ADD_LOCAL_SERVICE:case WifiP2pManager.REMOVE_LOCAL_SERVICE:case WifiP2pManager.CLEAR_LOCAL_SERVICES:case WifiP2pManager.DISCOVER_SERVICES:case WifiP2pManager.ADD_SERVICE_REQUEST:case WifiP2pManager.REMOVE_SERVICE_REQUEST:case WifiP2pManager.CLEAR_SERVICE_REQUESTS:case WifiP2pManager.REQUEST_PEERS:case WifiP2pManager.REQUEST_CONNECTION_INFO:case WifiP2pManager.REQUEST_GROUP_INFO:case WifiP2pManager.DELETE_PERSISTENT_GROUP:case WifiP2pManager.REQUEST_PERSISTENT_GROUP_INFO:mP2pStateMachine.sendMessage(Message.obtain(msg));break;default:Slog.d(TAG, "ClientHandler.handleMessage ignoring msg=" + msg);break;}}}

熟悉的状态机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)) {replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_SUCCEEDED);sendP2pDiscoveryChangedBroadcast(true);} else {replyToMessage(message, WifiP2pManager.DISCOVER_PEERS_FAILED,WifiP2pManager.ERROR);}break;
    // Set a two minute discover timeout to avoid STA scans from being blockedprivate static final int DISCOVER_TIMEOUT_S = 120;

有个120s的timeout限制。

WifiNative:

    /*** Initiate a P2P service discovery with a (optional) timeout.** @param timeout Max time to be spent is peforming discovery.*        Set to 0 to indefinely continue discovery untill and explicit*        |stopFind| is sent.* @return boolean value indicating whether operation was successful.*/public boolean p2pFind(int timeout) {return mSupplicantP2pIfaceHal.find(timeout);}

SupplicantP2pIfaceHal:

    /*** Initiate a P2P service discovery with a (optional) timeout.** @param timeout Max time to be spent is peforming discovery.*        Set to 0 to indefinely continue discovery untill and explicit*        |stopFind| is sent.* @return boolean value indicating whether operation was successful.*/public boolean find(int timeout) {synchronized (mLock) {if (!checkSupplicantP2pIfaceAndLogFailure("find")) return false;if (timeout < 0) {Log.e(TAG, "Invalid timeout value: " + timeout);return false;}SupplicantResult<Void> result = new SupplicantResult("find(" + timeout + ")");try {result.setResult(mISupplicantP2pIface.find(timeout));} catch (RemoteException e) {Log.e(TAG, "ISupplicantP2pIface exception: " + e);supplicantServiceDiedHandler();}return result.isSuccess();}}

 

2.2.2 requestPeers

WifiP2pManager:

    /*** Request the current list of peers.** @param c is the channel created at {@link #initialize}* @param listener for callback when peer list is available. Can be null.*/public void requestPeers(Channel c, PeerListListener listener) {checkChannel(c);Bundle callingPackage = new Bundle();callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName());c.mAsyncChannel.sendMessage(REQUEST_PEERS, 0, c.putListener(listener),callingPackage);}

WifiP2pServiceImpl:

DefaultState会处理该消息,并回复给WifiP2pManager

                    case WifiP2pManager.REQUEST_PEERS:replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,getPeers((Bundle) message.obj, message.sendingUid));break;

WifiManager:

                   case RESPONSE_PEERS:WifiP2pDeviceList peers = (WifiP2pDeviceList) message.obj;if (listener != null) {((PeerListListener) listener).onPeersAvailable(peers);}break;

WifiP2pSettings:

    @Overridepublic void onPeersAvailable(WifiP2pDeviceList peers) {if (DBG) Log.d(TAG, "Requested peers are available");mPeers = peers;handlePeersChanged();}
    private void handlePeersChanged() {mPeerCategoryController.removeAllChildren();mConnectedDevices = 0;if (DBG) Log.d(TAG, "List of available peers");for (WifiP2pDevice peer: mPeers.getDeviceList()) {if (DBG) Log.d(TAG, "-> " + peer);mPeerCategoryController.addChild(new WifiP2pPeer(getPrefContext(), peer));if (peer.status == WifiP2pDevice.CONNECTED) mConnectedDevices++;}if (DBG) Log.d(TAG, " mConnectedDevices " + mConnectedDevices);}

简单来看调用framework和回调获取扫描结果流程已经借宿了,回过头来看下WifiP2pServiceImpl的getPeers方法:

WifiP2pServiceImpl

                    case WifiP2pManager.REQUEST_PEERS:replyToMessage(message, WifiP2pManager.RESPONSE_PEERS,getPeers((Bundle) message.obj, message.sendingUid));break;
        /*** Enforces permissions on the caller who is requesting for P2p Peers* @param pkg Bundle containing the calling package string* @param uid of the caller* @return WifiP2pDeviceList the peer list*/private WifiP2pDeviceList getPeers(Bundle pkg, int uid) {String pkgName = pkg.getString(WifiP2pManager.CALLING_PACKAGE);boolean scanPermission = false;WifiPermissionsUtil wifiPermissionsUtil;// getPeers() is guaranteed to be invoked after Wifi Service is up// This ensures getInstance() will return a non-null object nowif (mWifiInjector == null) {mWifiInjector = WifiInjector.getInstance();}wifiPermissionsUtil = mWifiInjector.getWifiPermissionsUtil();// Minimum Version to enforce location permission is O or latertry {scanPermission = wifiPermissionsUtil.canAccessScanResults(pkgName, uid,Build.VERSION_CODES.O);} catch (SecurityException e) {Log.e(TAG, "Security Exception, cannot access peer list");}if (scanPermission) {return new WifiP2pDeviceList(mPeers);} else {return new WifiP2pDeviceList();}}}

这个方法只是校验了下权限,然后将mPeers封装出来了,mPeers应该是之前扫描结果封装起来的。

而mPeers的加载成员只有调用如下方法:

WifiP2pDeviceList:

/** Only updates details fetched from the supplicant @hide */public void updateSupplicantDetails(WifiP2pDevice device) {validateDevice(device);WifiP2pDevice d = mDevices.get(device.deviceAddress);if (d != null) {d.deviceName = device.deviceName;d.primaryDeviceType = device.primaryDeviceType;d.secondaryDeviceType = device.secondaryDeviceType;d.wpsConfigMethodsSupported = device.wpsConfigMethodsSupported;d.deviceCapability = device.deviceCapability;d.groupCapability = device.groupCapability;d.wfdInfo = device.wfdInfo;return;}//Not found, add a new onemDevices.put(device.deviceAddress, device);}

只有在WifiP2pServiceImpl$P2pEnabledState状态处理P2P_DEVICE_FOUND_EVENT的时候加载

                    case WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT:if (message.obj == null) {Log.e(TAG, "Illegal argument(s)");break;}WifiP2pDevice device = (WifiP2pDevice) message.obj;if (mThisDevice.deviceAddress.equals(device.deviceAddress)) break;mPeers.updateSupplicantDetails(device);sendPeersChangedBroadcast();break;

这个消息应该是WifiMonitor监听到supplicant返回来告知WifiP2pServiceImpl$P2pEnabledState处理的。

            mWifiMonitor.registerHandler(interfaceName,WifiP2pMonitor.P2P_DEVICE_FOUND_EVENT, getHandler());

 

2.3 connect

看下wifi p2p connect流程

WifiP2pSettings:

   @Overridepublic boolean onPreferenceTreeClick(Preference preference) {if (preference instanceof WifiP2pPeer) {mSelectedWifiPeer = (WifiP2pPeer) preference;if (mSelectedWifiPeer.device.status == WifiP2pDevice.CONNECTED) {showDialog(DIALOG_DISCONNECT);} else if (mSelectedWifiPeer.device.status == WifiP2pDevice.INVITED) {showDialog(DIALOG_CANCEL_CONNECT);} else {WifiP2pConfig config = new WifiP2pConfig();config.deviceAddress = mSelectedWifiPeer.device.deviceAddress;int forceWps = SystemProperties.getInt("wifidirect.wps", -1);if (forceWps != -1) {config.wps.setup = forceWps;} else {if (mSelectedWifiPeer.device.wpsPbcSupported()) {config.wps.setup = WpsInfo.PBC;} else if (mSelectedWifiPeer.device.wpsKeypadSupported()) {config.wps.setup = WpsInfo.KEYPAD;} else {config.wps.setup = WpsInfo.DISPLAY;}}mWifiP2pManager.connect(mChannel, config,new WifiP2pManager.ActionListener() {public void onSuccess() {if (DBG) Log.d(TAG, " connect success");}public void onFailure(int reason) {Log.e(TAG, " connect fail " + reason);Toast.makeText(getActivity(),R.string.wifi_p2p_failed_connect_message,Toast.LENGTH_SHORT).show();}});}} else if (preference instanceof WifiP2pPersistentGroup) {mSelectedGroup = (WifiP2pPersistentGroup) preference;showDialog(DIALOG_DELETE_GROUP);}return super.onPreferenceTreeClick(preference);}

WifiP2pManager:

    /*** Start a p2p connection to a device with the specified configuration.** <p> The function call immediately returns after sending a connection request* to the framework. The application is notified of a success or failure to initiate* connect through listener callbacks {@link ActionListener#onSuccess} or* {@link ActionListener#onFailure}.** <p> Register for {@link #WIFI_P2P_CONNECTION_CHANGED_ACTION} intent to* determine when the framework notifies of a change in connectivity.** <p> If the current device is not part of a p2p group, a connect request initiates* a group negotiation with the peer.** <p> If the current device is part of an existing p2p group or has created* a p2p group with {@link #createGroup}, an invitation to join the group is sent to* the peer device.** @param c is the channel created at {@link #initialize}* @param config options as described in {@link WifiP2pConfig} class* @param listener for callbacks on success or failure. Can be null.*/public void connect(Channel c, WifiP2pConfig config, ActionListener listener) {checkChannel(c);checkP2pConfig(config);c.mAsyncChannel.sendMessage(CONNECT, 0, c.putListener(listener), config);}

WifiP2pServiceImpl$GroupCreatedState(看InactiveState也会处理)

                    case WifiP2pManager.CONNECT:WifiP2pConfig config = (WifiP2pConfig) message.obj;if (isConfigInvalid(config)) {loge("Dropping connect request " + config);replyToMessage(message, WifiP2pManager.CONNECT_FAILED);break;}logd("Inviting device : " + config.deviceAddress);mSavedPeerConfig = config;if (mWifiNative.p2pInvite(mGroup, config.deviceAddress)) {mPeers.updateStatus(config.deviceAddress, WifiP2pDevice.INVITED);sendPeersChangedBroadcast();replyToMessage(message, WifiP2pManager.CONNECT_SUCCEEDED);} else {replyToMessage(message, WifiP2pManager.CONNECT_FAILED,WifiP2pManager.ERROR);}// TODO: figure out updating the status to declined// when invitation is rejectedbreak;

WifiNative

    /*** Invite a device to a persistent group.* If the peer device is the group owner of the persistent group, the peer* parameter is not needed. Otherwise it is used to specify which* device to invite. |goDeviceAddress| parameter may be used to override* the group owner device address for Invitation Request should it not be* known for some reason (this should not be needed in most cases).** @param group Group object to use.* @param deviceAddress MAC address of the device to invite.** @return boolean value indicating whether operation was successful.*/public boolean p2pInvite(WifiP2pGroup group, String deviceAddress) {return mSupplicantP2pIfaceHal.invite(group, deviceAddress);}

SupplicantP2pIfaceHal

/*** Invite a device to a persistent group.* If the peer device is the group owner of the persistent group, the peer* parameter is not needed. Otherwise it is used to specify which* device to invite. |goDeviceAddress| parameter may be used to override* the group owner device address for Invitation Request should it not be* known for some reason (this should not be needed in most cases).** @param group Group object to use.* @param peerAddress MAC address of the device to invite.** @return boolean value indicating whether operation was successful.*/public boolean invite(WifiP2pGroup group, String peerAddress) {if (TextUtils.isEmpty(peerAddress)) return false;synchronized (mLock) {if (!checkSupplicantP2pIfaceAndLogFailure("invite")) return false;if (group == null) {Log.e(TAG, "Cannot invite to null group.");return false;}if (group.getOwner() == null) {Log.e(TAG, "Cannot invite to group with null owner.");return false;}if (group.getOwner().deviceAddress == null) {Log.e(TAG, "Group owner has no mac address.");return false;}byte[] ownerMacAddress = null;try {ownerMacAddress = NativeUtil.macAddressToByteArray(group.getOwner().deviceAddress);} catch (Exception e) {Log.e(TAG, "Group owner mac address parse error.", e);return false;}if (peerAddress == null) {Log.e(TAG, "Cannot parse peer mac address.");return false;}byte[] peerMacAddress;try {peerMacAddress = NativeUtil.macAddressToByteArray(peerAddress);} catch (Exception e) {Log.e(TAG, "Peer mac address parse error.", e);return false;}SupplicantResult<Void> result = new SupplicantResult("invite(" + group.getInterface() + ", " + group.getOwner().deviceAddress+ ", " + peerAddress + ")");try {result.setResult(mISupplicantP2pIface.invite(group.getInterface(), ownerMacAddress, peerMacAddress));} catch (RemoteException e) {Log.e(TAG, "ISupplicantP2pIface exception: " + e);supplicantServiceDiedHandler();}return result.isSuccess();}}

先梳理到这。。。

 

3.总结

wifi p2p 时序图

这篇关于(七十三)WifiP2pSettings学习的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/511420

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

线性代数|机器学习-P36在图中找聚类

文章目录 1. 常见图结构2. 谱聚类 感觉后面几节课的内容跨越太大,需要补充太多的知识点,教授讲得内容跨越较大,一般一节课的内容是书本上的一章节内容,所以看视频比较吃力,需要先预习课本内容后才能够很好的理解教授讲解的知识点。 1. 常见图结构 假设我们有如下图结构: Adjacency Matrix:行和列表示的是节点的位置,A[i,j]表示的第 i 个节点和第 j 个

Node.js学习记录(二)

目录 一、express 1、初识express 2、安装express 3、创建并启动web服务器 4、监听 GET&POST 请求、响应内容给客户端 5、获取URL中携带的查询参数 6、获取URL中动态参数 7、静态资源托管 二、工具nodemon 三、express路由 1、express中路由 2、路由的匹配 3、路由模块化 4、路由模块添加前缀 四、中间件