Implement addUsdInterface and removeUsdInterface
in the mainline supplicant.

Bug: 365585450
Test: Manual test - call the add and remove
      methods from the framework
Change-Id: Idc66472dabd183cea790ebc553d97be230c586f7
diff --git a/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp b/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
index 97ad056..dd2babe 100644
--- a/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
+++ b/wpa_supplicant/aidl/mainline/mainline_supplicant.cpp
@@ -6,14 +6,78 @@
  * See README for more details.
  */
 
+#include "aidl/shared/shared_utils.h"
 #include "mainline_supplicant.h"
+#include "utils.h"
 
 using ::ndk::ScopedAStatus;
 
+const std::string kConfigFilePath = "/apex/com.android.wifi/etc/mainline_supplicant.conf";
+
 MainlineSupplicant::MainlineSupplicant(struct wpa_global* global) {
     wpa_global_ = global;
 }
 
+ndk::ScopedAStatus MainlineSupplicant::addUsdInterface(const std::string& ifaceName) {
+    if (ifaceName.empty()) {
+        wpa_printf(MSG_ERROR, "Empty iface name provided");
+        return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+    }
+
+    if (active_usd_ifaces_.find(ifaceName) != active_usd_ifaces_.end()) {
+        wpa_printf(MSG_INFO, "Interface %s already exists", ifaceName.c_str());
+        return ndk::ScopedAStatus::ok();
+    }
+
+    if (ensureConfigFileExistsAtPath(kConfigFilePath) != 0) {
+        wpa_printf(MSG_ERROR, "Unable to find config file at %s", kConfigFilePath.c_str());
+        return createStatusWithMsg(
+            SupplicantStatusCode::FAILURE_UNKNOWN, "Config file does not exist");
+    }
+
+    struct wpa_interface iface_params = {};
+    iface_params.driver = kIfaceDriverName;
+    iface_params.ifname = ifaceName.c_str();
+    iface_params.confname = kConfigFilePath.c_str();
+
+    struct wpa_supplicant* wpa_s = wpa_supplicant_add_iface(wpa_global_, &iface_params, NULL);
+    if (!wpa_s) {
+        wpa_printf(MSG_ERROR, "Unable to add interface %s", ifaceName.c_str());
+        return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+    }
+
+    wpa_printf(MSG_INFO, "Interface %s was added successfully", ifaceName.c_str());
+    active_usd_ifaces_.insert(ifaceName);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus MainlineSupplicant::removeUsdInterface(const std::string& ifaceName) {
+    if (ifaceName.empty()) {
+        wpa_printf(MSG_ERROR, "Empty iface name provided");
+        return createStatus(SupplicantStatusCode::FAILURE_ARGS_INVALID);
+    }
+
+    if (active_usd_ifaces_.find(ifaceName) == active_usd_ifaces_.end()) {
+        wpa_printf(MSG_ERROR, "Interface %s does not exist", ifaceName.c_str());
+        return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+    }
+
+    struct wpa_supplicant* wpa_s =
+        wpa_supplicant_get_iface(wpa_global_, ifaceName.c_str());
+    if (!wpa_s) {
+        wpa_printf(MSG_ERROR, "Interface %s does not exist", ifaceName.c_str());
+        return createStatus(SupplicantStatusCode::FAILURE_IFACE_UNKNOWN);
+    }
+    if (wpa_supplicant_remove_iface(wpa_global_, wpa_s, 0)) {
+        wpa_printf(MSG_ERROR, "Unable to remove interface %s", ifaceName.c_str());
+        return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
+    }
+
+    wpa_printf(MSG_INFO, "Interface %s was removed successfully", ifaceName.c_str());
+    active_usd_ifaces_.erase(ifaceName);
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus MainlineSupplicant::terminate() {
     wpa_printf(MSG_INFO, "Terminating...");
     wpa_supplicant_terminate_proc(wpa_global_);
diff --git a/wpa_supplicant/aidl/mainline/mainline_supplicant.h b/wpa_supplicant/aidl/mainline/mainline_supplicant.h
index 4cdc9c8..38a355f 100644
--- a/wpa_supplicant/aidl/mainline/mainline_supplicant.h
+++ b/wpa_supplicant/aidl/mainline/mainline_supplicant.h
@@ -9,7 +9,10 @@
 #ifndef MAINLINE_SUPPLICANT_IMPL_H
 #define MAINLINE_SUPPLICANT_IMPL_H
 
+#include <set>
+
 #include <aidl/android/system/wifi/mainline_supplicant/BnMainlineSupplicant.h>
+#include <aidl/android/system/wifi/mainline_supplicant/SupplicantStatusCode.h>
 
 extern "C"
 {
@@ -17,18 +20,24 @@
 #include "utils/includes.h"
 #include "utils/wpa_debug.h"
 #include "wpa_supplicant_i.h"
+#include "scan.h"
 }
 
 using ::aidl::android::system::wifi::mainline_supplicant::BnMainlineSupplicant;
+using ::aidl::android::system::wifi::mainline_supplicant::SupplicantStatusCode;
 
 class MainlineSupplicant : public BnMainlineSupplicant {
     public:
         MainlineSupplicant(struct wpa_global* global);
+        ndk::ScopedAStatus addUsdInterface(const std::string& ifaceName);
+        ndk::ScopedAStatus removeUsdInterface(const std::string& ifaceName);
         ndk::ScopedAStatus terminate();
 
     private:
         // Raw pointer to the global structure maintained by the core
         struct wpa_global* wpa_global_;
+        // Names of all active USD interfaces
+        std::set<std::string> active_usd_ifaces_;
 };
 
 #endif  // MAINLINE_SUPPLICANT_IMPL_H
diff --git a/wpa_supplicant/aidl/mainline/utils.h b/wpa_supplicant/aidl/mainline/utils.h
new file mode 100644
index 0000000..703b9ee
--- /dev/null
+++ b/wpa_supplicant/aidl/mainline/utils.h
@@ -0,0 +1,25 @@
+/*
+ * WPA Supplicant - Utilities for the mainline supplicant
+ * Copyright (c) 2024, Google Inc. All rights reserved.
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef MAINLINE_SUPPLICANT_UTILS_H
+#define MAINLINE_SUPPLICANT_UTILS_H
+
+#include <aidl/android/system/wifi/mainline_supplicant/SupplicantStatusCode.h>
+
+inline ndk::ScopedAStatus createStatus(SupplicantStatusCode statusCode) {
+	return ndk::ScopedAStatus::fromServiceSpecificError(
+		static_cast<int32_t>(statusCode));
+}
+
+inline ndk::ScopedAStatus createStatusWithMsg(
+	    SupplicantStatusCode statusCode, std::string msg) {
+	return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+		static_cast<int32_t>(statusCode), msg.c_str());
+}
+
+#endif // MAINLINE_SUPPLICANT_UTILS_H