wfd: Support to configured WFD R2 Element

Bug: 179342930
Test: atest VtsHalWifiSupplicantP2pV1_4TargetTest
Change-Id: Id289a894fa3ac6a5954a328d2eb83557c7b43196
diff --git a/wpa_supplicant/hidl/1.4/hidl.cpp b/wpa_supplicant/hidl/1.4/hidl.cpp
index 1e55305..649772a 100644
--- a/wpa_supplicant/hidl/1.4/hidl.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl.cpp
@@ -397,7 +397,8 @@
 void wpas_hidl_notify_p2p_device_found(
     struct wpa_supplicant *wpa_s, const u8 *addr,
     const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len)
+    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+    u8 peer_wfd_r2_device_info_len)
 {
 	if (!wpa_s || !addr || !info)
 		return;
@@ -411,7 +412,9 @@
 		return;
 
 	hidl_manager->notifyP2pDeviceFound(
-	    wpa_s, addr, info, peer_wfd_device_info, peer_wfd_device_info_len);
+	    wpa_s, addr, info, peer_wfd_device_info,
+	    peer_wfd_device_info_len, peer_wfd_r2_device_info,
+	    peer_wfd_r2_device_info_len);
 }
 
 void wpas_hidl_notify_p2p_device_lost(
diff --git a/wpa_supplicant/hidl/1.4/hidl.h b/wpa_supplicant/hidl/1.4/hidl.h
index 1d67d82..0974048 100644
--- a/wpa_supplicant/hidl/1.4/hidl.h
+++ b/wpa_supplicant/hidl/1.4/hidl.h
@@ -65,7 +65,8 @@
 	void wpas_hidl_notify_p2p_device_found(
 	    struct wpa_supplicant *wpa_s, const u8 *addr,
 	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len);
+	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	    u8 peer_wfd_r2_device_info_len);
 	void wpas_hidl_notify_p2p_device_lost(
 	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
 	void wpas_hidl_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index b7a7cf7..4a09da1 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -24,6 +24,7 @@
 using android::hardware::hidl_array;
 
 constexpr uint8_t kWfdDeviceInfoLen = 6;
+constexpr uint8_t kWfdR2DeviceInfoLen = 2;
 // GSM-AUTH:<RAND1>:<RAND2>[:<RAND3>]
 constexpr char kGsmAuthRegex2[] = "GSM-AUTH:([0-9a-f]+):([0-9a-f]+)";
 constexpr char kGsmAuthRegex3[] =
@@ -414,6 +415,8 @@
 namespace V1_4 {
 namespace implementation {
 using V1_0::ISupplicantStaIfaceCallback;
+using V1_0::ISupplicantP2pIfaceCallback;
+using ISupplicantP2pIfaceCallbackV1_4 = V1_4::ISupplicantP2pIfaceCallback;
 
 HidlManager *HidlManager::instance_ = NULL;
 
@@ -1224,7 +1227,8 @@
 void HidlManager::notifyP2pDeviceFound(
     struct wpa_supplicant *wpa_s, const u8 *addr,
     const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-    u8 peer_wfd_device_info_len)
+    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+    u8 peer_wfd_r2_device_info_len)
 {
 	if (!wpa_s || !addr || !info)
 		return;
@@ -1246,13 +1250,39 @@
 		}
 	}
 
-	callWithEachP2pIfaceCallback(
-	    wpa_s->ifname,
-	    std::bind(
-		&ISupplicantP2pIfaceCallback::onDeviceFound,
-		std::placeholders::_1, addr, info->p2p_device_addr,
-		info->pri_dev_type, info->device_name, info->config_methods,
-		info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
+	std::array<uint8_t, kWfdR2DeviceInfoLen> hidl_peer_wfd_r2_device_info{};
+	if (peer_wfd_r2_device_info) {
+		if (peer_wfd_r2_device_info_len != kWfdR2DeviceInfoLen) {
+			wpa_printf(
+			    MSG_ERROR, "Unexpected WFD R2 device info len: %d",
+			    peer_wfd_r2_device_info_len);
+			return;
+		} else {
+			os_memcpy(
+			    hidl_peer_wfd_r2_device_info.data(),
+			    peer_wfd_r2_device_info, kWfdR2DeviceInfoLen);
+		}
+	}
+
+	if (peer_wfd_r2_device_info_len == kWfdR2DeviceInfoLen) {
+		const std::function<
+		    Return<void>(android::sp<V1_4::ISupplicantP2pIfaceCallback>)>
+		    func = std::bind(
+			&ISupplicantP2pIfaceCallbackV1_4::onR2DeviceFound,
+			std::placeholders::_1, addr, info->p2p_device_addr,
+			info->pri_dev_type, info->device_name, info->config_methods,
+			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info,
+			hidl_peer_wfd_r2_device_info);
+		callWithEachP2pIfaceCallbackDerived(wpa_s->ifname, func);
+	} else {
+		callWithEachP2pIfaceCallback(
+		    wpa_s->ifname,
+		    std::bind(
+			&ISupplicantP2pIfaceCallback::onDeviceFound,
+			std::placeholders::_1, addr, info->p2p_device_addr,
+			info->pri_dev_type, info->device_name, info->config_methods,
+			info->dev_capab, info->group_capab, hidl_peer_wfd_device_info));
+	}
 }
 
 void HidlManager::notifyP2pDeviceLost(
@@ -1815,7 +1845,7 @@
 		//wnm_bss_termination_duration contains 12 bytes of BSS
 		//termination duration subelement. Format of IE is
 		// Sub eid | Length | BSS termination TSF | Duration
-		//    1         1             8                2
+		//    1	 1	     8		2
 		// Duration indicates number of minutes for which BSS is not
 		// present.
 		duration_ms = WPA_GET_LE16(wpa_s->wnm_bss_termination_duration + 10);
@@ -2276,6 +2306,24 @@
 
 /**
  * Helper function to invoke the provided callback method on all the
+ * registered derived interface callback hidl objects for the specified
+ * |ifname|.
+ *
+ * @param ifname Name of the corresponding interface.
+ * @param method Pointer to the required hidl method from
+ * derived |V1_x::ISupplicantIfaceCallback|.
+ */
+template <class CallbackTypeDerived>
+void HidlManager::callWithEachP2pIfaceCallbackDerived(
+    const std::string &ifname,
+    const std::function<
+	Return<void>(android::sp<CallbackTypeDerived>)> &method)
+{
+	callWithEachIfaceCallbackDerived(ifname, method, p2p_iface_callbacks_map_);
+}
+
+/**
+ * Helper function to invoke the provided callback method on all the
  * registered V1.1 interface callback hidl objects for the specified
  * |ifname|.
  *
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index 21b2ed4..ccde11c 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -118,7 +118,8 @@
 	void notifyP2pDeviceFound(
 	    struct wpa_supplicant *wpa_s, const u8 *addr,
 	    const struct p2p_peer_info *info, const u8 *peer_wfd_device_info,
-	    u8 peer_wfd_device_info_len);
+	    u8 peer_wfd_device_info_len, const u8 *peer_wfd_r2_device_info,
+	    u8 peer_wfd_r2_device_info_len);
 	void notifyP2pDeviceLost(
 	    struct wpa_supplicant *wpa_s, const u8 *p2p_device_addr);
 	void notifyP2pFindStopped(struct wpa_supplicant *wpa_s);
@@ -236,6 +237,11 @@
 	    const std::string &ifname,
 	    const std::function<android::hardware::Return<void>(
 		android::sp<ISupplicantP2pIfaceCallback>)> &method);
+	template <class CallbackTypeDerived>
+	void callWithEachP2pIfaceCallbackDerived(
+	    const std::string &ifname,
+	    const std::function<
+		Return<void>(android::sp<CallbackTypeDerived>)> &method);
 	void callWithEachStaIfaceCallback(
 	    const std::string &ifname,
 	    const std::function<android::hardware::Return<void>(
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index 7baffa2..16fd11a 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -33,6 +33,7 @@
 const char kConfigMethodStrKeypad[] = "keypad";
 constexpr char kSetMiracastMode[] = "MIRACAST ";
 constexpr uint8_t kWfdDeviceInfoSubelemId = 0;
+constexpr uint8_t kWfdR2DeviceInfoSubelemId = 11;
 constexpr char kWfdDeviceInfoSubelemLenHexStr[] = "0006";
 
 std::function<void()> pending_join_scan_callback = NULL;
@@ -895,6 +896,23 @@
 	    &P2pIface::getEdmgInternal, _hidl_cb);
 }
 
+Return<void> P2pIface::registerCallback_1_4(
+    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
+    registerCallback_1_4_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::registerCallback_1_4Internal, _hidl_cb, callback);
+}
+
+Return<void> P2pIface::setWfdR2DeviceInfo(
+    const hidl_array<uint8_t, 4>& info, setWfdR2DeviceInfo_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, V1_4::SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::setWfdR2DeviceInfoInternal, _hidl_cb, info);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -1855,6 +1873,40 @@
 		(wpa_s->p2p_go_edmg == 1)};
 }
 
+V1_4::SupplicantStatus P2pIface::registerCallback_1_4Internal(
+    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback)
+{
+	HidlManager* hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager ||
+	    hidl_manager->addP2pIfaceCallbackHidlObject(ifname_, callback)) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
+V1_4::SupplicantStatus P2pIface::setWfdR2DeviceInfoInternal(
+    const std::array<uint8_t, 4>& info)
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	uint32_t wfd_r2_device_info_hex_len = info.size() * 2 + 1;
+	std::vector<char> wfd_r2_device_info_hex(wfd_r2_device_info_hex_len);
+	wpa_snprintf_hex(
+	    wfd_r2_device_info_hex.data(), wfd_r2_device_info_hex.size(),
+	    info.data(),info.size());
+	std::string wfd_r2_device_info_set_cmd_str =
+	     std::to_string(kWfdR2DeviceInfoSubelemId) + " " +
+	     wfd_r2_device_info_hex.data();
+	std::vector<char> wfd_r2_device_info_set_cmd(
+	     wfd_r2_device_info_set_cmd_str.c_str(),
+	     wfd_r2_device_info_set_cmd_str.c_str() +
+	     wfd_r2_device_info_set_cmd_str.size() + 1);
+	if (wifi_display_subelem_set(
+		wpa_s->global, wfd_r2_device_info_set_cmd.data())) {
+		return {V1_4::SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {V1_4::SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.h b/wpa_supplicant/hidl/1.4/p2p_iface.h
index 1694efe..c8ddc01 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.h
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.h
@@ -200,6 +200,12 @@
 	    bool enable, setMacRandomization_cb _hidl_cb) override;
 	Return<void> setEdmg(bool enable, setEdmg_cb _hidl_cb) override;
 	Return<void> getEdmg(getEdmg_cb _hidl_cb) override;
+	Return<void> registerCallback_1_4(
+	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback,
+	    registerCallback_1_4_cb _hidl_cb) override;
+	Return<void> setWfdR2DeviceInfo(
+	    const hidl_array<uint8_t, 4>& info,
+	    setWfdR2DeviceInfo_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -311,6 +317,10 @@
 	SupplicantStatus setMacRandomizationInternal(bool enable);
 	V1_4::SupplicantStatus setEdmgInternal(bool enable);
 	std::pair<V1_4::SupplicantStatus, bool> getEdmgInternal();
+	V1_4::SupplicantStatus registerCallback_1_4Internal(
+	    const sp<V1_4::ISupplicantP2pIfaceCallback>& callback);
+	V1_4::SupplicantStatus setWfdR2DeviceInfoInternal(
+	    const std::array<uint8_t, 4>& info);
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index 731808d..1bf279e 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -1756,6 +1756,7 @@
 #ifdef CONFIG_SAE_PK
 	mask |= V1_4::WpaDriverCapabilitiesMask::SAE_PK;
 #endif
+	mask |= V1_4::WpaDriverCapabilitiesMask::WFD_R2;
 
 	wpa_printf(MSG_DEBUG, "Driver capability mask: 0x%x", mask);
 
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index aae3c3f..5508f16 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -660,7 +660,9 @@
 
 	wpas_hidl_notify_p2p_device_found(wpa_s, addr, info,
 					  peer_wfd_device_info,
-					  peer_wfd_device_info_len);
+					  peer_wfd_device_info_len,
+					  peer_wfd_r2_device_info,
+					  peer_wfd_r2_device_info_len);
 }
 
 
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 759a05e..a7e7587 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2496,7 +2496,7 @@
 	u8 *wfd_dev_info = NULL;
 	u8 wfd_dev_info_len = 0;
 	u8 *wfd_r2_dev_info = NULL;
-	u8 wfd_r2_dev_info_len = 0
+	u8 wfd_r2_dev_info_len = 0;
 #ifndef CONFIG_NO_STDOUT_DEBUG
 	struct wpa_supplicant *wpa_s = ctx;
 	char devtype[WPS_DEV_TYPE_BUFSIZE];