wpa_supplicant(hidl): Invoke bssid changed callback

Bug: 36451639
Test: Compiles & manual tests
Change-Id: I2f218033838ced66fe68c62fb7973d3b40fe5c02
diff --git a/wpa_supplicant/hidl/hidl.cpp b/wpa_supplicant/hidl/hidl.cpp
index ffc482f..753c87b 100644
--- a/wpa_supplicant/hidl/hidl.cpp
+++ b/wpa_supplicant/hidl/hidl.cpp
@@ -303,6 +303,20 @@
 	hidl_manager->notifyAuthTimeout(wpa_s);
 }
 
+void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	wpa_printf(MSG_DEBUG, "Notifying bssid changed to hidl control");
+
+	HidlManager *hidl_manager = HidlManager::getInstance();
+	if (!hidl_manager)
+		return;
+
+	hidl_manager->notifyBssidChanged(wpa_s);
+}
+
 void wpas_hidl_notify_wps_event_fail(
     struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
     uint16_t error_indication)
diff --git a/wpa_supplicant/hidl/hidl.h b/wpa_supplicant/hidl/hidl.h
index dbc655e..9e2d650 100644
--- a/wpa_supplicant/hidl/hidl.h
+++ b/wpa_supplicant/hidl/hidl.h
@@ -49,6 +49,7 @@
 void wpas_hidl_notify_disconnect_reason(struct wpa_supplicant *wpa_s);
 void wpas_hidl_notify_assoc_reject(struct wpa_supplicant *wpa_s);
 void wpas_hidl_notify_auth_timeout(struct wpa_supplicant *wpa_s);
+void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s);
 void wpas_hidl_notify_wps_event_fail(
     struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr, uint16_t config_error,
     uint16_t error_indication);
@@ -145,6 +146,7 @@
     uint16_t error_indication)
 {
 }
+static void wpas_hidl_notify_bssid_changed(struct wpa_supplicant *wpa_s) {}
 static void wpas_hidl_notify_wps_event_success(struct wpa_supplicant *wpa_s) {}
 static void wpas_hidl_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s)
 {
diff --git a/wpa_supplicant/hidl/hidl_manager.cpp b/wpa_supplicant/hidl/hidl_manager.cpp
index a22a0d1..a6749e8 100644
--- a/wpa_supplicant/hidl/hidl_manager.cpp
+++ b/wpa_supplicant/hidl/hidl_manager.cpp
@@ -951,14 +951,53 @@
 	if (is_zero_ether_addr(bssid)) {
 		bssid = wpa_s->pending_bssid;
 	}
-	std::array<uint8_t, ETH_ALEN> hidl_bssid;
-	os_memcpy(hidl_bssid.data(), bssid, ETH_ALEN);
-
 	callWithEachStaIfaceCallback(
 	    wpa_s->ifname,
 	    std::bind(
 		&ISupplicantStaIfaceCallback::onAuthenticationTimeout,
-		std::placeholders::_1, hidl_bssid));
+		std::placeholders::_1, bssid));
+}
+
+void HidlManager::notifyBssidChanged(struct wpa_supplicant *wpa_s)
+{
+	if (!wpa_s)
+		return;
+
+	const std::string ifname(wpa_s->ifname);
+	if (sta_iface_object_map_.find(ifname) == sta_iface_object_map_.end())
+		return;
+
+	// wpa_supplicant does not explicitly give us the reason for bssid
+	// change, but we figure that out from what is set out of |wpa_s->bssid|
+	// & |wpa_s->pending_bssid|.
+	const u8 *bssid;
+	ISupplicantStaIfaceCallback::BssidChangeReason reason;
+	if (is_zero_ether_addr(wpa_s->bssid) &&
+	    !is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason =
+		    ISupplicantStaIfaceCallback::BssidChangeReason::ASSOC_START;
+	} else if (
+	    !is_zero_ether_addr(wpa_s->bssid) &&
+	    is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->bssid;
+		reason = ISupplicantStaIfaceCallback::BssidChangeReason::
+		    ASSOC_COMPLETE;
+	} else if (
+	    is_zero_ether_addr(wpa_s->bssid) &&
+	    is_zero_ether_addr(wpa_s->pending_bssid)) {
+		bssid = wpa_s->pending_bssid;
+		reason =
+		    ISupplicantStaIfaceCallback::BssidChangeReason::DISASSOC;
+	} else {
+		wpa_printf(MSG_ERROR, "Unknown bssid change reason");
+		return;
+	}
+
+	callWithEachStaIfaceCallback(
+	    wpa_s->ifname, std::bind(
+			       &ISupplicantStaIfaceCallback::onBssidChanged,
+			       std::placeholders::_1, reason, bssid));
 }
 
 void HidlManager::notifyWpsEventFail(
diff --git a/wpa_supplicant/hidl/hidl_manager.h b/wpa_supplicant/hidl/hidl_manager.h
index 07680ba..ada9324 100644
--- a/wpa_supplicant/hidl/hidl_manager.h
+++ b/wpa_supplicant/hidl/hidl_manager.h
@@ -77,6 +77,7 @@
 	void notifyDisconnectReason(struct wpa_supplicant *wpa_s);
 	void notifyAssocReject(struct wpa_supplicant *wpa_s);
 	void notifyAuthTimeout(struct wpa_supplicant *wpa_s);
+	void notifyBssidChanged(struct wpa_supplicant *wpa_s);
 	void notifyWpsEventFail(
 	    struct wpa_supplicant *wpa_s, uint8_t *peer_macaddr,
 	    uint16_t config_error, uint16_t error_indication);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 2f163ac..d7adaa0 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -190,6 +190,8 @@
 		return;
 
 	wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_BSS);
+
+	wpas_hidl_notify_bssid_changed(wpa_s);
 }