Merge "p2p: set ap_configured_cb during p2p group reform process"
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/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 21151a8..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, "");