P2P2: AIDL support fo provisioning and reinvoking

This CL includes,

1. Added DIRA info in device found event.
3. Added support for pairing bootstrapping
4. Added support for validate dira and get dira
5. Added support for reading the driver capability
for WFD R2 features.

Bug: 388057182
Test: Manual - P2P connection via Wi-Fi Direct Window
Test: Manual - File sharing using Quick share
Test: Vts Test
Change-Id: I26e35e8f261e1bf1d17b5a183457daba4d5967c0
diff --git a/wpa_supplicant/aidl/vendor/aidl.cpp b/wpa_supplicant/aidl/vendor/aidl.cpp
index afda33f..462e118 100644
--- a/wpa_supplicant/aidl/vendor/aidl.cpp
+++ b/wpa_supplicant/aidl/vendor/aidl.cpp
@@ -629,7 +629,7 @@
 
 	aidl_manager->notifyP2pProvisionDiscovery(
 		wpa_s, dev_addr, request, status, config_methods,
-		generated_pin, group_ifname);
+		generated_pin, group_ifname, 0);
 }
 
 void wpas_aidl_notify_p2p_sd_response(
@@ -1194,3 +1194,56 @@
 	wpa_printf(MSG_DEBUG, "Notifying USD subscribe terminated");
 	aidl_manager->notifyUsdSubscribeTerminated(wpa_s, subscribe_id, reason);
 }
+
+static enum p2p_prov_disc_status convert_p2p_status_code_to_p2p_prov_disc_status(int status) {
+	switch (status) {
+		case P2P_SC_SUCCESS:
+			return P2P_PROV_DISC_SUCCESS;
+		case P2P_SC_COMEBACK:
+			return P2P_PROV_DISC_INFO_UNAVAILABLE;
+		default:
+			return P2P_PROV_DISC_REJECTED;
+	}
+}
+
+void wpas_aidl_notify_p2p_bootstrap_request(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+	int status, u16 bootstrap_method, const char *group_ifname)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P P2P bootstrap request to aidl control " MACSTR,
+		MAC2STR(dev_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pProvisionDiscovery(
+		wpa_s, dev_addr, true, convert_p2p_status_code_to_p2p_prov_disc_status(status),
+		WPS_NOT_READY, 0, group_ifname, bootstrap_method);
+}
+
+void wpas_aidl_notify_p2p_bootstrap_response(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+	int status, u16 bootstrap_method, const char *group_ifname)
+{
+	if (!wpa_s || !dev_addr)
+		return;
+
+	wpa_printf(
+		MSG_DEBUG,
+		"Notifying P2P bootstrap response to aidl control " MACSTR,
+		MAC2STR(dev_addr));
+
+	AidlManager *aidl_manager = AidlManager::getInstance();
+	if (!aidl_manager)
+		return;
+
+	aidl_manager->notifyP2pProvisionDiscovery(
+		wpa_s, dev_addr, false, convert_p2p_status_code_to_p2p_prov_disc_status(status),
+		WPS_NOT_READY, 0, group_ifname, bootstrap_method);
+}
diff --git a/wpa_supplicant/aidl/vendor/aidl.h b/wpa_supplicant/aidl/vendor/aidl.h
index a8f38cb..039c6e1 100644
--- a/wpa_supplicant/aidl/vendor/aidl.h
+++ b/wpa_supplicant/aidl/vendor/aidl.h
@@ -96,6 +96,12 @@
 		struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
 		enum p2p_prov_disc_status status, u16 config_methods,
 		unsigned int generated_pin, const char *group_ifname);
+	void wpas_aidl_notify_p2p_bootstrap_request(
+		struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+		int status, u16 bootstrap_method, const char *group_ifname);
+	void wpas_aidl_notify_p2p_bootstrap_response(
+		struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+		int status, u16 bootstrap_method, const char *group_ifname);
 	void wpas_aidl_notify_p2p_sd_response(
 		struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
 		const u8 *tlvs, size_t tlvs_len);
