wpa_supplicant: Update to Version 0.8.26 from BRCM

- Add interface command
- Improve scan handling during P2P

BUG: b/6324527, b/6427094

Change-Id: I4425f44d2a15de0725ba4a1b42cc56e10954b314
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c
index a4c6a8f..68dfb8d 100644
--- a/src/p2p/p2p.c
+++ b/src/p2p/p2p.c
@@ -42,10 +42,38 @@
  * P2P_PEER_EXPIRATION_AGE - Number of seconds after which inactive peer
  * entries will be removed
  */
+#ifdef ANDROID_P2P
+#define P2P_PEER_EXPIRATION_AGE 30
+#else
 #define P2P_PEER_EXPIRATION_AGE 300
+#endif
 
 #define P2P_PEER_EXPIRATION_INTERVAL (P2P_PEER_EXPIRATION_AGE / 2)
 
+#ifdef ANDROID_P2P
+int p2p_connection_in_progress(struct p2p_data *p2p)
+{
+	int ret = 0;
+
+	switch (p2p->state) {
+		case P2P_CONNECT:
+		case P2P_CONNECT_LISTEN:
+		case P2P_GO_NEG:
+		case P2P_WAIT_PEER_CONNECT:
+		case P2P_PROVISIONING:
+		case P2P_INVITE:
+		case P2P_INVITE_LISTEN:
+			ret = 1;
+			break;
+
+		default:
+			ret = 0;
+	}
+
+	return ret;
+}
+#endif
+
 static void p2p_expire_peers(struct p2p_data *p2p)
 {
 	struct p2p_device *dev, *n;
@@ -82,7 +110,14 @@
 			continue;
 		}
 
-		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer "
+#ifdef ANDROID_P2P
+		/* If Connection is in progress, don't expire the peer
+		*/
+		if (p2p_connection_in_progress(p2p))
+			continue;
+#endif
+
+		wpa_msg(p2p->cfg->msg_ctx, MSG_ERROR, "P2P: Expiring old peer "
 			"entry " MACSTR, MAC2STR(dev->info.p2p_device_addr));
 		dl_list_del(&dev->list);
 		p2p_device_free(p2p, dev);
@@ -996,6 +1031,18 @@
 	return res;
 }
 
+#ifdef ANDROID_P2P
+int p2p_search_pending(struct p2p_data *p2p)
+{
+	if(p2p == NULL)
+		return 0;
+
+	if(p2p->state == P2P_SEARCH_WHEN_READY)
+		return 1;
+
+	return 0;
+}
+#endif
 
 int p2p_other_scan_completed(struct p2p_data *p2p)
 {
@@ -2094,7 +2141,6 @@
 {
 	struct wpabuf *p2p_ie;
 	struct p2p_message msg;
-	int ret = -1;
 
 	p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len,
 					     P2P_IE_VENDOR_TYPE);
@@ -2106,16 +2152,14 @@
 		return -1;
 	}
 
-	if (msg.p2p_device_addr) {
-		os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
-		ret = 0;
-	} else if (msg.device_id) {
-		os_memcpy(dev_addr, msg.device_id, ETH_ALEN);
-		ret = 0;
+	if (msg.p2p_device_addr == NULL) {
+		wpabuf_free(p2p_ie);
+		return -1;
 	}
 
+	os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN);
 	wpabuf_free(p2p_ie);
-	return ret;
+	return 0;
 }
 
 
diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h
index 6e3f232..fe98f5e 100644
--- a/src/p2p/p2p.h
+++ b/src/p2p/p2p.h
@@ -1616,11 +1616,18 @@
 
 #ifdef ANDROID_P2P
 /**
- * p2p_in_progress - Check whether a P2P SEARCH is in progress
+ * p2p_search_in_progress - Check whether a P2P SEARCH is in progress
  * @p2p: P2P module context from p2p_init()
  * Returns: 0 if P2P module is idle or 1 if an operation is in progress
  */
 int p2p_search_in_progress(struct p2p_data *p2p);
