wifi: Create 1.3::IfaceParams to support dual bands (AP+AP Part 1)

1. Use 1.3::IfaceParams to support AP+AP.
The design still uses 1.2::IfaceParams to create the AP but it updates
1.2::IfaceParams from 1.3::IfaceParams since dual APs information are stored
in 1.3::IfaceParams.

a. Support interface query from bridge interface.
b. Read dual APs configuration adn enable it.
c. Callback use bridge interface in dual APs mode.

AP+AP Part 1 includes:
1. HIDL: Hostapd support dual bands/channels configuration
2. Framework: HostapdHal support only
3. Hostapd deamon:
a. Support briged interface
b. Support config dual bands/channel
c. Callback use bridge interface in dual APs mode.

Bug: 162686273
Test: Manual Test to test single AP mode.
Test: Manual test code to check hostapd.conf is expected.
Test: atest -c VtsHalWifiHostapdV1_3TargetTest
Test: atest -c VtsHalWifiHostapdV1_2TargetTest
Test: atest -c VtsHalWifiHostapdV1_1TargetTest
Test: atest -c VtsHalWifiHostapdV1_0TargetTest
Change-Id: I7d2a0ae1f935a18dd62daa3befc0eae0452882cc
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index 668d8f4..6bbf3d9 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -10,9 +10,14 @@
 #include <sstream>
 #include <string>
 #include <vector>
+#include <net/if.h>
+#include <sys/socket.h>
+#include <linux/if_bridge.h>
+
 
 #include <android-base/file.h>
 #include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
 
 #include "hostapd.h"
 #include "hidl_return_util.h"
@@ -20,6 +25,7 @@
 extern "C"
 {
 #include "common/wpa_ctrl.h"
+#include "drivers/linux_ioctl.h"
 }
 
 // The HIDL implementation for hostapd creates a hostapd.conf dynamically for
@@ -37,6 +43,46 @@
 using android::hardware::wifi::hostapd::V1_3::Generation;
 using android::hardware::wifi::hostapd::V1_3::Bandwidth;
 
+#define MAX_PORTS 1024
+bool GetInterfacesInBridge(std::string br_name,
+                           std::vector<std::string>* interfaces) {
+	android::base::unique_fd sock(socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
+	if (sock.get() < 0) {
+		wpa_printf(MSG_ERROR, "Failed to create sock (%s) in %s",
+			strerror(errno), __FUNCTION__);
+		return false;
+	}
+
+	struct ifreq request;
+	int i, ifindices[MAX_PORTS];
+	char if_name[IFNAMSIZ];
+	unsigned long args[3];
+
+	memset(ifindices, 0, MAX_PORTS * sizeof(int));
+
+	args[0] = BRCTL_GET_PORT_LIST;
+	args[1] = (unsigned long) ifindices;
+	args[2] = MAX_PORTS;
+
+	strlcpy(request.ifr_name, br_name.c_str(), IFNAMSIZ);
+	request.ifr_data = (char *)args;
+
+	if (ioctl(sock.get(), SIOCDEVPRIVATE, &request) < 0) {
+		wpa_printf(MSG_ERROR, "Failed to ioctl SIOCDEVPRIVATE in %s",
+			__FUNCTION__);
+		return false;
+	}
+
+	for (i = 0; i < MAX_PORTS; i ++) {
+		memset(if_name, 0, IFNAMSIZ);
+		if (ifindices[i] == 0 || !if_indextoname(ifindices[i], if_name)) {
+			continue;
+		}
+		interfaces->push_back(if_name);
+	}
+	return true;
+}
+
 std::string WriteHostapdConfig(
     const std::string& interface_name, const std::string& config)
 {
@@ -217,8 +263,9 @@
 }
 
 std::string CreateHostapdConfig(
-    const IHostapd::IfaceParams& iface_params,
-    const IHostapd::NetworkParams& nw_params)
+    const android::hardware::wifi::hostapd::V1_2::IHostapd::IfaceParams& iface_params,
+    const IHostapd::NetworkParams& nw_params,
+    const std::string br_name)
 {
 	if (nw_params.V1_2.V1_0.ssid.size() >
 	    static_cast<uint32_t>(
@@ -412,6 +459,11 @@
 	}
 #endif /* CONFIG_INTERWORKING */
 
+	std::string bridge_as_string;
+	if (!br_name.empty()) {
+		bridge_as_string = StringPrintf("bridge=%s", br_name.c_str());
+	}
+
 	return StringPrintf(
 	    "interface=%s\n"
 	    "driver=nl80211\n"
@@ -431,6 +483,7 @@
 #ifdef CONFIG_INTERWORKING
 	    "%s\n"
 #endif /* CONFIG_INTERWORKING */
+	    "%s\n"
 	    "%s\n",
 	    iface_params.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
 	    channel_config_as_string.c_str(),
@@ -440,9 +493,10 @@
 	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
 	    nw_params.V1_2.V1_0.isHidden ? 1 : 0,
 #ifdef CONFIG_INTERWORKING
-            access_network_params_as_string.c_str(),
+	    access_network_params_as_string.c_str(),
 #endif /* CONFIG_INTERWORKING */
-            encryption_config_as_string.c_str());
+	    encryption_config_as_string.c_str(),
+	    bridge_as_string.c_str());
 }
 
 Generation getGeneration(hostapd_hw_modes *current_mode)