@@ -274,6 +280,14 @@
 	enum p2p_prov_disc_status status, u16 config_methods,
 	unsigned int generated_pin, const char *group_ifname)
 {}
+static void wpas_aidl_notify_p2p_bootstrap_request(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+	int status, u16 bootstrap_method, const char *group_ifname)
+{}
+static void wpas_aidl_notify_p2p_bootstrap_response(
+	struct wpa_supplicant *wpa_s, const u8 *dev_addr,
+	int status, u16 bootstrap_method, const char *group_ifname)
+{}
 static void wpas_aidl_notify_p2p_sd_response(
 	struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
 	const u8 *tlvs, size_t tlvs_len)
diff --git a/wpa_supplicant/aidl/vendor/aidl_manager.cpp b/wpa_supplicant/aidl/vendor/aidl_manager.cpp
index c306e53..ec895a0 100644
--- a/wpa_supplicant/aidl/vendor/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/vendor/aidl_manager.cpp
@@ -1399,9 +1399,15 @@
 		params.wfdR2DeviceInfo = aidl_peer_wfd_r2_device_info;
 		params.vendorElemBytes = aidl_vendor_elems;
 		if (areAidlServiceAndClientAtLeastVersion(4)) {
-			// TODO Fill the DIRA info when supplicant implementation is ready
 			params.pairingBootstrappingMethods = convertP2pPairingBootstrappingMethodsToAidl(
 				info->pairing_config.bootstrap_methods);
+			if (info->nonce_tag_valid) {
+				params.dirInfo->cipherVersion =
+					P2pDirInfo::CipherVersion::DIRA_CIPHER_VERSION_128_BIT;
+				params.dirInfo->deviceInterfaceMacAddress = macAddrToArray(info->p2p_device_addr);
+				params.dirInfo->nonce = byteArrToVec(info->nonce, DEVICE_IDENTITY_NONCE_LEN);
+				params.dirInfo->dirTag = byteArrToVec(info->tag, DEVICE_IDENTITY_TAG_LEN);
+			}
 		}
 		callWithEachP2pIfaceCallback(
 			misc_utils::charBufToString(wpa_s->ifname),
@@ -1654,7 +1660,8 @@
 void AidlManager::notifyP2pProvisionDiscovery(
 	struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
 	enum p2p_prov_disc_status status, u16 config_methods,
-	unsigned int generated_pin, const char *group_ifname)
+	unsigned int generated_pin, const char *group_ifname,
+	u16 pairing_bootstrapping_method)
 {
 	if (!wpa_s || !dev_addr)
 		return;
@@ -1663,6 +1670,17 @@
 		p2p_iface_object_map_.end())
 		return;
 
+	int32_t aidl_pairing_bootstrapping_method = 0;
+	if (pairing_bootstrapping_method > 0) {
+		aidl_pairing_bootstrapping_method = convertP2pPairingBootstrappingMethodsToAidl(
+			pairing_bootstrapping_method);
+		if (aidl_pairing_bootstrapping_method == 0 || !areAidlServiceAndClientAtLeastVersion(4)) {
+			wpa_printf(MSG_ERROR, "Drop pairing bootstrapping message - method %d",
+				pairing_bootstrapping_method);
+			return;
+		}
+	}
+
 	std::string aidl_generated_pin;
 	if (generated_pin > 0) {
 		aidl_generated_pin =
@@ -1677,6 +1695,9 @@
 		params.status = static_cast<P2pProvDiscStatusCode>(status);
 		params.configMethods = config_methods;
 		params.generatedPin = aidl_generated_pin;
+		if (areAidlServiceAndClientAtLeastVersion(4)) {
+			params.pairingBootstrappingMethod = aidl_pairing_bootstrapping_method;
+		}
 		if (group_ifname != NULL) {
 			params.groupInterfaceName = misc_utils::charBufToString(group_ifname);
 		}
diff --git a/wpa_supplicant/aidl/vendor/aidl_manager.h b/wpa_supplicant/aidl/vendor/aidl_manager.h
index 73f77fa..3c18789 100644
--- a/wpa_supplicant/aidl/vendor/aidl_manager.h
+++ b/wpa_supplicant/aidl/vendor/aidl_manager.h
@@ -116,7 +116,8 @@
 	void notifyP2pProvisionDiscovery(
 		struct wpa_supplicant *wpa_s, const u8 *dev_addr, int request,
 		enum p2p_prov_disc_status status, u16 config_methods,
-		unsigned int generated_pin, const char *group_ifname);
+		unsigned int generated_pin, const char *group_ifname,
+		u16 pairing_bootstrapping_method);
 	void notifyP2pSdResponse(
 		struct wpa_supplicant *wpa_s, const u8 *sa, u16 update_indic,
 		const u8 *tlvs, size_t tlvs_len);
