Snap for 8720775 from a7fe56ca95bb38d8a27a9077c5164d4c2da278ad to mainline-sdkext-release

Change-Id: Ifec2aa8379ad4f6341ca718068ce343db0ca110a
diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c
index 8c475f1..ee7010d 100644
--- a/src/eap_peer/eap_aka.c
+++ b/src/eap_peer/eap_aka.c
@@ -385,6 +385,7 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
+		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-AKA: (encr) AT_NEXT_PSEUDONYM",
@@ -400,6 +401,17 @@
 					break;
 			}
 		}
+		// If no realm from the permanent identity, look for the
+		// realm of the anonymous identity.
+		if (realm_len == 0 && config && config->anonymous_identity
+		    && config->anonymous_identity_len > 0) {
+			for (realm = config->anonymous_identity,
+			    realm_len = config->anonymous_identity_len;
+			    realm_len > 0; realm_len--, realm++) {
+				if (*realm == '@')
+					break;
+			}
+		}
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c
index 0986627..de423e8 100644
--- a/src/eap_peer/eap_sim.c
+++ b/src/eap_peer/eap_sim.c
@@ -407,6 +407,7 @@
 		size_t identity_len = 0;
 		const u8 *realm = NULL;
 		size_t realm_len = 0;
+		struct eap_peer_config *config = eap_get_config(sm);
 
 		wpa_hexdump_ascii(MSG_DEBUG,
 				  "EAP-SIM: (encr) AT_NEXT_PSEUDONYM",
@@ -422,6 +423,17 @@
 					break;
 			}
 		}
+		// If no realm from the permanent identity, look for the
+		// realm of the anonymous identity.
+		if (realm_len == 0 && config && config->anonymous_identity
+		    && config->anonymous_identity_len > 0) {
+			for (realm = config->anonymous_identity,
+			    realm_len = config->anonymous_identity_len;
+			    realm_len > 0; realm_len--, realm++) {
+				if (*realm == '@')
+					break;
+			}
+		}
 		data->pseudonym = os_malloc(attr->next_pseudonym_len +
 					    realm_len);
 		if (data->pseudonym == NULL) {
diff --git a/wpa_supplicant/aidl/aidl.cpp b/wpa_supplicant/aidl/aidl.cpp
index 1add3df..a7945cc 100644
--- a/wpa_supplicant/aidl/aidl.cpp
+++ b/wpa_supplicant/aidl/aidl.cpp
@@ -923,7 +923,7 @@
 	aidl_manager->notifyNetworkNotFound(wpa_s);
 }
 
-void wpas_aidl_notify_bss_freq_changed(struct wpa_supplicant *wpa_s)
+void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
 {
 	if (!wpa_s)
 		return;
@@ -932,10 +932,10 @@
 	if (!aidl_manager)
 		return;
 
-	wpa_printf(MSG_DEBUG, "Notify %s frequency changed to %d",
-	    wpa_s->ifname, wpa_s->assoc_freq);
+	wpa_printf(MSG_INFO, "Notify %s frequency changed to %d",
+	    wpa_s->ifname, frequency);
 
-	aidl_manager->notifyBssFreqChanged(wpa_s);
+	aidl_manager->notifyFrequencyChanged(wpa_s, frequency);
 }
 
 void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
diff --git a/wpa_supplicant/aidl/aidl.h b/wpa_supplicant/aidl/aidl.h
index d9ab7bd..2f3c7a0 100644
--- a/wpa_supplicant/aidl/aidl.h
+++ b/wpa_supplicant/aidl/aidl.h
@@ -126,7 +126,7 @@
 	void wpas_aidl_notify_transition_disable(
 		struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, u8 bitmap);
 	void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s);
-	void wpas_aidl_notify_bss_freq_changed(struct wpa_supplicant *wpa_s);
+	void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency);
 	void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
 		int depth, const char *subject,
 		const char *altsubject[],
@@ -293,7 +293,7 @@
 {}
 static void wpas_aidl_notify_network_not_found(struct wpa_supplicant *wpa_s)
 {}
