Merge "Bug fix of 6GHz band channelization"
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index aa16e8c..14c04a5 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -19,6 +19,7 @@
 
 extern "C"
 {
+#include "common/wpa_ctrl.h"
 #include "utils/eloop.h"
 }
 
@@ -34,6 +35,8 @@
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 using android::hardware::wifi::hostapd::V1_2::IHostapd;
+using android::hardware::wifi::hostapd::V1_3::Generation;
+using android::hardware::wifi::hostapd::V1_3::Bandwidth;
 
 std::string WriteHostapdConfig(
     const std::string& interface_name, const std::string& config)
@@ -422,6 +425,51 @@
 	    nw_params.V1_0.isHidden ? 1 : 0, encryption_config_as_string.c_str());
 }
 
+Generation getGeneration(hostapd_hw_modes *current_mode)
+{
+	wpa_printf(MSG_DEBUG, "getGeneration hwmode=%d, ht_enabled=%d, vht_enabled=%d",
+		   current_mode->mode, current_mode->ht_capab != 0,
+		   current_mode->vht_capab != 0);
+	switch (current_mode->mode) {
+	case HOSTAPD_MODE_IEEE80211B:
+		return Generation::WIFI_STANDARD_LEGACY;
+	case HOSTAPD_MODE_IEEE80211G:
+		return current_mode->ht_capab == 0 ?
+		       Generation::WIFI_STANDARD_LEGACY : Generation::WIFI_STANDARD_11N;
+	case HOSTAPD_MODE_IEEE80211A:
+		return current_mode->vht_capab == 0 ?
+		       Generation::WIFI_STANDARD_11N : Generation::WIFI_STANDARD_11AC;
+        // TODO: b/162484222 miss HOSTAPD_MODE_IEEE80211AX definition.
+	default:
+		return Generation::WIFI_STANDARD_UNKNOWN;
+	}
+}
+
+Bandwidth getBandwidth(struct hostapd_config *iconf)
+{
+	wpa_printf(MSG_DEBUG, "getBandwidth %d, isHT=%d, isHT40=%d",
+		   iconf->vht_oper_chwidth, iconf->ieee80211n,
+		   iconf->secondary_channel);
+	switch (iconf->vht_oper_chwidth) {
+	case CHANWIDTH_80MHZ:
+		return Bandwidth::WIFI_BANDWIDTH_80;
+	case CHANWIDTH_80P80MHZ:
+		return Bandwidth::WIFI_BANDWIDTH_80P80;
+		break;
+	case CHANWIDTH_160MHZ:
+		return Bandwidth::WIFI_BANDWIDTH_160;
+		break;
+	case CHANWIDTH_USE_HT:
+		if (iconf->ieee80211n) {
+			return iconf->secondary_channel != 0 ?
+				Bandwidth::WIFI_BANDWIDTH_40 : Bandwidth::WIFI_BANDWIDTH_20;
+		}
+		return Bandwidth::WIFI_BANDWIDTH_20_NOHT;
+	default:
+		return Bandwidth::WIFI_BANDWIDTH_INVALID;
+	}
+}
+
 // hostapd core functions accept "C" style function pointers, so use global
 // functions to pass to the hostapd core function and store the corresponding
 // std::function methods to be invoked.
@@ -454,6 +502,22 @@
 	}
 }
 
+std::function<void(struct hostapd_data*, int level,
+                   enum wpa_msg_type type, const char *txt,
+                   size_t len)> on_wpa_msg_internal_callback;
+
+void onAsyncWpaEventCb(void *ctx, int level,
+                   enum wpa_msg_type type, const char *txt,
+                   size_t len)
+{
+	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+	if (on_wpa_msg_internal_callback) {
+		on_wpa_msg_internal_callback(iface_hapd, level,
+					       type, txt, len);
+	}
+}
+
+
 }  // namespace
 
 namespace android {
@@ -619,12 +683,29 @@
 		}
 	    };
 
+	// Register for wpa_event which used to get channel switch event
+	on_wpa_msg_internal_callback =
+	    [this](struct hostapd_data* iface_hapd, int level,
+		   enum wpa_msg_type type, const char *txt,
+		   size_t len) {
+		wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
+		if (os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
+			       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),
+				getGeneration(iface_hapd->iface->current_mode));
+		    }
+		}
+	    };
 
 	// Setup callback
 	iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
 	iface_hapd->setup_complete_cb_ctx = iface_hapd;
 	iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
 	iface_hapd->sta_authorized_cb_ctx = iface_hapd;