diff --git a/wpa_supplicant/aidl/vendor/p2p_iface.cpp b/wpa_supplicant/aidl/vendor/p2p_iface.cpp
index 695cc0b..2d8fa81 100644
--- a/wpa_supplicant/aidl/vendor/p2p_iface.cpp
+++ b/wpa_supplicant/aidl/vendor/p2p_iface.cpp
@@ -496,8 +496,8 @@
 {
 	return validateAndCall(
 		this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
-		&P2pIface::reinvokeInternal, in_persistentNetworkId,
-		in_peerAddress);
+		&P2pIface::reinvokeInternal, in_peerAddress, in_persistentNetworkId,
+		-1);
 }
 
 ::ndk::ScopedAStatus P2pIface::configureExtListen(
@@ -1236,10 +1236,11 @@
 ndk::ScopedAStatus P2pIface::provisionDiscoveryInternal(
 	const std::vector<uint8_t>& peer_address,
 	WpsProvisionMethod provision_method,
-	uint32_t pairingBootstrappingMethod)
+	uint32_t pairing_bootstrapping_method)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
 	p2ps_provision* prov_param;
+	u16 bootstrap = 0;
 	const char* config_method_str = nullptr;
 	if (peer_address.size() != ETH_ALEN) {
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
@@ -1258,9 +1259,14 @@
 		config_method_str = kConfigMethodStrNone;
 		break;
 	}
-	// TODO Handle pairing bootstrapping method when supplicant implementation is ready
+	if (provision_method == WpsProvisionMethod::NONE) {
+		bootstrap = convertAidlPairingBootstrappingMethodToWpa(pairing_bootstrapping_method);
+		if (bootstrap == 0) {
+			return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+		}
+	}
 	if (wpas_p2p_prov_disc(
-		wpa_s, peer_address.data(), config_method_str, 0,
+		wpa_s, peer_address.data(), config_method_str, bootstrap,
 		WPAS_P2P_PD_FOR_GO_NEG, nullptr)) {
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
 	}