-void wpas_aidl_notify_bss_freq_changed(struct wpa_supplicant *wpa_s)
+void wpas_aidl_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
 {}
 void wpas_aidl_notify_ceritification(struct wpa_supplicant *wpa_s,
 	int depth, const char *subject,
diff --git a/wpa_supplicant/aidl/aidl_manager.cpp b/wpa_supplicant/aidl/aidl_manager.cpp
index ac7b8e8..da90c38 100644
--- a/wpa_supplicant/aidl/aidl_manager.cpp
+++ b/wpa_supplicant/aidl/aidl_manager.cpp
@@ -1905,7 +1905,7 @@
 	callWithEachStaIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
 }
 
-void AidlManager::notifyBssFreqChanged(struct wpa_supplicant *wpa_group_s)
+void AidlManager::notifyFrequencyChanged(struct wpa_supplicant *wpa_group_s, int frequency)
 {
 	if (!wpa_group_s || !wpa_group_s->parent)
 		return;
@@ -1913,18 +1913,15 @@
 	// For group notifications, need to use the parent iface for callbacks.
 	struct wpa_supplicant *wpa_s = getTargetP2pIfaceForGroup(wpa_group_s);
 	if (!wpa_s) {
-		wpa_printf(MSG_INFO, "Drop BSS frequency changed event");
+		wpa_printf(MSG_INFO, "Drop frequency changed event");
 		return;
 	}
 
-	uint32_t aidl_freq = wpa_group_s->current_bss
-				? wpa_group_s->current_bss->freq
-				: wpa_group_s->assoc_freq;
-
 	const std::function<
 		ndk::ScopedAStatus(std::shared_ptr<ISupplicantP2pIfaceCallback>)>
 		func = std::bind(&ISupplicantP2pIfaceCallback::onGroupFrequencyChanged,
-		std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname), aidl_freq);
+		std::placeholders::_1, misc_utils::charBufToString(wpa_group_s->ifname),
+		frequency);
 	callWithEachP2pIfaceCallback(misc_utils::charBufToString(wpa_s->ifname), func);
 }
 
diff --git a/wpa_supplicant/aidl/aidl_manager.h b/wpa_supplicant/aidl/aidl_manager.h
index 6acacf5..1ed6899 100644
--- a/wpa_supplicant/aidl/aidl_manager.h
+++ b/wpa_supplicant/aidl/aidl_manager.h
@@ -143,7 +143,7 @@
 			struct wpa_ssid *ssid,
 			u8 bitmap);
 	void notifyNetworkNotFound(struct wpa_supplicant *wpa_s);
