wifi: Add access network type support

The access network type can be used to indicate network metered state.
Add access network type support when create access point.

Test: Manual Test, check client scan IE to show correct interworking
value. see: b/137879206#comment14
Test: atest VtsHalWifiHostapdV1_0TargetTest
Test: atest VtsHalWifiHostapdV1_1TargetTest
Test: atest VtsHalWifiHostapdV1_2TargetTest
Bug: 137879206

Change-Id: I2b539486821e159d6cb0edf66d2ee6fafd33e9bc
diff --git a/hostapd/android.config b/hostapd/android.config
index cd54efc..5b46bc4 100644
--- a/hostapd/android.config
+++ b/hostapd/android.config
@@ -231,3 +231,7 @@
 # be completely removed in a future release.
 CONFIG_WEP=y
 
+# Interworking (IEEE 802.11u)
+# This can be used to enable functionality to improve interworking with
+# external networks.
+CONFIG_INTERWORKING=y
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index 765e5ae..b68ddc7 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -34,7 +34,7 @@
 using android::base::RemoveFileIfExists;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
-using android::hardware::wifi::hostapd::V1_2::IHostapd;
+using android::hardware::wifi::hostapd::V1_3::IHostapd;
 using android::hardware::wifi::hostapd::V1_3::Generation;
 using android::hardware::wifi::hostapd::V1_3::Bandwidth;
 
@@ -221,11 +221,11 @@
     const IHostapd::IfaceParams& iface_params,
     const IHostapd::NetworkParams& nw_params)
 {
-	if (nw_params.V1_0.ssid.size() >
+	if (nw_params.V1_2.V1_0.ssid.size() >
 	    static_cast<uint32_t>(
 		IHostapd::ParamSizeLimits::SSID_MAX_LEN_IN_BYTES)) {
 		wpa_printf(
-		    MSG_ERROR, "Invalid SSID size: %zu", nw_params.V1_0.ssid.size());
+		    MSG_ERROR, "Invalid SSID size: %zu", nw_params.V1_2.V1_0.ssid.size());
 		return "";
 	}
 
@@ -233,20 +233,20 @@
 	std::stringstream ss;
 	ss << std::hex;
 	ss << std::setfill('0');
-	for (uint8_t b : nw_params.V1_0.ssid) {
+	for (uint8_t b : nw_params.V1_2.V1_0.ssid) {
 		ss << std::setw(2) << static_cast<unsigned int>(b);
 	}
 	const std::string ssid_as_string = ss.str();
 
 	// Encryption config string
 	std::string encryption_config_as_string;
-	switch (nw_params.encryptionType) {
+	switch (nw_params.V1_2.encryptionType) {
 	case IHostapd::EncryptionType::NONE:
 		// no security params
 		break;
 	case IHostapd::EncryptionType::WPA:
 		if (!validatePassphrase(
-		    nw_params.passphrase.size(),
+		    nw_params.V1_2.passphrase.size(),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
@@ -257,11 +257,11 @@
 		    "wpa=3\n"
 		    "wpa_pairwise=TKIP CCMP\n"
 		    "wpa_passphrase=%s",
-		    nw_params.passphrase.c_str());
+		    nw_params.V1_2.passphrase.c_str());
 		break;
 	case IHostapd::EncryptionType::WPA2:
 		if (!validatePassphrase(
-		    nw_params.passphrase.size(),
+		    nw_params.V1_2.passphrase.size(),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
@@ -272,11 +272,11 @@
 		    "wpa=2\n"
 		    "rsn_pairwise=CCMP\n"
 		    "wpa_passphrase=%s",
-		    nw_params.passphrase.c_str());
+		    nw_params.V1_2.passphrase.c_str());
 		break;
 	case IHostapd::EncryptionType::WPA3_SAE_TRANSITION:
 		if (!validatePassphrase(
-		    nw_params.passphrase.size(),
+		    nw_params.V1_2.passphrase.size(),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
 				WPA2_PSK_PASSPHRASE_MIN_LEN_IN_BYTES),
 		    static_cast<uint32_t>(IHostapd::ParamSizeLimits::
@@ -291,11 +291,11 @@
 		    "sae_require_mfp=1\n"
 		    "wpa_passphrase=%s\n"
 		    "sae_password=%s",
-		    nw_params.passphrase.c_str(),
-		    nw_params.passphrase.c_str());
+		    nw_params.V1_2.passphrase.c_str(),
+		    nw_params.V1_2.passphrase.c_str());
 		break;
 	case IHostapd::EncryptionType::WPA3_SAE:
-		if (!validatePassphrase(nw_params.passphrase.size(), 1, -1)) {
+		if (!validatePassphrase(nw_params.V1_2.passphrase.size(), 1, -1)) {
 			return "";
 		}
 		encryption_config_as_string = StringPrintf(
@@ -305,7 +305,7 @@
 		    "ieee80211w=2\n"
 		    "sae_require_mfp=2\n"
 		    "sae_password=%s",
-		    nw_params.passphrase.c_str());
+		    nw_params.V1_2.passphrase.c_str());
 		break;
 	default:
 		wpa_printf(MSG_ERROR, "Unknown encryption type");
@@ -399,6 +399,18 @@
 	}
 #endif /* CONFIG_IEEE80211AX */
 
+#ifdef CONFIG_INTERWORKING
+	std::string access_network_params_as_string;
+	if (nw_params.isMetered) {
+		access_network_params_as_string = StringPrintf(
+		    "interworking=1\n"
+		    "access_network_type=2\n"); // CHARGEABLE_PUBLIC_NETWORK
+	} else {
+	    access_network_params_as_string = StringPrintf(
+		    "interworking=0\n");
+	}
+#endif /* CONFIG_INTERWORKING */
+
 	return StringPrintf(
 	    "interface=%s\n"
 	    "driver=nl80211\n"
@@ -415,6 +427,9 @@
 	    "%s\n"
 	    "ignore_broadcast_ssid=%d\n"
 	    "wowlan_triggers=any\n"
+#ifdef CONFIG_INTERWORKING
+	    "%s\n"
+#endif /* CONFIG_INTERWORKING */
 	    "%s\n",
 	    iface_params.V1_1.V1_0.ifaceName.c_str(), ssid_as_string.c_str(),
 	    channel_config_as_string.c_str(),
@@ -422,7 +437,11 @@
 	    iface_params.V1_1.V1_0.hwModeParams.enable80211AC ? 1 : 0,
 	    he_params_as_string.c_str(),
 	    hw_mode_as_string.c_str(), ht_cap_vht_oper_chwidth_as_string.c_str(),
-	    nw_params.V1_0.isHidden ? 1 : 0, encryption_config_as_string.c_str());
+	    nw_params.V1_2.V1_0.isHidden ? 1 : 0,
+#ifdef CONFIG_INTERWORKING
+            access_network_params_as_string.c_str(),
+#endif /* CONFIG_INTERWORKING */
+            encryption_config_as_string.c_str());
 }
 
 Generation getGeneration(hostapd_hw_modes *current_mode)
@@ -551,7 +570,8 @@
 }
 
 Return<void> Hostapd::addAccessPoint_1_2(
-    const IfaceParams& iface_params, const NetworkParams& nw_params,
+    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_2::IHostapd::NetworkParams& nw_params,
     addAccessPoint_1_2_cb _hidl_cb)
 {
 	return call(
@@ -559,6 +579,16 @@
 	    nw_params);
 }
 