@@ -504,8 +558,10 @@
 	if (on_setup_complete_internal_callback) {
 		on_setup_complete_internal_callback(iface_hapd);
 		// Invalidate this callback since we don't want this firing
-		// again.
-		on_setup_complete_internal_callback = nullptr;
+		// again in single AP mode.
+		if (strlen(iface_hapd->conf->bridge) > 0) {
+		    on_setup_complete_internal_callback = nullptr;
+		}
 	}
 }
 
@@ -655,17 +711,89 @@
 	return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
 }
 
+V1_2::IHostapd::IfaceParams prepareIfaceParams1_2From1_3(const std::string interfaceName,
+	const V1_3::IHostapd::IfaceParams iface_1_3,
+	const V1_3::IHostapd::ChannelParams channelParams_1_3)
+{
+	// Using HIDL 1.2 iface_params to enable the AP
+	V1_2::IHostapd::IfaceParams iface_params_1_2 = iface_1_3.V1_2;
+	iface_params_1_2.V1_1.V1_0.ifaceName = interfaceName;
+	// Prepare bandMask & acsChannelFreqRangesMhz
+	iface_params_1_2.channelParams = channelParams_1_3.V1_2;
+	// Prepare channel
+	iface_params_1_2.V1_1.V1_0.channelParams.channel = channelParams_1_3.channel;
+	// Prepare enableAcs
+	iface_params_1_2.V1_1.V1_0.channelParams.enableAcs = channelParams_1_3.enableAcs;
+	return iface_params_1_2;
+}
+
 V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
