Merge "p2p: route events to P2P device"
diff --git a/hostapd/hidl/1.3/hostapd.cpp b/hostapd/hidl/1.3/hostapd.cpp
index 7d8f842..908473d 100644
--- a/hostapd/hidl/1.3/hostapd.cpp
+++ b/hostapd/hidl/1.3/hostapd.cpp
@@ -436,6 +436,20 @@
 		on_setup_complete_internal_callback = nullptr;
 	}
 }
+
+// Callback to be invoked on hotspot client connection/disconnection
+std::function<void(struct hostapd_data*, const u8 *mac_addr, int authorized,
+		   const u8 *p2p_dev_addr)> on_sta_authorized_internal_callback;
+void onAsyncStaAuthorizedCb(void* ctx, const u8 *mac_addr, int authorized,
+			    const u8 *p2p_dev_addr)
+{
+	struct hostapd_data* iface_hapd = (struct hostapd_data*)ctx;
+	if (on_sta_authorized_internal_callback) {
+		on_sta_authorized_internal_callback(iface_hapd, mac_addr,
+			authorized, p2p_dev_addr);
+	}
+}
+
 }  // namespace
 
 namespace android {
@@ -584,8 +598,30 @@
 			    }
 		    }
 	    };
+
+	// Rgegister for new client connect/disconnect indication.
+	on_sta_authorized_internal_callback =
+	    [this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
+		   int authorized, const u8 *p2p_dev_addr) {
+		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,
+			    iface_hapd->conf->iface, mac_addr, authorized);
+		}
+	    };
+
+
+	// 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;
+
 	if (hostapd_enable_iface(iface_hapd->iface) < 0) {
 		wpa_printf(
 		    MSG_ERROR, "Enabling interface %s failed",
diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index b158077..71baf9b 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -1411,7 +1411,8 @@
 
 static int is_11b(u8 rate)
 {
-	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16;
+	return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16
+		|| rate == 0x82 || rate == 0x84 || rate == 0x8b || rate == 0x96;
 }
 
 
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/events.c b/wpa_supplicant/events.c
index 7b68ebe..6b33ee3 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -2621,6 +2621,8 @@
 					   data->assoc_info.resp_ies_len,
 					   &resp_elems, 0) != ParseFailed) {
 			wpa_s->connection_set = 1;
+			wpa_s->connection_11b_only = supp_rates_11b_only(&req_elems) ||
+				supp_rates_11b_only(&resp_elems);
 			wpa_s->connection_ht = req_elems.ht_capabilities &&
 				resp_elems.ht_capabilities;
 			/* Do not include subset of VHT on 2.4 GHz vendor
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.cpp b/wpa_supplicant/hidl/1.4/sta_iface.cpp
index b47c5fa..7f476b1 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.cpp
+++ b/wpa_supplicant/hidl/1.4/sta_iface.cpp
@@ -35,9 +35,10 @@
 using android::hardware::wifi::supplicant::V1_0::SupplicantStatus;
 using android::hardware::wifi::supplicant::V1_0::SupplicantStatusCode;
 using android::hardware::wifi::supplicant::V1_0::ISupplicantStaNetwork;
-using android::hardware::wifi::supplicant::V1_3::ISupplicantStaIface;
-using android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities;
 using android::hardware::wifi::supplicant::V1_3::WifiTechnology;
+using android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface;
+using android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities;
+using android::hardware::wifi::supplicant::V1_4::LegacyMode;
 using android::hardware::wifi::supplicant::V1_4::implementation::HidlManager;
 
 constexpr uint32_t kMaxAnqpElems = 100;
@@ -765,6 +766,14 @@
 	    &StaIface::getConnectionCapabilitiesInternal, _hidl_cb);
 }
 
+Return<void> StaIface::getConnectionCapabilities_1_4(
+    getConnectionCapabilities_1_4_cb _hidl_cb)
+{
+	return validateAndCall(
+	    this, SupplicantStatusCode::FAILURE_UNKNOWN,
+	    &StaIface::getConnectionCapabilitiesInternal_1_4, _hidl_cb);
+}
+
 SupplicantStatus StaIface::removeNetworkInternal(SupplicantNetworkId id)
 {
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
@@ -1421,49 +1430,64 @@
 #endif
 }
 
-std::pair<SupplicantStatus, ConnectionCapabilities>
+std::pair<SupplicantStatus, android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities>
 StaIface::getConnectionCapabilitiesInternal()
 {
+  struct android::hardware::wifi::supplicant::V1_3::ConnectionCapabilities capa;
+	return {{SupplicantStatusCode::FAILURE_UNKNOWN, "deprecated"}, capa};
+}
+
+std::pair<SupplicantStatus, ConnectionCapabilities>
+StaIface::getConnectionCapabilitiesInternal_1_4()
+{
 	struct wpa_supplicant *wpa_s = retrieveIfacePtr();
 	struct ConnectionCapabilities capa;
 
 	if (wpa_s->connection_set) {
+		capa.legacyMode = LegacyMode::UNKNOWN;
 		if (wpa_s->connection_he) {
-			capa.technology = WifiTechnology::HE;
+			capa.V1_3.technology = WifiTechnology::HE;
 		} else if (wpa_s->connection_vht) {
-			capa.technology = WifiTechnology::VHT;
+			capa.V1_3.technology = WifiTechnology::VHT;
 		} else if (wpa_s->connection_ht) {
-			capa.technology = WifiTechnology::HT;
+			capa.V1_3.technology = WifiTechnology::HT;
 		} else {
-			capa.technology = WifiTechnology::LEGACY;
+			capa.V1_3.technology = WifiTechnology::LEGACY;
+			if (wpas_freq_to_band(wpa_s->assoc_freq) == BAND_2_4_GHZ) {
+				capa.legacyMode = (wpa_s->connection_11b_only) ? LegacyMode::B_MODE
+						: LegacyMode::G_MODE; 
+			} else {
+				capa.legacyMode = LegacyMode::A_MODE;
+			}
 		}
 		switch (wpa_s->connection_channel_bandwidth) {
 		case CHAN_WIDTH_20:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
 			break;
 		case CHAN_WIDTH_40:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_40;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_40;
 			break;
 		case CHAN_WIDTH_80:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80;
 			break;
 		case CHAN_WIDTH_160:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_160;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_160;
 			break;
 		case CHAN_WIDTH_80P80:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80P80;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_80P80;
 			break;
 		default:
-			capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+			capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
 			break;
 		}
-		capa.maxNumberRxSpatialStreams = wpa_s->connection_max_nss_rx;
-		capa.maxNumberTxSpatialStreams = wpa_s->connection_max_nss_tx;
+		capa.V1_3.maxNumberRxSpatialStreams = wpa_s->connection_max_nss_rx;
+		capa.V1_3.maxNumberTxSpatialStreams = wpa_s->connection_max_nss_tx;
 	} else {
-		capa.technology = WifiTechnology::UNKNOWN;
-		capa.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
-		capa.maxNumberTxSpatialStreams = 1;
-		capa.maxNumberRxSpatialStreams = 1;
+		capa.V1_3.technology = WifiTechnology::UNKNOWN;
+		capa.V1_3.channelBandwidth = WifiChannelWidthInMhz::WIDTH_20;
+		capa.V1_3.maxNumberTxSpatialStreams = 1;
+		capa.V1_3.maxNumberRxSpatialStreams = 1;
+		capa.legacyMode = LegacyMode::UNKNOWN;
 	}
 	return {{SupplicantStatusCode::SUCCESS, ""}, capa};
 }
diff --git a/wpa_supplicant/hidl/1.4/sta_iface.h b/wpa_supplicant/hidl/1.4/sta_iface.h
index 8338459..1b8584d 100644
--- a/wpa_supplicant/hidl/1.4/sta_iface.h
+++ b/wpa_supplicant/hidl/1.4/sta_iface.h
@@ -15,7 +15,7 @@
 
 #include <android-base/macros.h>
 
-#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaIface.h>
+#include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
 #include <android/hardware/wifi/supplicant/1.2/ISupplicantStaIfaceCallback.h>
 #include <android/hardware/wifi/supplicant/1.3/ISupplicantStaNetwork.h>
 
@@ -44,7 +44,7 @@
  * object is used for control operations on a specific interface
  * controlled by wpa_supplicant.
  */
-class StaIface : public V1_3::ISupplicantStaIface
+class StaIface : public V1_4::ISupplicantStaIface
 {
 public:
 	StaIface(struct wpa_global* wpa_global, const char ifname[]);
@@ -189,6 +189,8 @@
 	Return<void> stopDppInitiator(stopDppInitiator_cb _hidl_cb) override;
 	Return<void> getConnectionCapabilities(
 	    getConnectionCapabilities_cb _hidl_cb) override;
+	Return<void> getConnectionCapabilities_1_4(
+	    getConnectionCapabilities_1_4_cb _hidl_cb) override;
 	Return<void> getWpaDriverCapabilities(
 	    getWpaDriverCapabilities_cb _hidl_cb) override;
 	Return<void> setMboCellularDataStatus(bool available,
@@ -283,6 +285,8 @@
 			uint32_t own_bootstrap_id);
 	SupplicantStatus stopDppInitiatorInternal();
 	std::pair<SupplicantStatus, V1_3::ConnectionCapabilities> getConnectionCapabilitiesInternal();
+	std::pair<SupplicantStatus, V1_4::ConnectionCapabilities>
+			getConnectionCapabilitiesInternal_1_4();
 	std::pair<SupplicantStatus, uint32_t> getWpaDriverCapabilitiesInternal();
 	SupplicantStatus setMboCellularDataStatusInternal(bool available);
 	std::pair<SupplicantStatus, uint32_t> getKeyMgmtCapabilitiesInternal_1_3();
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 98b317e..7c792b3 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -779,6 +779,7 @@
 	unsigned int connection_max_nss_tx:4;
 	unsigned int connection_channel_bandwidth:5;
 	unsigned int disable_mbo_oce:1;
+	unsigned int connection_11b_only:1;
 
 	struct os_reltime last_mac_addr_change;
 	int last_mac_addr_style;