Merge "wpa_supplicant(hidl): Support for P2P client list and save config"
am: a252e40c0d

Change-Id: Iba9de70bf214be2802c8bf43d234a4a6c2f0d9a6
diff --git a/wpa_supplicant/hidl/p2p_iface.cpp b/wpa_supplicant/hidl/p2p_iface.cpp
index 86f6f8f..ce9aaf7 100644
--- a/wpa_supplicant/hidl/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/p2p_iface.cpp
@@ -495,6 +495,13 @@
 	    &P2pIface::reportNfcHandoverInitiationInternal, _hidl_cb, select);
 }
 
+Return<void> P2pIface::saveConfig(saveConfig_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &P2pIface::saveConfigInternal, _hidl_cb);
+}
+
 std::pair<SupplicantStatus, std::string> P2pIface::getNameInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, ifname_};
@@ -1207,6 +1214,18 @@
 	return {SupplicantStatusCode::SUCCESS, ""};
 }
 
+SupplicantStatus P2pIface::saveConfigInternal()
+{
+	struct wpa_supplicant* wpa_s = retrieveIfacePtr();
+	if (!wpa_s->conf->update_config) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	if (wpa_config_write(wpa_s->confname, wpa_s->conf)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
 /**
  * Retrieve the underlying |wpa_supplicant| struct
  * pointer for this iface.
diff --git a/wpa_supplicant/hidl/p2p_iface.h b/wpa_supplicant/hidl/p2p_iface.h
index e8770c6..4f08a78 100644
--- a/wpa_supplicant/hidl/p2p_iface.h
+++ b/wpa_supplicant/hidl/p2p_iface.h
@@ -184,6 +184,7 @@
 	Return<void> reportNfcHandoverInitiation(
 	    const hidl_vec<uint8_t>& select,
 	    reportNfcHandoverInitiation_cb _hidl_cb) override;
+	Return<void> saveConfig(saveConfig_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -287,6 +288,7 @@
 	    const std::vector<uint8_t>& request);
 	SupplicantStatus reportNfcHandoverInitiationInternal(
 	    const std::vector<uint8_t>& select);
+	SupplicantStatus saveConfigInternal();
 
 	struct wpa_supplicant* retrieveIfacePtr();
 	struct wpa_supplicant* retrieveGroupIfacePtr(
diff --git a/wpa_supplicant/hidl/p2p_network.cpp b/wpa_supplicant/hidl/p2p_network.cpp
index 788f99c..7daa453 100644
--- a/wpa_supplicant/hidl/p2p_network.cpp
+++ b/wpa_supplicant/hidl/p2p_network.cpp
@@ -103,6 +103,21 @@
 	    &P2pNetwork::isGoInternal, _hidl_cb);
 }
 
+Return<void> P2pNetwork::setClientList(
+    const hidl_vec<hidl_array<uint8_t, 6>> &clients, setClientList_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::setClientListInternal, _hidl_cb, clients);
+}
+
+Return<void> P2pNetwork::getClientList(getClientList_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_NETWORK_INVALID,
+	    &P2pNetwork::getClientListInternal, _hidl_cb);
+}
+
 std::pair<SupplicantStatus, uint32_t> P2pNetwork::getIdInternal()
 {
 	return {{SupplicantStatusCode::SUCCESS, ""}, network_id_};
@@ -169,6 +184,47 @@
 		(wpa_ssid->mode == wpa_ssid::wpas_mode::WPAS_MODE_P2P_GO)};
 }
 
+SupplicantStatus P2pNetwork::setClientListInternal(
+    const std::vector<hidl_array<uint8_t, 6>> &clients)
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	os_free(wpa_ssid->p2p_client_list);
+	// Internal representation uses a generic MAC addr/mask storage format
+	// (even though the mask is always 0xFF'ed for p2p_client_list). So, the
+	// first 6 bytes holds the client MAC address and the next 6 bytes are
+	// OxFF'ed.
+	wpa_ssid->p2p_client_list =
+	    (u8 *)os_malloc(ETH_ALEN * 2 * clients.size());
+	if (!wpa_ssid->p2p_client_list) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (const auto &client : clients) {
+		os_memcpy(list, client.data(), ETH_ALEN);
+		list += ETH_ALEN;
+		os_memset(list, 0xFF, ETH_ALEN);
+		list += ETH_ALEN;
+	}
+	wpa_ssid->num_p2p_clients = clients.size();
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
+P2pNetwork::getClientListInternal()
+{
+	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
+	if (!wpa_ssid->p2p_client_list) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	std::vector<hidl_array<uint8_t, 6>> clients;
+	u8 *list = wpa_ssid->p2p_client_list;
+	for (size_t i = 0; i < wpa_ssid->num_p2p_clients; i++) {
+		clients.emplace_back(list);
+		list += 2 * ETH_ALEN;
+	}
+	return {{SupplicantStatusCode::SUCCESS, ""}, clients};
+}
+
 /**
  * Retrieve the underlying |wpa_ssid| struct pointer for
  * this network.
diff --git a/wpa_supplicant/hidl/p2p_network.h b/wpa_supplicant/hidl/p2p_network.h
index d09a6be..6164f43 100644
--- a/wpa_supplicant/hidl/p2p_network.h
+++ b/wpa_supplicant/hidl/p2p_network.h
@@ -55,6 +55,10 @@
 	Return<void> isCurrent(isCurrent_cb _hidl_cb) override;
 	Return<void> isPersistent(isPersistent_cb _hidl_cb) override;
 	Return<void> isGo(isGo_cb _hidl_cb) override;
+	Return<void> setClientList(
+	    const hidl_vec<hidl_array<uint8_t, 6>>& clients,
+	    setClientList_cb _hidl_cb) override;
+	Return<void> getClientList(getClientList_cb _hidl_cb) override;
 
 private:
 	// Corresponding worker functions for the HIDL methods.
@@ -68,6 +72,10 @@
 	std::pair<SupplicantStatus, bool> isCurrentInternal();
 	std::pair<SupplicantStatus, bool> isPersistentInternal();
 	std::pair<SupplicantStatus, bool> isGoInternal();
+	SupplicantStatus setClientListInternal(
+	    const std::vector<hidl_array<uint8_t, 6>>& clients);
+	std::pair<SupplicantStatus, std::vector<hidl_array<uint8_t, 6>>>
+	getClientListInternal();
 
 	struct wpa_ssid* retrieveNetworkPtr();
 	struct wpa_supplicant* retrieveIfacePtr();