+
+/**
+ * p2p_search_pending - Check whether there is a deferred P2P SEARCH
+ * @p2p: P2P module context from p2p_init()
+ * Returns: 0 if there is no deferred P2P search or 1 if there is one
+ */
+int p2p_search_pending(struct p2p_data *p2p);
 #endif
 
 /**
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index caecf75..06b725b 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -3307,17 +3307,17 @@
 		return 0;
 	}
 #ifdef ANDROID_P2P
-	if (os_strcmp(cmd, "conc_priority") == 0) {
-		if(os_strncmp(cmd+strlen("conc_priority")+1, "sta", 3) == 0)
-			os_strncpy(wpa_s->global->conc_priority, "sta", 3);
-		else if(os_strncmp(cmd+strlen("conc_priority")+1, "p2p", 3) == 0)
-			os_strncpy(wpa_s->global->conc_priority, "p2p", 3);
+	if (os_strcmp(cmd, "conc_pref") == 0) {
+		if (os_strcmp(param, "sta") == 0)
+			wpa_s->global->conc_pref = WPA_CONC_PREF_STA;
+		else if (os_strcmp(param, "p2p") == 0)
+			wpa_s->global->conc_pref = WPA_CONC_PREF_P2P;
 		else {
-			wpa_printf(MSG_ERROR, " conc_priority arg should be either sta or p2p");
+			wpa_printf(MSG_INFO, "Invalid conc_pref value");
 			return -1;
 		}
-		wpa_printf(MSG_DEBUG, "Single Channel Concurrency: Prioritize %s",
-			   wpa_s->global->conc_priority);
+		wpa_printf(MSG_DEBUG, "Single channel concurrency preference: "
+			"%s", param);
 		return 0;
 	}
 #endif
diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c
index 6513604..b4af793 100644
--- a/wpa_supplicant/ctrl_iface_unix.c
+++ b/wpa_supplicant/ctrl_iface_unix.c
@@ -164,6 +164,35 @@
 		else
 			reply_len = 2;
 	} else {
+#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
+		char *ifname = NULL, *arg;
+		char cmd[256];
+		/* Skip the command name */
+		arg = os_strchr(buf, ' ');
+		if (arg) {
+			*arg++ = '\0';
+			os_strncpy(cmd, buf, sizeof(cmd));
+			/* Now search for interface= */
+			if (os_strncmp(arg, "interface=", 10) == 0) {
+				ifname = arg + 10;
+				arg = os_strchr(ifname, ' ');
+				if (arg)
+					*arg++ = '\0';
+				wpa_printf(MSG_DEBUG, "Found interface= in the arg %s ifname %s", arg, ifname);
+				for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
+					if (os_strcmp(wpa_s->ifname, ifname) == 0)
+						break;
+				}
+				if (wpa_s == NULL) {
+					wpa_printf(MSG_ERROR, "P2P: interface=%s does not exist", ifname);
+					wpa_s = eloop_ctx;
+				}
+			}
+			if (arg)
+				os_snprintf(buf, sizeof(buf), "%s %s", cmd, arg);
+		}
+		wpa_printf(MSG_DEBUG, "wpa_s %p cmd %s", wpa_s, buf);
+#endif /* defined CONFIG_P2P && defined ANDROID_P2P */
 		reply = wpa_supplicant_ctrl_iface_process(wpa_s, buf,
 							  &reply_len);
 	}
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index c09245d..c6d91e8 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1017,7 +1017,11 @@
 	wpa_supplicant_notify_scanning(wpa_s, 0);
 
 #ifdef CONFIG_P2P
