GC channel fixes for better interop with SCC

- Force operating channel as the only channel in channel list attribute for go negotiation
and persistence
- Force an operating channel in go negotiation response even if the GO indicates a different
in negotiation request
- Fix a bug with updating peer operating channel based on GO negotiation confirm

Bug: 7217600
Change-Id: I6da0dc1a49c1d99ae97dcab8ee9899e07a80a6cb
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index f8db14e..53b2d5d 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2807,10 +2807,14 @@
 	p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
 
 #ifdef ANDROID_P2P
-	if(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)
+	if(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) {
 		p2p.p2p_concurrency = P2P_MULTI_CHANNEL_CONCURRENT;
-	else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CONCURRENT)
+		wpa_printf(MSG_DEBUG, "P2P: Multi channel concurrency support");
+	} else {
+	// Add support for WPA_DRIVER_FLAGS_P2P_CONCURRENT
 		p2p.p2p_concurrency = P2P_SINGLE_CHANNEL_CONCURRENT;
+		wpa_printf(MSG_DEBUG, "P2P: Single channel concurrency support");
+	}
 #endif
 
 	global->p2p = p2p_init(&p2p);
@@ -4427,6 +4431,7 @@
 {
 	enum p2p_invite_role role;
 	u8 *bssid = NULL;
+	int force_freq = 0, oper_freq = 0;
 
 	wpa_s->p2p_persistent_go_freq = freq;
 	wpa_s->p2p_go_ht40 = !!ht40;
@@ -4454,6 +4459,54 @@
 	}
 	wpa_s->pending_invite_ssid_id = ssid->id;
 
+	if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
+	    wpa_s->assoc_freq)
+		oper_freq = wpa_s->assoc_freq;
+	else {
+		oper_freq = wpa_drv_shared_freq(wpa_s);
+		if (oper_freq < 0)
+			oper_freq = 0;
+	}
+
+	if (freq > 0) {
+		if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+			wpa_printf(MSG_DEBUG, "P2P: The forced channel "
+				   "(%u MHz) is not supported for P2P uses",
+				   freq);
+			return -3;
+		}
+
+		if (oper_freq > 0 && freq != oper_freq &&
+		    !(wpa_s->drv_flags &
+		      WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+			wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
+				   "on %u MHz while connected on another "
+				   "channel (%u MHz)", freq, oper_freq);
+			return -2;
+		}
+		wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
+			   "requested channel (%u MHz)", freq);
+		force_freq = freq;
+	} else if (oper_freq > 0 &&
+		   !p2p_supported_freq(wpa_s->global->p2p, oper_freq)) {
+		if (!(wpa_s->drv_flags &
+		      WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+			wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
+				   "while connected on non-P2P supported "
+				   "channel (%u MHz)", oper_freq);
+			return -2;
+		}
+		wpa_printf(MSG_DEBUG, "P2P: Current operating channel "
+			   "(%u MHz) not available for P2P - try to use "
+			   "another channel", oper_freq);
+		force_freq = 0;
+	} else if (oper_freq > 0) {
+		wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
+			   "channel we are already using (%u MHz) on another "
+			   "interface", oper_freq);
+		force_freq = oper_freq;
+	}
+
 	if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
 		return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
 					  ssid->ssid, ssid->ssid_len,
@@ -4463,7 +4516,7 @@
 		return -1;
 
 	return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
-			  ssid->ssid, ssid->ssid_len, freq, go_dev_addr, 1);
+			  ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr, 1);
 }