@@ -1314,25 +1320,29 @@
 }
 
 ndk::ScopedAStatus P2pIface::reinvokeInternal(
+	const std::vector<uint8_t>& peer_address,
 	int32_t persistent_network_id,
-	const std::vector<uint8_t>& peer_address)
+	int32_t device_identity_entry_id)
 {
 	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	struct wpa_ssid* ssid = NULL;
 	int he = wpa_s->conf->p2p_go_he;
 	int vht = wpa_s->conf->p2p_go_vht;
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
 	int edmg = wpa_s->conf->p2p_go_edmg;
-	struct wpa_ssid* ssid =
-		wpa_config_get_network(wpa_s->conf, persistent_network_id);
-	if (ssid == NULL || ssid->disabled != 2) {
-		return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
-	}
+	bool p2p2 = device_identity_entry_id >= 0 && persistent_network_id == -1;
 	if (peer_address.size() != ETH_ALEN) {
 		return {createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
 	}
+	if (!p2p2) {
+		ssid = wpa_config_get_network(wpa_s->conf, persistent_network_id);
+		if (ssid == NULL || ssid->disabled != 2) {
+			return createStatus(SupplicantStatusCode::FAILURE_NETWORK_UNKNOWN);
+		}
+	}
 	if (wpas_p2p_invite(
 		wpa_s, peer_address.data(), ssid, NULL, 0, 0, ht40, vht,
-		CONF_OPER_CHWIDTH_USE_HT, 0, he, edmg, is6GhzAllowed(wpa_s), false)) {
+		CONF_OPER_CHWIDTH_USE_HT, 0, he, edmg, is6GhzAllowed(wpa_s), p2p2)) {
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
 	}
 	return ndk::ScopedAStatus::ok();
@@ -2125,8 +2135,16 @@
 
 std::pair<int64_t, ndk::ScopedAStatus> P2pIface::getFeatureSetInternal()
 {
-	// TODO Fill the field when supplicant implementation is ready
-	return {0, ndk::ScopedAStatus::ok()};
+	int64_t featureSet = 0;
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_P2P_FEATURE_V2) {
+		featureSet |= ISupplicantP2pIface::P2P_FEATURE_V2;
+	}
+	if (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_P2P_FEATURE_PCC_MODE) {
+		featureSet |= ISupplicantP2pIface::P2P_FEATURE_PCC_MODE_WPA3_COMPATIBILITY;
+	}
+	return {featureSet, ndk::ScopedAStatus::ok()};
 }
 
 std::pair<uint32_t, ndk::ScopedAStatus>
