wpa_supplicant(hidl): Support add/remove interfaces

Add HIDL API's for adding/removing interfaces dynamically.
These interface params are pixel specific, so other OEM's will need to
modify the params to suit their device configuration.

Bug: 65673678
Test: VTS tests
Change-Id: I41d3452652bb2e2139aad4670b71c07fab4c574d
diff --git a/wpa_supplicant/hidl/1.1/supplicant.cpp b/wpa_supplicant/hidl/1.1/supplicant.cpp
index 9d2dac7..950f0c7 100644
--- a/wpa_supplicant/hidl/1.1/supplicant.cpp
+++ b/wpa_supplicant/hidl/1.1/supplicant.cpp
@@ -11,6 +11,20 @@
 #include "hidl_return_util.h"
 #include "supplicant.h"
 
+namespace {
+// Pre-populated interface params for interfaces controlled by wpa_supplicant.
+// Note: This may differ for other OEM's. So, modify this accordingly.
+constexpr char kIfaceDriverName[] = "nl80211";
+constexpr char kStaIfaceConfPath[] =
+		"/data/misc/wifi/wpa_supplicant.conf";
+constexpr char kStaIfaceConfOverlayPath[] =
+		"/vendor/etc/wifi/wpa_supplicant_overlay.conf";
+constexpr char kP2pIfaceConfPath[] =
+		"/data/misc/wifi/p2p_supplicant.conf";
+constexpr char kP2pIfaceConfOverlayPath[] =
+		"/vendor/etc/wifi/p2p_supplicant_overlay.conf";
+}  // namespace
+
 namespace android {
 namespace hardware {
 namespace wifi {
@@ -19,11 +33,6 @@
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
-// These are hardcoded for android.
-const char Supplicant::kDriverName[] = "nl80211";
-const char Supplicant::kConfigFilePath[] =
-    "/data/misc/wifi/wpa_supplicant.conf";
-
 Supplicant::Supplicant(struct wpa_global* global) : wpa_global_(global) {}
 bool Supplicant::isValid()
 {
@@ -31,6 +40,22 @@
 	return true;
 }
 
+Return<void> Supplicant::addInterface(
+    const IfaceInfo& iface_info, addInterface_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::addInterfaceInternal, _hidl_cb, iface_info);
+}
+
+Return<void> Supplicant::removeInterface(
+    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_IFACE_INVALID,
+	    &Supplicant::removeInterfaceInternal, _hidl_cb, iface_info);
+}
+
 Return<void> Supplicant::getInterface(
     const IfaceInfo& iface_info, getInterface_cb _hidl_cb)
 {
@@ -94,6 +119,58 @@
 }
 
 std::pair<SupplicantStatus, sp<ISupplicantIface>>
+Supplicant::addInterfaceInternal(const IfaceInfo& iface_info)
+{
+	android::sp<ISupplicantIface> iface;
+
+	// Check if required |ifname| argument is empty.
+	if (iface_info.name.empty()) {
+		return {{SupplicantStatusCode::FAILURE_ARGS_INVALID, ""}, {}};
+	}
+	// Try to get the wpa_supplicant record for this iface, return
+	// the iface object with the appropriate status code if it exists.
+	SupplicantStatus status;
+	std::tie(status, iface) = getInterfaceInternal(iface_info);
+	if (status.code == SupplicantStatusCode::SUCCESS) {
+		return {{SupplicantStatusCode::FAILURE_IFACE_EXISTS, ""},
+			iface};
+	}
+
+	struct wpa_interface iface_params = {};
+	iface_params.driver = kIfaceDriverName;
+	if (iface_info.type == IfaceType::P2P) {
+		iface_params.confname = kP2pIfaceConfPath;
+		iface_params.confanother = kP2pIfaceConfOverlayPath;
+	} else {
+		iface_params.confname = kStaIfaceConfPath;
+		iface_params.confanother = kStaIfaceConfOverlayPath;
+	}
+	iface_params.ifname = iface_info.name.c_str();
+	struct wpa_supplicant* wpa_s =
+	    wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+	if (!wpa_s) {
+		return {{SupplicantStatusCode::FAILURE_UNKNOWN, ""}, {}};
+	}
+	// The supplicant core creates a corresponding hidl object via
+	// HidlManager when |wpa_supplicant_add_iface| is called.
+	return getInterfaceInternal(iface_info);
+}
+
+SupplicantStatus Supplicant::removeInterfaceInternal(
+    const IfaceInfo& iface_info)
+{
+	struct wpa_supplicant* wpa_s =
+	    wpa_supplicant_get_iface(wpa_global_, iface_info.name.c_str());
+	if (!wpa_s) {
+		return {SupplicantStatusCode::FAILURE_IFACE_UNKNOWN, ""};
+	}
+	if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+		return {SupplicantStatusCode::FAILURE_UNKNOWN, ""};
+	}
+	return {SupplicantStatusCode::SUCCESS, ""};
+}
+
+std::pair<SupplicantStatus, sp<ISupplicantIface>>
 Supplicant::getInterfaceInternal(const IfaceInfo& iface_info)
 {
 	struct wpa_supplicant* wpa_s =
diff --git a/wpa_supplicant/hidl/1.1/supplicant.h b/wpa_supplicant/hidl/1.1/supplicant.h
index b14065f..75fb0db 100644
--- a/wpa_supplicant/hidl/1.1/supplicant.h
+++ b/wpa_supplicant/hidl/1.1/supplicant.h
@@ -44,6 +44,10 @@
 	bool isValid();
 
 	// Hidl methods exposed.
+	Return<void> addInterface(
+	    const IfaceInfo& iface_info, addInterface_cb _hidl_cb) override;
+	Return<void> removeInterface(
+	    const IfaceInfo& iface_info, removeInterface_cb _hidl_cb) override;
 	Return<void> getInterface(
 	    const IfaceInfo& iface_info, getInterface_cb _hidl_cb) override;
 	Return<void> listInterfaces(listInterfaces_cb _hidl_cb) override;
@@ -63,6 +67,9 @@
 	// Corresponding worker functions for the HIDL methods.
 	std::pair<SupplicantStatus, sp<ISupplicantIface>> getInterfaceInternal(
 	    const IfaceInfo& iface_info);
+	std::pair<SupplicantStatus, sp<ISupplicantIface>> addInterfaceInternal(
+	    const IfaceInfo& iface_info);
+	SupplicantStatus removeInterfaceInternal(const IfaceInfo& iface_info);
 	std::pair<SupplicantStatus, std::vector<ISupplicant::IfaceInfo>>
 	listInterfacesInternal();
 	SupplicantStatus registerCallbackInternal(