+	wpa_msg_register_cb(onAsyncWpaEventCb);
 
 	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
 		wpa_printf(
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index 812c09a..9fae06d 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -210,7 +210,7 @@
 # Frequency list can be provided as range using hyphen ('-') or individual
 # frequencies can be specified by comma (',') separated values
 # Default: all frequencies allowed in selected hw_mode
-#freqlist=2437,5945,5965
+#freqlist=2437,5955,5975
 #freqlist=2437,5985-6105
 
 # Exclude DFS channels from ACS
@@ -822,11 +822,11 @@
 #he_rts_threshold=0
 
 # HE operating channel information; see matching vht_* parameters for details.
-# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset.
-# For example idx=3 would result in 5955 MHz center frequency. In addition,
+# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset.
+# For example idx=3 would result in 5965 MHz center frequency. In addition,
 # he_oper_chwidth is ignored, and the channel width is derived from the
 # configured operating class or center frequency indexes (see
-# IEEE P802.11ax/D4.3 Annex E, Table E-4).
+# IEEE P802.11ax/D6.1 Annex E, Table E-4).
 #he_oper_chwidth
 #he_oper_centr_freq_seg0_idx
 #he_oper_centr_freq_seg1_idx
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 71baf9b..6859787 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -939,9 +939,9 @@
 		return HOSTAPD_MODE_IEEE80211A;
 	}
 