-    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::IfaceParams& iface_params,
     const V1_3::IHostapd::NetworkParams& nw_params)
 {
+	int channelParamsListSize = iface_params.channelParamsList.size();
+	if (channelParamsListSize == 1) {
+		// Single AP
+		wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
+		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+		return addSingleAccessPoint(
+		    prepareIfaceParams1_2From1_3(iface_params.V1_2.V1_1.V1_0.ifaceName,
+						 iface_params, iface_params.channelParamsList[0]),
+		    nw_params, "");
+	} else if (channelParamsListSize == 2) {
+		// Concurrent APs
+		wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
+		    iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+		return addConcurrentAccessPoints(iface_params, nw_params);
+	}
+	return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addConcurrentAccessPoints(
+    const V1_3::IHostapd::IfaceParams& iface_params, const V1_3::IHostapd::NetworkParams& nw_params)
+{
+	int channelParamsListSize = iface_params.channelParamsList.size();
+	// Get available interfaces in bridge
+	std::vector<std::string> managed_interfaces;
+	std::string br_name = StringPrintf(
+	    "%s", iface_params.V1_2.V1_1.V1_0.ifaceName.c_str());
+	if (!GetInterfacesInBridge(br_name, &managed_interfaces)) {
+		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+		    "Get interfaces in bridge failed."};
+	}
+	if (managed_interfaces.size() < channelParamsListSize) {
+		return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN,
+		    "Available interfaces less than requested bands"};
+	}
+	// start BSS on specified bands
+	for (std::size_t i = 0; i < channelParamsListSize; i ++) {
+		V1_2::HostapdStatus status = addSingleAccessPoint(
+		    prepareIfaceParams1_2From1_3(managed_interfaces[i], iface_params,
+						 iface_params.channelParamsList[i]),
+		    nw_params, br_name);
+		if (status.code != V1_2::HostapdStatusCode::SUCCESS) {
+			wpa_printf(MSG_ERROR, "Failed to addAccessPoint %s",
+				   managed_interfaces[i].c_str());
+			return status;
+		}
+	}
+	// Save bridge interface info
+	br_interfaces_[br_name] = managed_interfaces;
+	return {V1_2::HostapdStatusCode::SUCCESS, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addSingleAccessPoint(
+    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::NetworkParams& nw_params,
+    const std::string br_name)
+{
 	if (hostapd_get_iface(interfaces_, iface_params.V1_1.V1_0.ifaceName.c_str())) {
 		wpa_printf(
 		    MSG_ERROR, "Interface %s already present",
 		    iface_params.V1_1.V1_0.ifaceName.c_str());
 		return {V1_2::HostapdStatusCode::FAILURE_IFACE_EXISTS, ""};
 	}
-	const auto conf_params = CreateHostapdConfig(iface_params, nw_params);
+	const auto conf_params = CreateHostapdConfig(iface_params, nw_params, br_name);
 	if (conf_params.empty()) {
 		wpa_printf(MSG_ERROR, "Failed to create config params");
 		return {V1_2::HostapdStatusCode::FAILURE_ARGS_INVALID, ""};
@@ -694,7 +822,7 @@
 	on_setup_complete_internal_callback =
 	    [this](struct hostapd_data* iface_hapd) {
 		    wpa_printf(
-			MSG_DEBUG, "AP interface setup completed - state %s",
+			MSG_INFO, "AP interface setup completed - state %s",
 			hostapd_state_text(iface_hapd->iface->state));
 		    if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
 			    // Invoke the failure callback on all registered
@@ -713,11 +841,9 @@
 		wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
 			   MAC2STR(mac_addr),
 			   (authorized) ? "Connected" : "Disconnected");
-
 		for (const auto &callback : callbacks_) {
-		    // TODO: The iface need to separate to iface and ap instance
-		    // identify for AP+AP case.
-		    callback->onConnectedClientsChanged(iface_hapd->conf->iface,
+		    callback->onConnectedClientsChanged(strlen(iface_hapd->conf->bridge) > 0 ?
+			    iface_hapd->conf->bridge : iface_hapd->conf->iface,
 			    iface_hapd->conf->iface, mac_addr, authorized);
 		}
 	    };
@@ -732,8 +858,10 @@
 			       strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
 		    for (const auto &callback : callbacks_) {
 			callback->onApInstanceInfoChanged(
-				iface_hapd->conf->iface, iface_hapd->conf->iface,
-				iface_hapd->iface->freq, getBandwidth(iface_hapd->iconf),
+				strlen(iface_hapd->conf->bridge) > 0 ?
+				iface_hapd->conf->bridge : iface_hapd->conf->iface,
+				iface_hapd->conf->iface, iface_hapd->iface->freq,
+				getBandwidth(iface_hapd->iconf),
 				getGeneration(iface_hapd->iface->current_mode),
 				iface_hapd->own_addr);
 		    }
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
index 79354d3..ceec080 100644
--- a/hostapd/hidl/1.3/hostapd.h
+++ b/hostapd/hidl/1.3/hostapd.h
@@ -71,7 +71,7 @@
 	    const V1_2::IHostapd::NetworkParams& nw_params,
 	    addAccessPoint_1_2_cb _hidl_cb) override;
 	Return<void> addAccessPoint_1_3(
-	    const V1_2::IHostapd::IfaceParams& iface_params,
+	    const V1_3::IHostapd::IfaceParams& iface_params,
 	    const V1_3::IHostapd::NetworkParams& nw_params,
 	    addAccessPoint_1_3_cb _hidl_cb) override;
 	Return<void> removeAccessPoint(
@@ -102,7 +102,14 @@
 	    const V1_2::IHostapd::IfaceParams& IfaceParams,
 	    const V1_2::IHostapd::NetworkParams& nw_params);
 	V1_2::HostapdStatus addAccessPointInternal_1_3(
+	    const V1_3::IHostapd::IfaceParams& IfaceParams,
+	    const V1_3::IHostapd::NetworkParams& nw_params);
+	V1_2::HostapdStatus addSingleAccessPoint(
 	    const V1_2::IHostapd::IfaceParams& IfaceParams,
+	    const V1_3::IHostapd::NetworkParams& nw_params,
+	    std::string br_name);
+	V1_2::HostapdStatus addConcurrentAccessPoints(
+	    const V1_3::IHostapd::IfaceParams& IfaceParams,
 	    const V1_3::IHostapd::NetworkParams& nw_params);
 	V1_0::HostapdStatus removeAccessPointInternal(const std::string& iface_name);
 	V1_0::HostapdStatus registerCallbackInternal(
@@ -120,6 +127,8 @@
 	std::vector<sp<V1_3::IHostapdCallback>> callbacks_;
 	// Death notifier.
 	android::sp<DeathNotifier> death_notifier_;
+	// Bridge and its managed interfaces.
+	std::map<std::string, std::vector<std::string>> br_interfaces_;
 	DISALLOW_COPY_AND_ASSIGN(Hostapd);
 };
 }  // namespace implementation