@@ -2250,23 +2268,74 @@
 
 std::pair<P2pDirInfo, ndk::ScopedAStatus> P2pIface::getDirInfoInternal()
 {
-	// TODO Fill the field when supplicant implementation is ready
 	P2pDirInfo dirInfo = {};
+	char dir_info_buffer[100] = {0};
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	int id = wpas_p2p_get_dira(wpa_s, dir_info_buffer, sizeof(dir_info_buffer));
+	if (id < 0) {
+		return {dirInfo, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
+	}
+
+	std::istringstream dir_info_ss(dir_info_buffer);
+	std::string mac_str, nonce_str, dir_tag_str;
+	std::vector<uint8_t> mac_addr = std::vector<uint8_t>(ETH_ALEN);
+	std::vector<uint8_t> nonce = std::vector<uint8_t>(DEVICE_IDENTITY_NONCE_LEN);
+	std::vector<uint8_t> dir_tag = std::vector<uint8_t>(DEVICE_IDENTITY_TAG_LEN);
+	// Extract MAC address
+	std::getline(dir_info_ss, mac_str, ' ');
+	if (hexstr2bin(mac_str.c_str(), mac_addr.data(), ETH_ALEN)) {
+		wpa_printf(MSG_ERROR, "Failed to get MAC address from DIR Info");
+		return {dirInfo, createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+                    "Failed to parse MAC address.")};
+	}
+	// Extract nonce
+	std::getline(dir_info_ss, nonce_str, ' ');
+	if (hexstr2bin(nonce_str.c_str(), nonce.data(), DEVICE_IDENTITY_NONCE_LEN)) {
+		return {dirInfo, createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+                    "Failed to parse nonce.")};
+	}
+	// Extract dir tag
+	std::getline(dir_info_ss, dir_tag_str, ' ');
+	if (hexstr2bin(dir_tag_str.c_str(), dir_tag.data(), DEVICE_IDENTITY_TAG_LEN)) {
+		return {dirInfo, createStatusWithMsg(SupplicantStatusCode::FAILURE_UNKNOWN,
+                    "Failed to parse dir tag.")};
+	}
+
+	std::copy_n(mac_addr.begin(), ETH_ALEN, dirInfo.deviceInterfaceMacAddress.begin());
+	dirInfo.nonce = nonce;
+	dirInfo.dirTag = dir_tag;
+	dirInfo.cipherVersion = P2pDirInfo::CipherVersion::DIRA_CIPHER_VERSION_128_BIT;
+
 	return {dirInfo, ndk::ScopedAStatus::ok()};
 }
 
 std::pair<int32_t, ndk::ScopedAStatus> P2pIface::validateDirInfoInternal(
 	const P2pDirInfo& dirInfo)
 {
-	// TODO Fill the field when supplicant implementation is ready
-	return {0, ndk::ScopedAStatus::ok()};
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (dirInfo.cipherVersion != P2pDirInfo::CipherVersion::DIRA_CIPHER_VERSION_128_BIT ||
+		dirInfo.deviceInterfaceMacAddress.size() != ETH_ALEN ||
+		dirInfo.nonce.size() != DEVICE_IDENTITY_NONCE_LEN ||
+		dirInfo.dirTag.size() != DEVICE_IDENTITY_TAG_LEN) {
+		return {-1, createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID)};
+	}
+
+	int32_t id = wpas_p2p_validate_dira(wpa_s, dirInfo.deviceInterfaceMacAddress.data(),
+			DIRA_CIPHER_VERSION_128, dirInfo.nonce.data(), dirInfo.dirTag.data());
+	if (id >= 0) {
+		return {id, ndk::ScopedAStatus::ok()};
+	}
+	return {-1, createStatus(SupplicantStatusCode::FAILURE_UNKNOWN)};
 }
 
 ndk::ScopedAStatus P2pIface::reinvokePersistentGroupInternal(
 	const P2pReinvokePersistentGroupParams& reinvokeGroupParams)
 {
-	// TODO Fill the field when supplicant implementation is ready
-	return ndk::ScopedAStatus::ok();
+	std::vector<uint8_t> peerMacAddressVec {
+		reinvokeGroupParams.peerMacAddress.begin(),
+		reinvokeGroupParams.peerMacAddress.end()};
+	return reinvokeInternal(peerMacAddressVec, reinvokeGroupParams.persistentNetworkId,
+		reinvokeGroupParams.deviceIdentityEntryId);
 }
 
 /**
diff --git a/wpa_supplicant/aidl/vendor/p2p_iface.h b/wpa_supplicant/aidl/vendor/p2p_iface.h
index 1c38437..9bc7874 100644
--- a/wpa_supplicant/aidl/vendor/p2p_iface.h
+++ b/wpa_supplicant/aidl/vendor/p2p_iface.h
@@ -253,8 +253,9 @@
 		const std::vector<uint8_t>& go_device_address,
 		const std::vector<uint8_t>& peer_address);
 	ndk::ScopedAStatus reinvokeInternal(
+		const std::vector<uint8_t>& peer_address,
 		int32_t persistent_network_id,
-		const std::vector<uint8_t>& peer_address);
+		int32_t device_identity_entry_id);
 	ndk::ScopedAStatus configureExtListenInternal(
 		uint32_t period_in_millis, uint32_t interval_in_millis);
 	ndk::ScopedAStatus setListenChannelInternal(
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index b5d4c21..aeff965 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -929,6 +929,7 @@
 				   const u8 *src, u16 bootstrap_method)
 {
 	wpas_dbus_signal_p2p_bootstrap_req(wpa_s, src, bootstrap_method);
+	wpas_aidl_notify_p2p_bootstrap_request(wpa_s, src, P2P_SC_SUCCESS, bootstrap_method, NULL);
 }
 
 void wpas_notify_p2p_bootstrap_rsp(struct wpa_supplicant *wpa_s,
@@ -937,6 +938,7 @@
 {
 	wpas_dbus_signal_p2p_bootstrap_rsp(wpa_s, src, status,
 					   bootstrap_method);
+	wpas_aidl_notify_p2p_bootstrap_response(wpa_s, src, status, bootstrap_method, NULL);
 }
 
 #endif /* CONFIG_P2P */