-	if (freq > 5940 && freq <= 7105) {
+	if (freq > 5950 && freq <= 7115) {
 		int bw;
-		u8 idx = (freq - 5940) / 5;
+		u8 idx = (freq - 5950) / 5;
 
 		bw = center_idx_to_bw_6ghz(idx);
 		if (bw < 0)
@@ -952,6 +952,12 @@
 		return HOSTAPD_MODE_IEEE80211A;
 	}
 
+	if (freq == 5935) {
+		*op_class = 136;
+		*channel = (freq - 5925) / 5;
+		return HOSTAPD_MODE_IEEE80211A;
+	}
+
 	/* 56.16 GHz, channel 1..6 */
 	if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 6) {
 		if (sec_channel)
@@ -1328,7 +1334,11 @@
 	case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
 		if (chan < 1 || chan > 233)
 			return -1;
-		return 5940 + chan * 5;
+		return 5950 + chan * 5;
+	case 136: /* UHB channels, 20 MHz: 2 */
+		if (chan == 2)
+			return 5935;
+		return -1;
 	case 180: /* 60 GHz band, channels 1..8 */
 		if (chan < 1 || chan > 8)
 			return -1;
@@ -2117,10 +2127,13 @@
 
 int is_6ghz_freq(int freq)
 {
-	if (freq < 5940 || freq > 7105)
+	if (freq < 5935 || freq > 7115)
 		return 0;
 
-	if (center_idx_to_bw_6ghz((freq - 5940) / 5) < 0)
+	if (freq == 5935)
+		return 1;
+
+	if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0)
 		return 0;
 
 	return 1;
@@ -2129,7 +2142,7 @@
 
 int is_6ghz_op_class(u8 op_class)
 {
-	return op_class >= 131 && op_class <= 135;
+	return op_class >= 131 && op_class <= 136;
 }
 
 
@@ -2137,14 +2150,14 @@
 {
 	int i;
 
-	if (!is_6ghz_freq(freq))
+	if (!is_6ghz_freq(freq) || freq == 5935)
 		return 0;
-	if ((((freq - 5940) / 5) & 0x3) != 0x1)
+	if ((((freq - 5950) / 5) & 0x3) != 0x1)
 		return 0;
 
-	i = (freq - 5940 + 55) % 80;
+	i = (freq - 5950 + 55) % 80;
 	if (i == 0)
-		i = (freq - 5940 + 55) / 80;
+		i = (freq - 5950 + 55) / 80;
 
 	if (i >= 1 && i <= 15)
 		return 1;
@@ -2380,6 +2393,8 @@
 	case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */
 	case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
 		return 160;
+	case 136: /* UHB channels, 20 MHz: 2 */
+		return 20;
 	case 180: /* 60 GHz band, channels 1..8 */
 		return 2160;
 	case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
@@ -2440,6 +2455,8 @@
 		return CHANWIDTH_160MHZ;
 	case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */
 		return CHANWIDTH_80P80MHZ;
+	case 136: /* UHB channels, 20 MHz: 2 */
+		return CHANWIDTH_USE_HT;
 	case 180: /* 60 GHz band, channels 1..8 */
 		return CHANWIDTH_2160MHZ;
 	case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */
diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk
index b440497..ed20fb3 100644
--- a/wpa_supplicant/Android.mk
+++ b/wpa_supplicant/Android.mk
@@ -16,10 +16,6 @@
   CONFIG_DRIVER_NL80211_QCA=y
 endif
 
-ifeq ($(WIFI_UPDATE_SUPPLICANT_MAC_ADDR), enabled)
-  FEATURE_UPDATE_STA_MAC_ADDR=y
-endif
-
 include $(LOCAL_PATH)/android.config
 
 # To ignore possible wrong network configurations
@@ -72,6 +68,10 @@
 L_CFLAGS += -DCONFIG_NO_ROAMING
 endif
 
+ifeq ($(WIFI_UPDATE_SUPPLICANT_MAC_ADDR), enabled)
+L_CFLAGS += -DFEATURE_UPDATE_STA_MAC_ADDR
+endif
+
 # Use Android specific directory for control interface sockets
 L_CFLAGS += -DCONFIG_CTRL_IFACE_CLIENT_DIR=\"/data/vendor/wifi/wpa/sockets\"
 L_CFLAGS += -DCONFIG_CTRL_IFACE_DIR=\"/data/vendor/wifi/wpa/sockets\"
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.cpp b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
index 431881c..5e74f48 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.cpp
@@ -1236,9 +1236,8 @@
 		return;
 
 	// For group notifications, need to use the parent iface for callbacks.
-	struct wpa_supplicant *wpa_s = wpa_group_s->parent;
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
+	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
 		return;
 
 	uint32_t hidl_freq = wpa_group_s->current_bss
@@ -1279,9 +1278,8 @@
 		return;
 
 	// For group notifications, need to use the parent iface for callbacks.
-	struct wpa_supplicant *wpa_s = wpa_group_s->parent;
-	if (p2p_iface_object_map_.find(wpa_s->ifname) ==
-	    p2p_iface_object_map_.end())
+	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
 		return;
 
 	bool hidl_is_go = (std::string(role) == "GO");
@@ -1386,15 +1384,15 @@
 }
 
 void HidlManager::notifyApStaAuthorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+    struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
 {
-	if (!wpa_s || !wpa_s->parent || !sta)
+	if (!wpa_group_s || !wpa_group_s->parent || !sta)
 		return;
-	if (p2p_iface_object_map_.find(wpa_s->parent->ifname) ==
-	    p2p_iface_object_map_.end())
+	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
 		return;
 	callWithEachP2pIfaceCallback(
-	    wpa_s->parent->ifname,
+	    wpa_s->ifname,
 	    std::bind(
 		&ISupplicantP2pIfaceCallback::onStaAuthorized,
 		std::placeholders::_1, sta,
@@ -1402,16 +1400,16 @@
 }
 
 void HidlManager::notifyApStaDeauthorized(
-    struct wpa_supplicant *wpa_s, const u8 *sta, const u8 *p2p_dev_addr)
+    struct wpa_supplicant *wpa_group_s, const u8 *sta, const u8 *p2p_dev_addr)
 {
-	if (!wpa_s || !wpa_s->parent || !sta)
+	if (!wpa_group_s || !wpa_group_s->parent || !sta)
 		return;
-	if (p2p_iface_object_map_.find(wpa_s->parent->ifname) ==
-	    p2p_iface_object_map_.end())
+	wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
+	if (!wpa_s)
 		return;
 
 	callWithEachP2pIfaceCallback(
-	    wpa_s->parent->ifname,
+	    wpa_s->ifname,
 	    std::bind(
 		&ISupplicantP2pIfaceCallback::onStaDeauthorized,
 		std::placeholders::_1, sta,
@@ -1976,6 +1974,35 @@
 }
 
 /**
+ * Finds the correct |wpa_supplicant| object for P2P notifications
+ *
+ * @param wpa_s the |wpa_supplicant| that triggered the P2P event.
+ * @return appropriate |wpa_supplicant| object or NULL if not found.
+ */
+struct wpa_supplicant *HidlManager::getTargetP2pIfaceForGroup(
+	    struct wpa_supplicant *wpa_group_s)
+{
+	if (!wpa_group_s || !wpa_group_s->parent)
+		return NULL;
+
+	struct wpa_supplicant *target_wpa_s = wpa_group_s->parent;
+	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+	    p2p_iface_object_map_.end())
+		return target_wpa_s;
+
+	// try P2P device if available
+	if (!target_wpa_s->p2pdev || !target_wpa_s->p2pdev->p2p_mgmt)
+		return NULL;
+
+	target_wpa_s = target_wpa_s->p2pdev;
+	if (p2p_iface_object_map_.find(target_wpa_s->ifname) !=
+	    p2p_iface_object_map_.end())
+		return target_wpa_s;
+
+	return NULL;
+}
+
+/**
  * Removes the provided |ISupplicantCallback| hidl object reference
  * from our global callback list.
  *
diff --git a/wpa_supplicant/hidl/1.4/hidl_manager.h b/wpa_supplicant/hidl/1.4/hidl_manager.h
index 9df7b55..e024427 100644
--- a/wpa_supplicant/hidl/1.4/hidl_manager.h
+++ b/wpa_supplicant/hidl/1.4/hidl_manager.h
@@ -185,6 +185,8 @@
 	HidlManager(const HidlManager &) = default;
 	HidlManager &operator=(const HidlManager &) = default;
 
+	struct wpa_supplicant *getTargetP2pIfaceForGroup(
+	    struct wpa_supplicant *wpa_s);
 	void removeSupplicantCallbackHidlObject(
 	    const android::sp<ISupplicantCallback> &callback);
 	void removeP2pIfaceCallbackHidlObject(
diff --git a/wpa_supplicant/hidl/1.4/p2p_iface.cpp b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
index ece1c04..8f4416c 100644
--- a/wpa_supplicant/hidl/1.4/p2p_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/p2p_iface.cpp
@@ -1083,8 +1083,9 @@
 	int ht40 = wpa_s->conf->p2p_go_ht40 || vht;
 	const char* pin =
 	    pre_selected_pin.length() > 0 ? pre_selected_pin.data() : nullptr;
+	bool auto_join = !join_existing_group;
 	int new_pin = wpas_p2p_connect(
-	    wpa_s, peer_address.data(), pin, wps_method, persistent, false,
+	    wpa_s, peer_address.data(), pin, wps_method, persistent, auto_join,
 	    join_existing_group, false, go_intent_signed, 0, 0, -1, false, ht40,
 	    vht, CHANWIDTH_USE_HT, he, 0, nullptr, 0);
 	if (new_pin < 0) {
diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c
index 983801f..bd97fee 100644
--- a/wpa_supplicant/op_classes.c
+++ b/wpa_supplicant/op_classes.c
@@ -22,13 +22,13 @@
 				       unsigned int *flags)
 {
 	int i;
-	int is_6ghz = op_class >= 131 && op_class <= 135;
+	int is_6ghz = op_class >= 131 && op_class <= 136;
 
 	for (i = 0; i < mode->num_channels; i++) {
 		int chan_is_6ghz;
 
-		chan_is_6ghz = mode->channels[i].freq > 5940 &&
-			mode->channels[i].freq <= 7105;
+		chan_is_6ghz = mode->channels[i].freq >= 5935 &&
+			mode->channels[i].freq <= 7115;
 		if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan)
 			break;
 	}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index b0bea61..2d33810 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -4925,6 +4925,15 @@
 				       MAC2STR(wpa_s->pending_join_dev_addr));
 			return;
 		}
+		if (wpa_s->p2p_fallback_to_go_neg) {
+			wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Join operating "
+				"failed - fall back to GO Negotiation");
+			wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
+				       P2P_EVENT_FALLBACK_TO_GO_NEG
+				       "reason=join-failed");
+			wpas_p2p_fallback_to_go_neg(wpa_s, 0);
+			return;
+		}
 		wpa_msg_global(wpa_s->p2pdev, MSG_INFO,
 			       P2P_EVENT_GROUP_FORMATION_FAILURE);
 		wpas_notify_p2p_group_formation_failure(wpa_s, "");
@@ -9383,6 +9392,12 @@
 	/* Stop the AP functionality */
 	/* TODO: Should do this in a way that does not indicated to possible
 	 * P2P Clients in the group that the group is terminated. */
+	/* If this action occurs before a group is started, the callback should be
+	 * preserved, or GROUP-STARTED event would be lost. If this action occurs after
+	 * a group is started, these poiners are all NULL and harmless. */
+	void (*ap_configured_cb)(void *ctx, void *data) = wpa_s->ap_configured_cb;
+	void *ap_configured_cb_ctx = wpa_s->ap_configured_cb_ctx;;
+	void *ap_configured_cb_data = wpa_s->ap_configured_cb_data;
 	wpa_supplicant_ap_deinit(wpa_s);
 
 	/* Reselect the GO frequency */
@@ -9406,6 +9421,9 @@
 		return;
 	}
 
+	wpa_s->ap_configured_cb = ap_configured_cb;
+	wpa_s->ap_configured_cb_ctx = ap_configured_cb_ctx;
+	wpa_s->ap_configured_cb_data = ap_configured_cb_data;
 	/* Update the frequency */
 	current_ssid->frequency = params.freq;
 	wpa_s->connect_without_scan = current_ssid;