+#ifdef ANDROID_P2P
+	if (p2p_search_pending(wpa_s->global->p2p) && !wpa_s->global->p2p_disabled &&
+#else
 	if (wpa_s->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
+#endif
 	    wpa_s->global->p2p != NULL) {
 		wpa_s->p2p_cb_on_scan_complete = 0;
 		if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) {
@@ -1196,18 +1200,26 @@
 		if (rn2 && os_strcmp(rn, rn2) == 0) {
 			wpa_printf(MSG_DEBUG, "%s: Updating scan results from "
 				   "sibling", ifs->ifname);
-#ifndef ANDROID_P2P
-			_wpa_supplicant_event_scan_results(ifs, data);
+#ifdef ANDROID_P2P
+			if ( (ifs->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) || (ifs->p2p_group_interface != NOT_P2P_GROUP_INTERFACE)) {
+				/* Do not update the scan results from STA interface to p2p interfaces */
+				wpa_printf(MSG_DEBUG, "Not Updating scan results on interface %s from "
+					   "sibling %s", ifs->ifname, wpa_s->ifname);
+				continue;
+			}
+			else {
+				/* P2P_FIND will result in too many SCAN_RESULT_EVENTS within
+				 * no time. Avoid announcing it to application as it may not
+				 * be that useful (since results will be that of only 1,6,11).
+				 * over to any other interface as it
+				 */
+				if(p2p_search_in_progress(wpa_s->global->p2p))
+					_wpa_supplicant_event_scan_results(ifs, data, 1);
+				else
+					_wpa_supplicant_event_scan_results(ifs, data, 0);
+			}
 #else
-			/* P2P_FIND will result in too many SCAN_RESULT_EVENTS within
-			 * no time. Avoid announcing it to application as it may not 
-			 * be that useful (since results will be that of only 1,6,11).
-			 * over to any other interface as it
-			 */
-			if((wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CAPABLE) && p2p_search_in_progress(wpa_s->global->p2p))
-				_wpa_supplicant_event_scan_results(ifs, data, 1);
-			else
-				_wpa_supplicant_event_scan_results(ifs, data, 0);
+			_wpa_supplicant_event_scan_results(ifs, data);
 #endif
 		}
 	}
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index 5e7edc8..f9317a8 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -47,7 +47,6 @@
 #define P2P_MAX_CLIENT_IDLE 10
 #endif /* P2P_MAX_CLIENT_IDLE */
 
-
 static void wpas_p2p_long_listen_timeout(void *eloop_ctx, void *timeout_ctx);
 static struct wpa_supplicant *
 wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated,
@@ -63,6 +62,22 @@
 static void wpas_p2p_group_idle_timeout(void *eloop_ctx, void *timeout_ctx);
 static void wpas_p2p_set_group_idle_timeout(struct wpa_supplicant *wpa_s);
 
+#ifdef ANDROID_P2P
+static int wpas_global_scan_in_progress(struct wpa_supplicant *wpa_s)
+{
+	struct wpa_supplicant *iface = NULL;
+
+	for (iface = wpa_s->global->ifaces; iface; iface = iface->next) {
+		if(iface->scanning  || iface->wpa_state == WPA_SCANNING) {
+			wpa_printf(MSG_DEBUG, "P2P: Scan in progress on %s,"
+			"defer P2P SEARCH", iface->ifname);
+			return 1;
+		}
+	}
+
+	return 0;
+}
+#endif
 
 static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s,
 				      struct wpa_scan_results *scan_res)
@@ -157,7 +172,11 @@
 
 	if (ret) {
 		wpa_s->scan_res_handler = NULL;
+#ifdef ANDROID_P2P
+		if (wpa_s->scanning || was_in_p2p_scan || wpas_global_scan_in_progress(wpa_s)) {
+#else
 		if (wpa_s->scanning || was_in_p2p_scan) {
+#endif
 			wpa_s->p2p_cb_on_scan_complete = 1;
 			ret = 1;
 		}
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index 43bcc55..4685970 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -80,6 +80,9 @@
 static const char *action_file = NULL;
 static int ping_interval = 5;
 static int interactive = 0;
+#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
+static char* redirect_interface = NULL;
+#endif
 
 struct cli_txt_entry {
 	struct dl_list list;
@@ -400,6 +403,9 @@
 #else		
 	char buf[2048];
 #endif	
+#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
+	char _cmd[256];
+#endif
 	size_t len;
 	int ret;
 
@@ -407,6 +413,22 @@
 		printf("Not connected to wpa_supplicant - command dropped.\n");
 		return -1;
 	}
+#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
+	if (redirect_interface) {
+		char *arg;
+		arg = os_strchr(cmd, ' ');
+		if (arg) {
+			*arg++ = '\0';
+			ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
+		}
+		else {
+			ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
+		}
+		cmd = _cmd;
+		os_free(redirect_interface);
+		redirect_interface = NULL;
+	}
+#endif
 	len = sizeof(buf) - 1;
 	ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
 			       wpa_cli_msg_cb);
@@ -3192,6 +3214,13 @@
 		printf("Unknown command '%s'\n", argv[0]);
 		ret = 1;
 	} else {
+#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
+		if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
+			redirect_interface = os_strdup(argv[1]);
+			ret = match->handler(ctrl, argc - 2, &argv[2]);
+		}
+		else
+#endif
 		ret = match->handler(ctrl, argc - 1, &argv[1]);
 	}
 
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 81d00f3..3b184fd 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3126,9 +3126,9 @@
 #ifdef ANDROID_P2P
 int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s)
 {
-	if(os_strncmp(wpa_s->global->conc_priority, "p2p", 3) == 0)
+	if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P)
 		return 1;
-	else if(os_strncmp(wpa_s->global->conc_priority, "sta", 3) == 0)
+	if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA)
 		return 0;
 
 	/* IF conc_priority is not set, return -1 */
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 74a0dde..21fe5cc 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -220,7 +220,11 @@
 	struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */
 	int p2p_disabled;
 #ifdef ANDROID_P2P
-	char conc_priority[5]; /* "sta" or "p2p" */
+	enum wpa_conc_pref {
+		WPA_CONC_PREF_NOT_SET,
+		WPA_CONC_PREF_STA,
+		WPA_CONC_PREF_P2P
+	} conc_pref;
 #endif
 	int cross_connection;
 };