-	void notifyBssFreqChanged(struct wpa_supplicant *wpa_s);
+	void notifyFrequencyChanged(struct wpa_supplicant *wpa_s, int frequency);
 	void notifyCertification(struct wpa_supplicant *wpa_s,
 			int depth, const char *subject,
 			const char *altsubject[],
diff --git a/wpa_supplicant/aidl/sta_network.cpp b/wpa_supplicant/aidl/sta_network.cpp
index 88e7b74..fe4a760 100644
--- a/wpa_supplicant/aidl/sta_network.cpp
+++ b/wpa_supplicant/aidl/sta_network.cpp
@@ -1242,11 +1242,24 @@
 	const std::vector<uint8_t> &identity)
 {
 	struct wpa_ssid *wpa_ssid = retrieveNetworkPtr();
-	if (setByteArrayFieldAndResetState(
+	// If current supplicant pseudonym is the prefix of new pseudonym,
+	// the credential is not changed, just update the decoration.
+	// As a result, no need to reset the state.
+	// The decorated identity will have a postfix like
+	// @mncXXX.mccYYY.3gppnetwork.org, so the length will be always
+	// greater than the current one.
+	bool resetState = wpa_ssid->eap.anonymous_identity == NULL
+		|| wpa_ssid->eap.anonymous_identity_len == 0
+		|| identity.size() == 0
+		|| wpa_ssid->eap.anonymous_identity_len >= identity.size()
+		|| os_strncmp((char *) identity.data(),
+			(char *) wpa_ssid->eap.anonymous_identity,
+			wpa_ssid->eap.anonymous_identity_len) != 0;
+	if (setByteArrayField(
 		identity.data(), identity.size(),
 		&(wpa_ssid->eap.anonymous_identity),
 		&(wpa_ssid->eap.anonymous_identity_len),
-		"eap anonymous_identity")) {
+		"eap anonymous_identity", resetState)) {
 		return createStatus(SupplicantStatusCode::FAILURE_UNKNOWN);
 	}
 	return ndk::ScopedAStatus::ok();
@@ -2385,9 +2398,9 @@
  * field in |wpa_ssid| structure instance for this network.
  * This function frees any existing data in these fields.
  */
-int StaNetwork::setByteArrayFieldAndResetState(
+int StaNetwork::setByteArrayField(
 	const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
-	size_t *to_update_field_len, const char *hexdump_prefix)
+	size_t *to_update_field_len, const char *hexdump_prefix, bool resetState)
 {
 	if (*to_update_field) {
 		os_free(*to_update_field);
@@ -2402,11 +2415,27 @@
 	wpa_hexdump_ascii(
 		MSG_MSGDUMP, hexdump_prefix, *to_update_field,
 		*to_update_field_len);
-	resetInternalStateAfterParamsUpdate();
+
+	if (resetState) {
+		resetInternalStateAfterParamsUpdate();
+	}
 	return 0;
 }
 
 /**
+ * Helper function to set value in a string field with a corresponding length
+ * field in |wpa_ssid| structure instance for this network.
+ * This function frees any existing data in these fields.
+ */
+int StaNetwork::setByteArrayFieldAndResetState(
+	const uint8_t *value, const size_t value_len, uint8_t **to_update_field,
+	size_t *to_update_field_len, const char *hexdump_prefix)
+{
+	return setByteArrayField(value, value_len, to_update_field,
+		to_update_field_len, hexdump_prefix, true);
+}
+
+/**
  * Helper function to set value in a string key field with a corresponding
  * length field in |wpa_ssid| structue instance for this network.
  * This function frees any existing data in these fields.
diff --git a/wpa_supplicant/aidl/sta_network.h b/wpa_supplicant/aidl/sta_network.h
index 5105669..524f44a 100644
--- a/wpa_supplicant/aidl/sta_network.h
+++ b/wpa_supplicant/aidl/sta_network.h
@@ -327,6 +327,10 @@
 	void setFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
 	void resetFastTransitionKeyMgmt(uint32_t &key_mgmt_mask);
 	ndk::ScopedAStatus setEapErpInternal(bool enable);
+	int setByteArrayField(
+		const uint8_t* value, const size_t value_len,
+		uint8_t** to_update_field, size_t* to_update_field_len,
+		const char* hexdump_prefix, bool resetState);
 
 	// Reference to the global wpa_struct. This is assumed to be valid
 	// for the lifetime of the process.
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index b724eec..0003d1f 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -5345,6 +5345,10 @@
 		if (event == EVENT_CH_SWITCH_STARTED)
 			break;
 
+		if (wpa_s->assoc_freq && data->ch_switch.freq &&
+			    (int) wpa_s->assoc_freq != data->ch_switch.freq) {
+			wpas_notify_frequency_changed(wpa_s, data->ch_switch.freq);
+		}
 		wpa_s->assoc_freq = data->ch_switch.freq;
 		wpa_s->current_ssid->frequency = data->ch_switch.freq;
 		if (wpa_s->current_bss &&
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 4c30518..c52e88f 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -472,8 +472,6 @@
 		return;
 
 	wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_FREQ, id);
-
-	wpas_aidl_notify_bss_freq_changed(wpa_s);
 }
 
 
@@ -1321,3 +1319,11 @@
 
 	wpas_aidl_notify_qos_policy_request(wpa_s, policies, num_policies);
 }
+
+void wpas_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency)
+{
+	if (!wpa_s)
+		return;
+
+	wpas_aidl_notify_frequency_changed(wpa_s, frequency);
+}
diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h
index f700017..996be84 100644
--- a/wpa_supplicant/notify.h
+++ b/wpa_supplicant/notify.h
@@ -217,5 +217,6 @@
 void wpas_notify_qos_policy_reset(struct wpa_supplicant *wpa_s);
 void wpas_notify_qos_policy_request(struct wpa_supplicant *wpa_s,
 		struct dscp_policy_data *policies, int num_policies);
+void wpas_notify_frequency_changed(struct wpa_supplicant *wpa_s, int frequency);
 
 #endif /* NOTIFY_H */