+Return<void> Hostapd::addAccessPoint_1_3(
+    const V1_3::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::NetworkParams& nw_params,
+    addAccessPoint_1_3_cb _hidl_cb)
+{
+        return call(
+            this, &Hostapd::addAccessPointInternal_1_3, _hidl_cb, iface_params,
+            nw_params);
+}
+
 Return<void> Hostapd::removeAccessPoint(
     const hidl_string& iface_name, removeAccessPoint_cb _hidl_cb)
 {
@@ -618,7 +648,14 @@
 }
 
 V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_2(
-    const IfaceParams& iface_params, const NetworkParams& nw_params)
+    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_2::IHostapd::NetworkParams& nw_params) {
+	return {V1_2::HostapdStatusCode::FAILURE_UNKNOWN, ""};
+}
+
+V1_2::HostapdStatus Hostapd::addAccessPointInternal_1_3(
+    const V1_2::IHostapd::IfaceParams& iface_params,
+    const V1_3::IHostapd::NetworkParams& nw_params)
 {
 	if (hostapd_get_iface(interfaces_, iface_params.V1_1.V1_0.ifaceName.c_str())) {
 		wpa_printf(
diff --git a/hostapd/hidl/1.3/hostapd.h b/hostapd/hidl/1.3/hostapd.h
index 630bc7d..059e24a 100644
--- a/hostapd/hidl/1.3/hostapd.h
+++ b/hostapd/hidl/1.3/hostapd.h
@@ -53,8 +53,13 @@
 	    const V1_1::IHostapd::IfaceParams& iface_params,
 	    const V1_0::IHostapd::NetworkParams& nw_params, addAccessPoint_cb _hidl_cb) override;
 	Return<void> addAccessPoint_1_2(
-	    const V1_2::IHostapd::IfaceParams& iface_params, const NetworkParams& nw_params,
+	    const V1_2::IHostapd::IfaceParams& iface_params,
+	    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::NetworkParams& nw_params,
+	    addAccessPoint_1_3_cb _hidl_cb) override;
 	Return<void> removeAccessPoint(
 	    const hidl_string& iface_name,
 	    removeAccessPoint_cb _hidl_cb) override;
@@ -82,6 +87,9 @@
 	V1_2::HostapdStatus addAccessPointInternal_1_2(
 	    const V1_2::IHostapd::IfaceParams& IfaceParams,
 	    const V1_2::IHostapd::NetworkParams& nw_params);
+	V1_2::HostapdStatus addAccessPointInternal_1_3(
+	    const V1_2::IHostapd::IfaceParams& IfaceParams,
+	    const V1_3::IHostapd::NetworkParams& nw_params);
 	V1_0::HostapdStatus removeAccessPointInternal(const std::string& iface_name);
 	V1_0::HostapdStatus registerCallbackInternal(
 	    const sp<V1_1::IHostapdCallback>& callback);