Merge "Use API TcpKeepalivePacketData in ClientModeImpl"
diff --git a/libs/WifiTrackerLib/res/values-af/strings.xml b/libs/WifiTrackerLib/res/values-af/strings.xml
index 1289205..dca16b5 100644
--- a/libs/WifiTrackerLib/res/values-af/strings.xml
+++ b/libs/WifiTrackerLib/res/values-af/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Beperkte verbinding"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Daar kan nie by private DNS-bediener ingegaan word nie"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Geen internet nie"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lae gehalte"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Geen"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Verval"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tik om aan te meld"</string>
diff --git a/libs/WifiTrackerLib/res/values-am/strings.xml b/libs/WifiTrackerLib/res/values-am/strings.xml
index cf57ddc..0280faa 100644
--- a/libs/WifiTrackerLib/res/values-am/strings.xml
+++ b/libs/WifiTrackerLib/res/values-am/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"የተገደበ ግንኙነት"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"የግል ዲኤንኤስ አገልጋይ ሊደረስበት አይችልም"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ምንም በይነመረብ የለም"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"አነስተኛ ጥራት"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"የለም"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ጊዜው አልፏል"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ለመመዝገብ መታ ያድርጉ"</string>
diff --git a/libs/WifiTrackerLib/res/values-ar/strings.xml b/libs/WifiTrackerLib/res/values-ar/strings.xml
index ccb2dfa..a73a403 100644
--- a/libs/WifiTrackerLib/res/values-ar/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ar/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"اتصال محدود"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"لا يمكن الوصول إلى خادم أسماء نظام نطاقات خاص"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"لا يتوفر اتصال إنترنت."</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"جودة منخفضة"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"بلا أمان"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"منتهية الصلاحية"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"انقر للاشتراك."</string>
diff --git a/libs/WifiTrackerLib/res/values-as/strings.xml b/libs/WifiTrackerLib/res/values-as/strings.xml
index a211b32..b460831 100644
--- a/libs/WifiTrackerLib/res/values-as/strings.xml
+++ b/libs/WifiTrackerLib/res/values-as/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ইণ্টাৰনেট সংযোগ সীমিত"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ব্যক্তিগত DNS ছাৰ্ভাৰ এক্সেছ কৰিব নোৱাৰি"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ইণ্টাৰনেট সংযোগ নাই"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"নিম্ন মানৰ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"নাই"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ম্যাদ উকলিছে"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ছাইন আপ কৰিবলৈ টিপক"</string>
diff --git a/libs/WifiTrackerLib/res/values-az/strings.xml b/libs/WifiTrackerLib/res/values-az/strings.xml
index 5bc7a70..06adad2 100644
--- a/libs/WifiTrackerLib/res/values-az/strings.xml
+++ b/libs/WifiTrackerLib/res/values-az/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Məhdud bağlantı"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Özəl DNS serverinə giriş mümkün deyil"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"İnternet yoxdur"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Aşağı keyfiyyət"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Heç biri"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vaxtı keçib"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Qeydiyyatdan keçmək üçün toxunun"</string>
diff --git a/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml b/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
index ebc3a7b..7c578d3 100644
--- a/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-b+sr+Latn/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Pristup privatnom DNS serveru nije uspeo"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema interneta"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Loš kvalitet"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ništa"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite da biste se registrovali"</string>
diff --git a/libs/WifiTrackerLib/res/values-be/strings.xml b/libs/WifiTrackerLib/res/values-be/strings.xml
index a381027..abbee6a 100644
--- a/libs/WifiTrackerLib/res/values-be/strings.xml
+++ b/libs/WifiTrackerLib/res/values-be/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Абмежаваныя магчымасці падключэння"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Не ўдалося атрымаць доступ да прыватнага DNS-сервера"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Няма падключэння да інтэрнэту"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Нізкая якасць"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Няма"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Тэрмін скончыўся"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Націсніце, каб зарэгістравацца"</string>
diff --git a/libs/WifiTrackerLib/res/values-bg/strings.xml b/libs/WifiTrackerLib/res/values-bg/strings.xml
index f17e36a..b824133 100644
--- a/libs/WifiTrackerLib/res/values-bg/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bg/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена връзка"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Не може да се осъществи достъп до частния DNS сървър"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Няма интернет"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ниско качество"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Няма"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Изтекло"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Докоснете, за да се регистрирате"</string>
diff --git a/libs/WifiTrackerLib/res/values-bn/strings.xml b/libs/WifiTrackerLib/res/values-bn/strings.xml
index 8b3bdc2..6c7c3e8 100644
--- a/libs/WifiTrackerLib/res/values-bn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bn/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"সীমিত কানেকশন"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ব্যক্তিগত ডিএনএস সার্ভার অ্যাক্সেস করা যাবে না"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ইন্টারনেট কানেকশন নেই"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"খারাপ কোয়ালিটি"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"কোনও কিছুই নয়"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"মেয়াদ শেষ হয়ে গেছে"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"সাইন-আপ করতে ট্যাপ করুন"</string>
diff --git a/libs/WifiTrackerLib/res/values-bs/arrays.xml b/libs/WifiTrackerLib/res/values-bs/arrays.xml
index 727f5d7..9428a37 100644
--- a/libs/WifiTrackerLib/res/values-bs/arrays.xml
+++ b/libs/WifiTrackerLib/res/values-bs/arrays.xml
@@ -27,7 +27,7 @@
     <item msgid="1176401854208153464">"Autentifikacija…"</item>
     <item msgid="1377026397901197257">"Dobivanje IP adrese…"</item>
     <item msgid="7627139816052121509">"Povezano"</item>
-    <item msgid="1598801023719359130">"Suspendirano"</item>
+    <item msgid="1598801023719359130">"Obustavljeno"</item>
     <item msgid="9160765456671002324">"Prekidanje veze…"</item>
     <item msgid="8013176736494493734">"Veza je prekinuta"</item>
     <item msgid="4077393480368783785">"Neuspješno"</item>
diff --git a/libs/WifiTrackerLib/res/values-bs/strings.xml b/libs/WifiTrackerLib/res/values-bs/strings.xml
index 92a747c..efc8884 100644
--- a/libs/WifiTrackerLib/res/values-bs/strings.xml
+++ b/libs/WifiTrackerLib/res/values-bs/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Nije moguće pristupiti privatnom DNS serveru"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema internetske veze"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizak kvalitet"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ništa"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite za registraciju"</string>
diff --git a/libs/WifiTrackerLib/res/values-ca/strings.xml b/libs/WifiTrackerLib/res/values-ca/strings.xml
index 4711bd4..83b3f63 100644
--- a/libs/WifiTrackerLib/res/values-ca/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ca/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexió limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"No es pot accedir al servidor DNS privat"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sense connexió a Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Qualitat baixa"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Cap"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducada"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca per registrar-te"</string>
diff --git a/libs/WifiTrackerLib/res/values-cs/strings.xml b/libs/WifiTrackerLib/res/values-cs/strings.xml
index 69d90f5..f2317e8 100644
--- a/libs/WifiTrackerLib/res/values-cs/strings.xml
+++ b/libs/WifiTrackerLib/res/values-cs/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Omezené připojení"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Nelze získat přístup k soukromému serveru DNS"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nejste připojeni k internetu"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízká kvalita"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Žádné"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Platnost vypršela"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Klepnutím se zaregistrujete"</string>
diff --git a/libs/WifiTrackerLib/res/values-da/strings.xml b/libs/WifiTrackerLib/res/values-da/strings.xml
index ff21ffb..758bc1a 100644
--- a/libs/WifiTrackerLib/res/values-da/strings.xml
+++ b/libs/WifiTrackerLib/res/values-da/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Begrænset forbindelse"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Der er ikke adgang til den private DNS-server"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Intet internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Dårlig kvalitet"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Udløbet"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tryk for at registrere"</string>
diff --git a/libs/WifiTrackerLib/res/values-de/strings.xml b/libs/WifiTrackerLib/res/values-de/strings.xml
index 9007073..a525510 100644
--- a/libs/WifiTrackerLib/res/values-de/strings.xml
+++ b/libs/WifiTrackerLib/res/values-de/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Eingeschränkte Verbindung"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Auf den privaten DNS-Server kann nicht zugegriffen werden"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Kein Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niedrige Qualität"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Keine"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Abgelaufen"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Zum Registrieren tippen"</string>
diff --git a/libs/WifiTrackerLib/res/values-el/strings.xml b/libs/WifiTrackerLib/res/values-el/strings.xml
index 31c065d..3e3d2ba 100644
--- a/libs/WifiTrackerLib/res/values-el/strings.xml
+++ b/libs/WifiTrackerLib/res/values-el/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Περιορισμένη σύνδεση"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Δεν είναι δυνατή η πρόσβαση στον ιδιωτικό διακομιστή DNS."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Χωρίς σύνδεση στο διαδίκτυο"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Χαμηλή ποιότητα"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Καμία"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Έληξε"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Πατήστε για εγγραφή"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
index 2f8fc15..e191bd3 100644
--- a/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rAU/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"None"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
index 2f8fc15..e191bd3 100644
--- a/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rCA/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"None"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
index 2f8fc15..e191bd3 100644
--- a/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rGB/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"None"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
index 2f8fc15..e191bd3 100644
--- a/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rIN/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Limited connection"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Private DNS server cannot be accessed"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"No Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Low quality"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"None"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expired"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tap to sign up"</string>
diff --git a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
index 087ad38..b2574af 100644
--- a/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
+++ b/libs/WifiTrackerLib/res/values-en-rXC/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎Limited connection‎‏‎‎‏‎"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‎‏‎‏‏‎‎‎‎Private DNS server cannot be accessed‎‏‎‎‏‎"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‎‏‎‏‏‏‎‏‏‎No internet‎‏‎‎‏‎"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‎‎‏‏‏‏‎‎‎‎‎‎‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎Low quality‎‏‎‎‏‎"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‎‏‎None‎‏‎‎‏‎"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‏‎Expired‎‏‎‎‏‎"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‏‏‏‎Tap to sign up‎‏‎‎‏‎"</string>
@@ -46,7 +47,8 @@
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‏‏‏‎Completing sign-up…‎‏‎‎‏‎"</string>
     <string name="osu_sign_up_failed" msgid="2725057866968590279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎Couldn’t complete sign-up. Tap to try again.‎‏‎‎‏‎"</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‏‎Sign-up complete. Connecting…‎‏‎‎‏‎"</string>
-    <string name="imsi_protection_warning" msgid="3207104049473134195">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎This network receives a unique ID that can be used to track device location. ‎‏‎‎‏‏‎"<annotation id="url">"‎‏‎‎‏‏‏‎Learn more‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <!-- no translation found for imsi_protection_warning (3207104049473134195) -->
+    <skip />
     <string name="speed_label_very_slow" msgid="2401582671941367179">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎Very Slow‎‏‎‎‏‎"</string>
     <string name="speed_label_slow" msgid="8410385703344502127">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‏‎‏‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎Slow‎‏‎‎‏‎"</string>
     <string name="speed_label_okay" msgid="3741857805086997968">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‎‎OK‎‏‎‎‏‎"</string>
diff --git a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
index c0ac95b..9012ba9 100644
--- a/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
+++ b/libs/WifiTrackerLib/res/values-es-rUS/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexión limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"No se puede acceder al servidor DNS privado"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sin Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baja calidad"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ninguna"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vencida"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Presiona para registrarte"</string>
diff --git a/libs/WifiTrackerLib/res/values-es/strings.xml b/libs/WifiTrackerLib/res/values-es/strings.xml
index 6c6990e..4cdb27c 100644
--- a/libs/WifiTrackerLib/res/values-es/strings.xml
+++ b/libs/WifiTrackerLib/res/values-es/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexión limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"No se ha podido acceder al servidor DNS privado"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sin Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calidad baja"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ninguna"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducada"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca para registrarte"</string>
diff --git a/libs/WifiTrackerLib/res/values-et/strings.xml b/libs/WifiTrackerLib/res/values-et/strings.xml
index 6843d21..9fe7960 100644
--- a/libs/WifiTrackerLib/res/values-et/strings.xml
+++ b/libs/WifiTrackerLib/res/values-et/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Piiratud ühendus"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Privaatsele DNS-serverile ei pääse juurde"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Interneti pole"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kehva kvaliteediga"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Puudub"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Aegunud"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Puudutage registreerimiseks"</string>
diff --git a/libs/WifiTrackerLib/res/values-eu/strings.xml b/libs/WifiTrackerLib/res/values-eu/strings.xml
index a440007..cc86325 100644
--- a/libs/WifiTrackerLib/res/values-eu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-eu/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Konexio mugatua"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Ezin da atzitu DNS zerbitzari pribatua"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ez dago Interneteko konexiorik"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kalitate txikia"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Bat ere ez"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Iraungita"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Sakatu izena emateko"</string>
diff --git a/libs/WifiTrackerLib/res/values-fa/arrays.xml b/libs/WifiTrackerLib/res/values-fa/arrays.xml
index af40e8f..51ef4b8 100644
--- a/libs/WifiTrackerLib/res/values-fa/arrays.xml
+++ b/libs/WifiTrackerLib/res/values-fa/arrays.xml
@@ -24,7 +24,7 @@
     <item msgid="8763475525292171481"></item>
     <item msgid="903308535197209786">"درحال اسکن کردن…"</item>
     <item msgid="6222852518007967736">"درحال اتصال…"</item>
-    <item msgid="1176401854208153464">"درحال احراز هویت…"</item>
+    <item msgid="1176401854208153464">"درحال اصالت‌سنجی…"</item>
     <item msgid="1377026397901197257">"‏درحال دریافت نشانی IP…"</item>
     <item msgid="7627139816052121509">"متصل"</item>
     <item msgid="1598801023719359130">"معلق"</item>
diff --git a/libs/WifiTrackerLib/res/values-fa/strings.xml b/libs/WifiTrackerLib/res/values-fa/strings.xml
index 70f79b6..35c3961 100644
--- a/libs/WifiTrackerLib/res/values-fa/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fa/strings.xml
@@ -21,7 +21,7 @@
     <string name="saved_network" msgid="6241977554502802914">"ذخیره‌شده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"اتصال به‌طور خودکار انجام نمی‌شود"</string>
     <string name="wifi_no_internet" msgid="4461212237521310895">"بدون دسترسی به اینترنت"</string>
-    <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"مشکل احراز هویت"</string>
+    <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"مشکل اصالت‌سنجی"</string>
     <string name="wifi_check_password_try_again" msgid="2643230209986217827">"گذرواژه را بررسی و دوباره امتحان کنید"</string>
     <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"‏پیکربندی IP انجام نشد"</string>
     <string name="wifi_disabled_generic" msgid="8307050327779256414">"غیرفعال شد"</string>
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"اتصال محدود"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"‏سرور DNS خصوصی قابل دسترسی نیست"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"عدم اتصال به اینترنت"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"کیفیت پایین"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"خالی"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"منقضی‌شده"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"برای ثبت‌نام ضربه بزنید"</string>
diff --git a/libs/WifiTrackerLib/res/values-fi/strings.xml b/libs/WifiTrackerLib/res/values-fi/strings.xml
index 43c1eea..fe285fa 100644
--- a/libs/WifiTrackerLib/res/values-fi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fi/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Rajallinen yhteys"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Ei pääsyä yksityiselle DNS-palvelimelle"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ei internetyhteyttä"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Heikko laatu"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ei mitään"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Vanhentunut"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Rekisteröidy napauttamalla"</string>
diff --git a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
index 15cbde5..83b3201 100644
--- a/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fr-rCA/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexion limitée"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Impossible d\'accéder au serveur DNS privé"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Aucune connexion Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Aucune"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expiré"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toucher pour vous inscrire"</string>
diff --git a/libs/WifiTrackerLib/res/values-fr/strings.xml b/libs/WifiTrackerLib/res/values-fr/strings.xml
index f917d8f..40dedca 100644
--- a/libs/WifiTrackerLib/res/values-fr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-fr/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Connexion limitée"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Impossible d\'accéder au serveur DNS privé"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Aucun accès à Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Faible qualité"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Aucune"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Arrivé à expiration"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Appuyez ici pour vous connecter"</string>
diff --git a/libs/WifiTrackerLib/res/values-gl/strings.xml b/libs/WifiTrackerLib/res/values-gl/strings.xml
index d4a8c0e..19691ad 100644
--- a/libs/WifiTrackerLib/res/values-gl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-gl/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Pouca conexión"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Non se puido acceder ao servidor DNS privado"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Non hai conexión a Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Pouca calidade"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ningunha"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Caducou"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toca para rexistrarte"</string>
diff --git a/libs/WifiTrackerLib/res/values-gu/strings.xml b/libs/WifiTrackerLib/res/values-gu/strings.xml
index e387dd3..1bd9b3f 100644
--- a/libs/WifiTrackerLib/res/values-gu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-gu/strings.xml
@@ -33,10 +33,11 @@
     <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> દ્વારા કનેક્ટ થયેલ"</string>
     <string name="available_via_app" msgid="9110324040292242769">"<xliff:g id="NAME">%1$s</xliff:g> મારફતે ઉપલબ્ધ"</string>
     <string name="connected_via_network_scorer" msgid="209764314005159012">"<xliff:g id="NAME">%1$s</xliff:g> મારફતે ઑટોમૅટિક રીતે કનેક્ટ કર્યું છે"</string>
-    <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા આપમેળે કનેક્ટ થયું"</string>
+    <string name="connected_via_network_scorer_default" msgid="3084818437004202462">"નેટવર્ક રેટિંગ પ્રદાતા દ્વારા ઑટોમૅટિક રીતે કનેક્ટ થયું"</string>
     <string name="wifi_limited_connection" msgid="3646701342701276239">"મર્યાદિત કનેક્શન"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ખાનગી DNS સર્વર ઍક્સેસ કરી શકાતા નથી"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"કોઈ ઇન્ટરનેટ નથી"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ઓછી ક્વૉલિટી"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"કોઈ નહીં"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"સમય સમાપ્ત થયો"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"સાઇન અપ કરવા માટે ટૅપ કરો"</string>
diff --git a/libs/WifiTrackerLib/res/values-hi/strings.xml b/libs/WifiTrackerLib/res/values-hi/strings.xml
index 53d55e7..8ce4af1 100644
--- a/libs/WifiTrackerLib/res/values-hi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hi/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"सीमित कनेक्शन"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"निजी डीएनएस सर्वर को ऐक्सेस नहीं किया जा सकता"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इंटरनेट कनेक्शन नहीं है"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"खराब कनेक्शन"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"कोई नहीं"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"समयसीमा खत्म हो गई"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप करने के लिए टैप करें"</string>
diff --git a/libs/WifiTrackerLib/res/values-hr/strings.xml b/libs/WifiTrackerLib/res/values-hr/strings.xml
index 6ddae4f..016b41a 100644
--- a/libs/WifiTrackerLib/res/values-hr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hr/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograničena veza"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Nije moguće pristupiti privatnom DNS poslužitelju"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nema interneta"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska kvaliteta"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nema"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Isteklo"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Dodirnite da biste se registrirali"</string>
diff --git a/libs/WifiTrackerLib/res/values-hu/strings.xml b/libs/WifiTrackerLib/res/values-hu/strings.xml
index 3f3afef..baeda41 100644
--- a/libs/WifiTrackerLib/res/values-hu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hu/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Korlátozott kapcsolat"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"A privát DNS-kiszolgálóhoz nem lehet hozzáférni"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nincs internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Gyenge minőségű"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nincs"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Lejárt"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Koppintson a regisztrációhoz"</string>
diff --git a/libs/WifiTrackerLib/res/values-hy/strings.xml b/libs/WifiTrackerLib/res/values-hy/strings.xml
index 34c1fbd..9ef2f69 100644
--- a/libs/WifiTrackerLib/res/values-hy/strings.xml
+++ b/libs/WifiTrackerLib/res/values-hy/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Սահմանափակ կապ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Մասնավոր DNS սերվերն անհասանելի է"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Կապ չկա"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ցածր որակ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ոչ մեկը"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Սպառվել է"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Հպեք՝ գրանցվելու համար"</string>
diff --git a/libs/WifiTrackerLib/res/values-in/strings.xml b/libs/WifiTrackerLib/res/values-in/strings.xml
index adb4a72..e870613 100644
--- a/libs/WifiTrackerLib/res/values-in/strings.xml
+++ b/libs/WifiTrackerLib/res/values-in/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Koneksi terbatas"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Server DNS pribadi tidak dapat diakses"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Tidak ada internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualitas rendah"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Tidak ada"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Sudah tidak berlaku"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Ketuk untuk mendaftar"</string>
diff --git a/libs/WifiTrackerLib/res/values-is/strings.xml b/libs/WifiTrackerLib/res/values-is/strings.xml
index b937486..2a535f3 100644
--- a/libs/WifiTrackerLib/res/values-is/strings.xml
+++ b/libs/WifiTrackerLib/res/values-is/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Takmörkuð tenging"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Ekki næst í DNS-einkaþjón"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Engin nettenging"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lítil gæði"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ekkert"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Útrunnin"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Ýttu til að skrá þig"</string>
diff --git a/libs/WifiTrackerLib/res/values-it/strings.xml b/libs/WifiTrackerLib/res/values-it/strings.xml
index 20c113d..b4bb149 100644
--- a/libs/WifiTrackerLib/res/values-it/strings.xml
+++ b/libs/WifiTrackerLib/res/values-it/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Connessione limitata"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Non è possibile accedere al server DNS privato"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Internet assente"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Bassa qualità"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nessuna"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Scaduta"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tocca per registrarti"</string>
diff --git a/libs/WifiTrackerLib/res/values-iw/strings.xml b/libs/WifiTrackerLib/res/values-iw/strings.xml
index 3c43377..1cf516a 100644
--- a/libs/WifiTrackerLib/res/values-iw/strings.xml
+++ b/libs/WifiTrackerLib/res/values-iw/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"חיבור מוגבל"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"‏לא ניתן לגשת לשרת DNS הפרטי"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"אין אינטרנט"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"איכות נמוכה"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ללא"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"התוקף פג"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"יש להקיש כדי להירשם"</string>
diff --git a/libs/WifiTrackerLib/res/values-ja/strings.xml b/libs/WifiTrackerLib/res/values-ja/strings.xml
index bb7187b..f6b25d9 100644
--- a/libs/WifiTrackerLib/res/values-ja/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ja/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"接続が制限されています"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"プライベート DNS サーバーにアクセスできません"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"インターネットに接続されていません"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"低品質"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"なし"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"期限切れ"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"タップして登録してください"</string>
diff --git a/libs/WifiTrackerLib/res/values-ka/strings.xml b/libs/WifiTrackerLib/res/values-ka/strings.xml
index 56e8836..a4f8e5e 100644
--- a/libs/WifiTrackerLib/res/values-ka/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ka/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"შეზღუდული კავშირი"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"პირად DNS სერვერზე წვდომა შეუძლებელია"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ინტერნეტ-კავშირი არ არის"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"დაბალი ხარისხი"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"არცერთი"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ვადაგასულია"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"შეეხეთ რეგისტრაციისთვის"</string>
diff --git a/libs/WifiTrackerLib/res/values-kk/strings.xml b/libs/WifiTrackerLib/res/values-kk/strings.xml
index 591170d..6f9c82a 100644
--- a/libs/WifiTrackerLib/res/values-kk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-kk/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Шектеулі байланыс"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Жеке DNS серверіне кіру мүмкін емес."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернетпен байланыс жоқ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Төмен сапа"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ешқандай"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Мерзімі өтті"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Тіркелу үшін түртіңіз."</string>
diff --git a/libs/WifiTrackerLib/res/values-km/strings.xml b/libs/WifiTrackerLib/res/values-km/strings.xml
index 32150fa..e7466ea 100644
--- a/libs/WifiTrackerLib/res/values-km/strings.xml
+++ b/libs/WifiTrackerLib/res/values-km/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ការតភ្ជាប់មានកម្រិត"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"មិនអាច​ចូលប្រើ​ម៉ាស៊ីនមេ DNS ឯកជន​បានទេ"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"គ្មាន​អ៊ីនធឺណិតទេ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"គុណភាព​ទាប"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"គ្មាន"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"បានផុតកំណត់"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ចុច​ដើម្បី​ចុះឈ្មោះ"</string>
diff --git a/libs/WifiTrackerLib/res/values-kn/strings.xml b/libs/WifiTrackerLib/res/values-kn/strings.xml
index 6793a96..558892b 100644
--- a/libs/WifiTrackerLib/res/values-kn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-kn/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ಸೀಮಿತ ಸಂಪರ್ಕ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ಖಾಸಗಿ DNS ಸರ್ವರ್ ಅನ್ನು ಪ್ರವೇಶಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ಇಂಟರ್ನೆಟ್ ಇಲ್ಲ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ಕಳಪೆ ಕನೆಕ್ಷನ್"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ಯಾವುದೂ ಇಲ್ಲ"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ಅವಧಿ ಮುಕ್ತಾಯವಾಗಿದೆ"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ಸೈನ್ ಅಪ್ ಮಾಡಲು ಟ್ಯಾಪ್‌ ಮಾಡಿ"</string>
diff --git a/libs/WifiTrackerLib/res/values-ko/strings.xml b/libs/WifiTrackerLib/res/values-ko/strings.xml
index eea05e8..6e32a8e 100644
--- a/libs/WifiTrackerLib/res/values-ko/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ko/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"제한된 연결"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"비공개 DNS 서버에 액세스할 수 없습니다."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"인터넷 연결 없음"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"품질 낮음"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"없음"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"만료됨"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"가입하려면 탭하세요."</string>
diff --git a/libs/WifiTrackerLib/res/values-ky/arrays.xml b/libs/WifiTrackerLib/res/values-ky/arrays.xml
index 8bcf777..00ab8f6 100644
--- a/libs/WifiTrackerLib/res/values-ky/arrays.xml
+++ b/libs/WifiTrackerLib/res/values-ky/arrays.xml
@@ -26,7 +26,7 @@
     <item msgid="6222852518007967736">"Туташууда…"</item>
     <item msgid="1176401854208153464">"Аныктыгы текшерилүүдө…"</item>
     <item msgid="1377026397901197257">"IP дареги алынууда…"</item>
-    <item msgid="7627139816052121509">"Туташты"</item>
+    <item msgid="7627139816052121509">"Туташып турат"</item>
     <item msgid="1598801023719359130">"Убактылуу токтотулду"</item>
     <item msgid="9160765456671002324">"Ажыратылууда…"</item>
     <item msgid="8013176736494493734">"Ажыратылды"</item>
diff --git a/libs/WifiTrackerLib/res/values-ky/strings.xml b/libs/WifiTrackerLib/res/values-ky/strings.xml
index 5294103..d9c7a9f 100644
--- a/libs/WifiTrackerLib/res/values-ky/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ky/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Байланыш чектелген"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Жеке DNS сервери жеткиликсиз"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернет жок"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Начар сапат"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Жок"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Эскирип калган"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Катталуу үчүн таптап коюңуз"</string>
diff --git a/libs/WifiTrackerLib/res/values-lo/strings.xml b/libs/WifiTrackerLib/res/values-lo/strings.xml
index 96d421b..c9067d6 100644
--- a/libs/WifiTrackerLib/res/values-lo/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lo/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ການເຊື່ອມຕໍ່ຈຳກັດ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ບໍ່ສາມາດເຂົ້າເຖິງເຊີບເວີ DNS ສ່ວນຕົວໄດ້"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ບໍ່ມີອິນເຕີເນັດ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ຄຸນນະພາບຕໍ່າ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ບໍ່ໃຊ້"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ໝົດອາຍຸແລ້ວ"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ແຕະເພື່ອສະໝັກ"</string>
diff --git a/libs/WifiTrackerLib/res/values-lt/strings.xml b/libs/WifiTrackerLib/res/values-lt/strings.xml
index ff32f1c..f3848c4 100644
--- a/libs/WifiTrackerLib/res/values-lt/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lt/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ribotas ryšys"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Privataus DNS serverio negalima pasiekti"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nėra interneto ryšio"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Prastas ryšys"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nėra"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Baigėsi galiojimo laikas"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Palieskite, kad prisiregistruotumėte"</string>
diff --git a/libs/WifiTrackerLib/res/values-lv/strings.xml b/libs/WifiTrackerLib/res/values-lv/strings.xml
index 4aebe32..e0300d6 100644
--- a/libs/WifiTrackerLib/res/values-lv/strings.xml
+++ b/libs/WifiTrackerLib/res/values-lv/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ierobežots savienojums"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Nevar piekļūt privātam DNS serverim."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nav interneta"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Zema kvalitāte"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nav"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Beidzies derīguma termiņš"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Pieskarieties, lai reģistrētos."</string>
diff --git a/libs/WifiTrackerLib/res/values-mk/strings.xml b/libs/WifiTrackerLib/res/values-mk/strings.xml
index 36064f3..7cc1856 100644
--- a/libs/WifiTrackerLib/res/values-mk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mk/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена врска"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Не може да се пристапи до приватниот DNS-сервер"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нема интернет"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ниедна"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Истечено"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Допрете за да се регистрирате"</string>
@@ -44,7 +45,7 @@
     <string name="osu_opening_provider" msgid="5633521771769175139">"Се отвора <xliff:g id="PASSPOINTPROVIDER">%1$s</xliff:g>"</string>
     <string name="osu_connect_failed" msgid="8503501619299851793">"Не може да се поврзе"</string>
     <string name="osu_completing_sign_up" msgid="7188493241442946231">"Се завршува регистрацијата…"</string>
-    <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не можеше да се заврши регистрацијата. Допрете за да се обидете повторно."</string>
+    <string name="osu_sign_up_failed" msgid="2725057866968590279">"Не може да се заврши регистрацијата. Допрете за да се обидете повторно."</string>
     <string name="osu_sign_up_complete" msgid="7013805426618985953">"Регистрацијата е завршена. Се поврзува…"</string>
     <string name="imsi_protection_warning" msgid="3207104049473134195">"Мрежава прима уникатен ID што може да се користи за следење на локацијата на уредот. "<annotation id="url">"Дознајте повеќе"</annotation></string>
     <string name="speed_label_very_slow" msgid="2401582671941367179">"Многу бавна"</string>
diff --git a/libs/WifiTrackerLib/res/values-ml/strings.xml b/libs/WifiTrackerLib/res/values-ml/strings.xml
index 90798a6..c90220a 100644
--- a/libs/WifiTrackerLib/res/values-ml/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ml/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"പരിമിത കണക്‌ഷൻ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"സ്വകാര്യ DNS സെർവർ ആക്‌സസ് ചെയ്യാനാവില്ല"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ഇന്റർനെറ്റ് ഇല്ല"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"കുറഞ്ഞ നിലവാരം"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ഒന്നുമില്ല"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"കാലഹരണപ്പെട്ടത്"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"സൈൻ അപ്പ് ചെയ്യാൻ ടാപ്പ് ചെയ്യുക"</string>
diff --git a/libs/WifiTrackerLib/res/values-mn/strings.xml b/libs/WifiTrackerLib/res/values-mn/strings.xml
index 577bd6e..e52776c 100644
--- a/libs/WifiTrackerLib/res/values-mn/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mn/strings.xml
@@ -21,7 +21,7 @@
     <string name="saved_network" msgid="6241977554502802914">"<xliff:g id="NAME">%1$s</xliff:g> хадгалсан"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="3089980800841926268">"Автоматаар холбогдохгүй"</string>
     <string name="wifi_no_internet" msgid="4461212237521310895">"Интернэт хандалт байхгүй байна"</string>
-    <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Нотолгооны асуудал"</string>
+    <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"Баталгаажуулалтын асуудал"</string>
     <string name="wifi_check_password_try_again" msgid="2643230209986217827">"Нууц үгийг шалгаад дахин оролдоно уу"</string>
     <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP тохируулга амжилтгүй боллоо"</string>
     <string name="wifi_disabled_generic" msgid="8307050327779256414">"Идэвхгүйжүүлсэн"</string>
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Хязгаарлагдмал холболт"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Хувийн DNS серверт хандах боломжгүй байна"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Интернэт алга"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Чанар муу"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Байхгүй"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Хугацаа дууссан"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Бүртгүүлэхийн тулд товшино уу"</string>
diff --git a/libs/WifiTrackerLib/res/values-mr/strings.xml b/libs/WifiTrackerLib/res/values-mr/strings.xml
index fc7811f..d714d30 100644
--- a/libs/WifiTrackerLib/res/values-mr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-mr/strings.xml
@@ -23,7 +23,7 @@
     <string name="wifi_no_internet" msgid="4461212237521310895">"इंटरनेट अ‍ॅक्सेस नाही"</string>
     <string name="wifi_disabled_password_failure" msgid="3015007143699702403">"ऑथेंटिकेशन समस्या"</string>
     <string name="wifi_check_password_try_again" msgid="2643230209986217827">"पासवर्ड तपासा आणि पुन्‍हा प्रयत्‍न करा"</string>
-    <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP कॉन्फिगरेशन अयशस्वी"</string>
+    <string name="wifi_disabled_network_failure" msgid="6506742207778007439">"IP कॉंफिगरेशन अयशस्वी"</string>
     <string name="wifi_disabled_generic" msgid="8307050327779256414">"अक्षम"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"अ‍ॅक्सेस पॉइंट तात्पुरते भरलेले"</string>
     <string name="wifi_disconnected" msgid="3720926757662831062">"डिस्कनेक्ट केले"</string>
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"मर्यादित कनेक्शन"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"खाजगी DNS सर्व्हर ॲक्सेस करू शकत नाही"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इंटरनेट नाही"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"कमी गुणवत्ता"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"काहीही नाही"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"मुदत संपली"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप करण्यासाठी टॅप करा"</string>
diff --git a/libs/WifiTrackerLib/res/values-ms/strings.xml b/libs/WifiTrackerLib/res/values-ms/strings.xml
index 81b0ce3..12da6ba 100644
--- a/libs/WifiTrackerLib/res/values-ms/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ms/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Sambungan terhad"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Pelayan DNS peribadi tidak boleh diakses"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Tiada Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Kualiti rendah"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Tiada"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Tamat tempoh"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Ketik untuk daftar"</string>
diff --git a/libs/WifiTrackerLib/res/values-my/strings.xml b/libs/WifiTrackerLib/res/values-my/strings.xml
index a3f67e1..ce11f4e 100644
--- a/libs/WifiTrackerLib/res/values-my/strings.xml
+++ b/libs/WifiTrackerLib/res/values-my/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ချိတ်ဆက်မှု ကန့်သတ်ထားသည်"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"သီးသန့် ဒီအန်အက်စ် (DNS) ဆာဗာကို သုံး၍မရပါ။"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"အင်တာနက် မရှိပါ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"အရည်အသွေး နိမ့်သည်"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"မရှိ"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"သက်တမ်းကုန်သွားပါပြီ"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"အကောင့်ဖွင့်ရန် တို့ပါ"</string>
diff --git a/libs/WifiTrackerLib/res/values-nb/strings.xml b/libs/WifiTrackerLib/res/values-nb/strings.xml
index 8379223..a4d3f88 100644
--- a/libs/WifiTrackerLib/res/values-nb/strings.xml
+++ b/libs/WifiTrackerLib/res/values-nb/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Begrenset tilkobling"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Den private DNS-tjeneren kan ikke nås"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ingen internettilkobling"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lav kvalitet"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Utløpt"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Trykk for å registrere deg"</string>
diff --git a/libs/WifiTrackerLib/res/values-ne/strings.xml b/libs/WifiTrackerLib/res/values-ne/strings.xml
index 39e62d8..64b06c7 100644
--- a/libs/WifiTrackerLib/res/values-ne/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ne/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"सीमित जडान"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"निजी DNS सर्भरमाथि पहुँच प्राप्त गर्न सकिँदैन"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"इन्टरनेट छैन"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"न्यून गुणस्तर"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"कुनै पनि होइन"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"म्याद सकियो"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"साइन अप गर्न ट्याप गर्नुहोस्"</string>
diff --git a/libs/WifiTrackerLib/res/values-nl/strings.xml b/libs/WifiTrackerLib/res/values-nl/strings.xml
index a026429..910b2e0 100644
--- a/libs/WifiTrackerLib/res/values-nl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-nl/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Beperkte verbinding"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Geen toegang tot privé-DNS-server"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Geen internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Lage kwaliteit"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Geen"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Verlopen"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tik om aan te melden"</string>
diff --git a/libs/WifiTrackerLib/res/values-or/strings.xml b/libs/WifiTrackerLib/res/values-or/strings.xml
index cec830b..3e681b5 100644
--- a/libs/WifiTrackerLib/res/values-or/strings.xml
+++ b/libs/WifiTrackerLib/res/values-or/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ସୀମିତ ସଂଯୋଗ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ବ୍ୟକ୍ତିଗତ DNS ସର୍ଭର୍ ଆକ୍ସେସ୍ କରିହେବ ନାହିଁ"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ଇଣ୍ଟର୍ନେଟ୍ ସଂଯୋଗ ନାହିଁ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ନିମ୍ନ ଗୁଣବତ୍ତା"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"କିଛି ନାହିଁ"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ମିଆଦ ଶେଷ ହୋଇଯାଇଛି"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ସାଇନ୍ ଅପ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string>
diff --git a/libs/WifiTrackerLib/res/values-pa/strings.xml b/libs/WifiTrackerLib/res/values-pa/strings.xml
index 7966cd7..06c2c97 100644
--- a/libs/WifiTrackerLib/res/values-pa/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pa/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"ਸੀਮਤ ਕਨੈਕਸ਼ਨ"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ਨਿੱਜੀ ਡੋਮੇਨ ਨਾਮ ਪ੍ਰਣਾਲੀ (DNS) ਸਰਵਰ \'ਤੇ ਪਹੁੰਚ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ਇੰਟਰਨੈੱਟ ਨਹੀਂ"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ਠੀਕ-ਠਾਕ ਕਨੈਕਸ਼ਨ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ਕੋਈ ਨਹੀਂ"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"ਮਿਆਦ ਮੁੱਕ ਗਈ"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ਸਾਈਨ-ਅੱਪ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
diff --git a/libs/WifiTrackerLib/res/values-pl/strings.xml b/libs/WifiTrackerLib/res/values-pl/strings.xml
index f4d5cca..b3287e0 100644
--- a/libs/WifiTrackerLib/res/values-pl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pl/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ograniczone połączenie"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Brak dostępu do prywatnego serwera DNS"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Brak internetu"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Niska jakość"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Brak"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Ważność wygasła"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Kliknij, by się zarejestrować"</string>
diff --git a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
index d3adf52..408cc66 100644
--- a/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt-rBR/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexão limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível acessar o servidor DNS privado"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever"</string>
diff --git a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
index bcce991..59141f6 100644
--- a/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt-rPT/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ligação limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível aceder ao servidor DNS."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Baixa qualidade"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever."</string>
diff --git a/libs/WifiTrackerLib/res/values-pt/strings.xml b/libs/WifiTrackerLib/res/values-pt/strings.xml
index d3adf52..408cc66 100644
--- a/libs/WifiTrackerLib/res/values-pt/strings.xml
+++ b/libs/WifiTrackerLib/res/values-pt/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexão limitada"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Não é possível acessar o servidor DNS privado"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Sem Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Conexão lenta"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Nenhuma"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirada"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Toque para se inscrever"</string>
diff --git a/libs/WifiTrackerLib/res/values-ro/strings.xml b/libs/WifiTrackerLib/res/values-ro/strings.xml
index e4d24eb..47b137f 100644
--- a/libs/WifiTrackerLib/res/values-ro/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ro/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Conexiune limitată"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Serverul DNS privat nu poate fi accesat"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Fără conexiune la internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Calitate slabă"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Niciuna"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Expirat"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Atingeți pentru a vă înscrie"</string>
diff --git a/libs/WifiTrackerLib/res/values-ru/strings.xml b/libs/WifiTrackerLib/res/values-ru/strings.xml
index f8dc5c8..7be5fca 100644
--- a/libs/WifiTrackerLib/res/values-ru/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ru/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Подключение к сети ограничено."</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Доступа к частному DNS-серверу нет."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нет подключения к Интернету"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"низкое качество"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Без защиты"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Срок действия истек"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Нажмите, чтобы зарегистрироваться."</string>
diff --git a/libs/WifiTrackerLib/res/values-si/strings.xml b/libs/WifiTrackerLib/res/values-si/strings.xml
index 16a0501..0cbd370 100644
--- a/libs/WifiTrackerLib/res/values-si/strings.xml
+++ b/libs/WifiTrackerLib/res/values-si/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"සීමිත සම්බන්ධතාව"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"පුද්ගලික DNS සේවාදායකයට ප්‍රවේශ වීමට නොහැකිය"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"අන්තර්ජාලය නැත"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"අඩු ගුණත්වය"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"කිසිවක් නැත"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"කල් ඉකුත් විය"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"ලියාපදිංචි වීමට තට්ටු කරන්න"</string>
diff --git a/libs/WifiTrackerLib/res/values-sk/strings.xml b/libs/WifiTrackerLib/res/values-sk/strings.xml
index d432ef6..1c28870 100644
--- a/libs/WifiTrackerLib/res/values-sk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sk/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Obmedzené pripojenie"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"K súkromnému serveru DNS sa nepodarilo získať prístup"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Bez internetu"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nízka kvalita"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Žiadne"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Platnosť vypršala"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Prihláste sa klepnutím"</string>
diff --git a/libs/WifiTrackerLib/res/values-sl/strings.xml b/libs/WifiTrackerLib/res/values-sl/strings.xml
index 4501d82..3be8f0e 100644
--- a/libs/WifiTrackerLib/res/values-sl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sl/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Omejena povezava"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Do zasebnega strežnika DNS ni mogoče dostopati"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ni internetne povezave"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Nizka kakovost"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Brez"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Poteklo"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Dotaknite se, če se želite registrirati"</string>
diff --git a/libs/WifiTrackerLib/res/values-sq/strings.xml b/libs/WifiTrackerLib/res/values-sq/strings.xml
index dde5ee0..78dc083 100644
--- a/libs/WifiTrackerLib/res/values-sq/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sq/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Lidhje e kufizuar"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Serveri privat DNS nuk mund të qaset"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Nuk ka internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Cilësi e ulët"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Asnjë"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Skaduar"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Trokit për t\'u regjistruar"</string>
diff --git a/libs/WifiTrackerLib/res/values-sr/strings.xml b/libs/WifiTrackerLib/res/values-sr/strings.xml
index 1d133e3..87cc17c 100644
--- a/libs/WifiTrackerLib/res/values-sr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sr/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Ограничена веза"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Приступ приватном DNS серверу није успео"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Нема интернета"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Лош квалитет"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ништа"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Истекло"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Додирните да бисте се регистровали"</string>
diff --git a/libs/WifiTrackerLib/res/values-sv/strings.xml b/libs/WifiTrackerLib/res/values-sv/strings.xml
index 589ab84..bea6449 100644
--- a/libs/WifiTrackerLib/res/values-sv/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sv/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Begränsad anslutning"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Det går inte att komma åt den privata DNS-servern."</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Inget internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Låg kvalitet"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Ingen"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Har upphört att gälla"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Tryck för att registrera dig"</string>
diff --git a/libs/WifiTrackerLib/res/values-sw/strings.xml b/libs/WifiTrackerLib/res/values-sw/strings.xml
index 573ba22..10bcf89 100644
--- a/libs/WifiTrackerLib/res/values-sw/strings.xml
+++ b/libs/WifiTrackerLib/res/values-sw/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Muunganisho hafifu"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Seva ya faragha ya DNS haiwezi kufikiwa"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Hakuna intaneti"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ubora wa chini"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Hamna"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Muda umeisha"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Gusa ili ujisajili"</string>
diff --git a/libs/WifiTrackerLib/res/values-ta/strings.xml b/libs/WifiTrackerLib/res/values-ta/strings.xml
index 5b2f258..bc21c8e 100644
--- a/libs/WifiTrackerLib/res/values-ta/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ta/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"வரம்பிற்கு உட்பட்ட இணைப்பு"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"தனிப்பட்ட DNS சேவையகத்தை அணுக இயலாது"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"இணைய இணைப்பு இல்லை"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"குறைந்த தரம்"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ஏதுமில்லை"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"காலாவதியாகிவிட்டது"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"பதிவு செய்ய தட்டவும்"</string>
diff --git a/libs/WifiTrackerLib/res/values-te/strings.xml b/libs/WifiTrackerLib/res/values-te/strings.xml
index aef857d..e63b2e0 100644
--- a/libs/WifiTrackerLib/res/values-te/strings.xml
+++ b/libs/WifiTrackerLib/res/values-te/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"పరిమిత కనెక్షన్"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"ప్రైవేట్ DNS సర్వర్‌ను యాక్సెస్ చేయడం సాధ్యపడదు"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ఇంటర్నెట్ లేదు"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"తక్కువ క్వాలిటీ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ఏదీ లేదు"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"గడువు ముగిసింది"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"సైన్ అప్ చేయడానికి ట్యాప్ చేయండి"</string>
diff --git a/libs/WifiTrackerLib/res/values-th/strings.xml b/libs/WifiTrackerLib/res/values-th/strings.xml
index 716d232..b093fd6 100644
--- a/libs/WifiTrackerLib/res/values-th/strings.xml
+++ b/libs/WifiTrackerLib/res/values-th/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"การเชื่อมต่อที่จำกัด"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"เข้าถึงเซิร์ฟเวอร์ DNS ไม่ได้"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"ไม่มีอินเทอร์เน็ต"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"คุณภาพต่ำ"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"ไม่มี"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"หมดอายุแล้ว"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"แตะเพื่อลงชื่อสมัครใช้"</string>
diff --git a/libs/WifiTrackerLib/res/values-tl/strings.xml b/libs/WifiTrackerLib/res/values-tl/strings.xml
index a55511e..88c0d39 100644
--- a/libs/WifiTrackerLib/res/values-tl/strings.xml
+++ b/libs/WifiTrackerLib/res/values-tl/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Limitadong koneksyon"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Hindi ma-access ang pribadong DNS server"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Walang internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Mababang kalidad"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Wala"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Nag-expire na"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"I-tap para mag-sign up"</string>
diff --git a/libs/WifiTrackerLib/res/values-tr/strings.xml b/libs/WifiTrackerLib/res/values-tr/strings.xml
index 6673fff..9c165cd 100644
--- a/libs/WifiTrackerLib/res/values-tr/strings.xml
+++ b/libs/WifiTrackerLib/res/values-tr/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Sınırlı bağlantı"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Gizli DNS sunucusuna erişilemiyor"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"İnternet yok"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Düşük kalite"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Yok"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Süresi sona erdi"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Kaydolmak için dokunun"</string>
diff --git a/libs/WifiTrackerLib/res/values-uk/strings.xml b/libs/WifiTrackerLib/res/values-uk/strings.xml
index 94b9852..dbb1b89 100644
--- a/libs/WifiTrackerLib/res/values-uk/strings.xml
+++ b/libs/WifiTrackerLib/res/values-uk/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Обмежене з’єднання"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Немає доступу до приватного DNS-сервера"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Немає Інтернету"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Низька якість"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Немає"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Термін дії минув"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Торкніться, щоб зареєструватись"</string>
diff --git a/libs/WifiTrackerLib/res/values-ur/strings.xml b/libs/WifiTrackerLib/res/values-ur/strings.xml
index 84ae38d..3003a5a 100644
--- a/libs/WifiTrackerLib/res/values-ur/strings.xml
+++ b/libs/WifiTrackerLib/res/values-ur/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"محدود کنکشن"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"‏نجی DNS سرور تک رسائی حاصل نہیں کی جا سکی"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"انٹرنیٹ نہیں ہے"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"ادنٰی معیار"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"کوئی نہیں"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"میعاد ختم ہو گئی"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"سائن اپ کے لیے تھپتھپائیں"</string>
diff --git a/libs/WifiTrackerLib/res/values-uz/strings.xml b/libs/WifiTrackerLib/res/values-uz/strings.xml
index c2a17db..c32a3e0 100644
--- a/libs/WifiTrackerLib/res/values-uz/strings.xml
+++ b/libs/WifiTrackerLib/res/values-uz/strings.xml
@@ -27,7 +27,7 @@
     <string name="wifi_disabled_generic" msgid="8307050327779256414">"Yoqilmagan"</string>
     <string name="wifi_ap_unable_to_handle_new_sta" msgid="6552198761671428871">"Internet kirish nuqtasi vaqtinchalik to‘lgan"</string>
     <string name="wifi_disconnected" msgid="3720926757662831062">"Ulanmagan"</string>
-    <string name="wifi_remembered" msgid="5126903736498678708">"Saqlandi"</string>
+    <string name="wifi_remembered" msgid="5126903736498678708">"Saqlangan"</string>
     <string name="wifi_metered_label" msgid="1362621600006544014">"Trafik hisoblanadigan tarmoq"</string>
     <string name="wifi_unmetered_label" msgid="499466875639448350">"Trafik hisobi yuritilmaydigan tarmoq"</string>
     <string name="connected_via_app" msgid="1818040967936972127">"<xliff:g id="NAME">%1$s</xliff:g> orqali ulandi"</string>
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Cheklangan aloqa"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Xususiy DNS server ishlamayapti"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Internetga ulanmagansiz"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Sifati past"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Hech qanday"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Muddati tugagan"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Registratsiya qilish uchun bosing"</string>
diff --git a/libs/WifiTrackerLib/res/values-vi/strings.xml b/libs/WifiTrackerLib/res/values-vi/strings.xml
index 18f7693..68fe6fc 100644
--- a/libs/WifiTrackerLib/res/values-vi/strings.xml
+++ b/libs/WifiTrackerLib/res/values-vi/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Kết nối giới hạn"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Không thể truy cập máy chủ DNS riêng tư"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Không có Internet"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Chất lượng thấp"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Không"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Đã hết hạn"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Nhấn để đăng ký"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
index 2011a15..4b8e777 100644
--- a/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rCN/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"网络连接受限"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"无法访问私人 DNS 服务器"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"无法访问互联网"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"质量不佳"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"无"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已失效"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"点按即可注册"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
index eb8007d..81d8212 100644
--- a/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rHK/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"連線受限"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"無法存取私人 DNS 伺服器"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"沒有互聯網連線"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質欠佳"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"無"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已過期"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"輕按即可登入"</string>
diff --git a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
index d5721fe..4195427 100644
--- a/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zh-rTW/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"連線能力受限"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"無法存取私人 DNS 伺服器"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"沒有網際網路連線"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"品質不佳"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"無"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"已失效"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"輕觸即可註冊"</string>
diff --git a/libs/WifiTrackerLib/res/values-zu/strings.xml b/libs/WifiTrackerLib/res/values-zu/strings.xml
index 9a56c40..2f405d8 100644
--- a/libs/WifiTrackerLib/res/values-zu/strings.xml
+++ b/libs/WifiTrackerLib/res/values-zu/strings.xml
@@ -37,6 +37,7 @@
     <string name="wifi_limited_connection" msgid="3646701342701276239">"Iqoqo elikhawulelwe"</string>
     <string name="private_dns_broken" msgid="2212227512243587416">"Iseva eyimfihlo ye-DNS ayikwazi ukufinyelelwa"</string>
     <string name="wifi_connected_no_internet" msgid="7273909077465731259">"Ayikho i-inthanethi"</string>
+    <string name="wifi_connected_low_quality" msgid="4478331645458058445">"Ikhwalithi ephansi"</string>
     <string name="wifi_security_none" msgid="6680263031386719053">"Lutho"</string>
     <string name="wifi_passpoint_expired" msgid="3257021415099577815">"Iphelelwe isikhathi"</string>
     <string name="tap_to_sign_up" msgid="2409214576606918295">"Thepha ukuze ubhalisele"</string>
diff --git a/libs/WifiTrackerLib/res/values/strings.xml b/libs/WifiTrackerLib/res/values/strings.xml
index c238f66..0436982 100644
--- a/libs/WifiTrackerLib/res/values/strings.xml
+++ b/libs/WifiTrackerLib/res/values/strings.xml
@@ -85,6 +85,9 @@
     <!-- Summary for Connected wifi network without internet [CHAR LIMIT=NONE] -->
     <string name="wifi_connected_no_internet">No internet</string>
 
+    <!-- Summary for Connected wifi network with a low quality connection [CHAR LIMIT=NONE] -->
+    <string name="wifi_connected_low_quality">Low quality</string>
+
     <!-- Do not translate.  Concise terminology for wifi with 802.1x EAP security -->
     <string name="wifi_security_short_eap" translatable="false">802.1x</string>
 
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
index 18611e2..8eaef6e 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/BaseWifiTracker.java
@@ -16,6 +16,8 @@
 
 package com.android.wifitrackerlib;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
 import static java.util.stream.Collectors.toList;
@@ -133,6 +135,9 @@
     protected final long mScanIntervalMillis;
     protected final ScanResultUpdater mScanResultUpdater;
     protected final WifiNetworkScoreCache mWifiNetworkScoreCache;
+    protected boolean mIsWifiValidated;
+    protected boolean mIsWifiDefaultRoute;
+    protected boolean mIsCellDefaultRoute;
     private final Set<NetworkKey> mRequestedScoreKeys = new HashSet<>();
 
     // Network request for listening on changes to Wifi link properties and network capabilities
@@ -143,15 +148,56 @@
     private final ConnectivityManager.NetworkCallback mNetworkCallback =
             new ConnectivityManager.NetworkCallback() {
                 @Override
-                public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
+                public void onLinkPropertiesChanged(@NonNull Network network,
+                        @NonNull LinkProperties lp) {
                     handleLinkPropertiesChanged(lp);
                 }
 
                 @Override
-                public void onCapabilitiesChanged(Network network,
-                        NetworkCapabilities networkCapabilities) {
+                public void onCapabilitiesChanged(@NonNull Network network,
+                        @NonNull NetworkCapabilities networkCapabilities) {
+                    final boolean oldWifiValidated = mIsWifiValidated;
+                    mIsWifiValidated = networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED);
+                    if (isVerboseLoggingEnabled() && mIsWifiValidated != oldWifiValidated) {
+                        Log.v(mTag, "Is Wifi validated: " + mIsWifiValidated);
+                    }
                     handleNetworkCapabilitiesChanged(networkCapabilities);
                 }
+
+                @Override
+                public void onLost(@NonNull Network network) {
+                    mIsWifiValidated = false;
+                }
+            };
+
+    private final ConnectivityManager.NetworkCallback mDefaultNetworkCallback =
+            new ConnectivityManager.NetworkCallback() {
+                @Override
+                public void onCapabilitiesChanged(@NonNull Network network,
+                        @NonNull NetworkCapabilities networkCapabilities) {
+                    final boolean oldWifiDefault = mIsWifiDefaultRoute;
+                    final boolean oldCellDefault = mIsCellDefaultRoute;
+                    mIsWifiDefaultRoute = networkCapabilities.hasTransport(TRANSPORT_WIFI);
+                    mIsCellDefaultRoute = networkCapabilities.hasTransport(TRANSPORT_CELLULAR);
+                    if (mIsWifiDefaultRoute != oldWifiDefault
+                            || mIsCellDefaultRoute != oldCellDefault) {
+                        if (isVerboseLoggingEnabled()) {
+                            Log.v(mTag, "Wifi is the default route: " + mIsWifiDefaultRoute);
+                            Log.v(mTag, "Cell is the default route: " + mIsCellDefaultRoute);
+                        }
+                        handleDefaultRouteChanged();
+                    }
+                }
+
+                public void onLost(@NonNull Network network) {
+                    mIsWifiDefaultRoute = false;
+                    mIsCellDefaultRoute = false;
+                    if (isVerboseLoggingEnabled()) {
+                        Log.v(mTag, "Wifi is the default route: false");
+                        Log.v(mTag, "Cell is the default route: false");
+                    }
+                    handleDefaultRouteChanged();
+                }
             };
 
     /**
@@ -220,6 +266,22 @@
                 /* broadcastPermission */ null, mWorkerHandler);
         mConnectivityManager.registerNetworkCallback(mNetworkRequest, mNetworkCallback,
                 mWorkerHandler);
+        mConnectivityManager.registerDefaultNetworkCallback(mDefaultNetworkCallback,
+                mWorkerHandler);
+        final NetworkCapabilities defaultNetworkCapabilities = mConnectivityManager
+                .getNetworkCapabilities(mConnectivityManager.getActiveNetwork());
+        if (defaultNetworkCapabilities != null) {
+            mIsWifiDefaultRoute = defaultNetworkCapabilities.hasTransport(TRANSPORT_WIFI);
+            mIsCellDefaultRoute = defaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR);
+        } else {
+            mIsWifiDefaultRoute = false;
+            mIsCellDefaultRoute = false;
+        }
+        if (isVerboseLoggingEnabled()) {
+            Log.v(mTag, "Wifi is the default route: " + mIsWifiDefaultRoute);
+            Log.v(mTag, "Cell is the default route: " + mIsCellDefaultRoute);
+        }
+
         mNetworkScoreManager.registerNetworkScoreCache(
                 NetworkKey.TYPE_WIFI,
                 mWifiNetworkScoreCache,
@@ -241,6 +303,7 @@
         mWorkerHandler.post(mScanner::stop);
         mContext.unregisterReceiver(mBroadcastReceiver);
         mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
+        mConnectivityManager.unregisterNetworkCallback(mDefaultNetworkCallback);
         mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI,
                 mWifiNetworkScoreCache);
         mWorkerHandler.post(mRequestedScoreKeys::clear);
@@ -326,6 +389,15 @@
     }
 
     /**
+     * Handle when the default route changes. Whether Wifi is the default route is stored in
+     * mIsWifiDefaultRoute.
+     */
+    @WorkerThread
+    protected void handleDefaultRouteChanged() {
+        // Do nothing.
+    }
+
+    /**
      * Handle updates to the Wifi network score cache, which is stored in mWifiNetworkScoreCache
      */
     @WorkerThread
@@ -393,8 +465,7 @@
      */
     protected interface BaseWifiTrackerCallback {
         /**
-         * Called when the state of Wi-Fi has changed. The new value can be read through
-         * {@link #getWifiState()}
+         * Called when the value for {@link #getWifiState() has changed.
          */
         @MainThread
         void onWifiStateChanged();
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
index 91805f7..be50679 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/NetworkDetailsTracker.java
@@ -16,14 +16,24 @@
 
 package com.android.wifitrackerlib;
 
+import static androidx.core.util.Preconditions.checkNotNull;
+
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
+
 import android.content.Context;
+import android.content.Intent;
 import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
 import android.net.NetworkScoreManager;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
 
 import androidx.annotation.AnyThread;
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.WorkerThread;
 import androidx.lifecycle.Lifecycle;
 
 import java.time.Clock;
@@ -75,6 +85,8 @@
         }
     }
 
+    protected NetworkInfo mCurrentNetworkInfo;
+
     /**
      * Abstract constructor for NetworkDetailsTracker.
      * Clients must use {@link NetworkDetailsTracker#createNetworkDetailsTracker} for creating
@@ -95,6 +107,49 @@
                 null /* listener */, tag);
     }
 
+    @WorkerThread
+    @Override
+    protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
+        checkNotNull(intent, "Intent cannot be null!");
+        mCurrentNetworkInfo = (NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO);
+        getWifiEntry().updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+    }
+
+    @WorkerThread
+    @Override
+    protected void handleRssiChangedAction() {
+        getWifiEntry().updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
+    }
+
+    @WorkerThread
+    @Override
+    protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
+        final WifiEntry chosenEntry = getWifiEntry();
+        if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+            chosenEntry.updateLinkProperties(linkProperties);
+        }
+    }
+
+    @WorkerThread
+    @Override
+    protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
+        final WifiEntry chosenEntry = getWifiEntry();
+        if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+            chosenEntry.updateNetworkCapabilities(capabilities);
+            chosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+        }
+    }
+
+    @WorkerThread
+    @Override
+    protected void handleDefaultRouteChanged() {
+        final WifiEntry chosenEntry = getWifiEntry();
+        if (chosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
+            chosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
+            chosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+        }
+    }
+
     /**
      * Returns the WifiEntry object representing the single network being tracked.
      */
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
index 134ceef..b1d7d4a 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/OsuWifiEntry.java
@@ -24,6 +24,7 @@
 import android.annotation.MainThread;
 import android.content.Context;
 import android.net.NetworkInfo;
+import android.net.Uri;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
@@ -60,11 +61,12 @@
     @NonNull private final String mKey;
     @NonNull private final Context mContext;
     @NonNull private OsuProvider mOsuProvider;
+    private String mSsid;
     private String mOsuStatusString;
     private boolean mIsAlreadyProvisioned = false;
 
     /**
-     * Create n OsuWifiEntry with the associated OsuProvider
+     * Create an OsuWifiEntry with the associated OsuProvider
      */
     OsuWifiEntry(@NonNull Context context, @NonNull Handler callbackHandler,
             @NonNull OsuProvider osuProvider,
@@ -87,7 +89,18 @@
 
     @Override
     public String getTitle() {
-        return mOsuProvider.getFriendlyName();
+        final String friendlyName = mOsuProvider.getFriendlyName();
+        if (!TextUtils.isEmpty(friendlyName)) {
+            return friendlyName;
+        }
+        if (!TextUtils.isEmpty(mSsid)) {
+            return mSsid;
+        }
+        final Uri serverUri = mOsuProvider.getServerUri();
+        if (serverUri != null) {
+            return serverUri.toString();
+        }
+        return "";
     }
 
     @Override
@@ -105,8 +118,7 @@
 
     @Override
     public String getSsid() {
-        // TODO(b/70983952): Fill this method in in case we need the SSID for verbose logging
-        return "";
+        return mSsid;
     }
 
     @Override
@@ -267,10 +279,13 @@
         }
 
         final ScanResult bestScanResult = getBestScanResultByLevel(scanResults);
-        if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
-            mLevel = bestScanResult != null
-                    ? mWifiManager.calculateSignalLevel(bestScanResult.level)
-                    : WIFI_LEVEL_UNREACHABLE;
+        if (bestScanResult != null) {
+            mSsid = bestScanResult.SSID;
+            if (getConnectedState() == CONNECTED_STATE_DISCONNECTED) {
+                mLevel = mWifiManager.calculateSignalLevel(bestScanResult.level);
+            }
+        } else {
+            mLevel = WIFI_LEVEL_UNREACHABLE;
         }
         notifyOnUpdated();
     }
@@ -336,7 +351,7 @@
                 case OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE:
                     newStatusString = String.format(mContext.getString(
                             R.string.osu_opening_provider),
-                            mOsuProvider.getFriendlyName());
+                            getTitle());
                     break;
                 case OSU_STATUS_REDIRECT_RESPONSE_RECEIVED:
                 case OSU_STATUS_SECOND_SOAP_EXCHANGE:
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
index e2d7acc..e4efcb9 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointNetworkDetailsTracker.java
@@ -19,13 +19,11 @@
 import static androidx.core.util.Preconditions.checkNotNull;
 
 import static com.android.wifitrackerlib.PasspointWifiEntry.uniqueIdToPasspointWifiEntryKey;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
 import static com.android.wifitrackerlib.WifiEntry.WIFI_LEVEL_UNREACHABLE;
 
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
-import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkInfo;
 import android.net.NetworkScoreManager;
@@ -45,7 +43,6 @@
 import androidx.lifecycle.Lifecycle;
 
 import java.time.Clock;
-import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
@@ -59,6 +56,7 @@
     private final PasspointWifiEntry mChosenEntry;
     private OsuWifiEntry mOsuWifiEntry;
     private NetworkInfo mCurrentNetworkInfo;
+    private WifiConfiguration mCurrentWifiConfig;
 
     PasspointNetworkDetailsTracker(@NonNull Lifecycle lifecycle,
             @NonNull Context context,
@@ -101,16 +99,6 @@
                         "Cannot find config for given PasspointWifiEntry key!");
             }
         }
-
-        cacheNewScanResults();
-        conditionallyUpdateScanResults(true /* lastScanSucceeded */);
-        conditionallyUpdateConfig();
-        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-        final Network currentNetwork = mWifiManager.getCurrentNetwork();
-        mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
-        mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
-        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(
-                mWifiManager.getCurrentNetwork()));
     }
 
     @AnyThread
@@ -122,6 +110,22 @@
 
     @WorkerThread
     @Override
+    protected  void handleOnStart() {
+        conditionallyUpdateScanResults(true /* lastScanSucceeded */);
+        conditionallyUpdateConfig();
+        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        final Network currentNetwork = mWifiManager.getCurrentNetwork();
+        mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
+        mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
+        handleNetworkCapabilitiesChanged(
+                mConnectivityManager.getNetworkCapabilities(currentNetwork));
+        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
+        mChosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
+        mChosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+    }
+
+    @WorkerThread
+    @Override
     protected void handleWifiStateChangedAction() {
         conditionallyUpdateScanResults(true /* lastScanSucceeded */);
     }
@@ -142,34 +146,6 @@
     }
 
     @WorkerThread
-    @Override
-    protected void handleRssiChangedAction() {
-        mChosenEntry.updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
-        checkNotNull(intent, "Intent cannot be null!");
-        mCurrentNetworkInfo = (NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO);
-        mChosenEntry.updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleLinkPropertiesChanged(@NonNull LinkProperties linkProperties) {
-        if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
-            mChosenEntry.updateLinkProperties(linkProperties);
-        }
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleNetworkScoreCacheUpdated() {
-        mChosenEntry.onScoreCacheUpdated();
-    }
-
-    @WorkerThread
     private void updatePasspointWifiEntryScans(@NonNull List<ScanResult> scanResults) {
         checkNotNull(scanResults, "Scan Result list should not be null!");
 
@@ -180,14 +156,16 @@
             final String key = uniqueIdToPasspointWifiEntryKey(wifiConfig.getKey());
 
             if (TextUtils.equals(key, mChosenEntry.getKey())) {
-                mChosenEntry.updateScanResultInfo(wifiConfig,
+                mCurrentWifiConfig = wifiConfig;
+                mChosenEntry.updateScanResultInfo(mCurrentWifiConfig,
                         pair.second.get(WifiManager.PASSPOINT_HOME_NETWORK),
                         pair.second.get(WifiManager.PASSPOINT_ROAMING_NETWORK));
                 return;
             }
         }
-        // No AP in range; set scan results and connection config to null.
-        mChosenEntry.updateScanResultInfo(null /* wifiConfig */,
+        // No AP in range; set scan results to null but keep the last seen WifiConfig to display
+        // the previous information while out of range.
+        mChosenEntry.updateScanResultInfo(mCurrentWifiConfig,
                 null /* homeScanResults */,
                 null /* roamingScanResults */);
     }
@@ -235,8 +213,9 @@
      */
     private void conditionallyUpdateScanResults(boolean lastScanSucceeded) {
         if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
-            mChosenEntry.updateScanResultInfo(null /* wifiConfig */,
-                    Collections.emptyList(), Collections.emptyList());
+            mChosenEntry.updateScanResultInfo(mCurrentWifiConfig,
+                    null /* homeScanResults */,
+                    null /* roamingScanResults */);
             return;
         }
 
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
index d873c25..1f0a34b 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/PasspointWifiEntry.java
@@ -16,6 +16,7 @@
 
 package com.android.wifitrackerlib;
 
+import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS;
 import static android.net.wifi.WifiInfo.sanitizeSsid;
 
 import static androidx.core.util.Preconditions.checkNotNull;
@@ -244,6 +245,11 @@
                         ? carrierName
                         : suggestorLabel);
             }
+
+            if (mIsLowQuality) {
+                return mContext.getString(R.string.wifi_connected_low_quality);
+            }
+
             String networkCapabilitiesinformation =
                     getCurrentNetworkCapabilitiesInformation(mContext, mNetworkCapabilities);
             if (!TextUtils.isEmpty(networkCapabilitiesinformation)) {
@@ -277,16 +283,21 @@
 
     @Override
     public String getMacAddress() {
+        if (mWifiInfo != null) {
+            final String wifiInfoMac = mWifiInfo.getMacAddress();
+            if (!TextUtils.isEmpty(wifiInfoMac)
+                    && !TextUtils.equals(wifiInfoMac, DEFAULT_MAC_ADDRESS)) {
+                return wifiInfoMac;
+            }
+        }
         if (mWifiConfig == null || getPrivacy() != PRIVACY_RANDOMIZED_MAC) {
             final String[] factoryMacs = mWifiManager.getFactoryMacAddresses();
             if (factoryMacs.length > 0) {
                 return factoryMacs[0];
-            } else {
-                return null;
             }
-        } else {
-            return mWifiConfig.getRandomizedMacAddress().toString();
+            return null;
         }
+        return mWifiConfig.getRandomizedMacAddress().toString();
     }
 
     @Override
@@ -470,26 +481,27 @@
     @Override
     public boolean isAutoJoinEnabled() {
         // Suggestion network; use WifiConfig instead
-        if (mPasspointConfig == null && mWifiConfig != null) {
+        if (mPasspointConfig != null) {
+            return mPasspointConfig.isAutojoinEnabled();
+        }
+        if (mWifiConfig != null) {
             return mWifiConfig.allowAutojoin;
         }
-
-        return mPasspointConfig.isAutojoinEnabled();
+        return false;
     }
 
     @Override
     public boolean canSetAutoJoinEnabled() {
-        return true;
+        return mPasspointConfig != null || mWifiConfig != null;
     }
 
     @Override
     public void setAutoJoinEnabled(boolean enabled) {
-        if (mPasspointConfig == null && mWifiConfig != null) {
+        if (mPasspointConfig != null) {
+            mWifiManager.allowAutojoinPasspoint(mPasspointConfig.getHomeSp().getFqdn(), enabled);
+        } else if (mWifiConfig != null) {
             mWifiManager.allowAutojoin(mWifiConfig.networkId, enabled);
-            return;
         }
-
-        mWifiManager.allowAutojoinPasspoint(mPasspointConfig.getHomeSp().getFqdn(), enabled);
     }
 
     @Override
@@ -614,7 +626,9 @@
     /** Pass a reference to a matching OsuWifiEntry for expiration handling */
     void setOsuWifiEntry(OsuWifiEntry osuWifiEntry) {
         mOsuWifiEntry = osuWifiEntry;
-        mOsuWifiEntry.setListener(this);
+        if (mOsuWifiEntry != null) {
+            mOsuWifiEntry.setListener(this);
+        }
     }
 
     /** Callback for updates to the linked OsuWifiEntry */
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
index 3ef1b47..356af41 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardNetworkDetailsTracker.java
@@ -21,16 +21,13 @@
 import static com.android.wifitrackerlib.NetworkRequestEntry.wifiConfigToNetworkRequestEntryKey;
 import static com.android.wifitrackerlib.StandardWifiEntry.wifiConfigToStandardWifiEntryKey;
 import static com.android.wifitrackerlib.Utils.getSecurityTypesFromScanResult;
-import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_CONNECTED;
 
 import static java.util.stream.Collectors.toList;
 
 import android.content.Context;
 import android.content.Intent;
 import android.net.ConnectivityManager;
-import android.net.LinkProperties;
 import android.net.Network;
-import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkScoreManager;
 import android.net.wifi.WifiConfiguration;
@@ -41,7 +38,6 @@
 
 import androidx.annotation.AnyThread;
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.WorkerThread;
 import androidx.lifecycle.Lifecycle;
 
@@ -81,14 +77,6 @@
             mChosenEntry = new StandardWifiEntry(mContext, mMainHandler, key, mWifiManager,
                     mWifiNetworkScoreCache, false /* forSavedNetworksPage */);
         }
-        cacheNewScanResults();
-        conditionallyUpdateScanResults(true /* lastScanSucceeded */);
-        conditionallyUpdateConfig();
-        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-        final Network currentNetwork = mWifiManager.getCurrentNetwork();
-        mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
-        mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
-        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
     }
 
     @AnyThread
@@ -100,6 +88,22 @@
 
     @WorkerThread
     @Override
+    protected void handleOnStart() {
+        conditionallyUpdateScanResults(true /* lastScanSucceeded */);
+        conditionallyUpdateConfig();
+        final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+        final Network currentNetwork = mWifiManager.getCurrentNetwork();
+        mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
+        mChosenEntry.updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
+        handleNetworkCapabilitiesChanged(
+                mConnectivityManager.getNetworkCapabilities(currentNetwork));
+        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
+        mChosenEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
+        mChosenEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+    }
+
+    @WorkerThread
+    @Override
     protected void handleWifiStateChangedAction() {
         conditionallyUpdateScanResults(true /* lastScanSucceeded */);
     }
@@ -134,36 +138,6 @@
 
     @WorkerThread
     @Override
-    protected void handleNetworkStateChangedAction(@NonNull Intent intent) {
-        checkNotNull(intent, "Intent cannot be null!");
-        mCurrentNetworkInfo = (NetworkInfo) intent.getExtra(WifiManager.EXTRA_NETWORK_INFO);
-        mChosenEntry.updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleRssiChangedAction() {
-        mChosenEntry.updateConnectionInfo(mWifiManager.getConnectionInfo(), mCurrentNetworkInfo);
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleLinkPropertiesChanged(@Nullable LinkProperties linkProperties) {
-        if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
-            mChosenEntry.updateLinkProperties(linkProperties);
-        }
-    }
-
-    @WorkerThread
-    @Override
-    protected void handleNetworkCapabilitiesChanged(@Nullable NetworkCapabilities capabilities) {
-        if (mChosenEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
-            mChosenEntry.updateNetworkCapabilities(capabilities);
-        }
-    }
-
-    @WorkerThread
-    @Override
     protected void handleNetworkScoreCacheUpdated() {
         mChosenEntry.onScoreCacheUpdated();
     }
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
index 19c2619..5127054 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/StandardWifiEntry.java
@@ -20,6 +20,7 @@
 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS;
 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD;
 import static android.net.wifi.WifiConfiguration.NetworkSelectionStatus.NETWORK_SELECTION_ENABLED;
+import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS;
 import static android.net.wifi.WifiInfo.sanitizeSsid;
 
 import static androidx.core.util.Preconditions.checkNotNull;
@@ -54,6 +55,9 @@
 import android.net.wifi.WifiNetworkScoreCache;
 import android.os.Handler;
 import android.os.SystemClock;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import androidx.annotation.GuardedBy;
@@ -280,8 +284,12 @@
                 return mContext.getString(R.string.connected_via_network_scorer_default);
             }
 
+            if (mIsLowQuality) {
+                return mContext.getString(R.string.wifi_connected_low_quality);
+            }
+
             String networkCapabilitiesinformation =
-                    getCurrentNetworkCapabilitiesInformation(mContext, mNetworkCapabilities);
+                    getCurrentNetworkCapabilitiesInformation(mContext,  mNetworkCapabilities);
             if (!TextUtils.isEmpty(networkCapabilitiesinformation)) {
                 return networkCapabilitiesinformation;
             }
@@ -309,16 +317,21 @@
 
     @Override
     public String getMacAddress() {
+        if (mWifiInfo != null) {
+            final String wifiInfoMac = mWifiInfo.getMacAddress();
+            if (!TextUtils.isEmpty(wifiInfoMac)
+                    && !TextUtils.equals(wifiInfoMac, DEFAULT_MAC_ADDRESS)) {
+                return wifiInfoMac;
+            }
+        }
         if (mWifiConfig == null || getPrivacy() != PRIVACY_RANDOMIZED_MAC) {
             final String[] factoryMacs = mWifiManager.getFactoryMacAddresses();
             if (factoryMacs.length > 0) {
                 return factoryMacs[0];
-            } else {
-                return null;
             }
-        } else {
-            return mWifiConfig.getRandomizedMacAddress().toString();
+            return null;
         }
+        return mWifiConfig.getRandomizedMacAddress().toString();
     }
 
     @Override
@@ -357,8 +370,35 @@
 
     @Override
     public boolean canConnect() {
-        return mLevel != WIFI_LEVEL_UNREACHABLE
-                && getConnectedState() == CONNECTED_STATE_DISCONNECTED;
+        if (mLevel == WIFI_LEVEL_UNREACHABLE
+                || getConnectedState() != CONNECTED_STATE_DISCONNECTED) {
+            return false;
+        }
+        // Allow connection for EAP SIM dependent methods if the SIM of specified carrier ID is
+        // active in the device.
+        if (getSecurity() == SECURITY_EAP && mWifiConfig != null
+                && mWifiConfig.enterpriseConfig != null) {
+            if (!mWifiConfig.enterpriseConfig.isAuthenticationSimBased()) {
+                return true;
+            }
+            List<SubscriptionInfo> activeSubscriptionInfos = ((SubscriptionManager) mContext
+                    .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
+                    .getActiveSubscriptionInfoList();
+            if (activeSubscriptionInfos == null || activeSubscriptionInfos.size() == 0) {
+                return false;
+            }
+            if (mWifiConfig.carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
+                // To connect via default subscription.
+                return true;
+            }
+            for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfos) {
+                if (subscriptionInfo.getCarrierId() == mWifiConfig.carrierId) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return true;
     }
 
     @Override
@@ -642,12 +682,6 @@
             return false;
         }
 
-        // The secured Wi-Fi entry is never connected.
-        if (getSecurity() != SECURITY_NONE && getSecurity() != SECURITY_OWE
-                && !wifiConfig.getNetworkSelectionStatus().hasEverConnected()) {
-            return true;
-        }
-
         // The network is disabled because of one of the authentication problems.
         NetworkSelectionStatus networkSelectionStatus = wifiConfig.getNetworkSelectionStatus();
         if (networkSelectionStatus.getNetworkSelectionStatus() != NETWORK_SELECTION_ENABLED) {
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
index d1added..90d62f2 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/Utils.java
@@ -494,6 +494,11 @@
             sj.add(wifiInfoDescription);
         }
 
+        final String networkCapabilityDescription = wifiEntry.getNetworkCapabilityDescription();
+        if (!TextUtils.isEmpty(networkCapabilityDescription)) {
+            sj.add(networkCapabilityDescription);
+        }
+
         final String scanResultsDescription = wifiEntry.getScanResultDescription();
         if (!TextUtils.isEmpty(scanResultsDescription)) {
             sj.add(scanResultsDescription);
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
index c7dc5c4..675c80d 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiEntry.java
@@ -223,6 +223,10 @@
     protected boolean mCalledConnect = false;
     protected boolean mCalledDisconnect = false;
 
+    private boolean mIsValidated;
+    private boolean mIsDefaultNetwork;
+    protected boolean mIsLowQuality;
+
     WifiEntry(@NonNull Handler callbackHandler, @NonNull WifiManager wifiManager,
             @NonNull WifiNetworkScoreCache scoreCache,
             boolean forSavedNetworksPage) throws IllegalArgumentException {
@@ -289,6 +293,14 @@
         return mLevel;
     };
 
+    /**
+     * Returns whether the level icon for this network should show an X or not.
+     */
+    public boolean shouldShowXLevelIcon() {
+        return getConnectedState() != CONNECTED_STATE_DISCONNECTED
+                && (!mIsValidated || !mIsDefaultNetwork) && !canSignIn();
+    }
+
     /** Returns the speed value of the network defined by the SPEED constants */
     @Speed
     public int getSpeed() {
@@ -452,6 +464,20 @@
         return "";
     }
 
+    /** Returns the network capability information of a WifiEntry */
+    String getNetworkCapabilityDescription() {
+        final StringBuilder sb = new StringBuilder();
+        if (getConnectedState() == CONNECTED_STATE_CONNECTED) {
+            sb.append("isValidated:")
+                    .append(mIsValidated)
+                    .append(", isDefaultNetwork:")
+                    .append(mIsDefaultNetwork)
+                    .append(", isLowQuality:")
+                    .append(mIsLowQuality);
+        }
+        return sb.toString();
+    }
+
     /**
      * In Wi-Fi picker, when users click a saved network, it will connect to the Wi-Fi network.
      * However, for some special cases, Wi-Fi picker should show Wi-Fi editor UI for users to edit
@@ -627,6 +653,9 @@
             mNetworkInfo = null;
             mNetworkCapabilities = null;
             mConnectedInfo = null;
+            mIsValidated = false;
+            mIsDefaultNetwork = false;
+            mIsLowQuality = false;
             if (mCalledDisconnect) {
                 mCalledDisconnect = false;
                 mCallbackHandler.post(() -> {
@@ -686,10 +715,27 @@
         notifyOnUpdated();
     }
 
+    @WorkerThread
+    void setIsDefaultNetwork(boolean isDefaultNetwork) {
+        mIsDefaultNetwork = isDefaultNetwork;
+        notifyOnUpdated();
+    }
+
+    @WorkerThread
+    void setIsLowQuality(boolean isLowQuality) {
+        mIsLowQuality = isLowQuality;
+    }
+
     // Method for WifiTracker to update a connected WifiEntry's network capabilities.
     @WorkerThread
     void updateNetworkCapabilities(@Nullable NetworkCapabilities capabilities) {
         mNetworkCapabilities = capabilities;
+        if (mConnectedInfo == null) {
+            return;
+        }
+        mIsValidated = mNetworkCapabilities != null
+                && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
+        notifyOnUpdated();
     }
 
     String getWifiInfoDescription() {
@@ -803,12 +849,17 @@
                 .append(isSuggestion())
                 .append(",level:")
                 .append(getLevel())
+                .append(shouldShowXLevelIcon() ? "X" : "")
                 .append(",security:")
                 .append(getSecurity())
                 .append(",connected:")
                 .append(getConnectedState() == CONNECTED_STATE_CONNECTED ? "true" : "false")
                 .append(",connectedInfo:")
                 .append(getConnectedInfo())
+                .append(",isValidated:")
+                .append(mIsValidated)
+                .append(",isDefaultNetwork:")
+                .append(mIsDefaultNetwork)
                 .toString();
     }
 }
diff --git a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
index bb3a224..eef865a 100644
--- a/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
+++ b/libs/WifiTrackerLib/src/com/android/wifitrackerlib/WifiPickerTracker.java
@@ -195,10 +195,15 @@
         final Network currentNetwork = mWifiManager.getCurrentNetwork();
         mCurrentNetworkInfo = mConnectivityManager.getNetworkInfo(currentNetwork);
         updateConnectionInfo(wifiInfo, mCurrentNetworkInfo);
-        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
         notifyOnNumSavedNetworksChanged();
         notifyOnNumSavedSubscriptionsChanged();
         updateWifiEntries();
+
+        // Populate mConnectedWifiEntry with information from missed callbacks.
+        handleNetworkCapabilitiesChanged(
+                mConnectivityManager.getNetworkCapabilities(currentNetwork));
+        handleLinkPropertiesChanged(mConnectivityManager.getLinkProperties(currentNetwork));
+        handleDefaultRouteChanged();
     }
 
     @WorkerThread
@@ -276,6 +281,15 @@
         if (mConnectedWifiEntry != null
                 && mConnectedWifiEntry.getConnectedState() == CONNECTED_STATE_CONNECTED) {
             mConnectedWifiEntry.updateNetworkCapabilities(capabilities);
+            mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
+        }
+    }
+
+    @WorkerThread
+    protected void handleDefaultRouteChanged() {
+        if (mConnectedWifiEntry != null) {
+            mConnectedWifiEntry.setIsDefaultNetwork(mIsWifiDefaultRoute);
+            mConnectedWifiEntry.setIsLowQuality(mIsWifiValidated && mIsCellDefaultRoute);
         }
     }
 
@@ -491,7 +505,8 @@
         // Remove entries that are now unreachable
         mPasspointWifiEntryCache.entrySet()
                 .removeIf(entry -> entry.getValue().getLevel() == WIFI_LEVEL_UNREACHABLE
-                        || !seenKeys.contains(entry.getKey()));
+                        || (!seenKeys.contains(entry.getKey()))
+                        && entry.getValue().getConnectedState() == CONNECTED_STATE_DISCONNECTED);
     }
 
     @WorkerThread
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
index 80a31e5..aa96fb8 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/PasspointWifiEntryTest.java
@@ -30,6 +30,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkKey;
 import android.net.ScoredNetwork;
@@ -147,7 +148,8 @@
         ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
         when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mockConnectivityManager);
-
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
         WifiInfo wifiInfo = mock(WifiInfo.class);
         when(wifiInfo.isPasspointAp()).thenReturn(true);
         when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
@@ -159,11 +161,55 @@
                 getPasspointConfiguration(), mMockWifiManager, mMockScoreCache,
                 false /* forSavedNetworksPage */);
         entry.updateConnectionInfo(wifiInfo, networkInfo);
+        entry.updateNetworkCapabilities(networkCapabilities);
+        entry.setIsDefaultNetwork(true);
 
         assertThat(entry.getSummary()).isEqualTo("Connected");
     }
 
     @Test
+    public void testShouldShowXLevelIcon_unvalidatedOrNotDefault_returnsTrue() {
+        ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
+        when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+                .thenReturn(mockConnectivityManager);
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
+        WifiInfo wifiInfo = mock(WifiInfo.class);
+        when(wifiInfo.isPasspointAp()).thenReturn(true);
+        when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+        final NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+        PasspointWifiEntry entry = new PasspointWifiEntry(mMockContext, mTestHandler,
+                getPasspointConfiguration(), mMockWifiManager, mMockScoreCache,
+                false /* forSavedNetworksPage */);
+
+        // Disconnected should return false;
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
+
+        // Not validated, Not Default
+        entry.updateConnectionInfo(wifiInfo, networkInfo);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+
+        // Not Validated, Default
+        entry.setIsDefaultNetwork(true);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+
+        // Validated, Default
+        entry.updateNetworkCapabilities(networkCapabilities);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
+
+        // Validated, Not Default
+        entry.setIsDefaultNetwork(false);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+    }
+
+    @Test
     public void testGetSpeed_cacheUpdated_speedValueChanges() {
         when(mMockScoredNetwork.calculateBadge(GOOD_RSSI)).thenReturn(SPEED_FAST);
         PasspointWifiEntry entry = new PasspointWifiEntry(mMockContext, mTestHandler,
@@ -221,4 +267,40 @@
 
         assertThat(entry.getSpeed()).isEqualTo(SPEED_SLOW);
     }
+
+    @Test
+    public void testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress() {
+        final String factoryMac = "01:23:45:67:89:ab";
+        final String wifiInfoMac = "11:23:45:67:89:ab";
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "\"ssid\"";
+        config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
+        config.FQDN = FQDN;
+        when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
+        WifiInfo wifiInfo = mock(WifiInfo.class);
+        when(wifiInfo.isPasspointAp()).thenReturn(true);
+        when(wifiInfo.getPasspointFqdn()).thenReturn(FQDN);
+        when(wifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+        PasspointWifiEntry entry = new PasspointWifiEntry(mMockContext, mTestHandler,
+                getPasspointConfiguration(), mMockWifiManager, mMockScoreCache,
+                false /* forSavedNetworksPage */);
+
+        entry.updateConnectionInfo(wifiInfo, networkInfo);
+
+        assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
+    }
+
+    @Test
+    public void testIsAutoJoinEnabled_nullConfigs_returnsFalse() {
+        PasspointWifiEntry entry = new PasspointWifiEntry(mMockContext, mTestHandler,
+                getPasspointConfiguration(), mMockWifiManager, mMockScoreCache,
+                false /* forSavedNetworksPage */);
+
+        entry.updatePasspointConfig(null);
+
+        assertThat(entry.isAutoJoinEnabled()).isFalse();
+    }
 }
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
index b9a0ca1..e9194f3 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/StandardWifiEntryTest.java
@@ -31,6 +31,7 @@
 import static com.android.wifitrackerlib.WifiEntry.SECURITY_NONE;
 import static com.android.wifitrackerlib.WifiEntry.SECURITY_OWE;
 import static com.android.wifitrackerlib.WifiEntry.SECURITY_PSK;
+import static com.android.wifitrackerlib.WifiEntry.SECURITY_SAE;
 import static com.android.wifitrackerlib.WifiEntry.SECURITY_WEP;
 import static com.android.wifitrackerlib.WifiEntry.SPEED_FAST;
 import static com.android.wifitrackerlib.WifiEntry.SPEED_SLOW;
@@ -61,11 +62,15 @@
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
+import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiNetworkScoreCache;
 import android.os.Handler;
 import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -89,6 +94,7 @@
     @Mock private WifiEntry.ConnectCallback mMockConnectCallback;
     @Mock private WifiManager mMockWifiManager;
     @Mock private ConnectivityManager mMockConnectivityManager;
+    @Mock private SubscriptionManager mSubscriptionManager;
     @Mock private WifiInfo mMockWifiInfo;
     @Mock private NetworkInfo mMockNetworkInfo;
     @Mock private Context mMockContext;
@@ -120,6 +126,9 @@
                 .thenReturn(mMockNetworkScoreManager);
         when(mMockScoreCache.getScoredNetwork((ScanResult) any())).thenReturn(mMockScoredNetwork);
         when(mMockScoreCache.getScoredNetwork((NetworkKey) any())).thenReturn(mMockScoredNetwork);
+
+        when(mMockContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
+                .thenReturn(mSubscriptionManager);
     }
 
     /**
@@ -470,6 +479,32 @@
     }
 
     @Test
+    public void testGetMacAddress_wifiInfoAvailable_usesWifiInfoMacAddress() {
+        final int networkId = 1;
+        final String factoryMac = "01:23:45:67:89:ab";
+        final String wifiInfoMac = "11:23:45:67:89:ab";
+
+        final NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+
+        when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
+        when(mMockWifiInfo.getMacAddress()).thenReturn(wifiInfoMac);
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "\"ssid\"";
+        config.networkId = networkId;
+        config.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
+        when(mMockWifiManager.getFactoryMacAddresses()).thenReturn(new String[]{factoryMac});
+        final StandardWifiEntry entry = new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_NONE), config,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */);
+
+        entry.updateConnectionInfo(mMockWifiInfo, networkInfo);
+
+        assertThat(entry.getMacAddress()).isEqualTo(wifiInfoMac);
+    }
+
+    @Test
     public void testCanShare_securityCanShare_shouldReturnTrue() {
         final StandardWifiEntry pskWifiEntry =
                 getSavedStandardWifiEntry(WifiConfiguration.SECURITY_TYPE_PSK);
@@ -587,6 +622,8 @@
         when(mockResources.getString(R.string.summary_separator)).thenReturn(summarySeparator);
         when(mockResources.getStringArray(R.array.wifi_status)).thenReturn(wifiStatusArray);
         final ConnectivityManager mockConnectivityManager = mock(ConnectivityManager.class);
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
         when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE))
                 .thenReturn(mockConnectivityManager);
 
@@ -603,11 +640,56 @@
                 mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */);
 
         entry.updateConnectionInfo(wifiInfo, networkInfo);
+        entry.updateNetworkCapabilities(networkCapabilities);
+        entry.setIsDefaultNetwork(true);
 
         assertThat(entry.getSummary()).isEqualTo("Connected");
     }
 
     @Test
+    public void testShouldShowXLevelIcon_unvalidatedOrNotDefault_returnsTrue() {
+        final int networkId = 1;
+        when(mMockContext.getSystemService(Context.CONNECTIVITY_SERVICE))
+                .thenReturn(mMockConnectivityManager);
+        final NetworkCapabilities networkCapabilities = new NetworkCapabilities.Builder()
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build();
+        final WifiInfo wifiInfo = new WifiInfo.Builder().setNetworkId(networkId).build();
+        final NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, "", "");
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "\"ssid\"";
+        config.networkId = networkId;
+
+        final StandardWifiEntry entry = new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_NONE), config,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */);
+
+        // Disconnected should return false;
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
+
+        // Not validated, Not Default
+        entry.updateConnectionInfo(wifiInfo, networkInfo);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+
+        // Not Validated, Default
+        entry.setIsDefaultNetwork(true);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+
+        // Validated, Default
+        entry.updateNetworkCapabilities(networkCapabilities);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(false);
+
+        // Validated, Not Default
+        entry.setIsDefaultNetwork(false);
+
+        assertThat(entry.shouldShowXLevelIcon()).isEqualTo(true);
+    }
+
+    @Test
     public void testGetSecurityString_pskTypeWpa2_getWpa2() {
         final StandardWifiEntry entry =
                 getSavedStandardWifiEntry(WifiConfiguration.SECURITY_TYPE_PSK);
@@ -722,27 +804,6 @@
     }
 
     @Test
-    public void testShouldEditBeforeConnect_securedNetwork_returnTrueIfNeverConnected() {
-        // Test never connected.
-        WifiConfiguration wifiConfig = spy(new WifiConfiguration());
-        wifiConfig.SSID = "\"ssid\"";
-        wifiConfig.setSecurityParams(WifiConfiguration.SECURITY_TYPE_PSK);
-        StandardWifiEntry entry = new StandardWifiEntry(mMockContext, mTestHandler,
-                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_PSK),
-                wifiConfig, mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */);
-        NetworkSelectionStatus networkSelectionStatus =
-                spy(new NetworkSelectionStatus.Builder().build());
-        doReturn(networkSelectionStatus).when(wifiConfig).getNetworkSelectionStatus();
-
-        assertThat(entry.shouldEditBeforeConnect()).isTrue();
-
-        // Test ever connected.
-        doReturn(true).when(networkSelectionStatus).hasEverConnected();
-
-        assertThat(entry.shouldEditBeforeConnect()).isFalse();
-    }
-
-    @Test
     public void testShouldEditBeforeConnect_authenticationFailure_returnTrue() {
         // Test DISABLED_AUTHENTICATION_FAILURE.
         WifiConfiguration wifiConfig = spy(new WifiConfiguration());
@@ -833,4 +894,135 @@
 
         assertThat(entry.getSpeed()).isEqualTo(SPEED_SLOW);
     }
+
+    @Test
+    public void testCanConnect_nonEapMethod_returnTrueIfReachable() {
+        StandardWifiEntry spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_NONE),
+                Arrays.asList(buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+
+        spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_OWE),
+                Arrays.asList(buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+
+        spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_WEP),
+                Arrays.asList(buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+
+        spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_PSK),
+                Arrays.asList(buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+
+        spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_SAE),
+                Arrays.asList(buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)),
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+    }
+
+    @Test
+    public void testCanConnect_nonSimMethod_returnTrueIfReachable() {
+        WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        mockWifiConfiguration.SSID = "\"ssid\"";
+        WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(false);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        StandardWifiEntry spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_EAP),
+                mockWifiConfiguration,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        spyEntry.updateScanResultInfo(Arrays.asList(
+                buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+    }
+
+    @Test
+    public void testCanConnect_unknownCarrierId_returnTrueIfActiveSubscriptionAvailable() {
+        WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        mockWifiConfiguration.SSID = "\"ssid\"";
+        mockWifiConfiguration.carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        StandardWifiEntry spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_EAP),
+                mockWifiConfiguration,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        spyEntry.updateScanResultInfo(Arrays.asList(
+                buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList())
+                .thenReturn(Arrays.asList(mock(SubscriptionInfo.class)));
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+    }
+
+    @Test
+    public void testCanConnect_specifiedCarrierIdMatched_returnTrue() {
+        WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        mockWifiConfiguration.SSID = "\"ssid\"";
+        int carrierId = 6;
+        mockWifiConfiguration.carrierId = carrierId;
+        WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        StandardWifiEntry spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_EAP),
+                mockWifiConfiguration,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        spyEntry.updateScanResultInfo(Arrays.asList(
+                buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+        SubscriptionInfo mockSubscriptionInfo = mock(SubscriptionInfo.class);
+        when(mockSubscriptionInfo.getCarrierId()).thenReturn(carrierId);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList())
+                .thenReturn(Arrays.asList(mockSubscriptionInfo));
+
+        assertThat(spyEntry.canConnect()).isEqualTo(true);
+    }
+
+    @Test
+    public void testCanConnect_specifiedCarrierIdNotMatched_returnFalse() {
+        WifiConfiguration mockWifiConfiguration = mock(WifiConfiguration.class);
+        mockWifiConfiguration.SSID = "\"ssid\"";
+        int specifiedCarrierId = 6;
+        int simCarrierId = 7;
+        mockWifiConfiguration.carrierId = specifiedCarrierId;
+        WifiEnterpriseConfig mockWifiEnterpriseConfig = mock(WifiEnterpriseConfig.class);
+        when(mockWifiEnterpriseConfig.isAuthenticationSimBased()).thenReturn(true);
+        mockWifiConfiguration.enterpriseConfig = mockWifiEnterpriseConfig;
+        StandardWifiEntry spyEntry = spy(new StandardWifiEntry(mMockContext, mTestHandler,
+                ssidAndSecurityToStandardWifiEntryKey("ssid", SECURITY_EAP),
+                mockWifiConfiguration,
+                mMockWifiManager, mMockScoreCache, false /* forSavedNetworksPage */));
+        spyEntry.updateScanResultInfo(Arrays.asList(
+                buildScanResult("ssid", "bssid0", 0, GOOD_RSSI)));
+        when(spyEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+        SubscriptionInfo mockSubscriptionInfo = mock(SubscriptionInfo.class);
+        when(mockSubscriptionInfo.getCarrierId()).thenReturn(simCarrierId);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList())
+                .thenReturn(Arrays.asList(mockSubscriptionInfo));
+
+        assertThat(spyEntry.canConnect()).isEqualTo(false);
+    }
 }
diff --git a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
index feec984..1260266 100644
--- a/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
+++ b/libs/WifiTrackerLib/tests/src/com/android/wifitrackerlib/WifiPickerTrackerTest.java
@@ -21,6 +21,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
@@ -29,7 +30,10 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkScoreManager;
 import android.net.wifi.ScanResult;
@@ -73,6 +77,8 @@
     @Mock
     private Context mMockContext;
     @Mock
+    private Resources mMockResources;
+    @Mock
     private WifiManager mMockWifiManager;
     @Mock
     private ConnectivityManager mMockConnectivityManager;
@@ -86,11 +92,19 @@
     private WifiInfo mMockWifiInfo;
     @Mock
     private NetworkInfo mMockNetworkInfo;
+    @Mock
+    private Network mMockNetwork;
 
     private TestLooper mTestLooper;
 
     private final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
             ArgumentCaptor.forClass(BroadcastReceiver.class);
+    private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
+            mNetworkCallbackCaptor =
+                ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
+    private final ArgumentCaptor<ConnectivityManager.NetworkCallback>
+            mDefaultNetworkCallbackCaptor =
+                ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class);
 
     private WifiPickerTracker createTestWifiPickerTracker() {
         final Handler testHandler = new Handler(mTestLooper.getLooper());
@@ -121,6 +135,7 @@
         when(mMockWifiInfo.getRssi()).thenReturn(WifiInfo.INVALID_RSSI);
         when(mMockNetworkInfo.getDetailedState()).thenReturn(
                 NetworkInfo.DetailedState.DISCONNECTED);
+        when(mMockContext.getResources()).thenReturn(mMockResources);
         when(mMockContext.getSystemService(Context.NETWORK_SCORE_SERVICE))
                 .thenReturn(mMockNetworkScoreManager);
     }
@@ -504,6 +519,44 @@
     }
 
     /**
+     * Tests that a connected WifiEntry will return "Low quality" as the summary if Wifi is
+     * validated but cell is the default route.
+     */
+    @Test
+    public void testGetConnectedEntry_wifiValidatedCellDefault_isLowQuality() {
+        final String lowQuality = "Low quality";
+        when(mMockResources.getString(anyInt())).thenReturn("");
+        when(mMockResources.getString(R.string.wifi_connected_low_quality)).thenReturn(lowQuality);
+        final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+        final WifiConfiguration config = new WifiConfiguration();
+        config.SSID = "\"ssid\"";
+        config.networkId = 1;
+        when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+                .thenReturn(Collections.singletonList(config));
+        when(mMockWifiManager.getScanResults()).thenReturn(Arrays.asList(
+                buildScanResult("ssid", "bssid", START_MILLIS)));
+        when(mMockWifiInfo.getNetworkId()).thenReturn(1);
+        when(mMockWifiInfo.getRssi()).thenReturn(-50);
+        when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
+        when(mMockConnectivityManager.getNetworkInfo(any())).thenReturn(mMockNetworkInfo);
+        wifiPickerTracker.onStart();
+        verify(mMockConnectivityManager)
+                .registerNetworkCallback(any(), mNetworkCallbackCaptor.capture(), any());
+        verify(mMockConnectivityManager)
+                .registerDefaultNetworkCallback(mDefaultNetworkCallbackCaptor.capture(), any());
+        mTestLooper.dispatchAll();
+
+        mNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
+                new NetworkCapabilities.Builder()
+                        .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED).build());
+        mDefaultNetworkCallbackCaptor.getValue().onCapabilitiesChanged(mMockNetwork,
+                new NetworkCapabilities.Builder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR).build());
+
+        assertThat(wifiPickerTracker.getConnectedWifiEntry().getSummary()).isEqualTo(lowQuality);
+    }
+
+    /**
      * Tests that a PasspointWifiEntry is returned when Passpoint scans are visible.
      */
     @Test
@@ -596,7 +649,6 @@
         config.networkId = networkId;
         config.allowedKeyManagement = new BitSet();
         config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
-
         when(config.isPasspoint()).thenReturn(true);
         when(config.getKey()).thenReturn(passpointConfig.getUniqueId());
         when(mMockWifiManager.getPrivilegedConfiguredNetworks())
@@ -617,6 +669,51 @@
         assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo(friendlyName);
     }
 
+    @Test
+    public void testGetConnectedEntry_passpointWithoutScans_returnsPasspointEntry() {
+        final String fqdn = "fqdn";
+        final String friendlyName = "friendlyName";
+        final int networkId = 1;
+        // Create a passpoint configuration to match with the current network
+        final PasspointConfiguration passpointConfig = new PasspointConfiguration();
+        final HomeSp homeSp = new HomeSp();
+        homeSp.setFqdn(fqdn);
+        homeSp.setFriendlyName(friendlyName);
+        passpointConfig.setHomeSp(homeSp);
+        passpointConfig.setCredential(new Credential());
+        when(mMockWifiManager.getPasspointConfigurations())
+                .thenReturn(Collections.singletonList(passpointConfig));
+        // Create a wifi config to match the WifiInfo netId and unique id of the passpoint config
+        final WifiConfiguration config = Mockito.mock(WifiConfiguration.class);
+        config.SSID = "\"ssid\"";
+        config.networkId = networkId;
+        config.allowedKeyManagement = new BitSet();
+        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.SUITE_B_192);
+        when(config.isPasspoint()).thenReturn(true);
+        when(config.getKey()).thenReturn(passpointConfig.getUniqueId());
+        when(mMockWifiManager.getPrivilegedConfiguredNetworks())
+                .thenReturn(Collections.singletonList(config));
+        when(mMockWifiInfo.isPasspointAp()).thenReturn(true);
+        when(mMockWifiInfo.getNetworkId()).thenReturn(networkId);
+        when(mMockWifiInfo.getPasspointFqdn()).thenReturn(fqdn);
+        when(mMockWifiInfo.getRssi()).thenReturn(-50);
+        when(mMockNetworkInfo.getDetailedState()).thenReturn(NetworkInfo.DetailedState.CONNECTED);
+        final WifiPickerTracker wifiPickerTracker = createTestWifiPickerTracker();
+        wifiPickerTracker.onStart();
+        verify(mMockContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
+                any(), any(), any());
+        mTestLooper.dispatchAll();
+
+        // Update with SCAN_RESULTS_AVAILABLE action while there are no scan results available yet.
+        mBroadcastReceiverCaptor.getValue().onReceive(mMockContext,
+                new Intent(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+        mTestLooper.dispatchAll();
+
+        verify(mMockCallback, atLeastOnce()).onWifiEntriesChanged();
+        assertThat(wifiPickerTracker.getConnectedWifiEntry()).isNotNull();
+        assertThat(wifiPickerTracker.getConnectedWifiEntry().getTitle()).isEqualTo(friendlyName);
+    }
+
     /**
      * Tests that SCAN_RESULTS_AVAILABLE_ACTION calls WifiManager#getMatchingOsuProviders()
      */
diff --git a/service/Android.bp b/service/Android.bp
index 71cf728..2e51f74 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -92,7 +92,8 @@
         "libnanohttpd",
         "services.net-module-wifi",
         "wifi-lite-protos",
-        "wifi-nano-protos"
+        "wifi-nano-protos",
+        "modules-utils-os",
     ],
 }
 
diff --git a/service/apex/apex_manifest.json b/service/apex/apex_manifest.json
index 3333298..30e46b4 100644
--- a/service/apex/apex_manifest.json
+++ b/service/apex/apex_manifest.json
@@ -1,5 +1,5 @@
 {
   "name": "com.android.wifi",
-  "version": 300900700
+  "version": 300000000
 }
 
diff --git a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
index dffd774..e3fe32a 100644
--- a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
+++ b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
@@ -18,9 +18,12 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.Context;
+import android.net.wifi.ScanResult;
 import android.net.wifi.WifiManager;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Log;
 
@@ -32,8 +35,11 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -55,7 +61,7 @@
     public static final int REASON_EAP_FAILURE = 3;
     // Other association rejection failures
     public static final int REASON_ASSOCIATION_REJECTION = 4;
-    // Associated timeout failures, when the RSSI is good
+    // Association timeout failures.
     public static final int REASON_ASSOCIATION_TIMEOUT = 5;
     // Other authentication failures
     public static final int REASON_AUTHENTICATION_FAILURE = 6;
@@ -63,8 +69,15 @@
     public static final int REASON_DHCP_FAILURE = 7;
     // Abnormal disconnect error
     public static final int REASON_ABNORMAL_DISCONNECT = 8;
+    // AP initiated disconnect for a given duration.
+    public static final int REASON_FRAMEWORK_DISCONNECT_MBO_OCE = 9;
+    // Avoid connecting to the failed AP when trying to reconnect on other available candidates.
+    public static final int REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT = 10;
+    // The connected scorer has disconnected this network.
+    public static final int REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE = 11;
     // Constant being used to keep track of how many failure reasons there are.
-    public static final int NUMBER_REASON_CODES = 9;
+    public static final int NUMBER_REASON_CODES = 12;
+    public static final int INVALID_REASON = -1;
 
     @IntDef(prefix = { "REASON_" }, value = {
             REASON_AP_UNABLE_TO_HANDLE_NEW_STA,
@@ -74,7 +87,11 @@
             REASON_ASSOCIATION_REJECTION,
             REASON_ASSOCIATION_TIMEOUT,
             REASON_AUTHENTICATION_FAILURE,
-            REASON_DHCP_FAILURE
+            REASON_DHCP_FAILURE,
+            REASON_ABNORMAL_DISCONNECT,
+            REASON_FRAMEWORK_DISCONNECT_MBO_OCE,
+            REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT,
+            REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FailureReason {}
@@ -91,11 +108,23 @@
             "REASON_ASSOCIATION_TIMEOUT",
             "REASON_AUTHENTICATION_FAILURE",
             "REASON_DHCP_FAILURE",
-            "REASON_ABNORMAL_DISCONNECT"
+            "REASON_ABNORMAL_DISCONNECT",
+            "REASON_FRAMEWORK_DISCONNECT_MBO_OCE",
+            "REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT",
+            "REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE"
     };
-    private static final String FAILURE_BSSID_BLOCKED_BY_FRAMEWORK_REASON_STRING =
-            "BlockedByFramework";
+    private static final Set<Integer> LOW_RSSI_SENSITIVE_FAILURES = new ArraySet<>(Arrays.asList(
+            REASON_NETWORK_VALIDATION_FAILURE,
+            REASON_EAP_FAILURE,
+            REASON_ASSOCIATION_REJECTION,
+            REASON_ASSOCIATION_TIMEOUT,
+            REASON_AUTHENTICATION_FAILURE,
+            REASON_DHCP_FAILURE,
+            REASON_ABNORMAL_DISCONNECT,
+            REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE
+    ));
     private static final long ABNORMAL_DISCONNECT_RESET_TIME_MS = TimeUnit.HOURS.toMillis(3);
+    private static final int MIN_RSSI_DIFF_TO_UNBLOCK_BSSID = 5;
     private static final String TAG = "BssidBlocklistMonitor";
 
     private final Context mContext;
@@ -105,6 +134,7 @@
     private final LocalLog mLocalLog;
     private final Calendar mCalendar;
     private final WifiScoreCard mWifiScoreCard;
+    private final ScoringParams mScoringParams;
 
     // Map of bssid to BssidStatus
     private Map<String, BssidStatus> mBssidStatusMap = new ArrayMap<>();
@@ -117,7 +147,7 @@
      */
     BssidBlocklistMonitor(Context context, WifiConnectivityHelper connectivityHelper,
             WifiLastResortWatchdog wifiLastResortWatchdog, Clock clock, LocalLog localLog,
-            WifiScoreCard wifiScoreCard) {
+            WifiScoreCard wifiScoreCard, ScoringParams scoringParams) {
         mContext = context;
         mConnectivityHelper = connectivityHelper;
         mWifiLastResortWatchdog = wifiLastResortWatchdog;
@@ -125,6 +155,7 @@
         mLocalLog = localLog;
         mCalendar = Calendar.getInstance();
         mWifiScoreCard = wifiScoreCard;
+        mScoringParams = scoringParams;
     }
 
     // A helper to log debugging information in the local log buffer, which can
@@ -160,10 +191,12 @@
         mBssidStatusHistoryLogger.dump(pw);
     }
 
-    private void addToBlocklist(@NonNull BssidStatus entry, long durationMs, String reasonString) {
-        entry.addToBlocklist(durationMs, reasonString);
+    private void addToBlocklist(@NonNull BssidStatus entry, long durationMs,
+            @FailureReason int reason, int rssi) {
+        entry.setAsBlocked(durationMs, reason, rssi);
         localLog(TAG + " addToBlocklist: bssid=" + entry.bssid + ", ssid=" + entry.ssid
-                + ", durationMs=" + durationMs + ", reason=" + reasonString);
+                + ", durationMs=" + durationMs + ", reason=" + getFailureReasonString(reason)
+                + ", rssi=" + rssi);
     }
 
     /**
@@ -217,13 +250,20 @@
 
     /**
      * Block any attempts to auto-connect to the BSSID for the specified duration.
+     * This is meant to be used by features that need wifi to avoid a BSSID for a certain duration,
+     * and thus will not increase the failure streak counters.
+     * @param bssid identifies the AP to block.
+     * @param ssid identifies the SSID the AP belongs to.
+     * @param durationMs duration in millis to block.
+     * @param blockReason reason for blocking the BSSID.
+     * @param rssi the latest RSSI observed.
      */
     public void blockBssidForDurationMs(@NonNull String bssid, @NonNull String ssid,
-            long durationMs) {
-        if (bssid == null || ssid == null || WifiManager.UNKNOWN_SSID.equals(ssid)
-                || bssid.equals(ClientModeImpl.SUPPLICANT_BSSID_ANY) || durationMs <= 0) {
+            long durationMs, @FailureReason int blockReason, int rssi) {
+        if (durationMs <= 0 || !isValidNetworkAndFailureReason(bssid, ssid, blockReason)) {
             Log.e(TAG, "Invalid input: BSSID=" + bssid + ", SSID=" + ssid
-                    + ", durationMs=" + durationMs);
+                    + ", durationMs=" + durationMs + ", blockReason=" + blockReason
+                    + ", rssi=" + rssi);
             return;
         }
         BssidStatus status = getOrCreateBssidStatus(bssid, ssid);
@@ -232,11 +272,13 @@
             // Return because this BSSID is already being blocked for a longer time.
             return;
         }
-        addToBlocklist(status, durationMs, FAILURE_BSSID_BLOCKED_BY_FRAMEWORK_REASON_STRING);
+        addToBlocklist(status, durationMs, blockReason, rssi);
     }
 
     private String getFailureReasonString(@FailureReason int reasonCode) {
-        if (reasonCode >= FAILURE_REASON_STRINGS.length) {
+        if (reasonCode == INVALID_REASON) {
+            return "INVALID_REASON";
+        } else if (reasonCode < 0 || reasonCode >= FAILURE_REASON_STRINGS.length) {
             return "REASON_UNKNOWN";
         }
         return FAILURE_REASON_STRINGS[reasonCode];
@@ -278,7 +320,7 @@
     }
 
     private boolean handleBssidConnectionFailureInternal(String bssid, String ssid,
-            @FailureReason int reasonCode, boolean isLowRssi) {
+            @FailureReason int reasonCode, int rssi) {
         BssidStatus entry = incrementFailureCountForBssid(bssid, ssid, reasonCode);
         int failureThreshold = getFailureThresholdForReason(reasonCode);
         int currentStreak = mWifiScoreCard.getBssidBlocklistStreak(ssid, bssid, reasonCode);
@@ -288,28 +330,33 @@
             if (shouldWaitForWatchdogToTriggerFirst(bssid, reasonCode)) {
                 return false;
             }
-            int baseBlockDurationMs = mContext.getResources().getInteger(
-                    R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs);
-            if ((reasonCode == REASON_ASSOCIATION_TIMEOUT
-                    || reasonCode == REASON_ABNORMAL_DISCONNECT) && isLowRssi) {
-                baseBlockDurationMs = mContext.getResources().getInteger(
-                        R.integer.config_wifiBssidBlocklistMonitorBaseLowRssiBlockDurationMs);
-            }
+            int baseBlockDurationMs = getBaseBlockDurationForReason(reasonCode);
             addToBlocklist(entry,
                     getBlocklistDurationWithExponentialBackoff(currentStreak, baseBlockDurationMs),
-                    getFailureReasonString(reasonCode));
+                    reasonCode, rssi);
             mWifiScoreCard.incrementBssidBlocklistStreak(ssid, bssid, reasonCode);
             return true;
         }
         return false;
     }
 
+    private int getBaseBlockDurationForReason(int blockReason) {
+        switch (blockReason) {
+            case REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE:
+                return mContext.getResources().getInteger(R.integer
+                        .config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs);
+            default:
+                return mContext.getResources().getInteger(
+                        R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs);
+        }
+    }
+
     /**
      * Note a failure event on a bssid and perform appropriate actions.
      * @return True if the blocklist has been modified.
      */
     public boolean handleBssidConnectionFailure(String bssid, String ssid,
-            @FailureReason int reasonCode, boolean isLowRssi) {
+            @FailureReason int reasonCode, int rssi) {
         if (!isValidNetworkAndFailureReason(bssid, ssid, reasonCode)) {
             return false;
         }
@@ -322,7 +369,7 @@
                 return false;
             }
         }
-        return handleBssidConnectionFailureInternal(bssid, ssid, reasonCode, isLowRssi);
+        return handleBssidConnectionFailureInternal(bssid, ssid, reasonCode, rssi);
     }
 
     /**
@@ -346,6 +393,8 @@
                 ssid, bssid, connectionTime);
         if (connectionTime - prevConnectionTime > ABNORMAL_DISCONNECT_RESET_TIME_MS) {
             mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid, REASON_ABNORMAL_DISCONNECT);
+            mWifiScoreCard.resetBssidBlocklistStreak(ssid, bssid,
+                    REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE);
         }
 
         BssidStatus status = mBssidStatusMap.get(bssid);
@@ -380,7 +429,10 @@
          * remove the BSSID from blocklist to make sure we are not accidentally blocking good
          * BSSIDs.
          **/
-        status.removeFromBlocklist();
+        if (status.isInBlocklist) {
+            mBssidStatusHistoryLogger.add(status, "Network validation success");
+            mBssidStatusMap.remove(bssid);
+        }
     }
 
     /**
@@ -448,11 +500,36 @@
      * @param ssid
      * @return the number of BSSIDs currently in the blocklist for the |ssid|.
      */
-    public int getNumBlockedBssidsForSsid(@NonNull String ssid) {
+    public int updateAndGetNumBlockedBssidsForSsid(@NonNull String ssid) {
         return (int) updateAndGetBssidBlocklistInternal()
                 .filter(entry -> ssid.equals(entry.ssid)).count();
     }
 
+    private int getNumBlockedBssidsForSsid(@Nullable String ssid) {
+        if (ssid == null) {
+            return 0;
+        }
+        return (int) mBssidStatusMap.values().stream()
+                .filter(entry -> entry.isInBlocklist && ssid.equals(entry.ssid))
+                .count();
+    }
+
+    /**
+     * Overloaded version of updateAndGetBssidBlocklist.
+     * Accepts a @Nullable String ssid as input, and updates the firmware roaming
+     * configuration if the blocklist for the input ssid has been changed.
+     * @param ssid to update firmware roaming configuration for.
+     * @return Set of BSSIDs currently in the blocklist
+     */
+    public Set<String> updateAndGetBssidBlocklistForSsid(@Nullable String ssid) {
+        int numBefore = getNumBlockedBssidsForSsid(ssid);
+        Set<String> bssidBlocklist = updateAndGetBssidBlocklist();
+        if (getNumBlockedBssidsForSsid(ssid) != numBefore) {
+            updateFirmwareRoamingConfiguration(ssid);
+        }
+        return bssidBlocklist;
+    }
+
     /**
      * Gets the BSSIDs that are currently in the blocklist.
      * @return Set of BSSIDs currently in the blocklist
@@ -464,6 +541,47 @@
     }
 
     /**
+     * Gets the list of block reasons for BSSIDs currently in the blocklist.
+     * @return The set of unique reasons for blocking BSSIDs with this SSID.
+     */
+    public Set<Integer> getFailureReasonsForSsid(@NonNull String ssid) {
+        if (ssid == null) {
+            return Collections.emptySet();
+        }
+        return mBssidStatusMap.values().stream()
+                .filter(entry -> entry.isInBlocklist && ssid.equals(entry.ssid))
+                .map(entry -> entry.blockReason)
+                .collect(Collectors.toSet());
+    }
+
+    /**
+     * Attempts to re-enable BSSIDs that likely experienced failures due to low RSSI.
+     * @param scanDetails
+     */
+    public void tryEnablingBlockedBssids(List<ScanDetail> scanDetails) {
+        if (scanDetails == null) {
+            return;
+        }
+        for (ScanDetail scanDetail : scanDetails) {
+            ScanResult scanResult = scanDetail.getScanResult();
+            if (scanResult == null) {
+                continue;
+            }
+            BssidStatus status = mBssidStatusMap.get(scanResult.BSSID);
+            if (status == null || !status.isInBlocklist
+                    || !LOW_RSSI_SENSITIVE_FAILURES.contains(status.blockReason)) {
+                continue;
+            }
+            int sufficientRssi = mScoringParams.getSufficientRssi(scanResult.frequency);
+            if (status.lastRssi < sufficientRssi && scanResult.level >= sufficientRssi
+                    && scanResult.level - status.lastRssi >= MIN_RSSI_DIFF_TO_UNBLOCK_BSSID) {
+                mBssidStatusHistoryLogger.add(status, "rssi significantly improved");
+                mBssidStatusMap.remove(status.bssid);
+            }
+        }
+    }
+
+    /**
      * Removes expired BssidStatus entries and then return remaining entries in the blocklist.
      * @return Stream of BssidStatus for BSSIDs that are in the blocklist.
      */
@@ -567,7 +685,9 @@
         public final String bssid;
         public final String ssid;
         public final int[] failureCount = new int[NUMBER_REASON_CODES];
-        private String mBlockReason = ""; // reason of blocking for logging only
+        public int blockReason = INVALID_REASON; // reason of blocking this BSSID
+        // The latest RSSI that's seen before this BSSID is added to blocklist.
+        public int lastRssi = 0;
 
         // The following are used to flag how long this BSSID stays in the blocklist.
         public boolean isInBlocklist;
@@ -588,26 +708,17 @@
         }
 
         /**
-         * Add this BSSID to blocklist for the specified duration.
+         * Set this BSSID as blocked for the specified duration.
          * @param durationMs
+         * @param blockReason
+         * @param rssi
          */
-        public void addToBlocklist(long durationMs, String blockReason) {
+        public void setAsBlocked(long durationMs, @FailureReason int blockReason, int rssi) {
             isInBlocklist = true;
             blocklistStartTimeMs = mClock.getWallClockMillis();
             blocklistEndTimeMs = blocklistStartTimeMs + durationMs;
-            mBlockReason = blockReason;
-        }
-
-        /**
-         * Remove this BSSID from the blocklist.
-         */
-        public void removeFromBlocklist() {
-            mBssidStatusHistoryLogger.add(this, "removeFromBlocklist");
-            isInBlocklist = false;
-            blocklistStartTimeMs = 0;
-            blocklistEndTimeMs = 0;
-            mBlockReason = "";
-            localLog(TAG + " removeFromBlocklist BSSID=" + bssid);
+            this.blockReason = blockReason;
+            lastRssi = rssi;
         }
 
         @Override
@@ -617,7 +728,8 @@
             sb.append(", SSID=" + ssid);
             sb.append(", isInBlocklist=" + isInBlocklist);
             if (isInBlocklist) {
-                sb.append(", blockReason=" + mBlockReason);
+                sb.append(", blockReason=" + getFailureReasonString(blockReason));
+                sb.append(", lastRssi=" + lastRssi);
                 mCalendar.setTimeInMillis(blocklistStartTimeMs);
                 sb.append(", blocklistStartTimeMs="
                         + String.format("%tm-%td %tH:%tM:%tS.%tL", mCalendar, mCalendar,
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index e73024c..520999e 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -814,7 +814,8 @@
 
         mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock,
                 mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor,
-                mWifiInjector.getWifiThreadRunner());
+                mWifiInjector.getWifiThreadRunner(), mWifiInjector.getDeviceConfigFacade(),
+                mContext, looper, mFacade);
 
         mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder()
                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
@@ -912,8 +913,6 @@
                 getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_CONNECTION_EVENT,
                 getHandler());
-        mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.FILS_NETWORK_CONNECTION_EVENT,
-                getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.NETWORK_DISCONNECTION_EVENT,
                 getHandler());
         mWifiMonitor.registerHandler(mInterfaceName, WifiMonitor.RX_HS20_ANQP_ICON_EVENT,
@@ -1115,6 +1114,10 @@
             // Clear invalid cached data.
             mWifiNative.removeNetworkCachedData(oldConfig.networkId);
 
+            if (WifiConfigurationUtil.hasCredentialChanged(oldConfig, newConfig)) {
+                mBssidBlocklistMonitor.handleNetworkRemoved(newConfig.SSID);
+            }
+
             // Check if user/app change meteredOverride for connected network.
             if (newConfig.networkId != mLastNetworkId
                     || newConfig.meteredOverride == oldConfig.meteredOverride) {
@@ -1996,7 +1999,6 @@
                 }
                 sb.append(" blacklist=" + Boolean.toString(mDidBlackListBSSID));
                 break;
-            case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
             case WifiMonitor.NETWORK_CONNECTION_EVENT:
                 sb.append(" ");
                 sb.append(Integer.toString(msg.arg1));
@@ -2262,9 +2264,6 @@
             case WifiMonitor.NETWORK_CONNECTION_EVENT:
                 s = "NETWORK_CONNECTION_EVENT";
                 break;
-            case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
-                s = "FILS_NETWORK_CONNECTION_EVENT";
-                break;
             case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                 s = "NETWORK_DISCONNECTION_EVENT";
                 break;
@@ -2561,7 +2560,6 @@
     private void sendLinkConfigurationChangedBroadcast() {
         Intent intent = new Intent(WifiManager.ACTION_LINK_CONFIGURATION_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties(mLinkProperties));
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
     }
 
@@ -2969,13 +2967,8 @@
                         mWifiHealthMonitor.getScanRssiValidTimeMs());
                 mWifiScoreCard.noteConnectionFailure(mWifiInfo, scanRssi, ssid, blocklistReason);
                 checkAbnormalConnectionFailureAndTakeBugReport(ssid);
-                boolean isLowRssi = false;
-                int sufficientRssi = getSufficientRssi(networkId, bssid);
-                if (scanRssi != WifiInfo.INVALID_RSSI && sufficientRssi != WifiInfo.INVALID_RSSI) {
-                    isLowRssi = scanRssi < sufficientRssi;
-                }
                 mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, blocklistReason,
-                        isLowRssi);
+                        scanRssi);
             }
         }
 
@@ -3444,6 +3437,7 @@
                     break;
                 case CMD_INITIALIZE:
                     mWifiNative.initialize();
+                    mWifiScoreReport.initialize();
                     break;
                 case CMD_BOOT_COMPLETED:
                     // get other services that we need to manage
@@ -3458,7 +3452,6 @@
                 case CMD_RECONNECT:
                 case CMD_REASSOCIATE:
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
-                case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
                 case WifiMonitor.NETWORK_DISCONNECTION_EVENT:
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                 case WifiMonitor.AUTHENTICATION_FAILURE_EVENT:
@@ -3689,9 +3682,10 @@
         // TODO: b/79504296 This broadcast has been deprecated and should be removed
         sendSupplicantConnectionChangedBroadcast(false);
 
-        // Let's remove any ephemeral or passpoint networks.
+        // Remove any ephemeral or Passpoint networks, flush ANQP cache
         mWifiConfigManager.removeAllEphemeralOrPasspointConfiguredNetworks();
         mWifiConfigManager.clearUserTemporarilyDisabledList();
+        mPasspointManager.clearAnqpRequestsAndFlushCache();
     }
 
     void registerConnected() {
@@ -4214,12 +4208,11 @@
                     }
                     handleStatus = NOT_HANDLED;
                     break;
-                case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
-                    mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount();
-                    mSentHLPs = true;
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
                     if (mVerboseLoggingEnabled) log("Network connection established");
                     mLastNetworkId = message.arg1;
+                    mSentHLPs = message.arg2 == 1;
+                    if (mSentHLPs) mWifiMetrics.incrementL2ConnectionThroughFilsAuthCount();
                     mWifiConfigManager.clearRecentFailureReason(mLastNetworkId);
                     mLastBssid = (String) message.obj;
                     reasonCode = message.arg2;
@@ -4909,14 +4902,11 @@
                     }
                     break;
                 case WifiMonitor.NETWORK_CONNECTION_EVENT:
-                case WifiMonitor.FILS_NETWORK_CONNECTION_EVENT:
                     mWifiInfo.setBSSID((String) message.obj);
                     mLastNetworkId = message.arg1;
                     mWifiInfo.setNetworkId(mLastNetworkId);
                     mWifiInfo.setMacAddress(mWifiNative.getMacAddress(mInterfaceName));
-                    if (!mLastBssid.equals(message.obj)) {
-                        mLastBssid = (String) message.obj;
-                    }
+                    mLastBssid = (String) message.obj;
                     break;
                 case CMD_ONESHOT_RSSI_POLL:
                     if (!mEnableRssiPolling) {
@@ -5017,11 +5007,12 @@
                             && mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID) {
                         WifiConfiguration config =
                                 mWifiConfigManager.getConfiguredNetwork(mLastNetworkId);
-                        if ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED
+                        if (config != null
+                            && ((message.arg1 == RESET_SIM_REASON_DEFAULT_DATA_SIM_CHANGED
                                 && config.carrierId != TelephonyManager.UNKNOWN_CARRIER_ID)
                                 || (config.enterpriseConfig != null
                                         && config.enterpriseConfig.isAuthenticationSimBased()
-                                        && !mWifiCarrierInfoManager.isSimPresent(mLastSubId))) {
+                                        && !mWifiCarrierInfoManager.isSimPresent(mLastSubId)))) {
                             mWifiMetrics.logStaEvent(StaEvent.TYPE_FRAMEWORK_DISCONNECT,
                                     StaEvent.DISCONNECT_RESET_SIM_NETWORKS);
                             // remove local PMKSA cache in framework
@@ -5436,15 +5427,11 @@
                                     mWifiConfigManager.updateNetworkSelectionStatus(
                                             config.networkId,
                                             DISABLED_NO_INTERNET_TEMPORARY);
+                                    mBssidBlocklistMonitor.handleBssidConnectionFailure(
+                                            mLastBssid, config.SSID,
+                                            BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE,
+                                            mWifiInfo.getRssi());
                                 }
-                                int rssi = mWifiInfo.getRssi();
-                                int sufficientRssi = mWifiInjector.getScoringParams()
-                                        .getSufficientRssi(mWifiInfo.getFrequency());
-                                boolean isLowRssi = rssi < sufficientRssi;
-                                mBssidBlocklistMonitor.handleBssidConnectionFailure(
-                                        mLastBssid, config.SSID,
-                                        BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE,
-                                        isLowRssi);
                                 mWifiScoreCard.noteValidationFailure(mWifiInfo);
                             }
                         }
@@ -5500,13 +5487,10 @@
                     boolean localGen = message.arg1 == 1;
                     if (!localGen) { // ignore disconnects initiated by wpa_supplicant.
                         mWifiScoreCard.noteNonlocalDisconnect(message.arg2);
-                        int rssi = mWifiInfo.getRssi();
-                        int sufficientRssi = mWifiInjector.getScoringParams()
-                                .getSufficientRssi(mWifiInfo.getFrequency());
-                        boolean isLowRssi = rssi < sufficientRssi;
                         mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
                                 mWifiInfo.getSSID(),
-                                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, isLowRssi);
+                                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT,
+                                mWifiInfo.getRssi());
                     }
                     config = getCurrentWifiConfiguration();
 
@@ -5711,6 +5695,7 @@
                     }
                     clearNetworkCachedDataIfNeeded(getTargetWifiConfiguration(), message.arg2);
                     mTargetNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+                    mWifiInfo.reset();
                     break;
                 case WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT:
                     StateChangeResult stateChangeResult = (StateChangeResult) message.obj;
@@ -5841,15 +5826,20 @@
     }
 
     void handleGsmAuthRequest(SimAuthRequestData requestData) {
+        WifiConfiguration requestingWifiConfiguration = null;
         if (mTargetWifiConfiguration != null
                 && mTargetWifiConfiguration.networkId
                 == requestData.networkId) {
+            requestingWifiConfiguration = mTargetWifiConfiguration;
             logd("id matches targetWifiConfiguration");
         } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
                 && mLastNetworkId == requestData.networkId) {
+            requestingWifiConfiguration = getCurrentWifiConfiguration();
             logd("id matches currentWifiConfiguration");
-        } else {
-            logd("id does not match targetWifiConfiguration");
+        }
+
+        if (requestingWifiConfiguration == null) {
+            logd("GsmAuthRequest received with null target/current WifiConfiguration.");
             return;
         }
 
@@ -5866,15 +5856,15 @@
          *                            [SRES][Cipher Key Kc]
          */
         String response = mWifiCarrierInfoManager
-                .getGsmSimAuthResponse(requestData.data, mTargetWifiConfiguration);
+                .getGsmSimAuthResponse(requestData.data, requestingWifiConfiguration);
         if (response == null) {
             // In case of failure, issue may be due to sim type, retry as No.2 case
             response = mWifiCarrierInfoManager
-                    .getGsmSimpleSimAuthResponse(requestData.data, mTargetWifiConfiguration);
+                    .getGsmSimpleSimAuthResponse(requestData.data, requestingWifiConfiguration);
             if (response == null) {
                 // In case of failure, issue may be due to sim type, retry as No.3 case
                 response = mWifiCarrierInfoManager.getGsmSimpleSimNoLengthAuthResponse(
-                                requestData.data, mTargetWifiConfiguration);
+                                requestData.data, requestingWifiConfiguration);
             }
         }
         if (response == null || response.length() == 0) {
@@ -5887,20 +5877,25 @@
     }
 
     void handle3GAuthRequest(SimAuthRequestData requestData) {
+        WifiConfiguration requestingWifiConfiguration = null;
         if (mTargetWifiConfiguration != null
                 && mTargetWifiConfiguration.networkId
                 == requestData.networkId) {
+            requestingWifiConfiguration = mTargetWifiConfiguration;
             logd("id matches targetWifiConfiguration");
         } else if (mLastNetworkId != WifiConfiguration.INVALID_NETWORK_ID
                 && mLastNetworkId == requestData.networkId) {
+            requestingWifiConfiguration = getCurrentWifiConfiguration();
             logd("id matches currentWifiConfiguration");
-        } else {
-            logd("id does not match targetWifiConfiguration");
+        }
+
+        if (requestingWifiConfiguration == null) {
+            logd("3GAuthRequest received with null target/current WifiConfiguration.");
             return;
         }
 
         SimAuthResponseData response = mWifiCarrierInfoManager
-                .get3GAuthResponse(requestData, mTargetWifiConfiguration);
+                .get3GAuthResponse(requestData, requestingWifiConfiguration);
         if (response != null) {
             mWifiNative.simAuthResponse(
                     mInterfaceName, response.type, response.response);
@@ -6298,19 +6293,24 @@
 
 
         if ((frameData.mBssTmDataFlagsMask
-                & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED)
-                != 0) {
-            long duration = frameData.mBlackListDurationMs;
-            mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
+                & MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT) != 0) {
+            long duration = 0;
+            if ((frameData.mBssTmDataFlagsMask
+                    & MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED) != 0) {
+                mWifiMetrics.incrementSteeringRequestCountIncludingMboAssocRetryDelay();
+                duration = frameData.mBlockListDurationMs;
+            }
             if (duration == 0) {
                 /*
-                 * When MBO assoc retry delay is set to zero(reserved as per spec),
-                 * blacklist the BSS for sometime to avoid AP rejecting the re-connect request.
+                 * When disassoc imminent bit alone is set or MBO assoc retry delay is
+                 * set to zero(reserved as per spec), blocklist the BSS for sometime to
+                 * avoid AP rejecting the re-connect request.
                  */
-                duration = MboOceConstants.DEFAULT_BLACKLIST_DURATION_MS;
+                duration = MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS;
             }
-            // Blacklist the current BSS
-            mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, duration);
+            // Blocklist the current BSS
+            mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid, duration,
+                    BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 0);
         }
 
         if (frameData.mStatus != MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT) {
diff --git a/service/java/com/android/server/wifi/DeviceConfigFacade.java b/service/java/com/android/server/wifi/DeviceConfigFacade.java
index 0b70770..a7bcfc7 100644
--- a/service/java/com/android/server/wifi/DeviceConfigFacade.java
+++ b/service/java/com/android/server/wifi/DeviceConfigFacade.java
@@ -129,6 +129,19 @@
     // Default health monitor firmware alert valid time.
     // -1 disables firmware alert time check
     static final int DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS = -1;
+    // Default minimum confirmation duration for sending network score to connectivity service
+    // when score breaches low. The actual confirmation duration is longer in general and it
+    // depends on the score evaluation period normally controlled by
+    // 'com.android.wifi.resources.R' config_wifiPollRssiIntervalMilliseconds.
+    static final int DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS = 5000;
+    // Default minimum confirmation duration for sending network score to connectivity service
+    // when score breaches high. The actual confirmation duration is longer in general and it
+    // depends on the score evaluation period normally controlled by
+    // 'com.android.wifi.resources.R' config_wifiPollRssiIntervalMilliseconds.
+    static final int DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS = 0;
+    // Default RSSI threshold in dBm above which low score is not sent to connectivity service
+    // when external scorer takes action.
+    static final int DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM = -67;
     // Cached values of fields updated via updateDeviceConfigFlags()
     private boolean mIsAbnormalConnectionBugreportEnabled;
     private int mAbnormalConnectionDurationMs;
@@ -177,6 +190,9 @@
     private int mNonstationaryScanRssiValidTimeMs;
     private int mStationaryScanRssiValidTimeMs;
     private int mHealthMonitorFwAlertValidTimeMs;
+    private int mMinConfirmationDurationSendLowScoreMs;
+    private int mMinConfirmationDurationSendHighScoreMs;
+    private int mRssiThresholdNotSendLowScoreToCsDbm;
 
     public DeviceConfigFacade(Context context, Handler handler, WifiMetrics wifiMetrics) {
         mContext = context;
@@ -324,7 +340,15 @@
                 "health_monitor_fw_alert_valid_time_ms",
                 DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS);
         mWifiMetrics.setHealthMonitorRssiPollValidTimeMs(mHealthMonitorRssiPollValidTimeMs);
-
+        mMinConfirmationDurationSendLowScoreMs = DeviceConfig.getInt(NAMESPACE,
+                "min_confirmation_duration_send_low_score_ms",
+                DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS);
+        mMinConfirmationDurationSendHighScoreMs = DeviceConfig.getInt(NAMESPACE,
+                "min_confirmation_duration_send_high_score_ms",
+                DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS);
+        mRssiThresholdNotSendLowScoreToCsDbm = DeviceConfig.getInt(NAMESPACE,
+                "rssi_threshold_not_send_low_score_to_cs_dbm",
+                DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM);
     }
 
     private Set<String> getUnmodifiableSetQuoted(String key) {
@@ -673,4 +697,28 @@
     public int getHealthMonitorFwAlertValidTimeMs() {
         return mHealthMonitorFwAlertValidTimeMs;
     }
+
+    /**
+     * Gets the minimum confirmation duration for sending network score to connectivity service
+     * when score breaches low.
+     */
+    public int getMinConfirmationDurationSendLowScoreMs() {
+        return mMinConfirmationDurationSendLowScoreMs;
+    }
+
+    /**
+     * Gets the minimum confirmation duration for sending network score to connectivity service
+     * when score breaches high.
+     */
+    public int getMinConfirmationDurationSendHighScoreMs() {
+        return mMinConfirmationDurationSendHighScoreMs;
+    }
+
+    /**
+     * Gets the RSSI threshold above which low score is not sent to connectivity service when
+     * external scorer takes action.
+     */
+    public int getRssiThresholdNotSendLowScoreToCsDbm() {
+        return mRssiThresholdNotSendLowScoreToCsDbm;
+    }
 }
diff --git a/service/java/com/android/server/wifi/EapFailureNotifier.java b/service/java/com/android/server/wifi/EapFailureNotifier.java
index cdb1203..1d82082 100644
--- a/service/java/com/android/server/wifi/EapFailureNotifier.java
+++ b/service/java/com/android/server/wifi/EapFailureNotifier.java
@@ -16,23 +16,29 @@
 
 package com.android.server.wifi;
 
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.graphics.drawable.Icon;
 import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 
+import java.util.List;
+
 /**
  * This class may be used to launch notifications when EAP failure occurs.
  */
@@ -92,13 +98,29 @@
         showNotification(errorMessage, config.SSID);
     }
 
+    private String getSettingsPackageName() {
+        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
+        List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivitiesAsUser(
+                intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY,
+                UserHandle.of(ActivityManager.getCurrentUser()));
+        if (resolveInfos == null || resolveInfos.isEmpty()) {
+            Log.e(TAG, "Failed to resolve wifi settings activity");
+            return null;
+        }
+        // Pick the first one if there are more than 1 since the list is ordered from best to worst.
+        return resolveInfos.get(0).activityInfo.packageName;
+    }
+
     /**
      * Display eap error notification which defined by carrier.
      *
      * @param ssid Error Message which defined by carrier
      */
     private void showNotification(String errorMessage, String ssid) {
-        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
+        String settingsPackage = getSettingsPackageName();
+        if (settingsPackage == null) return;
+        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS)
+                .setPackage(settingsPackage);
         Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
                 WifiService.NOTIFICATION_NETWORK_ALERTS)
                 .setAutoCancel(true)
diff --git a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java b/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
index 98664d0..a9c99ae 100644
--- a/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
+++ b/service/java/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreData.java
@@ -28,6 +28,7 @@
 import org.xmlpull.v1.XmlSerializer;
 
 import java.io.IOException;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -92,6 +93,7 @@
             throws XmlPullParserException, IOException {
         // Ignore empty reads.
         if (in == null) {
+            mDataSource.fromDeserialized(Collections.emptyMap());
             return;
         }
 
diff --git a/service/java/com/android/server/wifi/MboOceConstants.java b/service/java/com/android/server/wifi/MboOceConstants.java
index 4ef3cab..66948b0 100644
--- a/service/java/com/android/server/wifi/MboOceConstants.java
+++ b/service/java/com/android/server/wifi/MboOceConstants.java
@@ -176,7 +176,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface MboCellularDataConnectionPreference{}
 
-    /** default Blacklist duration when AP doesn't advertise it */
-    public static final long DEFAULT_BLACKLIST_DURATION_MS = 300_000; // 5 minutes
+    /** default Blocklist duration when AP doesn't advertise non zero MBO assoc retry delay */
+    public static final long DEFAULT_BLOCKLIST_DURATION_MS = 300_000; // 5 minutes
 
 }
diff --git a/service/java/com/android/server/wifi/MboOceController.java b/service/java/com/android/server/wifi/MboOceController.java
index 4100637..d71034d 100644
--- a/service/java/com/android/server/wifi/MboOceController.java
+++ b/service/java/com/android/server/wifi/MboOceController.java
@@ -130,7 +130,7 @@
         public @MboOceConstants.BtmResponseStatus int mStatus =
                 MboOceConstants.BTM_RESPONSE_STATUS_INVALID;
         public int mBssTmDataFlagsMask = 0;
-        public long mBlackListDurationMs = 0;
+        public long mBlockListDurationMs = 0;
         public @MboOceConstants.MboTransitionReason int mTransitionReason =
                 MboOceConstants.MBO_TRANSITION_REASON_INVALID;
         public @MboOceConstants.MboCellularDataConnectionPreference int mCellPreference =
@@ -140,7 +140,7 @@
         public String toString() {
             return new StringBuilder("BtmFrameData status=").append(mStatus).append(
                     ", flags=").append(mBssTmDataFlagsMask).append(
-                    ", assocRetryDelay=").append(mBlackListDurationMs).append(
+                    ", assocRetryDelay=").append(mBlockListDurationMs).append(
                     ", transitionReason=").append(mTransitionReason).append(
                     ", cellPref=").append(mCellPreference).toString();
         }
diff --git a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
index b174be5..8c901cf 100644
--- a/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
+++ b/service/java/com/android/server/wifi/NetworkSuggestionNominator.java
@@ -246,6 +246,7 @@
                 mLocalLog.log("Failed to add network suggestion");
                 continue;
             }
+            mWifiConfigManager.allowAutojoin(result.getNetworkId(), config.allowAutojoin);
             WifiConfiguration currentWCmConfiguredNetwork =
                     mWifiConfigManager.getConfiguredNetwork(result.netId);
             // Try to enable network selection
@@ -276,6 +277,7 @@
             mLocalLog.log("Failed to add network suggestion");
             return null;
         }
+        mWifiConfigManager.allowAutojoin(result.getNetworkId(), wifiConfiguration.allowAutojoin);
         if (!mWifiConfigManager.updateNetworkSelectionStatus(result.getNetworkId(),
                 WifiConfiguration.NetworkSelectionStatus.DISABLED_NONE)) {
             mLocalLog.log("Failed to make network suggestion selectable");
diff --git a/service/java/com/android/server/wifi/ScanRequestProxy.java b/service/java/com/android/server/wifi/ScanRequestProxy.java
index c054b90..622fcda 100644
--- a/service/java/com/android/server/wifi/ScanRequestProxy.java
+++ b/service/java/com/android/server/wifi/ScanRequestProxy.java
@@ -464,7 +464,8 @@
      * @return the list of results
      */
     public List<ScanResult> getScanResults() {
-        return mLastScanResults;
+        // return a copy to prevent external modification
+        return new ArrayList<>(mLastScanResults);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/SimRequiredNotifier.java b/service/java/com/android/server/wifi/SimRequiredNotifier.java
index 8e3d22d..fed7bd8 100644
--- a/service/java/com/android/server/wifi/SimRequiredNotifier.java
+++ b/service/java/com/android/server/wifi/SimRequiredNotifier.java
@@ -16,22 +16,31 @@
 
 package com.android.server.wifi;
 
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.graphics.drawable.Icon;
 import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.Log;
 
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.wifi.resources.R;
+
+import java.util.List;
+
 /**
  * Helper class to generate SIM required notification
  *
  */
 public class SimRequiredNotifier {
 
+    private static final String TAG = "SimRequiredNotifier";
     private final WifiContext mContext;
     private final FrameworkFacade mFrameworkFacade;
     private final NotificationManager mNotificationManager;
@@ -53,8 +62,7 @@
         } else {
             name = config.SSID;
         }
-        mNotificationManager.notify(SystemMessage.NOTE_ID_WIFI_SIM_REQUIRED,
-                buildSimRequiredNotification(name, carrier));
+        showNotification(name, carrier);
     }
 
     /**
@@ -64,15 +72,33 @@
         mNotificationManager.cancel(null, SystemMessage.NOTE_ID_WIFI_SIM_REQUIRED);
     }
 
-    private Notification buildSimRequiredNotification(String ssid, String carrier) {
+    private String getSettingsPackageName() {
+        Intent intent = new Intent(Settings.ACTION_WIFI_SETTINGS);
+        List<ResolveInfo> resolveInfos = mContext.getPackageManager().queryIntentActivitiesAsUser(
+                intent, PackageManager.MATCH_SYSTEM_ONLY | PackageManager.MATCH_DEFAULT_ONLY,
+                UserHandle.of(ActivityManager.getCurrentUser()));
+        if (resolveInfos == null || resolveInfos.isEmpty()) {
+            Log.e(TAG, "Failed to resolve wifi settings activity");
+            return null;
+        }
+        // Pick the first one if there are more than 1 since the list is ordered from best to worst.
+        return resolveInfos.get(0).activityInfo.packageName;
+    }
+
+    private void showNotification(String ssid, String carrier) {
+        String settingsPackage = getSettingsPackageName();
+        if (settingsPackage == null) return;
+        Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                .setPackage(settingsPackage);
+
         String title = mContext.getResources().getString(
                 R.string.wifi_sim_required_title);
         String message = mContext.getResources().getString(
                 R.string.wifi_sim_required_message,
                 (ssid == null ? "" : ssid),
                 (carrier == null ? "" : carrier));
-
-        return mFrameworkFacade.makeNotificationBuilder(mContext,
+        Notification.Builder builder = mFrameworkFacade.makeNotificationBuilder(mContext,
                 WifiService.NOTIFICATION_NETWORK_ALERTS)
                 .setAutoCancel(true)
                 .setShowWhen(false)
@@ -85,14 +111,9 @@
                 .setStyle(new Notification.BigTextStyle().bigText(message))
                 .setSmallIcon(Icon.createWithResource(mContext.getWifiOverlayApkPkgName(),
                         R.drawable.stat_notify_wifi_in_range))
-                .setContentIntent(launchWirelessSettings())
-                .build();
-    }
-
-    private PendingIntent launchWirelessSettings() {
-        Intent intent = new Intent(Settings.ACTION_WIRELESS_SETTINGS)
-                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        return mFrameworkFacade.getActivity(mContext, 0, intent,
-                PendingIntent.FLAG_UPDATE_CURRENT);
+                .setContentIntent(mFrameworkFacade.getActivity(
+                        mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+        mNotificationManager.notify(SystemMessage.NOTE_ID_WIFI_SIM_REQUIRED,
+                builder.build());
     }
 }
diff --git a/service/java/com/android/server/wifi/SoftApManager.java b/service/java/com/android/server/wifi/SoftApManager.java
index 9ef52e7..b321a78 100644
--- a/service/java/com/android/server/wifi/SoftApManager.java
+++ b/service/java/com/android/server/wifi/SoftApManager.java
@@ -221,16 +221,7 @@
     public void stop() {
         Log.d(TAG, " currentstate: " + getCurrentStateName());
         mTargetRole = ROLE_UNSPECIFIED;
-        if (mApInterfaceName != null) {
-            if (mIfaceIsUp) {
-                updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
-                        WifiManager.WIFI_AP_STATE_ENABLED, 0);
-            } else {
-                updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
-                        WifiManager.WIFI_AP_STATE_ENABLING, 0);
-            }
-        }
-        mStateMachine.quitNow();
+        mStateMachine.sendMessage(SoftApStateMachine.CMD_STOP);
     }
 
     @Override
@@ -517,6 +508,7 @@
     private class SoftApStateMachine extends StateMachine {
         // Commands for the state machine.
         public static final int CMD_START = 0;
+        public static final int CMD_STOP = 1;
         public static final int CMD_FAILURE = 2;
         public static final int CMD_INTERFACE_STATUS_CHANGED = 3;
         public static final int CMD_ASSOCIATED_STATIONS_CHANGED = 4;
@@ -574,6 +566,9 @@
             @Override
             public boolean processMessage(Message message) {
                 switch (message.what) {
+                    case CMD_STOP:
+                        mStateMachine.quitNow();
+                        break;
                     case CMD_START:
                         mApInterfaceName = mWifiNative.setupInterfaceForSoftApMode(
                                 mWifiNativeInterfaceCallback);
@@ -908,6 +903,16 @@
                         boolean isUp = message.arg1 == 1;
                         onUpChanged(isUp);
                         break;
+                    case CMD_STOP:
+                        if (mIfaceIsUp) {
+                            updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
+                                    WifiManager.WIFI_AP_STATE_ENABLED, 0);
+                        } else {
+                            updateApState(WifiManager.WIFI_AP_STATE_DISABLING,
+                                    WifiManager.WIFI_AP_STATE_ENABLING, 0);
+                        }
+                        transitionTo(mIdleState);
+                        break;
                     case CMD_START:
                         // Already started, ignore this command.
                         break;
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
index 92ba43b..0e2189b 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackImpl.java
@@ -55,7 +55,8 @@
     private final String mIfaceName;
     private final Object mLock;
     private final WifiMonitor mWifiMonitor;
-    private boolean mStateIsFourway = false; // Used to help check for PSK password mismatch
+    // Used to help check for PSK password mismatch & EAP connection failure.
+    private int mStateBeforeDisconnect = State.INACTIVE;
 
     SupplicantStaIfaceCallbackImpl(@NonNull SupplicantStaIfaceHal staIfaceHal,
             @NonNull String ifaceName,
@@ -151,14 +152,16 @@
     public void onNetworkRemoved(int id) {
         synchronized (mLock) {
             mStaIfaceHal.logCallback("onNetworkRemoved");
-            // Reset 4way handshake state since network has been removed.
-            mStateIsFourway = false;
+            // Reset state since network has been removed.
+            mStateBeforeDisconnect = State.INACTIVE;
         }
     }
 
-    @Override
-    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,
-                               ArrayList<Byte> ssid) {
+    /**
+     * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version.
+     */
+    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid,
+            boolean filsHlpSent) {
         synchronized (mLock) {
             mStaIfaceHal.logCallback("onStateChanged");
             SupplicantState newSupplicantState =
@@ -166,10 +169,15 @@
             WifiSsid wifiSsid =
                     WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
             String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
-            mStateIsFourway = (newState == ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE);
-            if (newSupplicantState == SupplicantState.COMPLETED) {
+            if (newState != State.DISCONNECTED) {
+                // onStateChanged(DISCONNECTED) may come before onDisconnected(), so add this
+                // cache to track the state before the disconnect.
+                mStateBeforeDisconnect = newState;
+            }
+            if (newState == State.COMPLETED) {
                 mWifiMonitor.broadcastNetworkConnectionEvent(
-                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
+                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), filsHlpSent,
+                        bssidStr);
             }
             mWifiMonitor.broadcastSupplicantStateChangeEvent(
                     mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), wifiSsid,
@@ -178,6 +186,11 @@
     }
 
     @Override
+    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid) {
+        onStateChanged(newState, bssid, id, ssid, false);
+    }
+
+    @Override
     public void onAnqpQueryDone(byte[/* 6 */] bssid,
                                 ISupplicantStaIfaceCallback.AnqpData data,
                                 ISupplicantStaIfaceCallback.Hs20AnqpData hs20Data) {
@@ -239,14 +252,23 @@
         synchronized (mLock) {
             mStaIfaceHal.logCallback("onDisconnected");
             if (mStaIfaceHal.isVerboseLoggingEnabled()) {
-                Log.e(TAG, "onDisconnected 4way=" + mStateIsFourway
+                Log.e(TAG, "onDisconnected state=" + mStateBeforeDisconnect
                         + " locallyGenerated=" + locallyGenerated
                         + " reasonCode=" + reasonCode);
             }
-            if (mStateIsFourway
-                    && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
-                mWifiMonitor.broadcastAuthenticationFailureEvent(
-                        mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
+            WifiConfiguration curConfiguration =
+                    mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
+            if (curConfiguration != null) {
+                if (mStateBeforeDisconnect == State.FOURWAY_HANDSHAKE
+                        && WifiConfigurationUtil.isConfigForPskNetwork(curConfiguration)
+                        && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
+                    mWifiMonitor.broadcastAuthenticationFailureEvent(
+                            mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
+                } else if (mStateBeforeDisconnect == State.ASSOCIATED
+                        && WifiConfigurationUtil.isConfigForEapNetwork(curConfiguration)) {
+                    mWifiMonitor.broadcastAuthenticationFailureEvent(
+                            mIfaceName, WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE, -1);
+                }
             }
             mWifiMonitor.broadcastNetworkDisconnectionEvent(
                     mIfaceName, locallyGenerated ? 1 : 0, reasonCode,
@@ -261,7 +283,6 @@
             boolean isWrongPwd = false;
             WifiConfiguration curConfiguration =
                     mStaIfaceHal.getCurrentNetworkLocalConfig(mIfaceName);
-
             if (curConfiguration != null) {
                 if (!timedOut) {
                     Log.d(TAG, "flush PMK cache due to association rejection for config id "
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java
index 12e025e..c4a3dda 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_1Impl.java
@@ -53,10 +53,18 @@
         mCallbackV10.onNetworkRemoved(id);
     }
 
+    /**
+     * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version.
+     */
+    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid,
+            boolean filsHlpSent) {
+        mCallbackV10.onStateChanged(newState, bssid, id, ssid, filsHlpSent);
+    }
+
     @Override
     public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,
                                ArrayList<Byte> ssid) {
-        mCallbackV10.onStateChanged(newState, bssid, id, ssid);
+        onStateChanged(newState, bssid, id, ssid, false);
     }
 
     @Override
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java
index 89e66d2..973e11a 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_2Impl.java
@@ -59,10 +59,18 @@
         mCallbackV11.onNetworkRemoved(id);
     }
 
+    /**
+     * Added to plumb the new {@code filsHlpSent} param from the V1.3 callback version.
+     */
+    public void onStateChanged(int newState, byte[/* 6 */] bssid, int id, ArrayList<Byte> ssid,
+            boolean filsHlpSent) {
+        mCallbackV11.onStateChanged(newState, bssid, id, ssid, filsHlpSent);
+    }
+
     @Override
     public void onStateChanged(int newState, byte[/* 6 */] bssid, int id,
             ArrayList<Byte> ssid) {
-        mCallbackV11.onStateChanged(newState, bssid, id, ssid);
+        onStateChanged(newState, bssid, id, ssid, false);
     }
 
     @Override
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
index 596b56d..154fde4 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceCallbackV1_3Impl.java
@@ -15,19 +15,13 @@
  */
 package com.android.server.wifi;
 
-import static com.android.server.wifi.SupplicantStaIfaceCallbackImpl.supplicantHidlStateToFrameworkState;
 
 import android.annotation.NonNull;
 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
-import android.hardware.wifi.supplicant.V1_3.ISupplicantStaIfaceCallback.BssTmData;
-import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiManager;
-import android.net.wifi.WifiSsid;
 import android.util.Log;
 
-import com.android.server.wifi.util.NativeUtil;
-
 import java.util.ArrayList;
 
 abstract class SupplicantStaIfaceCallbackV1_3Impl extends
@@ -37,7 +31,6 @@
     private final String mIfaceName;
     private final WifiMonitor mWifiMonitor;
     private final SupplicantStaIfaceHal.SupplicantStaIfaceHalCallbackV1_2 mCallbackV12;
-    private boolean mStateIsFourwayV13 = false; // Used to help check for PSK password mismatch
 
     SupplicantStaIfaceCallbackV1_3Impl(@NonNull SupplicantStaIfaceHal staIfaceHal,
             @NonNull String ifaceName,
@@ -57,9 +50,7 @@
 
     @Override
     public void onNetworkRemoved(int id) {
-        mStaIfaceHal.logCallback("onNetworkRemoved");
-        // Reset 4way handshake state since network has been removed.
-        mStateIsFourwayV13 = false;
+        mCallbackV12.onNetworkRemoved(id);
     }
 
     @Override
@@ -96,20 +87,7 @@
     @Override
     public void onDisconnected(byte[/* 6 */] bssid, boolean locallyGenerated,
             int reasonCode) {
-        mStaIfaceHal.logCallback("onDisconnected");
-        if (mStaIfaceHal.isVerboseLoggingEnabled()) {
-            Log.e(TAG, "onDisconnected 4way=" + mStateIsFourwayV13
-                    + " locallyGenerated=" + locallyGenerated
-                    + " reasonCode=" + reasonCode);
-        }
-        if (mStateIsFourwayV13
-                && (!locallyGenerated || reasonCode != ReasonCode.IE_IN_4WAY_DIFFERS)) {
-            mWifiMonitor.broadcastAuthenticationFailureEvent(
-                    mIfaceName, WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD, -1);
-        }
-        mWifiMonitor.broadcastNetworkDisconnectionEvent(
-                mIfaceName, locallyGenerated ? 1 : 0, reasonCode,
-                NativeUtil.macAddressFromByteArray(bssid));
+        mCallbackV12.onDisconnected(bssid, locallyGenerated, reasonCode);
     }
 
     @Override
@@ -252,7 +230,7 @@
 
         btmFrmData.mStatus = halToFrameworkBtmResponseStatus(tmData.status);
         btmFrmData.mBssTmDataFlagsMask = halToFrameworkBssTmDataFlagsMask(tmData.flags);
-        btmFrmData.mBlackListDurationMs = tmData.assocRetryDelayMs;
+        btmFrmData.mBlockListDurationMs = tmData.assocRetryDelayMs;
         if ((tmData.flags & BssTmDataFlagsMask.MBO_TRANSITION_REASON_CODE_INCLUDED) != 0) {
             btmFrmData.mTransitionReason = halToFrameworkMboTransitionReason(
                     tmData.mboTransitionReason);
@@ -365,25 +343,6 @@
     @Override
     public void onStateChanged_1_3(int newState, byte[/* 6 */] bssid, int id,
             ArrayList<Byte> ssid, boolean filsHlpSent) {
-        mStaIfaceHal.logCallback("onStateChanged_1_3");
-        SupplicantState newSupplicantState =
-                supplicantHidlStateToFrameworkState(newState);
-        WifiSsid wifiSsid =
-                WifiSsid.createFromByteArray(NativeUtil.byteArrayFromArrayList(ssid));
-        String bssidStr = NativeUtil.macAddressFromByteArray(bssid);
-        mStateIsFourwayV13 =
-                (newState == ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE);
-        if (newSupplicantState == SupplicantState.COMPLETED) {
-            if (filsHlpSent) {
-                mWifiMonitor.broadcastFilsNetworkConnectionEvent(
-                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
-            } else {
-                mWifiMonitor.broadcastNetworkConnectionEvent(
-                        mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName), bssidStr);
-            }
-        }
-        mWifiMonitor.broadcastSupplicantStateChangeEvent(
-                mIfaceName, mStaIfaceHal.getCurrentNetworkId(mIfaceName),
-                wifiSsid, bssidStr, newSupplicantState);
+        mCallbackV12.onStateChanged(newState, bssid, id, ssid, filsHlpSent);
     }
 }
diff --git a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
index 657b081..b587eed 100644
--- a/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
+++ b/service/java/com/android/server/wifi/SupplicantStaIfaceHal.java
@@ -527,6 +527,10 @@
                 Log.e(TAG, "ISupplicant.addInterface exception: " + e);
                 handleNoSuchElementException(e, "addInterface");
                 return null;
+            } catch (IllegalArgumentException e) {
+                handleIllegalArgumentException(e, "addInterface");
+                Log.e(TAG, "ISupplicant.addInterface exception: " + e);
+                return null;
             }
             return supplicantIface.value;
         }
@@ -2556,7 +2560,7 @@
     private boolean checkStatusAndLogFailure(SupplicantStatus status,
             final String methodStr) {
         synchronized (mLock) {
-            if (status.code != SupplicantStatusCode.SUCCESS) {
+            if (status == null || status.code != SupplicantStatusCode.SUCCESS) {
                 Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed: " + status);
                 return false;
             } else {
@@ -2593,6 +2597,13 @@
         }
     }
 
+    private void handleIllegalArgumentException(IllegalArgumentException e, String methodStr) {
+        synchronized (mLock) {
+            clearState();
+            Log.e(TAG, "ISupplicantStaIface." + methodStr + " failed with exception", e);
+        }
+    }
+
     /**
      * Converts the Wps config method string to the equivalent enum value.
      */
diff --git a/service/java/com/android/server/wifi/WifiConfigManager.java b/service/java/com/android/server/wifi/WifiConfigManager.java
index f04874e..f620c59 100644
--- a/service/java/com/android/server/wifi/WifiConfigManager.java
+++ b/service/java/com/android/server/wifi/WifiConfigManager.java
@@ -1132,7 +1132,6 @@
         newInternalConfig.noInternetAccessExpected = externalConfig.noInternetAccessExpected;
         newInternalConfig.ephemeral = externalConfig.ephemeral;
         newInternalConfig.osu = externalConfig.osu;
-        newInternalConfig.trusted = externalConfig.trusted;
         newInternalConfig.fromWifiNetworkSuggestion = externalConfig.fromWifiNetworkSuggestion;
         newInternalConfig.fromWifiNetworkSpecifier = externalConfig.fromWifiNetworkSpecifier;
         newInternalConfig.useExternalScores = externalConfig.useExternalScores;
@@ -1801,7 +1800,7 @@
             int disableReason = networkStatus.getNetworkSelectionDisableReason();
             int blockedBssids = Math.min(MAX_BLOCKED_BSSID_PER_NETWORK,
                     mWifiInjector.getBssidBlocklistMonitor()
-                            .getNumBlockedBssidsForSsid(config.SSID));
+                            .updateAndGetNumBlockedBssidsForSsid(config.SSID));
             // if no BSSIDs are blocked then we should keep trying to connect to something
             long disableTimeoutMs = 0;
             if (blockedBssids > 0) {
@@ -2927,14 +2926,22 @@
         Set<Integer> removedNetworkIds = new HashSet<>();
         // Remove any private networks of the old user before switching the userId.
         for (WifiConfiguration config : getConfiguredNetworks()) {
-            if (!config.shared && doesUidBelongToCurrentUser(config.creatorUid)) {
+            if ((!config.shared && doesUidBelongToCurrentUser(config.creatorUid))
+                    || config.ephemeral) {
                 removedNetworkIds.add(config.networkId);
                 localLog("clearInternalUserData: removed config."
                         + " netId=" + config.networkId
                         + " configKey=" + config.getKey());
                 mConfiguredNetworks.remove(config.networkId);
+                for (OnNetworkUpdateListener listener : mListeners) {
+                    listener.onNetworkRemoved(
+                            createExternalWifiConfiguration(config, true, Process.WIFI_UID));
+                }
             }
         }
+        if (!removedNetworkIds.isEmpty()) {
+            sendConfiguredNetworkChangedBroadcast(WifiManager.CHANGE_REASON_REMOVED);
+        }
         mUserTemporarilyDisabledList.clear();
         mScanDetailCaches.clear();
         clearLastSelectedNetwork();
diff --git a/service/java/com/android/server/wifi/WifiConfigurationUtil.java b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
index 130a254..55a8c00 100644
--- a/service/java/com/android/server/wifi/WifiConfigurationUtil.java
+++ b/service/java/com/android/server/wifi/WifiConfigurationUtil.java
@@ -224,6 +224,11 @@
             if (existingEnterpriseConfig.getEapMethod() != newEnterpriseConfig.getEapMethod()) {
                 return true;
             }
+            if (existingEnterpriseConfig.isAuthenticationSimBased()) {
+                // No other credential changes for SIM based methods.
+                // The SIM card is the credential.
+                return false;
+            }
             if (existingEnterpriseConfig.getPhase2Method()
                     != newEnterpriseConfig.getPhase2Method()) {
                 return true;
@@ -232,8 +237,7 @@
                                   newEnterpriseConfig.getIdentity())) {
                 return true;
             }
-            if (!existingEnterpriseConfig.isAuthenticationSimBased()
-                    && !TextUtils.equals(existingEnterpriseConfig.getAnonymousIdentity(),
+            if (!TextUtils.equals(existingEnterpriseConfig.getAnonymousIdentity(),
                     newEnterpriseConfig.getAnonymousIdentity())) {
                 return true;
             }
@@ -246,6 +250,21 @@
             if (!Arrays.equals(existingCaCerts, newCaCerts)) {
                 return true;
             }
+            if (!Arrays.equals(newEnterpriseConfig.getCaCertificateAliases(),
+                    existingEnterpriseConfig.getCaCertificateAliases())) {
+                return true;
+            }
+            if (!TextUtils.equals(newEnterpriseConfig.getClientCertificateAlias(),
+                    existingEnterpriseConfig.getClientCertificateAlias())) {
+                return true;
+            }
+            if (!TextUtils.equals(newEnterpriseConfig.getAltSubjectMatch(),
+                    existingEnterpriseConfig.getAltSubjectMatch())) {
+                return true;
+            }
+            if (newEnterpriseConfig.getOcsp() != existingEnterpriseConfig.getOcsp()) {
+                return true;
+            }
         } else {
             // One of the configs may have an enterpriseConfig
             if (existingEnterpriseConfig != null || newEnterpriseConfig != null) {
@@ -307,6 +326,9 @@
         if (existingConfig.requirePmf != newConfig.requirePmf) {
             return true;
         }
+        if (existingConfig.carrierId != newConfig.carrierId) {
+            return true;
+        }
         if (hasEnterpriseConfigChanged(existingConfig.enterpriseConfig,
                 newConfig.enterpriseConfig)) {
             return true;
diff --git a/service/java/com/android/server/wifi/WifiConnectivityManager.java b/service/java/com/android/server/wifi/WifiConnectivityManager.java
index 2ce0bc0..77af654 100644
--- a/service/java/com/android/server/wifi/WifiConnectivityManager.java
+++ b/service/java/com/android/server/wifi/WifiConnectivityManager.java
@@ -304,7 +304,9 @@
         updateUserDisabledList(scanDetails);
 
         // Check if any blocklisted BSSIDs can be freed.
-        Set<String> bssidBlocklist = mBssidBlocklistMonitor.updateAndGetBssidBlocklist();
+        mBssidBlocklistMonitor.tryEnablingBlockedBssids(scanDetails);
+        Set<String> bssidBlocklist = mBssidBlocklistMonitor.updateAndGetBssidBlocklistForSsid(
+                mWifiInfo.getSSID());
 
         if (mStateMachine.isSupplicantTransientState()) {
             localLog(listenerName
@@ -1758,7 +1760,8 @@
                 // Make sure that the failed BSSID is blocked for at least TEMP_BSSID_BLOCK_DURATION
                 // to prevent the supplicant from trying it again.
                 mBssidBlocklistMonitor.blockBssidForDurationMs(bssid, ssid,
-                        TEMP_BSSID_BLOCK_DURATION);
+                        TEMP_BSSID_BLOCK_DURATION,
+                        BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT, 0);
                 connectToNetwork(candidate);
             }
         } catch (IllegalArgumentException e) {
diff --git a/service/java/com/android/server/wifi/WifiDiagnostics.java b/service/java/com/android/server/wifi/WifiDiagnostics.java
index 6fc75c6..3804562 100644
--- a/service/java/com/android/server/wifi/WifiDiagnostics.java
+++ b/service/java/com/android/server/wifi/WifiDiagnostics.java
@@ -226,6 +226,10 @@
         if (!mActiveInterfaces.isEmpty()) {
             return;
         }
+        if (mLogLevel != VERBOSE_NO_LOG) {
+            stopLoggingAllBuffers();
+            mRingBuffers = null;
+        }
         if (mIsLoggingEventHandlerRegistered) {
             if (!mWifiNative.resetLogHandler()) {
                 mLog.wC("Fail to reset log handler");
@@ -236,10 +240,6 @@
             // the log handler is in an indeterminate state.
             mIsLoggingEventHandlerRegistered = false;
         }
-        if (mLogLevel != VERBOSE_NO_LOG) {
-            stopLoggingAllBuffers();
-            mRingBuffers = null;
-        }
     }
 
     @Override
diff --git a/service/java/com/android/server/wifi/WifiHealthMonitor.java b/service/java/com/android/server/wifi/WifiHealthMonitor.java
index bc1f9af..b21ea51 100644
--- a/service/java/com/android/server/wifi/WifiHealthMonitor.java
+++ b/service/java/com/android/server/wifi/WifiHealthMonitor.java
@@ -24,6 +24,7 @@
 import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.content.Context;
+import android.content.pm.ModuleInfo;
 import android.content.pm.PackageManager;
 import android.net.MacAddress;
 import android.net.wifi.ScanResult;
@@ -76,7 +77,7 @@
             "WifiHealthMonitor Schedule Post-Boot Detection Timer";
     // Package name of WiFi mainline module found from the following adb command
     // adb shell pm list packages --apex-only| grep wifi
-    private static final String WIFI_APK_PACKAGE_NAME = "com.google.android.wifi";
+    private static final String WIFI_APEX_NAME = "com.android.wifi";
     private static final String SYSTEM_INFO_DATA_NAME = "systemInfoData";
     // The time that device waits after device boot before triggering post-boot detection.
     // This needs be long enough so that memory read can complete before post-boot detection.
@@ -329,8 +330,20 @@
      * @Return a non-zero value if version code is available, 0 otherwise.
      */
     public long getWifiStackVersion() {
-        WifiSoftwareBuildInfo currentBuild = getWifiSystemInfoStats().getCurrSoftwareBuildInfo();
-        return (currentBuild == null) ? 0 : currentBuild.getWifiStackVersion();
+        PackageManager packageManager = mContext.getPackageManager();
+        long wifiStackVersion = 0;
+        try {
+            ModuleInfo wifiModule = packageManager.getModuleInfo(
+                    WIFI_APEX_NAME, PackageManager.MODULE_APEX_NAME);
+            String wifiPackageName = wifiModule.getPackageName();
+            if (wifiPackageName != null) {
+                wifiStackVersion = packageManager.getPackageInfo(
+                        wifiPackageName, PackageManager.MATCH_APEX).getLongVersionCode();
+            }
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, " Hit PackageManager exception", e);
+        }
+        return wifiStackVersion;
     }
 
     private synchronized void dailyDetectionHandler() {
@@ -539,14 +552,7 @@
         if (!mWifiEnabled) {
             return null;
         }
-        PackageManager packageManager = mContext.getPackageManager();
-        long wifiStackVersion = 0;
-        try {
-            wifiStackVersion = packageManager.getPackageInfo(
-                    WIFI_APK_PACKAGE_NAME, PackageManager.MATCH_APEX).getLongVersionCode();
-        } catch (PackageManager.NameNotFoundException e) {
-            Log.e(TAG, " Hit PackageManager exception", e);
-        }
+        long wifiStackVersion = getWifiStackVersion();
         String osBuildVersion = replaceNullByEmptyString(Build.DISPLAY);
         if (mWifiNative == null) {
             return null;
diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java
index b9aa052..993debb 100644
--- a/service/java/com/android/server/wifi/WifiInjector.java
+++ b/service/java/com/android/server/wifi/WifiInjector.java
@@ -192,6 +192,7 @@
         mFrameworkFacade = new FrameworkFacade();
         mMacAddressUtil = new MacAddressUtil();
         mContext = context;
+        mScoringParams = new ScoringParams(mContext);
         mSettingsMigrationDataHolder = new SettingsMigrationDataHolder(mContext);
         mConnectionFailureNotificationBuilder = new ConnectionFailureNotificationBuilder(
                 mContext, getWifiStackPackageName(), mFrameworkFacade);
@@ -284,7 +285,6 @@
         mWifiConnectivityHelper = new WifiConnectivityHelper(mWifiNative);
         mConnectivityLocalLog = new LocalLog(
                 mContext.getSystemService(ActivityManager.class).isLowRamDevice() ? 256 : 512);
-        mScoringParams = new ScoringParams(mContext);
         mWifiMetrics.setScoringParams(mScoringParams);
         mThroughputPredictor = new ThroughputPredictor(mContext);
         mWifiNetworkSelector = new WifiNetworkSelector(mContext, mWifiScoreCard, mScoringParams,
@@ -304,7 +304,8 @@
                 mWifiCarrierInfoManager, mWifiKeyStore, mLruConnectionTracker);
         mPasspointManager = new PasspointManager(mContext, this,
                 wifiHandler, mWifiNative, mWifiKeyStore, mClock, new PasspointObjectFactory(),
-                mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
+                mWifiConfigManager, mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager,
+                mMacAddressUtil);
         PasspointNetworkNominateHelper nominateHelper =
                 new PasspointNetworkNominateHelper(mPasspointManager, mWifiConfigManager,
                         mConnectivityLocalLog);
@@ -615,7 +616,8 @@
                 mWifiMetrics, clientModeImpl, mWifiHandlerThread.getLooper(), mDeviceConfigFacade,
                 mWifiThreadRunner);
         mBssidBlocklistMonitor = new BssidBlocklistMonitor(mContext, mWifiConnectivityHelper,
-                mWifiLastResortWatchdog, mClock, mConnectivityLocalLog, mWifiScoreCard);
+                mWifiLastResortWatchdog, mClock, mConnectivityLocalLog, mWifiScoreCard,
+                mScoringParams);
         mWifiMetrics.setBssidBlocklistMonitor(mBssidBlocklistMonitor);
         mWifiChannelUtilizationScan = new WifiChannelUtilization(mClock, mContext);
         return new WifiConnectivityManager(mContext, getScoringParams(),
diff --git a/service/java/com/android/server/wifi/WifiKeyStore.java b/service/java/com/android/server/wifi/WifiKeyStore.java
index 70daa0d..c248d22 100644
--- a/service/java/com/android/server/wifi/WifiKeyStore.java
+++ b/service/java/com/android/server/wifi/WifiKeyStore.java
@@ -30,6 +30,7 @@
 import java.security.Key;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
+import java.security.Principal;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -276,52 +277,110 @@
         // For WPA3-Enterprise 192-bit networks, set the SuiteBCipher field based on the
         // CA certificate type. Suite-B requires SHA384, reject other certs.
         if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.SUITE_B_192)) {
-            // Read the first CA certificate, and initialize
-            Certificate caCert = null;
-            try {
-                caCert = mKeyStore.getCertificate(config.enterpriseConfig.getCaCertificateAlias());
-            } catch (KeyStoreException e) {
-                Log.e(TAG, "Failed to get Suite-B certificate", e);
-            }
-            if (caCert == null || !(caCert instanceof X509Certificate)) {
-                Log.e(TAG, "Failed reading CA certificate for Suite-B");
+            // Read the CA certificates, and initialize
+            String[] caAliases = config.enterpriseConfig.getCaCertificateAliases();
+
+            if (caAliases == null || caAliases.length == 0) {
+                Log.e(TAG, "No CA aliases in profile");
                 return false;
             }
-            X509Certificate x509CaCert = (X509Certificate) caCert;
-            String sigAlgOid = x509CaCert.getSigAlgOID();
-            if (mVerboseLoggingEnabled) {
-                Log.d(TAG, "Signature algorithm: " + sigAlgOid);
-            }
-            config.allowedSuiteBCiphers.clear();
 
-            // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
-            // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
-            // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
-            // Suite-B was already coined in the IEEE 802.11-2016 specification for
-            // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
-            // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
-            // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
-            // we are supporting both types here.
-            if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
-                // sha384WithRSAEncryption
-                config.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_RSA);
-                if (mVerboseLoggingEnabled) {
-                    Log.d(TAG, "Selecting Suite-B RSA");
+            int caCertType = -1;
+            int prevCaCertType = -1;
+            for (String caAlias : caAliases) {
+                Certificate caCert = null;
+                try {
+                    caCert = mKeyStore.getCertificate(caAlias);
+                } catch (KeyStoreException e) {
+                    Log.e(TAG, "Failed to get Suite-B certificate", e);
                 }
-            } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
-                // ecdsa-with-SHA384
-                config.allowedSuiteBCiphers.set(
-                        WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
-                if (mVerboseLoggingEnabled) {
-                    Log.d(TAG, "Selecting Suite-B ECDSA");
+                if (caCert == null || !(caCert instanceof X509Certificate)) {
+                    Log.e(TAG, "Failed reading CA certificate for Suite-B");
+                    return false;
                 }
+
+                // Confirm that the CA certificate is compatible with Suite-B requirements
+                caCertType = getSuiteBCipherFromCert((X509Certificate) caCert);
+                if (caCertType < 0) {
+                    return false;
+                }
+                if (prevCaCertType != -1) {
+                    if (prevCaCertType != caCertType) {
+                        Log.e(TAG, "Incompatible CA certificates");
+                        return false;
+                    }
+                }
+                prevCaCertType = caCertType;
+            }
+
+            Certificate clientCert = null;
+            try {
+                clientCert = mKeyStore.getCertificate(config.enterpriseConfig
+                        .getClientCertificateAlias());
+            } catch (KeyStoreException e) {
+                Log.e(TAG, "Failed to get Suite-B client certificate", e);
+            }
+            if (clientCert == null || !(clientCert instanceof X509Certificate)) {
+                Log.e(TAG, "Failed reading client certificate for Suite-B");
+                return false;
+            }
+
+            int clientCertType = getSuiteBCipherFromCert((X509Certificate) clientCert);
+            if (clientCertType < 0) {
+                return false;
+            }
+
+            if (clientCertType == caCertType) {
+                config.allowedSuiteBCiphers.clear();
+                config.allowedSuiteBCiphers.set(clientCertType);
             } else {
-                Log.e(TAG, "Invalid CA certificate type for Suite-B: "
-                        + sigAlgOid);
+                Log.e(TAG, "Client certificate for Suite-B is incompatible with the CA "
+                        + "certificate");
                 return false;
             }
         }
         return true;
     }
+
+    /**
+     * Get the Suite-B cipher from the certificate
+     *
+     * @param x509Certificate Certificate to process
+     * @return WifiConfiguration.SuiteBCipher.ECDHE_RSA if the certificate OID matches the Suite-B
+     * requirements for RSA certificates, WifiConfiguration.SuiteBCipher.ECDHE_ECDSA if the
+     * certificate OID matches the Suite-B requirements for ECDSA certificates, or -1 otherwise.
+     */
+    private int getSuiteBCipherFromCert(X509Certificate x509Certificate) {
+        String sigAlgOid = x509Certificate.getSigAlgOID();
+        if (mVerboseLoggingEnabled) {
+            Principal p = x509Certificate.getSubjectX500Principal();
+            if (p != null && !TextUtils.isEmpty(p.getName())) {
+                Log.d(TAG, "Checking cert " + p.getName());
+            }
+        }
+
+        // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
+        // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
+        // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
+        // Suite-B was already coined in the IEEE 802.11-2016 specification for
+        // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
+        // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
+        // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
+        // we are supporting both types here.
+        if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
+            // sha384WithRSAEncryption
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Found Suite-B RSA certificate");
+            }
+            return WifiConfiguration.SuiteBCipher.ECDHE_RSA;
+        } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
+            // ecdsa-with-SHA384
+            if (mVerboseLoggingEnabled) {
+                Log.d(TAG, "Found Suite-B ECDSA certificate");
+            }
+            return WifiConfiguration.SuiteBCipher.ECDHE_ECDSA;
+        }
+        Log.e(TAG, "Invalid certificate type for Suite-B: " + sigAlgOid);
+        return -1;
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 3e4023c..2141389 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -29,6 +29,7 @@
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -73,6 +74,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
@@ -91,6 +93,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkRequestApiLog;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog.SuggestionAppCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
@@ -112,6 +115,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.BitSet;
 import java.util.Calendar;
 import java.util.HashMap;
@@ -231,11 +235,13 @@
     @VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200;
     private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<>();
     private LinkedList<UserActionEventWithTime> mUserActionEventList = new LinkedList<>();
+    private WifiStatusBuilder mWifiStatusBuilder = new WifiStatusBuilder();
     private int mLastPollRssi = -127;
     private int mLastPollLinkSpeed = -1;
     private int mLastPollRxLinkSpeed = -1;
     private int mLastPollFreq = -1;
     private int mLastScore = -1;
+    private boolean mAdaptiveConnectivityEnabled = true;
 
     /**
      * Metrics are stored within an instance of the WifiLog proto during runtime,
@@ -752,6 +758,88 @@
         }
     }
 
+    class WifiStatusBuilder {
+        private int mNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+        private boolean mConnected;
+        private boolean mValidated;
+        private int mRssi;
+        private int mEstimatedTxKbps;
+        private int mEstimatedRxKbps;
+        private boolean mIsStuckDueToUserChoice;
+
+        public void setNetworkId(int networkId) {
+            mNetworkId = networkId;
+        }
+
+        public int getNetworkId() {
+            return mNetworkId;
+        }
+
+        public void setConnected(boolean connected) {
+            mConnected = connected;
+        }
+
+        public void setValidated(boolean validated) {
+            mValidated = validated;
+        }
+
+        public void setRssi(int rssi) {
+            mRssi = rssi;
+        }
+
+        public void setEstimatedTxKbps(int estimatedTxKbps) {
+            mEstimatedTxKbps = estimatedTxKbps;
+        }
+
+        public void setEstimatedRxKbps(int estimatedRxKbps) {
+            mEstimatedRxKbps = estimatedRxKbps;
+        }
+
+        public void setUserChoice(boolean userChoice) {
+            mIsStuckDueToUserChoice = userChoice;
+        }
+
+        public WifiStatus toProto() {
+            WifiStatus result = new WifiStatus();
+            result.isConnected = mConnected;
+            result.isValidated = mValidated;
+            result.lastRssi = mRssi;
+            result.estimatedTxKbps = mEstimatedTxKbps;
+            result.estimatedRxKbps = mEstimatedRxKbps;
+            result.isStuckDueToUserConnectChoice = mIsStuckDueToUserChoice;
+            return result;
+        }
+    }
+
+    private NetworkDisableReason convertToNetworkDisableReason(
+            WifiConfiguration config, Set<Integer> bssidBlocklistReasons) {
+        NetworkSelectionStatus status = config.getNetworkSelectionStatus();
+        NetworkDisableReason result = new NetworkDisableReason();
+        if (config.allowAutojoin) {
+            if (!status.isNetworkEnabled()) {
+                result.disableReason =
+                        MetricsUtils.convertNetworkSelectionDisableReasonToWifiProtoEnum(
+                                status.getNetworkSelectionDisableReason());
+                if (status.isNetworkPermanentlyDisabled()) {
+                    result.configPermanentlyDisabled = true;
+                } else {
+                    result.configTemporarilyDisabled = true;
+                }
+            }
+        } else {
+            result.disableReason = NetworkDisableReason.REASON_AUTO_JOIN_DISABLED;
+            result.configPermanentlyDisabled = true;
+        }
+
+        int[] convertedBssidBlockReasons = bssidBlocklistReasons.stream()
+                .mapToInt(i -> MetricsUtils.convertBssidBlocklistReasonToWifiProtoEnum(i))
+                .toArray();
+        if (convertedBssidBlockReasons.length > 0) {
+            result.bssidDisableReasons = convertedBssidBlockReasons;
+        }
+        return result;
+    }
+
     class UserActionEventWithTime {
         private UserActionEvent mUserActionEvent;
         private long mWallClockTimeMs = 0; // wall clock time for debugging only
@@ -762,13 +850,11 @@
             mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
             mWallClockTimeMs = mClock.getWallClockMillis();
             mUserActionEvent.targetNetworkInfo = targetNetworkInfo;
+            mUserActionEvent.wifiStatus = mWifiStatusBuilder.toProto();
         }
 
         UserActionEventWithTime(int eventType, int targetNetId) {
-            mUserActionEvent = new UserActionEvent();
-            mUserActionEvent.eventType = eventType;
-            mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
-            mWallClockTimeMs = mClock.getWallClockMillis();
+            this(eventType, null);
             if (targetNetId >= 0) {
                 WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(targetNetId);
                 if (config != null) {
@@ -776,6 +862,8 @@
                     networkInfo.isEphemeral = config.isEphemeral();
                     networkInfo.isPasspoint = config.isPasspoint();
                     mUserActionEvent.targetNetworkInfo = networkInfo;
+                    mUserActionEvent.networkDisableReason = convertToNetworkDisableReason(
+                            config, mBssidBlocklistMonitor.getFailureReasonsForSsid(config.SSID));
                 }
             }
         }
@@ -823,6 +911,9 @@
                 case UserActionEvent.EVENT_MANUAL_CONNECT:
                     eventType = "EVENT_MANUAL_CONNECT";
                     break;
+                case UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK:
+                    eventType = "EVENT_ADD_OR_UPDATE_NETWORK";
+                    break;
             }
             sb.append(" eventType=").append(eventType);
             sb.append(" startTimeMillis=").append(mUserActionEvent.startTimeMillis);
@@ -831,6 +922,27 @@
                 sb.append(" isEphemeral=").append(networkInfo.isEphemeral);
                 sb.append(" isPasspoint=").append(networkInfo.isPasspoint);
             }
+            WifiStatus wifiStatus = mUserActionEvent.wifiStatus;
+            if (wifiStatus != null) {
+                sb.append("\nWifiStatus: isConnected=").append(wifiStatus.isConnected);
+                sb.append(" isValidated=").append(wifiStatus.isValidated);
+                sb.append(" lastRssi=").append(wifiStatus.lastRssi);
+                sb.append(" estimatedTxKbps=").append(wifiStatus.estimatedTxKbps);
+                sb.append(" estimatedRxKbps=").append(wifiStatus.estimatedRxKbps);
+                sb.append(" isStuckDueToUserConnectChoice=")
+                        .append(wifiStatus.isStuckDueToUserConnectChoice);
+            }
+            NetworkDisableReason disableReason = mUserActionEvent.networkDisableReason;
+            if (disableReason != null) {
+                sb.append("\nNetworkDisableReason: DisableReason=")
+                        .append(disableReason.disableReason);
+                sb.append(" configTemporarilyDisabled=")
+                        .append(disableReason.configTemporarilyDisabled);
+                sb.append(" configPermanentlyDisabled=")
+                        .append(disableReason.configPermanentlyDisabled);
+                sb.append(" bssidDisableReasons=")
+                        .append(Arrays.toString(disableReason.bssidDisableReasons));
+            }
             return sb.toString();
         }
 
@@ -1458,7 +1570,7 @@
                     mScanResultRssiTimestampMillis = mClock.getElapsedSinceBootMillis();
                 }
                 mCurrentConnectionEvent.mConnectionEvent.numBssidInBlocklist =
-                        mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(config.SSID);
+                        mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(config.SSID);
                 mCurrentConnectionEvent.mConnectionEvent.networkType =
                         WifiMetricsProto.ConnectionEvent.TYPE_UNKNOWN;
                 mCurrentConnectionEvent.mConnectionEvent.isOsuProvisioned = false;
@@ -1606,6 +1718,7 @@
                 if (!result) {
                     mScanResultRssiTimestampMillis = -1;
                 }
+                mWifiStatusBuilder.setConnected(result);
             }
         }
     }
@@ -2083,6 +2196,8 @@
         mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps();
         incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq);
         incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq);
+        mWifiStatusBuilder.setRssi(mLastPollRssi);
+        mWifiStatusBuilder.setNetworkId(wifiInfo.getNetworkId());
     }
 
     /**
@@ -2258,6 +2373,8 @@
                     mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000);
                 }
             }
+            mWifiStatusBuilder.setEstimatedTxKbps(txThroughputKbps);
+            mWifiStatusBuilder.setEstimatedRxKbps(rxThroughputKbps);
         }
     }
 
@@ -4645,6 +4762,10 @@
             mWifiState = wifiState;
             mWifiWins = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
             mWifiWinsUsabilityScore = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
+            if (wifiState == WifiMetricsProto.WifiLog.WIFI_DISCONNECTED
+                    || wifiState == WifiMetricsProto.WifiLog.WIFI_DISABLED) {
+                mWifiStatusBuilder = new WifiStatusBuilder();
+            }
         }
     }
 
@@ -4749,6 +4870,7 @@
             case StaEvent.TYPE_CMD_START_ROAM:
             case StaEvent.TYPE_CONNECT_NETWORK:
             case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
+                mWifiStatusBuilder.setValidated(true);
             case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
             case StaEvent.TYPE_SCORE_BREACH:
             case StaEvent.TYPE_MAC_CHANGE:
@@ -4786,6 +4908,7 @@
         if (mWifiDataStall != null) {
             staEvent.isCellularDataAvailable = mWifiDataStall.isCellularDataAvailable();
         }
+        staEvent.isAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabled;
         mSupplicantStateChangeBitmask = 0;
         mLastPollRssi = -127;
         mLastPollFreq = -1;
@@ -5002,6 +5125,7 @@
         if (event.totalRxBytes > 0) sb.append(" totalRxBytes=").append(event.totalRxBytes);
         sb.append(" screenOn=").append(event.screenOn);
         sb.append(" cellularData=").append(event.isCellularDataAvailable);
+        sb.append(" adaptiveConnectivity=").append(event.isAdaptiveConnectivityEnabled);
         if (event.supplicantStateChangesBitmask != 0) {
             sb.append(", ").append(supplicantStateChangesBitmaskToString(
                     event.supplicantStateChangesBitmask));
@@ -5221,6 +5345,15 @@
         return result;
     }
 
+    /**
+     * Converts Adaptive Connectivity state to UserActionEvent type.
+     * @param value
+     */
+    public static int convertAdaptiveConnectivityStateToUserActionEventType(boolean value) {
+        return value ? UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON
+                : UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF;
+    }
+
     static class MeteredNetworkStatsBuilder {
         // A map from network identifier to MeteredDetail
         Map<String, MeteredDetail> mNetworkMap = new ArrayMap<>();
@@ -6154,6 +6287,13 @@
         synchronized (mLock) {
             if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return;
             mNetworkIdToNominatorId.put(networkId, nominatorId);
+
+            // user connect choice is preventing switcing off from the connected network
+            if (nominatorId
+                    == WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE
+                    && mWifiStatusBuilder.getNetworkId() == networkId) {
+                mWifiStatusBuilder.setUserChoice(true);
+            }
         }
     }
 
@@ -6584,4 +6724,13 @@
             mCarrierWifiMetrics.numConnectionNonAuthFailure++;
         }
     }
+
+    /**
+     *  Set Adaptive Connectivity state (On/Off)
+     */
+    public void setAdaptiveConnectivityState(boolean adaptiveConnectivityEnabled) {
+        synchronized (mLock) {
+            mAdaptiveConnectivityEnabled = adaptiveConnectivityEnabled;
+        }
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiMonitor.java b/service/java/com/android/server/wifi/WifiMonitor.java
index 7f62085..32a96d0 100644
--- a/service/java/com/android/server/wifi/WifiMonitor.java
+++ b/service/java/com/android/server/wifi/WifiMonitor.java
@@ -100,9 +100,6 @@
     /* MBO/OCE events */
     public static final int MBO_OCE_BSS_TM_HANDLING_DONE         = BASE + 71;
 
-    /* Fils network connection completed */
-    public static final int FILS_NETWORK_CONNECTION_EVENT        = BASE + 62;
-
     /* WPS config errrors */
     private static final int CONFIG_MULTIPLE_PBC_DETECTED = 12;
     private static final int CONFIG_AUTH_FAILURE = 18;
@@ -500,21 +497,12 @@
      *
      * @param iface Name of iface on which this occurred.
      * @param networkId ID of the network in wpa_supplicant.
+     * @param filsHlpSent Whether the connection used FILS.
      * @param bssid BSSID of the access point.
      */
-    public void broadcastNetworkConnectionEvent(String iface, int networkId, String bssid) {
-        sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
-    }
-
-    /**
-     * Broadcast the fils network connection event to all the handlers registered for this event.
-     *
-     * @param iface Name of iface on which this occurred.
-     * @param networkId ID of the network in wpa_supplicant.
-     * @param bssid BSSID of the access point.
-     */
-    public void broadcastFilsNetworkConnectionEvent(String iface, int networkId, String bssid) {
-        sendMessage(iface, FILS_NETWORK_CONNECTION_EVENT, networkId, 0, bssid);
+    public void broadcastNetworkConnectionEvent(String iface, int networkId, boolean filsHlpSent,
+            String bssid) {
+        sendMessage(iface, NETWORK_CONNECTION_EVENT, networkId, filsHlpSent ? 1 : 0, bssid);
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java
index 9dc89ad..d1f9fbb 100644
--- a/service/java/com/android/server/wifi/WifiNetworkFactory.java
+++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java
@@ -65,6 +65,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -74,6 +75,7 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Network factory to handle trusted wifi network requests.
@@ -128,20 +130,23 @@
     private WifiScanner mWifiScanner;
     private CompanionDeviceManager mCompanionDeviceManager;
     // Temporary approval set by shell commands.
-    private String mApprovedApp = null;
+    @Nullable private String mApprovedApp = null;
 
     private int mGenericConnectionReqCount = 0;
     // Request that is being actively processed. All new requests start out as an "active" request
     // because we're processing it & handling all the user interactions associated with it. Once we
     // successfully connect to the network, we transition that request to "connected".
-    private NetworkRequest mActiveSpecificNetworkRequest;
-    private WifiNetworkSpecifier mActiveSpecificNetworkRequestSpecifier;
+    @Nullable private NetworkRequest mActiveSpecificNetworkRequest;
+    @Nullable private WifiNetworkSpecifier mActiveSpecificNetworkRequestSpecifier;
     // Request corresponding to the the network that the device is currently connected to.
-    private NetworkRequest mConnectedSpecificNetworkRequest;
-    private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier;
-    private WifiConfiguration mUserSelectedNetwork;
+    @Nullable private NetworkRequest mConnectedSpecificNetworkRequest;
+    @Nullable private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier;
+    @Nullable private WifiConfiguration mUserSelectedNetwork;
     private int mUserSelectedNetworkConnectRetryCount;
-    private List<ScanResult> mActiveMatchedScanResults;
+    // Map of bssid to latest scan results for all scan results matching a request. Will be
+    //  - null, if there are no active requests.
+    //  - empty, if there are no matching scan results received for the active request.
+    @Nullable private Map<String, ScanResult> mActiveMatchedScanResults;
     // Verbose logging flag.
     private boolean mVerboseLoggingEnabled = false;
     private boolean mPeriodicScanTimerSet = false;
@@ -237,7 +242,10 @@
                 Log.v(TAG, "Received " + scanResults.length + " scan results");
             }
             handleScanResults(scanResults);
-            sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults);
+            if (mActiveMatchedScanResults != null) {
+                sendNetworkRequestMatchCallbacksForActiveRequest(
+                        mActiveMatchedScanResults.values());
+            }
             scheduleNextPeriodicScan();
         }
 
@@ -432,7 +440,10 @@
 
         // If we are already in the midst of processing a request, send matching callbacks
         // immediately on registering the callback.
-        sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults);
+        if (mActiveMatchedScanResults != null) {
+            sendNetworkRequestMatchCallbacksForActiveRequest(
+                    mActiveMatchedScanResults.values());
+        }
     }
 
     /**
@@ -610,8 +621,11 @@
                 if (mVerboseLoggingEnabled) {
                     Log.v(TAG, "Using cached " + cachedScanResults.length + " scan results");
                 }
-                handleScanResults(cachedScanResults);
-                sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults);
+                handleScanResults(cachedScanResults);          
+                if (mActiveMatchedScanResults != null) {
+                    sendNetworkRequestMatchCallbacksForActiveRequest(
+                            mActiveMatchedScanResults.values());
+                }
                 startPeriodicScans();
             }
         }
@@ -1163,8 +1177,8 @@
     }
 
     private void sendNetworkRequestMatchCallbacksForActiveRequest(
-            @Nullable List<ScanResult> matchedScanResults) {
-        if (matchedScanResults == null || matchedScanResults.isEmpty()) return;
+            @NonNull Collection<ScanResult> matchedScanResults) {
+        if (matchedScanResults.isEmpty()) return;
         if (mRegisteredCallbacks.getNumCallbacks() == 0) {
             Log.e(TAG, "No callback registered for sending network request matches. "
                     + "Ignoring...");
@@ -1172,7 +1186,7 @@
         }
         for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) {
             try {
-                callback.onMatch(matchedScanResults);
+                callback.onMatch(new ArrayList<>(matchedScanResults));
             } catch (RemoteException e) {
                 Log.e(TAG, "Unable to invoke network request match callback " + callback, e);
             }
@@ -1265,6 +1279,7 @@
         if (mActiveSpecificNetworkRequestSpecifier == null
                 || mActiveMatchedScanResults == null) return null;
         ScanResult selectedScanResult = mActiveMatchedScanResults
+                .values()
                 .stream()
                 .filter(scanResult -> Objects.equals(
                         ScanResultMatchInfo.fromScanResult(scanResult),
@@ -1354,7 +1369,7 @@
 
         ScanResultMatchInfo fromWifiConfiguration =
                 ScanResultMatchInfo.fromWifiConfiguration(network);
-        for (ScanResult scanResult : mActiveMatchedScanResults) {
+        for (ScanResult scanResult : mActiveMatchedScanResults.values()) {
             ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult);
             if (fromScanResult.equals(fromWifiConfiguration)) {
                 AccessPoint approvedAccessPoint =
@@ -1433,7 +1448,19 @@
             mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram(
                     matchedScanResults.size());
         }
-        mActiveMatchedScanResults = matchedScanResults;
+        // First set of scan results for this request.
+        if (mActiveMatchedScanResults == null) mActiveMatchedScanResults = new HashMap<>();
+        // Coalesce the new set of scan results with previous scan results received for request.
+        mActiveMatchedScanResults.putAll(matchedScanResults
+                .stream()
+                .collect(Collectors.toMap(
+                        scanResult -> scanResult.BSSID, scanResult -> scanResult)));
+        // Weed out any stale cached scan results.
+        long currentTimeInMillis = mClock.getElapsedSinceBootMillis();
+        mActiveMatchedScanResults.entrySet().removeIf(
+                e -> ((currentTimeInMillis - (e.getValue().timestamp / 1000))
+                        >= CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS));
+
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java
index 50078b6..fbbcb31 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java
@@ -462,6 +462,17 @@
         return validScanDetails;
     }
 
+    private ScanDetail findScanDetailForBssid(List<ScanDetail> scanDetails,
+            String currentBssid) {
+        for (ScanDetail scanDetail : scanDetails) {
+            ScanResult scanResult = scanDetail.getScanResult();
+            if (scanResult.BSSID.equals(currentBssid)) {
+                return scanDetail;
+            }
+        }
+        return null;
+    }
+
     private boolean isEnhancedOpenSupported() {
         if (mIsEnhancedOpenSupportedInitialized) {
             return mIsEnhancedOpenSupported;
@@ -790,6 +801,8 @@
             WifiCandidates.Key key = new WifiCandidates.Key(
                     ScanResultMatchInfo.fromWifiConfiguration(currentNetwork),
                     bssid, currentNetwork.networkId);
+            ScanDetail scanDetail = findScanDetailForBssid(mFilteredNetworks, currentBssid);
+            int predictedTputMbps = (scanDetail == null) ? 0 : predictThroughput(scanDetail);
             wifiCandidates.add(key, currentNetwork,
                     NetworkNominator.NOMINATOR_ID_CURRENT,
                     wifiInfo.getRssi(),
@@ -797,7 +810,7 @@
                     calculateLastSelectionWeight(currentNetwork.networkId),
                     WifiConfiguration.isMetered(currentNetwork, wifiInfo),
                     isFromCarrierOrPrivilegedApp(currentNetwork),
-                    0 /* Mbps */);
+                    predictedTputMbps);
         }
         for (NetworkNominator registeredNominator : mNominators) {
             localLog("About to run " + registeredNominator.getName() + " :");
diff --git a/service/java/com/android/server/wifi/WifiScoreCard.java b/service/java/com/android/server/wifi/WifiScoreCard.java
index 64da835..2ab5fb4 100644
--- a/service/java/com/android/server/wifi/WifiScoreCard.java
+++ b/service/java/com/android/server/wifi/WifiScoreCard.java
@@ -1689,11 +1689,18 @@
      * @return
      */
     public static long computeHashLong(String ssid, MacAddress mac, String l2KeySeed) {
+        final ArrayList<Byte> decodedSsid;
+        try {
+            decodedSsid = NativeUtil.decodeSsid(ssid);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "NativeUtil.decodeSsid failed: malformed string: " + ssid);
+            return 0;
+        }
         byte[][] parts = {
                 // Our seed keeps the L2Keys specific to this device
                 l2KeySeed.getBytes(),
                 // ssid is either quoted utf8 or hex-encoded bytes; turn it into plain bytes.
-                NativeUtil.byteArrayFromArrayList(NativeUtil.decodeSsid(ssid)),
+                NativeUtil.byteArrayFromArrayList(decodedSsid),
                 // And the BSSID
                 mac.toByteArray()
         };
diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java
index fa0ba6a..bd92c6d 100644
--- a/service/java/com/android/server/wifi/WifiScoreReport.java
+++ b/service/java/com/android/server/wifi/WifiScoreReport.java
@@ -16,16 +16,25 @@
 
 package com.android.server.wifi;
 
+import android.content.Context;
+import android.database.ContentObserver;
 import android.net.Network;
 import android.net.NetworkAgent;
+import android.net.Uri;
 import android.net.wifi.IScoreUpdateObserver;
 import android.net.wifi.IWifiConnectedNetworkScorer;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.nl80211.WifiNl80211Manager;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
+import android.provider.Settings;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.wifi.resources.R;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.text.SimpleDateFormat;
@@ -51,9 +60,17 @@
     private static final int WIFI_CONNECTED_NETWORK_SCORER_IDENTIFIER = 0;
     private static final int INVALID_SESSION_ID = -1;
     private static final long MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS = 29000;
-    private static final long DURATION_TO_BLOCKLIST_BSSID_AFTER_FIRST_EXITING_MILLIS = 30000;
     private static final long INVALID_WALL_CLOCK_MILLIS = -1;
 
+    /**
+     * Copy of the settings string. Can't directly use the constant because it is @hide.
+     * See {@link android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED}.
+     * TODO(b/167709538) remove this hardcoded string and create new API in Wifi mainline.
+     */
+    @VisibleForTesting
+    public static final String SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED =
+            "adaptive_connectivity_enabled";
+
     // Cache of the last score
     private int mScore = ConnectedScore.WIFI_MAX_SCORE;
 
@@ -62,7 +79,9 @@
     private int mSessionNumber = 0; // not to be confused with sessionid, this just counts resets
     private String mInterfaceName;
     private final BssidBlocklistMonitor mBssidBlocklistMonitor;
-    private long mLastScoreBreachLowTimeMillis = -1;
+    private final Context mContext;
+    private long mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
+    private long mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
 
     ConnectedScore mAggressiveConnectedScore;
     VelocityBasedConnectedScore mVelocityBasedConnectedScore;
@@ -72,6 +91,9 @@
     WifiInfo mWifiInfo;
     WifiNative mWifiNative;
     WifiThreadRunner mWifiThreadRunner;
+    DeviceConfigFacade mDeviceConfigFacade;
+    Handler mHandler;
+    FrameworkFacade mFrameworkFacade;
 
     /**
      * Callback proxy. See {@link android.net.wifi.WifiManager.ScoreUpdateObserver}.
@@ -89,10 +111,6 @@
                              + " score=" + score);
                     return;
                 }
-                if (mNetworkAgent != null) {
-                    mNetworkAgent.sendNetworkScore(score);
-                }
-
                 long millis = mClock.getWallClockMillis();
                 if (score < ConnectedScore.WIFI_TRANSITION_SCORE) {
                     if (mScore >= ConnectedScore.WIFI_TRANSITION_SCORE) {
@@ -101,7 +119,14 @@
                 } else {
                     mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
                 }
-
+                if (score > ConnectedScore.WIFI_TRANSITION_SCORE) {
+                    if (mScore <= ConnectedScore.WIFI_TRANSITION_SCORE) {
+                        mLastScoreBreachHighTimeMillis = millis;
+                    }
+                } else {
+                    mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
+                }
+                reportNetworkScoreToConnectivityServiceIfNecessary(score);
                 mScore = score;
                 updateWifiMetrics(millis, -1, mScore);
             });
@@ -167,6 +192,49 @@
     }
 
     /**
+     * Report network score to connectivity service.
+     */
+    private void reportNetworkScoreToConnectivityServiceIfNecessary(int score) {
+        if (mNetworkAgent == null) {
+            return;
+        }
+        if (mWifiConnectedNetworkScorerHolder == null && score == mWifiInfo.getScore()) {
+            return;
+        }
+        if (mWifiConnectedNetworkScorerHolder != null
+                && mContext.getResources().getBoolean(
+                        R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)) {
+            long millis = mClock.getWallClockMillis();
+            if (mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS) {
+                if (mWifiInfo.getRssi()
+                        >= mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()) {
+                    Log.d(TAG, "Not reporting low score because RSSI is high "
+                            + mWifiInfo.getRssi());
+                    return;
+                }
+                if ((millis - mLastScoreBreachLowTimeMillis)
+                        < mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()) {
+                    Log.d(TAG, "Not reporting low score because elapsed time is shorter than "
+                            + "the minimum confirmation duration");
+                    return;
+                }
+            }
+            if (mLastScoreBreachHighTimeMillis != INVALID_WALL_CLOCK_MILLIS
+                    && (millis - mLastScoreBreachHighTimeMillis)
+                            < mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()) {
+                Log.d(TAG, "Not reporting high score because elapsed time is shorter than "
+                        + "the minimum confirmation duration");
+                return;
+            }
+        }
+        // Stay a notch above the transition score if adaptive connectivity is disabled.
+        if (!mAdaptiveConnectivityEnabled) {
+            score = ConnectedScore.WIFI_TRANSITION_SCORE + 1;
+        }
+        mNetworkAgent.sendNetworkScore(score);
+    }
+
+    /**
      * Container for storing info about external scorer and tracking its death.
      */
     private final class WifiConnectedNetworkScorerHolder implements IBinder.DeathRecipient {
@@ -249,9 +317,55 @@
 
     private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder;
 
+    /**
+     * Observer for adaptive connectivity enable settings changes.
+     * This is enabled by default. Will be toggled off via adb command or a settings
+     * toggle by the user to disable adaptive connectivity.
+     */
+    private class AdaptiveConnectivityEnabledSettingObserver extends ContentObserver {
+        AdaptiveConnectivityEnabledSettingObserver(Handler handler) {
+            super(handler);
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            super.onChange(selfChange);
+            mAdaptiveConnectivityEnabled = getValue();
+            Log.d(TAG, "Adaptive connectivity status changed: " + mAdaptiveConnectivityEnabled);
+            mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled);
+            mWifiMetrics.logUserActionEvent(
+                    mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
+                            mAdaptiveConnectivityEnabled));
+        }
+
+        /**
+         * Register settings change observer.
+         */
+        public void initialize() {
+            Uri uri = Settings.Secure.getUriFor(SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED);
+            if (uri == null) {
+                Log.e(TAG, "Adaptive connectivity user toggle does not exist in Settings");
+                return;
+            }
+            mFrameworkFacade.registerContentObserver(mContext, uri, true, this);
+            mAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabledSettingObserver.getValue();
+            mWifiMetrics.setAdaptiveConnectivityState(mAdaptiveConnectivityEnabled);
+        }
+
+        public boolean getValue() {
+            return mFrameworkFacade.getIntegerSetting(
+                    mContext, SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED, 1) == 1;
+        }
+    }
+
+    private final AdaptiveConnectivityEnabledSettingObserver
+            mAdaptiveConnectivityEnabledSettingObserver;
+    private boolean mAdaptiveConnectivityEnabled = true;
+
     WifiScoreReport(ScoringParams scoringParams, Clock clock, WifiMetrics wifiMetrics,
             WifiInfo wifiInfo, WifiNative wifiNative, BssidBlocklistMonitor bssidBlocklistMonitor,
-            WifiThreadRunner wifiThreadRunner) {
+            WifiThreadRunner wifiThreadRunner, DeviceConfigFacade deviceConfigFacade,
+            Context context, Looper looper, FrameworkFacade frameworkFacade) {
         mScoringParams = scoringParams;
         mClock = clock;
         mAggressiveConnectedScore = new AggressiveConnectedScore(scoringParams, clock);
@@ -261,6 +375,12 @@
         mWifiNative = wifiNative;
         mBssidBlocklistMonitor = bssidBlocklistMonitor;
         mWifiThreadRunner = wifiThreadRunner;
+        mDeviceConfigFacade = deviceConfigFacade;
+        mContext = context;
+        mFrameworkFacade = frameworkFacade;
+        mHandler = new Handler(looper);
+        mAdaptiveConnectivityEnabledSettingObserver =
+                new AdaptiveConnectivityEnabledSettingObserver(mHandler);
     }
 
     /**
@@ -276,6 +396,7 @@
         }
         mLastDownwardBreachTimeMillis = 0;
         mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
+        mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
         if (mVerboseLoggingEnabled) Log.d(TAG, "reset");
     }
 
@@ -357,12 +478,7 @@
         }
 
         //report score
-        if (score != mWifiInfo.getScore()) {
-            if (mNetworkAgent != null) {
-                mNetworkAgent.sendNetworkScore(score);
-            }
-        }
-
+        reportNetworkScoreToConnectivityServiceIfNecessary(score);
         updateWifiMetrics(millis, s2, score);
         mScore = score;
     }
@@ -427,6 +543,10 @@
      * @return true to indicate that an IP reachability check is recommended
      */
     public boolean shouldCheckIpLayer() {
+        // Don't recommend if adaptive connectivity is disabled.
+        if (!mAdaptiveConnectivityEnabled) {
+            return false;
+        }
         int nud = mScoringParams.getNudKnob();
         if (nud == 0) {
             return false;
@@ -609,8 +729,10 @@
                     + " sessionId=" + sessionId);
             return;
         }
+        mWifiInfo.setScore(ConnectedScore.WIFI_MAX_SCORE);
         mWifiConnectedNetworkScorerHolder.startSession(sessionId);
         mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
+        mLastScoreBreachHighTimeMillis = INVALID_WALL_CLOCK_MILLIS;
     }
 
     /**
@@ -628,9 +750,10 @@
         if ((mLastScoreBreachLowTimeMillis != INVALID_WALL_CLOCK_MILLIS)
                 && ((millis - mLastScoreBreachLowTimeMillis)
                         >= MIN_TIME_TO_WAIT_BEFORE_BLOCKLIST_BSSID_MILLIS)) {
-            mBssidBlocklistMonitor.blockBssidForDurationMs(mWifiInfo.getBSSID(),
+            mBssidBlocklistMonitor.handleBssidConnectionFailure(mWifiInfo.getBSSID(),
                     mWifiInfo.getSSID(),
-                    DURATION_TO_BLOCKLIST_BSSID_AFTER_FIRST_EXITING_MILLIS);
+                    BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE,
+                    mWifiInfo.getRssi());
             mLastScoreBreachLowTimeMillis = INVALID_WALL_CLOCK_MILLIS;
         }
     }
@@ -663,4 +786,11 @@
         mWifiConnectedNetworkScorerHolder = null;
         mWifiMetrics.setIsExternalWifiScorerOn(false);
     }
+
+    /**
+     * Initialize WifiScoreReport
+     */
+    public void initialize() {
+        mAdaptiveConnectivityEnabledSettingObserver.initialize();
+    }
 }
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index a398eac..5019f54 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -802,8 +802,13 @@
             Binder.restoreCallingIdentity(ident);
         }
         if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
-            mWifiMetrics.logUserActionEvent(enable ? UserActionEvent.EVENT_TOGGLE_WIFI_ON
-                    : UserActionEvent.EVENT_TOGGLE_WIFI_OFF);
+            if (enable) {
+                mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
+            } else {
+                WifiInfo wifiInfo = mClientModeImpl.syncRequestConnectionInfo();
+                mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF,
+                        wifiInfo == null ? -1 : wifiInfo.getNetworkId());
+            }
         }
         mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
         mActiveModeWarden.wifiToggled();
@@ -4118,10 +4123,15 @@
             throw new SecurityException(TAG + ": Permission denied");
         }
         mLog.info("connect uid=%").c(uid).flush();
-        mClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid);
         if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
-            mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_MANUAL_CONNECT, netId);
+            if (config == null) {
+                mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_MANUAL_CONNECT, netId);
+            } else {
+                mWifiMetrics.logUserActionEvent(
+                        UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId);
+            }
         }
+        mClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid);
     }
 
     /**
@@ -4135,6 +4145,10 @@
             throw new SecurityException(TAG + ": Permission denied");
         }
         mLog.info("save uid=%").c(Binder.getCallingUid()).flush();
+        if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
+            mWifiMetrics.logUserActionEvent(
+                    UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId);
+        }
         mClientModeImpl.save(
                 config, binder, callback, callbackIdentifier, Binder.getCallingUid());
     }
diff --git a/service/java/com/android/server/wifi/WifiShellCommand.java b/service/java/com/android/server/wifi/WifiShellCommand.java
index a3cae77..d445394 100644
--- a/service/java/com/android/server/wifi/WifiShellCommand.java
+++ b/service/java/com/android/server/wifi/WifiShellCommand.java
@@ -40,7 +40,6 @@
 import android.net.wifi.WifiNetworkSuggestion;
 import android.net.wifi.WifiScanner;
 import android.net.wifi.nl80211.WifiNl80211Manager;
-import android.os.BasicShellCommandHandler;
 import android.os.Binder;
 import android.os.Process;
 import android.os.RemoteException;
@@ -48,6 +47,7 @@
 import android.text.TextUtils;
 import android.util.Pair;
 
+import com.android.modules.utils.BasicShellCommandHandler;
 import com.android.server.wifi.util.ApConfigUtil;
 import com.android.server.wifi.util.ArrayUtils;
 import com.android.server.wifi.util.GeneralUtil;
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java b/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
index b715466..c96cf28 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareClientState.java
@@ -283,6 +283,19 @@
     }
 
     /**
+     * Check if client needs ranging enabled.
+     * @return True if one of the discovery session has ranging enabled, false otherwise.
+     */
+    public boolean isRangingEnabled() {
+        for (int i = 0; i < mSessions.size(); ++i) {
+            if (mSessions.valueAt(i).isRangingEnabled()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
      * Dump the internal state of the class.
      */
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
index e190a24..2263040 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDataPathStateManager.java
@@ -654,16 +654,9 @@
                 sNetworkCapabilitiesFilter);
         LinkProperties linkProperties = new LinkProperties();
         getInet6Address(nnri, mac);
-        if (nnri.peerIpv6 != null) {
-            final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo(
-                    nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol);
-            ncBuilder.setTransportInfo(ni);
-            if (VDBG) {
-                Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni);
-            }
-        }
-        if (!(mNiWrapper.configureAgentProperties(nnri, nnri.equivalentRequests, ndpId,
-                ncBuilder, linkProperties) && mNiWrapper.isAddressUsable(linkProperties))) {
+        if (!(nnri.peerIpv6 != null && mNiWrapper.configureAgentProperties(nnri,
+                nnri.equivalentRequests, ndpId, ncBuilder, linkProperties)
+                && mNiWrapper.isAddressUsable(linkProperties))) {
             if (VDBG) {
                 Log.d(TAG, "Failed address validation");
             }
@@ -674,6 +667,12 @@
             }
             return;
         }
+        final WifiAwareNetworkInfo ni = new WifiAwareNetworkInfo(
+                nnri.peerIpv6, nnri.peerPort, nnri.peerTransportProtocol);
+        ncBuilder.setTransportInfo(ni);
+        if (VDBG) {
+            Log.v(TAG, "onDataPathConfirm: AwareNetworkInfo=" + ni);
+        }
         final NetworkAgentConfig naConfig = new NetworkAgentConfig.Builder()
                 .setLegacyType(ConnectivityManager.TYPE_NONE)
                 .setLegacyTypeName(NETWORK_TAG)
@@ -691,6 +690,8 @@
         if (mClock.getElapsedSinceBootMillis() - nnri.startValidationTimestamp
                 > ADDRESS_VALIDATION_TIMEOUT_MS) {
             Log.e(TAG, "Timed-out while waiting for IPv6 address to be usable");
+            mMgr.endDataPath(ndpId);
+            nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
             declareUnfullfillableAndEndDp(nnri, ndpId);
             return true;
         }
@@ -1486,17 +1487,13 @@
             try {
                 ni = NetworkInterface.getByName(nnri.interfaceName);
             } catch (SocketException e) {
-                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
+                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
                         + ": can't get network interface - " + e);
-                mMgr.endDataPath(ndpId);
-                nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
                 return false;
             }
             if (ni == null) {
-                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
+                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri
                         + ": can't get network interface (null)");
-                mMgr.endDataPath(ndpId);
-                nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
                 return false;
             }
             Enumeration<InetAddress> addresses = ni.getInetAddresses();
@@ -1509,9 +1506,7 @@
             }
 
             if (linkLocal == null) {
-                Log.e(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
-                mMgr.endDataPath(ndpId);
-                nnri.state = AwareNetworkRequestInformation.STATE_TERMINATING;
+                Log.v(TAG, "onDataPathConfirm: ACCEPT nnri=" + nnri + ": no link local addresses");
                 return false;
             }
 
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
index 9af9545..bfd3e2c 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareDiscoverySessionState.java
@@ -103,6 +103,10 @@
         return mIsRangingEnabled;
     }
 
+    public void setRangingEnabled(boolean enabled) {
+        mIsRangingEnabled = enabled;
+    }
+
     public long getCreationTime() {
         return mCreationTime;
     }
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
index 4e6f086..a85fa27 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeApi.java
@@ -38,13 +38,13 @@
 import android.net.wifi.aware.PublishConfig;
 import android.net.wifi.aware.SubscribeConfig;
 import android.net.wifi.util.HexEncoding;
-import android.os.BasicShellCommandHandler;
 import android.os.RemoteException;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.modules.utils.BasicShellCommandHandler;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -355,10 +355,11 @@
      *            (true) or an update (false) to the configuration.
      * @param isInteractive PowerManager.isInteractive
      * @param isIdle PowerManager.isIdle
+     * @param rangingEnabled Indicates whether or not enable ranging.
      */
     public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest,
             boolean notifyIdentityChange, boolean initialConfiguration, boolean isInteractive,
-            boolean isIdle) {
+            boolean isIdle, boolean rangingEnabled) {
         if (mDbg) {
             Log.v(TAG, "enableAndConfigure: transactionId=" + transactionId + ", configRequest="
                     + configRequest + ", notifyIdentityChange=" + notifyIdentityChange
@@ -379,7 +380,7 @@
             configSupplemental12.discoveryBeaconIntervalMs = 0;
             configSupplemental12.numberOfSpatialStreamsInDiscovery = 0;
             configSupplemental12.enableDiscoveryWindowEarlyTermination = false;
-            configSupplemental12.enableRanging = true;
+            configSupplemental12.enableRanging = rangingEnabled;
         }
 
         NanBandSpecificConfig config24 = new NanBandSpecificConfig();
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
index c9616db..733bb04 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareNativeCallback.java
@@ -30,11 +30,12 @@
 import android.hardware.wifi.V1_2.NanDataPathScheduleUpdateInd;
 import android.net.MacAddress;
 import android.net.wifi.util.HexEncoding;
-import android.os.BasicShellCommandHandler;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
+import com.android.modules.utils.BasicShellCommandHandler;
+
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java b/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java
index 61afe1a..fbbd003 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareShellCommand.java
@@ -16,11 +16,12 @@
 
 package com.android.server.wifi.aware;
 
-import android.os.BasicShellCommandHandler;
 import android.os.Binder;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.modules.utils.BasicShellCommandHandler;
+
 import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Map;
diff --git a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
index 73e2d04..464723e 100644
--- a/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
+++ b/service/java/com/android/server/wifi/aware/WifiAwareStateManager.java
@@ -35,7 +35,6 @@
 import android.net.wifi.aware.WifiAwareManager;
 import android.net.wifi.aware.WifiAwareNetworkSpecifier;
 import android.net.wifi.util.HexEncoding;
-import android.os.BasicShellCommandHandler;
 import android.os.Bundle;
 import android.os.Looper;
 import android.os.Message;
@@ -54,6 +53,7 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.WakeupMessage;
+import com.android.modules.utils.BasicShellCommandHandler;
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.util.NetdWrapper;
 import com.android.server.wifi.util.WifiPermissionsUtil;
@@ -226,6 +226,7 @@
     private final SparseArray<WifiAwareClientState> mClients = new SparseArray<>();
     private ConfigRequest mCurrentAwareConfiguration = null;
     private boolean mCurrentIdentityNotification = false;
+    private boolean mCurrentRangingEnabled = false;
 
     private static final byte[] ALL_ZERO_MAC = new byte[] {0, 0, 0, 0, 0, 0};
     private byte[] mCurrentDiscoveryInterfaceMac = ALL_ZERO_MAC;
@@ -642,7 +643,7 @@
         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
         msg.arg1 = COMMAND_TYPE_UPDATE_PUBLISH;
         msg.arg2 = clientId;
-        msg.obj = publishConfig;
+        msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, publishConfig);
         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
         mSm.sendMessage(msg);
     }
@@ -669,7 +670,7 @@
         Message msg = mSm.obtainMessage(MESSAGE_TYPE_COMMAND);
         msg.arg1 = COMMAND_TYPE_UPDATE_SUBSCRIBE;
         msg.arg2 = clientId;
-        msg.obj = subscribeConfig;
+        msg.getData().putParcelable(MESSAGE_BUNDLE_KEY_CONFIG, subscribeConfig);
         msg.getData().putInt(MESSAGE_BUNDLE_KEY_SESSION_ID, sessionId);
         mSm.sendMessage(msg);
     }
@@ -1615,8 +1616,8 @@
                 case COMMAND_TYPE_UPDATE_PUBLISH: {
                     int clientId = msg.arg2;
                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
-                    PublishConfig publishConfig = (PublishConfig) msg.obj;
-
+                    PublishConfig publishConfig = (PublishConfig) msg.getData()
+                            .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
                     waitForResponse = updatePublishLocal(mCurrentTransactionId, clientId, sessionId,
                             publishConfig);
                     break;
@@ -1635,7 +1636,8 @@
                 case COMMAND_TYPE_UPDATE_SUBSCRIBE: {
                     int clientId = msg.arg2;
                     int sessionId = msg.getData().getInt(MESSAGE_BUNDLE_KEY_SESSION_ID);
-                    SubscribeConfig subscribeConfig = (SubscribeConfig) msg.obj;
+                    SubscribeConfig subscribeConfig = (SubscribeConfig) msg.getData()
+                            .getParcelable(MESSAGE_BUNDLE_KEY_CONFIG);
 
                     waitForResponse = updateSubscribeLocal(mCurrentTransactionId, clientId,
                             sessionId, subscribeConfig);
@@ -2247,7 +2249,8 @@
 
         boolean success = mWifiAwareNativeApi.enableAndConfigure(transactionId, merged,
                 notificationRequired, mCurrentAwareConfiguration == null,
-                mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode());
+                mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(),
+                mCurrentRangingEnabled);
         if (!success) {
             try {
                 callback.onConnectFail(NanStatusType.INTERNAL_FAILURE);
@@ -2292,13 +2295,16 @@
             return false;
         }
         boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications();
+        boolean rangingEnabled = doesAnyClientNeedRanging();
         if (merged.equals(mCurrentAwareConfiguration)
-                && mCurrentIdentityNotification == notificationReqs) {
+                && mCurrentIdentityNotification == notificationReqs
+                && mCurrentRangingEnabled == rangingEnabled) {
             return false;
         }
 
         return mWifiAwareNativeApi.enableAndConfigure(transactionId, merged, notificationReqs,
-                false, mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode());
+                false, mPowerManager.isInteractive(), mPowerManager.isDeviceIdleMode(),
+                rangingEnabled);
     }
 
     private boolean reconfigureLocal(short transactionId) {
@@ -2310,10 +2316,11 @@
         }
 
         boolean notificationReqs = doesAnyClientNeedIdentityChangeNotifications();
+        boolean rangingEnabled = doesAnyClientNeedRanging();
 
         return mWifiAwareNativeApi.enableAndConfigure(transactionId, mCurrentAwareConfiguration,
                 notificationReqs, false, mPowerManager.isInteractive(),
-                mPowerManager.isDeviceIdleMode());
+                mPowerManager.isDeviceIdleMode(), rangingEnabled);
     }
 
     private void terminateSessionLocal(int clientId, int sessionId) {
@@ -2329,6 +2336,10 @@
         }
 
         WifiAwareDiscoverySessionState session = client.terminateSession(sessionId);
+        // If Ranging enabled require changes, reconfigure.
+        if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) {
+            reconfigure();
+        }
         if (session != null) {
             mAwareMetrics.recordDiscoverySessionDuration(session.getCreationTime(),
                     session.isPublishSession());
@@ -2624,6 +2635,7 @@
             Log.wtf(TAG, "onConfigCompletedLocal: got a null merged configuration after config!?");
         }
         mCurrentIdentityNotification = doesAnyClientNeedIdentityChangeNotifications();
+        mCurrentRangingEnabled = doesAnyClientNeedRanging();
     }
 
     private void onConfigFailedLocal(Message failedCommand, int reason) {
@@ -2685,6 +2697,26 @@
                     + ", pubSubId=" + pubSubId + ", isPublish=" + isPublish);
         }
 
+        boolean isRangingEnabled = false;
+        int minRange = -1;
+        int maxRange = -1;
+        if (isPublish) {
+            PublishConfig publishConfig = completedCommand.getData().getParcelable(
+                    MESSAGE_BUNDLE_KEY_CONFIG);
+            isRangingEnabled = publishConfig.mEnableRanging;
+        } else {
+            SubscribeConfig subscribeConfig = completedCommand.getData().getParcelable(
+                    MESSAGE_BUNDLE_KEY_CONFIG);
+            isRangingEnabled =
+                    subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet;
+            if (subscribeConfig.mMinDistanceMmSet) {
+                minRange = subscribeConfig.mMinDistanceMm;
+            }
+            if (subscribeConfig.mMaxDistanceMmSet) {
+                maxRange = subscribeConfig.mMaxDistanceMm;
+            }
+        }
+
         if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH
                 || completedCommand.arg1 == COMMAND_TYPE_SUBSCRIBE) {
             int clientId = completedCommand.arg2;
@@ -2706,26 +2738,6 @@
                 return;
             }
 
-            boolean isRangingEnabled = false;
-            int minRange = -1;
-            int maxRange = -1;
-            if (completedCommand.arg1 == COMMAND_TYPE_PUBLISH) {
-                PublishConfig publishConfig = completedCommand.getData().getParcelable(
-                        MESSAGE_BUNDLE_KEY_CONFIG);
-                isRangingEnabled = publishConfig.mEnableRanging;
-            } else {
-                SubscribeConfig subscribeConfig = completedCommand.getData().getParcelable(
-                        MESSAGE_BUNDLE_KEY_CONFIG);
-                isRangingEnabled =
-                        subscribeConfig.mMinDistanceMmSet || subscribeConfig.mMaxDistanceMmSet;
-                if (subscribeConfig.mMinDistanceMmSet) {
-                    minRange = subscribeConfig.mMinDistanceMm;
-                }
-                if (subscribeConfig.mMaxDistanceMmSet) {
-                    maxRange = subscribeConfig.mMaxDistanceMm;
-                }
-            }
-
             WifiAwareDiscoverySessionState session = new WifiAwareDiscoverySessionState(
                     mWifiAwareNativeApi, sessionId, pubSubId, callback, isPublish, isRangingEnabled,
                     SystemClock.elapsedRealtime());
@@ -2767,11 +2779,17 @@
                 Log.e(TAG, "onSessionConfigSuccessLocal: onSessionConfigSuccess() RemoteException="
                         + e);
             }
+            session.setRangingEnabled(isRangingEnabled);
             mAwareMetrics.recordDiscoveryStatus(client.getUid(), NanStatusType.SUCCESS,
                     completedCommand.arg1 == COMMAND_TYPE_UPDATE_PUBLISH);
         } else {
             Log.wtf(TAG,
                     "onSessionConfigSuccessLocal: unexpected completedCommand=" + completedCommand);
+            return;
+        }
+        // If ranging require changes, reconfigure.
+        if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) {
+            reconfigure();
         }
     }
 
@@ -2829,6 +2847,9 @@
 
             if (reason == NanStatusType.INVALID_SESSION_ID) {
                 client.removeSession(sessionId);
+                if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) {
+                    reconfigure();
+                }
             }
         } else {
             Log.wtf(TAG, "onSessionConfigFailLocal: unexpected failedCommand=" + failedCommand);
@@ -3059,6 +3080,9 @@
                     "onSessionTerminatedLocal onSessionTerminated(): RemoteException (FYI): " + e);
         }
         data.first.removeSession(data.second.getSessionId());
+        if (mCurrentRangingEnabled != doesAnyClientNeedRanging()) {
+            reconfigure();
+        }
         mAwareMetrics.recordDiscoverySessionDuration(data.second.getCreationTime(),
                 data.second.isPublishSession());
     }
@@ -3228,6 +3252,15 @@
         return false;
     }
 
+    private boolean doesAnyClientNeedRanging() {
+        for (int i = 0; i < mClients.size(); ++i) {
+            if (mClients.valueAt(i).isRangingEnabled()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private static String messageToString(Message msg) {
         StringBuilder sb = new StringBuilder();
 
diff --git a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
index 25553b8..9cb4254 100644
--- a/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
+++ b/service/java/com/android/server/wifi/hotspot2/PasspointManager.java
@@ -18,12 +18,14 @@
 
 import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE;
 import static android.net.wifi.WifiConfiguration.MeteredOverride;
+import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS;
 
 import static java.security.cert.PKIXReason.NO_TRUST_ANCHOR;
 
 import android.annotation.NonNull;
 import android.app.AppOpsManager;
 import android.content.Context;
+import android.net.MacAddress;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiEnterpriseConfig;
@@ -40,6 +42,7 @@
 import android.util.Pair;
 
 import com.android.server.wifi.Clock;
+import com.android.server.wifi.MacAddressUtil;
 import com.android.server.wifi.NetworkUpdateResult;
 import com.android.server.wifi.WifiCarrierInfoManager;
 import com.android.server.wifi.WifiConfigManager;
@@ -118,6 +121,7 @@
     private final PasspointProvisioner mPasspointProvisioner;
     private final AppOpsManager mAppOps;
     private final WifiCarrierInfoManager mWifiCarrierInfoManager;
+    private final MacAddressUtil mMacAddressUtil;
 
     /**
      * Map of package name of an app to the app ops changed listener for the app.
@@ -304,7 +308,8 @@
             PasspointObjectFactory objectFactory, WifiConfigManager wifiConfigManager,
             WifiConfigStore wifiConfigStore,
             WifiMetrics wifiMetrics,
-            WifiCarrierInfoManager wifiCarrierInfoManager) {
+            WifiCarrierInfoManager wifiCarrierInfoManager,
+            MacAddressUtil macAddressUtil) {
         mPasspointEventHandler = objectFactory.makePasspointEventHandler(wifiNative,
                 new CallbackHandler(context));
         mWifiInjector = wifiInjector;
@@ -326,6 +331,7 @@
                 this, wifiMetrics);
         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         sPasspointManager = this;
+        mMacAddressUtil = macAddressUtil;
     }
 
     /**
@@ -1096,6 +1102,15 @@
                 continue;
             }
             WifiConfiguration config = provider.getWifiConfig();
+            if (mWifiConfigManager.shouldUseAggressiveRandomization(config)) {
+                config.setRandomizedMacAddress(MacAddress.fromString(DEFAULT_MAC_ADDRESS));
+            } else {
+                MacAddress result = mMacAddressUtil.calculatePersistentMac(config.getKey(),
+                        mMacAddressUtil.obtainMacRandHashFunction(Process.WIFI_UID));
+                if (result != null) {
+                    config.setRandomizedMacAddress(result);
+                }
+            }
             // If the Passpoint configuration is from a suggestion, check if the app shares this
             // suggestion with the user.
             if (provider.isFromSuggestion()
diff --git a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
index 2d08861..dca3a60 100644
--- a/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
+++ b/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java
@@ -63,7 +63,6 @@
     private static final String TAG = "SupplicantP2pIfaceHal";
     private static boolean sVerboseLoggingEnabled = true;
     private static final int RESULT_NOT_VALID = -1;
-    private static final int DEFAULT_GROUP_OWNER_INTENT = 6;
     private static final int DEFAULT_OPERATING_CLASS = 81;
     /**
      * Regex pattern for extracting the wps device type bytes.
@@ -307,7 +306,7 @@
                                 }
                                 supplicantIface.setResult(status, iface);
                             });
-                } catch (RemoteException e) {
+                } catch (RemoteException | IllegalArgumentException e) {
                     Log.e(TAG, "ISupplicant.getInterface exception: " + e);
                     supplicantServiceDiedHandler();
                     return null;
@@ -828,13 +827,9 @@
             String preSelectedPin = TextUtils.isEmpty(config.wps.pin) ? "" : config.wps.pin;
             boolean persistent = (config.netId == WifiP2pGroup.NETWORK_ID_PERSISTENT);
 
-            int goIntent = 0;
-            if (!joinExistingGroup) {
-                int groupOwnerIntent = config.groupOwnerIntent;
-                if (groupOwnerIntent < 0 || groupOwnerIntent > 15) {
-                    groupOwnerIntent = DEFAULT_GROUP_OWNER_INTENT;
-                }
-                goIntent = groupOwnerIntent;
+            if (config.groupOwnerIntent < 0 || config.groupOwnerIntent > 15) {
+                Log.e(TAG, "Invalid group owner intent: " + config.groupOwnerIntent);
+                return null;
             }
 
             SupplicantResult<String> result = new SupplicantResult(
@@ -842,7 +837,7 @@
             try {
                 mISupplicantP2pIface.connect(
                         peerAddress, provisionMethod, preSelectedPin, joinExistingGroup,
-                        persistent, goIntent,
+                        persistent, config.groupOwnerIntent,
                         (SupplicantStatus status, String generatedPin) -> {
                             result.setResult(status, generatedPin);
                         });
diff --git a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
index 61e6c16..eb2a89c 100644
--- a/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
+++ b/service/java/com/android/server/wifi/p2p/WifiP2pServiceImpl.java
@@ -44,6 +44,9 @@
 import android.net.ip.IpClientCallbacks;
 import android.net.ip.IpClientUtil;
 import android.net.shared.ProvisioningConfiguration;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WpsInfo;
 import android.net.wifi.p2p.IWifiP2pManager;
@@ -114,6 +117,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * WifiP2pService includes a state machine to perform Wi-Fi p2p operations. Applications
@@ -129,6 +133,8 @@
     private static final String TAG = "WifiP2pService";
     private boolean mVerboseLoggingEnabled = false;
     private static final String NETWORKTYPE = "WIFI_P2P";
+    @VisibleForTesting
+    static final int DEFAULT_GROUP_OWNER_INTENT = 6;
 
     private Context mContext;
 
@@ -240,7 +246,7 @@
 
     private final boolean mP2pSupported;
 
-    private WifiP2pDevice mThisDevice = new WifiP2pDevice();
+    private final WifiP2pDevice mThisDevice = new WifiP2pDevice();
 
     // When a group has been explicitly created by an app, we persist the group
     // even after all clients have been disconnected until an explicit remove
@@ -2239,6 +2245,8 @@
                         break;
                     case PEER_CONNECTION_USER_CONFIRM:
                         mSavedPeerConfig.wps.setup = WpsInfo.DISPLAY;
+                        mSavedPeerConfig.groupOwnerIntent =
+                                selectGroupOwnerIntentIfNecessary(mSavedPeerConfig);
                         mWifiNative.p2pConnect(mSavedPeerConfig, FORM_GROUP);
                         transitionTo(mGroupNegotiationState);
                         break;
@@ -3323,7 +3331,7 @@
         /**
          * This method unifies the persisent group list, cleans up unused
          * networks and if required, updates corresponding broadcast receivers
-         * @param boolean if true, reload the group list from scratch
+         * @param reload if true, reload the group list from scratch
          *                and send broadcast message with fresh list
          */
         private void updatePersistentNetworks(boolean reload) {
@@ -3333,7 +3341,11 @@
             // no network has been found.
             if (mWifiNative.p2pListNetworks(mGroups) || reload) {
                 for (WifiP2pGroup group : mGroups.getGroupList()) {
-                    if (mThisDevice.deviceAddress.equals(group.getOwner().deviceAddress)) {
+                    if (group.getOwner() == null) {
+                        Log.d(TAG, "group.getOwner() null");
+                        continue;
+                    }
+                    if (Objects.equals(mThisDevice.deviceAddress, group.getOwner().deviceAddress)) {
                         group.setOwner(mThisDevice);
                     }
                 }
@@ -3532,6 +3544,7 @@
                 Log.e(TAG, "Invalid device");
                 return;
             }
+            config.groupOwnerIntent = selectGroupOwnerIntentIfNecessary(config);
             String pin = mWifiNative.p2pConnect(config, dev.isGroupOwner());
             try {
                 Integer.parseInt(pin);
@@ -4308,6 +4321,38 @@
                 clearServiceRequests(c.mMessenger);
             }
         }
+
+        private int selectGroupOwnerIntentIfNecessary(WifiP2pConfig config) {
+            int intent = config.groupOwnerIntent;
+            // return the legacy default value for invalid values.
+            if (intent != WifiP2pConfig.GROUP_OWNER_INTENT_AUTO) {
+                if (intent < WifiP2pConfig.GROUP_OWNER_INTENT_MIN
+                        || intent > WifiP2pConfig.GROUP_OWNER_INTENT_MAX) {
+                    intent = DEFAULT_GROUP_OWNER_INTENT;
+                }
+                return intent;
+            }
+
+            WifiManager wifiManager = mContext.getSystemService(WifiManager.class);
+
+            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+            Log.d(TAG, "WifiInfo: " + wifiInfo);
+            int freq = wifiInfo.getFrequency();
+            if (wifiInfo.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID) {
+                intent = DEFAULT_GROUP_OWNER_INTENT + 1;
+            } else if (ScanResult.is24GHz(freq)) {
+                intent = WifiP2pConfig.GROUP_OWNER_INTENT_MIN;
+            } else if (ScanResult.is5GHz(freq)) {
+                // If both sides use the maximum, the negotiation would fail.
+                intent = WifiP2pConfig.GROUP_OWNER_INTENT_MAX - 1;
+            } else {
+                intent = DEFAULT_GROUP_OWNER_INTENT;
+            }
+            Log.i(TAG, "change GO intent value from "
+                    + config.groupOwnerIntent + " to " + intent);
+            return intent;
+        }
+
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
index ca986d1..3122a94 100644
--- a/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
+++ b/service/java/com/android/server/wifi/rtt/RttServiceImpl.java
@@ -39,7 +39,6 @@
 import android.net.wifi.rtt.ResponderConfig;
 import android.net.wifi.rtt.ResponderLocation;
 import android.net.wifi.rtt.WifiRttManager;
-import android.os.BasicShellCommandHandler;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -55,6 +54,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.WakeupMessage;
+import com.android.modules.utils.BasicShellCommandHandler;
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.WifiSettingsConfigStore;
 import com.android.server.wifi.proto.nano.WifiMetricsProto;
diff --git a/service/java/com/android/server/wifi/util/ApConfigUtil.java b/service/java/com/android/server/wifi/util/ApConfigUtil.java
index 39d0df5..1e8cc24 100644
--- a/service/java/com/android/server/wifi/util/ApConfigUtil.java
+++ b/service/java/com/android/server/wifi/util/ApConfigUtil.java
@@ -65,7 +65,8 @@
         sBandToOperatingClass.append(SoftApConfiguration.BAND_2GHZ, new int[]{81, 82, 83, 84});
         sBandToOperatingClass.append(SoftApConfiguration.BAND_5GHZ, new int[]{115, 116, 117, 118,
                 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130});
-        sBandToOperatingClass.append(SoftApConfiguration.BAND_6GHZ, new int[]{131, 132, 133, 134});
+        sBandToOperatingClass.append(SoftApConfiguration.BAND_6GHZ, new int[]{131, 132, 133, 134,
+                135, 136});
     }
 
     /**
diff --git a/service/java/com/android/server/wifi/util/InformationElementUtil.java b/service/java/com/android/server/wifi/util/InformationElementUtil.java
index 60d074e..a94c15f 100644
--- a/service/java/com/android/server/wifi/util/InformationElementUtil.java
+++ b/service/java/com/android/server/wifi/util/InformationElementUtil.java
@@ -918,8 +918,8 @@
         private static final int RSN_AKM_OWE = 0x12ac0f00;
         private static final int RSN_AKM_EAP_SUITE_B_192 = 0x0cac0f00;
         private static final int RSN_OSEN = 0x019a6f50;
-        private static final int RSN_AKM_FILS_SHA256 = 0x0eac0f00;
-        private static final int RSN_AKM_FILS_SHA384 = 0x0fac0f00;
+        private static final int RSN_AKM_EAP_FILS_SHA256 = 0x0eac0f00;
+        private static final int RSN_AKM_EAP_FILS_SHA384 = 0x0fac0f00;
 
         private static final int WPA_CIPHER_NONE = 0x00f25000;
         private static final int WPA_CIPHER_TKIP = 0x02f25000;
@@ -1022,10 +1022,10 @@
                         case RSN_OSEN:
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_OSEN);
                             break;
-                        case RSN_AKM_FILS_SHA256:
+                        case RSN_AKM_EAP_FILS_SHA256:
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA256);
                             break;
-                        case RSN_AKM_FILS_SHA384:
+                        case RSN_AKM_EAP_FILS_SHA384:
                             rsnKeyManagement.add(ScanResult.KEY_MGMT_FILS_SHA384);
                             break;
                         default:
@@ -1307,9 +1307,9 @@
                 case ScanResult.KEY_MGMT_WAPI_CERT:
                     return "WAPI-CERT";
                 case ScanResult.KEY_MGMT_FILS_SHA256:
-                    return "FILS-SHA256";
+                    return "EAP-FILS-SHA256";
                 case ScanResult.KEY_MGMT_FILS_SHA384:
-                    return "FILS-SHA384";
+                    return "EAP-FILS-SHA384";
                 default:
                     return "?";
             }
diff --git a/service/java/com/android/server/wifi/util/MetricsUtils.java b/service/java/com/android/server/wifi/util/MetricsUtils.java
index 2c9c7f7..4c87aa2 100644
--- a/service/java/com/android/server/wifi/util/MetricsUtils.java
+++ b/service/java/com/android/server/wifi/util/MetricsUtils.java
@@ -16,8 +16,12 @@
 
 package com.android.server.wifi.util;
 
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.util.SparseIntArray;
 
+import com.android.server.wifi.BssidBlocklistMonitor;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
+
 /**
  * Utilities for Metrics collections.
  */
@@ -188,4 +192,65 @@
 
         return protoArray;
     }
+
+    /**
+     * Converts NetworkSelectionStatus.NetworkSelectionDisableReason to
+     * WifiMetricsProto.NetworkDisableReason.DisableReason
+     */
+    public static int convertNetworkSelectionDisableReasonToWifiProtoEnum(int reason) {
+        switch (reason) {
+            case NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
+                return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
+            case NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
+                return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
+            case NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
+                return NetworkDisableReason.REASON_DHCP_FAILURE;
+            case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
+            case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
+                return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
+            case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS:
+                return NetworkDisableReason.REASON_AUTHENTICATION_NO_CREDENTIALS;
+            case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
+                return NetworkDisableReason.REASON_WRONG_PASSWORD;
+            case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
+                return NetworkDisableReason.REASON_AUTHENTICATION_NO_SUBSCRIPTION;
+            default:
+                return NetworkDisableReason.REASON_UNKNOWN;
+        }
+    }
+
+    /**
+     * Converts BssidBlocklistMonitor.FailureReason to
+     * WifiMetricsProto.NetworkDisableReason.DisableReason
+     */
+    public static int convertBssidBlocklistReasonToWifiProtoEnum(int reason) {
+        switch (reason) {
+            case BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA:
+                return NetworkDisableReason.REASON_AP_UNABLE_TO_HANDLE_NEW_STA;
+            case BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE:
+                return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
+            case BssidBlocklistMonitor.REASON_WRONG_PASSWORD:
+                return NetworkDisableReason.REASON_WRONG_PASSWORD;
+            case BssidBlocklistMonitor.REASON_EAP_FAILURE:
+                return NetworkDisableReason.REASON_EAP_FAILURE;
+            case BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION:
+                return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
+            case BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT:
+                return NetworkDisableReason.REASON_ASSOCIATION_TIMEOUT;
+            case BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE:
+                return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
+            case BssidBlocklistMonitor.REASON_DHCP_FAILURE:
+                return NetworkDisableReason.REASON_DHCP_FAILURE;
+            case BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT:
+                return NetworkDisableReason.REASON_ABNORMAL_DISCONNECT;
+            case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE:
+                return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_MBO_OCE;
+            case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT:
+                return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT;
+            case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE:
+                return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE;
+            default:
+                return NetworkDisableReason.REASON_UNKNOWN;
+        }
+    }
 }
diff --git a/service/java/com/android/server/wifi/util/ScanResultUtil.java b/service/java/com/android/server/wifi/util/ScanResultUtil.java
index dc2281a..4085045 100644
--- a/service/java/com/android/server/wifi/util/ScanResultUtil.java
+++ b/service/java/com/android/server/wifi/util/ScanResultUtil.java
@@ -233,6 +233,10 @@
                 } else {
                     rssiInfo = String.format("%9d         ", r.level);
                 }
+                if ((r.flags & ScanResult.FLAG_PASSPOINT_NETWORK)
+                        == ScanResult.FLAG_PASSPOINT_NETWORK) {
+                    r.capabilities += "[PASSPOINT]";
+                }
                 pw.printf("  %17s  %9d  %18s   %7s    %-32s  %s\n",
                         r.BSSID,
                         r.frequency,
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index 30b1690..1c3b278 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -1471,6 +1471,9 @@
 
   // Whether cellular data network is available
   optional bool is_cellular_data_available = 25;
+
+  //Whether Adaptive Connectivity is enabled
+  optional bool is_adaptive_connectivity_enabled = 26;
 }
 
 // Wi-Fi Aware metrics
@@ -3156,6 +3159,12 @@
     EVENT_MANUAL_CONNECT = 11;
     // User changes the metered setting to "detect automatically"
     EVENT_CONFIGURE_METERED_STATUS_AUTO = 12;
+    // User adds a new network or updates configurations for an existing network.
+    EVENT_ADD_OR_UPDATE_NETWORK = 13;
+    // User sets the adaptive connectivity to on
+    EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON = 14;
+    // User sets the adaptive connectivity to off
+    EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF = 15;
   }
 
   // The type of user action
@@ -3167,6 +3176,34 @@
   // Additional information on the target network for the action. This is not applicable and will
   // be null for some actions such as EVENT_TOGGLE_WIFI_ON.
   optional TargetNetworkInfo target_network_info = 3;
+
+  // Information about the currently connected network.
+  optional WifiStatus wifi_status = 4;
+
+  // Reasons why the network applicable for this user action is disabled.
+  // Normally this should be referring to the currently connected network.
+  // For a manual connection, this is referring to the user selected networks.
+  optional NetworkDisableReason network_disable_reason = 5;
+}
+
+message WifiStatus {
+  // Wifi is connected.
+  optional bool is_connected = 1;
+
+  // Wifi is validated
+  optional bool is_validated = 2;
+
+  // The last observed RSSI
+  optional sint32 last_rssi = 3;
+
+  // Estimated TX
+  optional int32 estimated_tx_kbps = 4;
+
+  // Estimated RX
+  optional int32 estimated_rx_kbps = 5;
+
+  // There is another candidate with better score, but user connect choice is preventing the switch.
+  optional bool is_stuck_due_to_user_connect_choice = 6;
 }
 
 // Additional information on a network
@@ -3178,6 +3215,56 @@
   optional bool is_passpoint = 2;
 }
 
+// Reasons why a configuration or BSSID is disabled.
+message NetworkDisableReason {
+  enum DisableReason {
+    // Default value, should not be used.
+    REASON_UNKNOWN = 0;
+    // AP unable to accept more clients, a special kind of association rejection failure.
+    REASON_AP_UNABLE_TO_HANDLE_NEW_STA = 1;
+    // No internet
+    REASON_NETWORK_VALIDATION_FAILURE = 2;
+    // Password is incorrect, a special kind of authentication failure.
+    REASON_WRONG_PASSWORD = 3;
+    // Incorrect EAP credentials.
+    REASON_EAP_FAILURE = 4;
+    // Other association rejection failures.
+    REASON_ASSOCIATION_REJECTION = 5;
+    // Associated timeout failures.
+    REASON_ASSOCIATION_TIMEOUT = 6;
+    // Other authentication failures.
+    REASON_AUTHENTICATION_FAILURE = 7;
+    // DHCP failures.
+    REASON_DHCP_FAILURE = 8;
+    // Device disconnected shortly after connection.
+    REASON_ABNORMAL_DISCONNECT = 9;
+    // AP initiated disconnect for a given duration.
+    REASON_FRAMEWORK_DISCONNECT_MBO_OCE = 10;
+    // Avoid connecting to the failed AP when trying to reconnect on other available candidates.
+    REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT = 11;
+    // The connected scorer has disconnected this network.
+    REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE = 12;
+    // The network is disabled due to absence of user credentials
+    REASON_AUTHENTICATION_NO_CREDENTIALS = 13;
+    // The network is disabled because service is not subscribed, a special kind of EAP failure.
+    REASON_AUTHENTICATION_NO_SUBSCRIPTION = 14;
+    // User disabled auto-join for this network.
+    REASON_AUTO_JOIN_DISABLED = 15;
+  }
+
+  // The reason for disabling a network.
+  optional DisableReason disable_reason = 1;
+
+  // The configuration is temporarily disabled.
+  optional bool config_temporarily_disabled = 2;
+
+  // The configuration is disabled until the user manually re-enables it.
+  optional bool config_permanently_disabled = 3;
+
+  // Reasons why 1 or more BSSIDs are temporarily disabled.
+  repeated DisableReason bssid_disable_reasons = 4;
+}
+
 // Number of networks with a large change of connection/disconnection
 // failure rate or high failure rate at high RSSI
 message HealthMonitorFailureStats {
diff --git a/service/res/values-b+sr+Latn/strings.xml b/service/res/values-b+sr+Latn/strings.xml
index 08970f9..fcd90f7 100644
--- a/service/res/values-b+sr+Latn/strings.xml
+++ b/service/res/values-b+sr+Latn/strings.xml
@@ -16,9 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemski Wi-Fi resursi"</string>
+    <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Sistemski WiFi resursi"</string>
     <string name="wifi_available_title" msgid="2844963247498642107">"Povežite se sa otvorenom Wi‑Fi mrežom"</string>
-    <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Povezuje se sa Wi-Fi mrežom..."</string>
+    <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Povezuje se sa WiFi mrežom..."</string>
     <string name="wifi_available_title_connected" msgid="922603556292157664">"Povezali ste se sa Wi‑Fi mrežom"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Povezivanje sa Wi‑Fi mrežom nije uspelo"</string>
     <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Dodirnite da biste videli sve mreže"</string>
@@ -44,10 +44,10 @@
     <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Ne uključuj ponovo"</string>
     <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi je automatski uključen"</string>
     <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"U blizini ste sačuvane mreže: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
-    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nije moguće povezati sa Wi-Fi mrežom"</string>
+    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Nije moguće povezati sa WiFi mrežom"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" ima lošu internet vezu."</string>
     <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Želite li da dozvolite povezivanje?"</string>
-    <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s želi da se poveže na Wi-Fi mrežu %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Aplikacija %1$s želi da se poveže na WiFi mrežu %2$s"</string>
     <string name="wifi_connect_default_application" msgid="6164721692891325243">"Aplikacija"</string>
     <string name="accept" msgid="5931271886782610829">"Prihvati"</string>
     <string name="decline" msgid="6874256900873707640">"Odbij"</string>
@@ -58,9 +58,9 @@
     <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Kome:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Unesite potrebni PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet će privremeno prekinuti vezu sa Wi-Fi-jem dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV uređaj će privremeno prekinuti vezu sa Wi-Fi mrežom dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon će privremeno prekinuti vezu sa Wi-Fi-jem dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Tablet će privremeno prekinuti vezu sa WiFi-em dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV uređaj će privremeno prekinuti vezu sa WiFi mrežom dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Telefon će privremeno prekinuti vezu sa WiFi-em dok je povezan sa uređajem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="dlg_ok" msgid="3250085870426030310">"Potvrdi"</string>
     <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Povezivanje na mrežu <xliff:g id="SSID">%1$s</xliff:g> nije uspelo"</string>
     <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Dodirnite da biste promenili podešavanja privatnosti i probali ponovo"</string>
@@ -79,6 +79,6 @@
     <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP greška pri potvrdi identiteta 32766"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Hotspot je isključen"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Nijedan uređaj nije povezan. Dodirnite da biste izmenili."</string>
-    <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi veza je prekinuta"</string>
+    <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi veza je prekinuta"</string>
     <string name="wifi_sim_required_message" msgid="6085636103482409595">"Da biste se povezali na mrežu <xliff:g id="SSID">%1$s</xliff:g>, umetnite <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM karticu"</string>
 </resources>
diff --git a/service/res/values-en-rXC/strings.xml b/service/res/values-en-rXC/strings.xml
index 22db537..75f465a 100644
--- a/service/res/values-en-rXC/strings.xml
+++ b/service/res/values-en-rXC/strings.xml
@@ -31,9 +31,12 @@
     <string name="wifi_suggestion_content" msgid="7796523101671166285">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ suggested networks. Device may connect automatically.‎‏‎‎‏‎"</string>
     <string name="wifi_suggestion_action_allow_app" msgid="1269853856167682235">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‏‎‏‏‎Allow‎‏‎‎‏‎"</string>
     <string name="wifi_suggestion_action_disallow_app" msgid="4844316521687534924">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‎No thanks‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_imsi_privacy_title" msgid="2915915091404141470">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="CARRIERNAME">%s</xliff:g>‎‏‎‎‏‏‏‎ wants to auto‑connect‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_imsi_privacy_content" msgid="2964867545127220548">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‏‎‎‎‏‎‎‎These networks receive a unique ID that can be used to track device location‎‏‎‎‏‎"</string>
-    <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_carrier" msgid="4510014692570591616">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‎‎‎‎Connect anyway‎‏‎‎‏‎"</string>
+    <!-- no translation found for wifi_suggestion_imsi_privacy_title (2915915091404141470) -->
+    <skip />
+    <!-- no translation found for wifi_suggestion_imsi_privacy_content (2964867545127220548) -->
+    <skip />
+    <!-- no translation found for wifi_suggestion_action_allow_imsi_privacy_exemption_carrier (4510014692570591616) -->
+    <skip />
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_carrier" msgid="1466870675651864648">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‎‏‏‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‎‎Don\'t connect‎‏‎‎‏‎"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_title" msgid="3252889810011175876">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‎‎‏‏‎‎‎‎‏‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎Confirm connection?‎‏‎‎‏‎"</string>
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎If you connect, ‎‏‎‎‏‏‎<xliff:g id="CARRIERNAME">%s</xliff:g>‎‏‎‎‏‏‏‎ Wi‑Fi networks may access or share a unique ID associated with your SIM. This may allow your device\'s location to be tracked.‎‏‎‎‏‎"</string>
diff --git a/service/res/values-fa/strings.xml b/service/res/values-fa/strings.xml
index b6d0139..e099370 100644
--- a/service/res/values-fa/strings.xml
+++ b/service/res/values-fa/strings.xml
@@ -70,13 +70,13 @@
     <string name="wifi_disable_mac_randomization_dialog_success" msgid="7288972191769783828">"تنظیم به‌روزرسانی شد. دوباره متصل شوید."</string>
     <string name="wifi_disable_mac_randomization_dialog_failure" msgid="1823128152758990275">"تنظیم حریم‌خصوصی تغییر نکرد"</string>
     <string name="wifi_disable_mac_randomization_dialog_network_not_found" msgid="2352188098110676023">"شبکه‌ای پیدا نشد"</string>
-    <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۰ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۱ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۲ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۳ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۴ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۵ احراز هویت EAP"</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۶ احراز هویت EAP"</string>
+    <string name="wifi_eap_error_message_code_32760" msgid="2272296327034079386">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۰ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="3110197168451423384">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۱ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="3515553222282833794">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۲ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="3790937365887990781">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۳ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="6883041845648321423">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۴ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="3134805513440435314">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۵ اصالت‌سنجی EAP"</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"‏<xliff:g id="SSID">%1$s</xliff:g> : خطای ۳۲۷۶۶ اصالت‌سنجی EAP"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"نقطه اتصال خاموش شد"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"هیچ دستگاهی متصل نیست. برای اصلاح ضربه بزنید."</string>
     <string name="wifi_sim_required_title" msgid="8362843050699015640">"‏Wi-Fi قطع شد."</string>
diff --git a/service/res/values-gu/strings.xml b/service/res/values-gu/strings.xml
index 634199e..72ee1ab 100644
--- a/service/res/values-gu/strings.xml
+++ b/service/res/values-gu/strings.xml
@@ -39,10 +39,10 @@
     <string name="wifi_suggestion_imsi_privacy_exemption_confirmation_content" msgid="1665277613133133730">"જો તમે કનેક્ટ કરો છો, તો <xliff:g id="CARRIERNAME">%s</xliff:g> વાઇ-ફાઇ નેટવર્ક, તમારા SIM સાથે સંકળાયેલા અજોડ IDને ઍક્સેસ અથવા શેર કરી શકે છે. આમ કરવાથી તમારા ડિવાઇસનું સ્થાન ટ્રૅક કરવાની મંજૂરી આપવામાં આવી શકે છે."</string>
     <string name="wifi_suggestion_action_allow_imsi_privacy_exemption_confirmation" msgid="3102046304611708608">"કનેક્ટ કરો"</string>
     <string name="wifi_suggestion_action_disallow_imsi_privacy_exemption_confirmation" msgid="8467281276632253246">"કનેક્ટ કરશો નહીં"</string>
-    <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"વાઇ-ફાઇ આપમેળે ચાલુ થઈ જશે"</string>
+    <string name="wifi_wakeup_onboarding_title" msgid="8825510461478671504">"વાઇ-ફાઇ ઑટોમૅટિક રીતે ચાલુ થઈ જશે"</string>
     <string name="wifi_wakeup_onboarding_subtext" msgid="2525097093651287599">"જ્યારે તમે એક ઉચ્ચ ક્વૉલિટીવાળા સાચવેલ નેટવર્કની નજીક હોવ"</string>
     <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"પાછું ચાલુ કરશો નહીં"</string>
-    <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"વાઇ-ફાઇ આપમેળે ચાલુ થયું"</string>
+    <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"વાઇ-ફાઇ ઑટોમૅટિક રીતે ચાલુ થયું"</string>
     <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"તમે એક સાચવેલ નેટવર્કની નજીકમાં છો: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
     <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"વાઇ-ફાઇ સાથે કનેક્ટ કરી શકાયું નથી"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" આમનું ઇન્ટરનેટ કનેક્શન નબળું છે."</string>
diff --git a/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml b/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml
index 4f7ce68..5ab12b1 100644
--- a/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml
+++ b/service/res/values-mcc310-mnc004-b+sr+Latn/strings.xml
@@ -16,11 +16,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon Wi-Fi Access van oblasti koju Verizon pokriva."</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon Wi-Fi Access. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon Wi-Fi Access nalogom. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon Wi-Fi Access."</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon Wi-Fi Access. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon Wi-Fi Access nalogom. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string>
+    <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon WiFi Access van oblasti koju Verizon pokriva."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon WiFi Access."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string>
 </resources>
diff --git a/service/res/values-mcc310-mnc004-sr/strings.xml b/service/res/values-mcc310-mnc004-sr/strings.xml
index 7acf5bf..176e51b 100644
--- a/service/res/values-mcc310-mnc004-sr/strings.xml
+++ b/service/res/values-mcc310-mnc004-sr/strings.xml
@@ -16,11 +16,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon Wi-Fi Access ван области коју Verizon покрива."</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon Wi-Fi Access. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon Wi-Fi Access налогом. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon Wi-Fi Access."</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon Wi-Fi Access. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon Wi-Fi Access налогом. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string>
+    <string name="wifi_eap_error_message_code_32760" msgid="2026634652595949365">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon WiFi Access ван области коју Verizon покрива."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="360877194229909012">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon WiFi Access. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="7728639390217187188">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="4245525855163845749">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon WiFi Access."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="7837099889588693332">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon WiFi Access. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="1430902733213412544">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="3201380662092880364">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string>
 </resources>
diff --git a/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml b/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml
index df22976..712334e 100644
--- a/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml
+++ b/service/res/values-mcc311-mnc480-b+sr+Latn/strings.xml
@@ -16,11 +16,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon Wi-Fi Access van oblasti koju Verizon pokriva."</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon Wi-Fi Access. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon Wi-Fi Access nalogom. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon Wi-Fi Access."</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon Wi-Fi Access. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon Wi-Fi Access nalogom. Pozovite nas na 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string>
+    <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Ne možete da se povežete na Verizon WiFi Access van oblasti koju Verizon pokriva."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Niste pretplaćeni na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Već ste povezani na Verizon WiFi Access."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Postoji problem pri povezivanju na Verizon WiFi Access. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Došlo je do problema u vezi sa Verizon WiFi Access nalogom. Pozovite nas na 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access nije dostupan sa vaše lokacije. Probajte ponovo kasnije ili probajte sa neke druge lokacije."</string>
 </resources>
diff --git a/service/res/values-mcc311-mnc480-sr/strings.xml b/service/res/values-mcc311-mnc480-sr/strings.xml
index 49c8d47..05b637a 100644
--- a/service/res/values-mcc311-mnc480-sr/strings.xml
+++ b/service/res/values-mcc311-mnc480-sr/strings.xml
@@ -16,11 +16,11 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon Wi-Fi Access ван области коју Verizon покрива."</string>
-    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon Wi-Fi Access. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon Wi-Fi Access налогом. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon Wi-Fi Access."</string>
-    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon Wi-Fi Access. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon Wi-Fi Access налогом. Позовите нас на 800 922 0204."</string>
-    <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon Wi-Fi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string>
+    <string name="wifi_eap_error_message_code_32760" msgid="4555573944292156870">"<xliff:g id="SSID">%1$s</xliff:g> : Не можете да се повежете на Verizon WiFi Access ван области коју Verizon покрива."</string>
+    <string name="wifi_eap_error_message_code_32761" msgid="6990683739673245807">"<xliff:g id="SSID">%1$s</xliff:g> : Нисте претплаћени на Verizon WiFi Access. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32762" msgid="6557033506833966794">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32763" msgid="3400795159444109915">"<xliff:g id="SSID">%1$s</xliff:g> : Већ сте повезани на Verizon WiFi Access."</string>
+    <string name="wifi_eap_error_message_code_32764" msgid="1312072776680938826">"<xliff:g id="SSID">%1$s</xliff:g> : Постоји проблем при повезивању на Verizon WiFi Access. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32765" msgid="8150337243297471644">"<xliff:g id="SSID">%1$s</xliff:g> : Дошло је до проблема у вези са Verizon WiFi Access налогом. Позовите нас на 800 922 0204."</string>
+    <string name="wifi_eap_error_message_code_32766" msgid="962325801073733226">"<xliff:g id="SSID">%1$s</xliff:g> : Verizon WiFi Access није доступан са ваше локације. Пробајте поново касније или пробајте са неке друге локације."</string>
 </resources>
diff --git a/service/res/values-mk/strings.xml b/service/res/values-mk/strings.xml
index 1852f52..6e73631 100644
--- a/service/res/values-mk/strings.xml
+++ b/service/res/values-mk/strings.xml
@@ -20,7 +20,7 @@
     <string name="wifi_available_title" msgid="2844963247498642107">"Поврзете се на отворена Wi‑Fi-мрежа"</string>
     <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Поврзување со Wi-Fi мрежа"</string>
     <string name="wifi_available_title_connected" msgid="922603556292157664">"Се поврзавте на Wi‑Fi-мрежа"</string>
-    <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не можеше да се поврзе на Wi‑Fi-мрежа"</string>
+    <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Не може да се поврзе на Wi‑Fi-мрежа"</string>
     <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Допрете за да ги видите сите мрежи"</string>
     <string name="wifi_available_action_connect" msgid="7989951293406720158">"Поврзете се"</string>
     <string name="wifi_available_action_all_networks" msgid="2616926772813472478">"Сите мрежи"</string>
@@ -44,7 +44,7 @@
     <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не вклучувај повторно"</string>
     <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi се вклучи автоматски"</string>
     <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"Близу сте до зачувана мрежа: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
-    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не можеше да се поврзе со Wi-Fi"</string>
+    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Не може да се поврзе на Wi-Fi"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" има слаба интернет-врска."</string>
     <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Дозволете поврзување?"</string>
     <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Апликацијата %1$s сака да се поврзе со Wifi-мрежата %2$s"</string>
diff --git a/service/res/values-sr/strings.xml b/service/res/values-sr/strings.xml
index c488c21..afc82f1 100644
--- a/service/res/values-sr/strings.xml
+++ b/service/res/values-sr/strings.xml
@@ -16,9 +16,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системски Wi-Fi ресурси"</string>
+    <string name="wifiResourcesAppLabel" product="default" msgid="4965162975090543792">"Системски WiFi ресурси"</string>
     <string name="wifi_available_title" msgid="2844963247498642107">"Повежите се са отвореном Wi‑Fi мрежом"</string>
-    <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Повезује се са Wi-Fi мрежом..."</string>
+    <string name="wifi_available_title_connecting" msgid="4308431577637294026">"Повезује се са WiFi мрежом..."</string>
     <string name="wifi_available_title_connected" msgid="922603556292157664">"Повезали сте се са Wi‑Fi мрежом"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="2304443371893419545">"Повезивање са Wi‑Fi мрежом није успело"</string>
     <string name="wifi_available_content_failed_to_connect" msgid="3171283790496729136">"Додирните да бисте видели све мреже"</string>
@@ -44,10 +44,10 @@
     <string name="wifi_wakeup_onboarding_action_disable" msgid="672002169958868470">"Не укључуј поново"</string>
     <string name="wifi_wakeup_enabled_title" msgid="7758584632765597662">"Wi‑Fi је аутоматски укључен"</string>
     <string name="wifi_wakeup_enabled_content" msgid="4713038331224656338">"У близини сте сачуване мреже: <xliff:g id="NETWORK_SSID">%1$s</xliff:g>"</string>
-    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Није могуће повезати са Wi-Fi мрежом"</string>
+    <string name="wifi_watchdog_network_disabled" msgid="688248897654073438">"Није могуће повезати са WiFi мрежом"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="2946200607682633112">" има лошу интернет везу."</string>
     <string name="wifi_connect_alert_title" msgid="6144470472092017636">"Желите ли да дозволите повезивање?"</string>
-    <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Апликација %1$s жели да се повеже на Wi-Fi мрежу %2$s"</string>
+    <string name="wifi_connect_alert_message" msgid="3123801378559831220">"Апликација %1$s жели да се повеже на WiFi мрежу %2$s"</string>
     <string name="wifi_connect_default_application" msgid="6164721692891325243">"Апликација"</string>
     <string name="accept" msgid="5931271886782610829">"Прихвати"</string>
     <string name="decline" msgid="6874256900873707640">"Одбиј"</string>
@@ -58,9 +58,9 @@
     <string name="wifi_p2p_to_message" msgid="6664932426704362946">"Коме:"</string>
     <string name="wifi_p2p_enter_pin_message" msgid="5661843905965463456">"Унесите потребни PIN:"</string>
     <string name="wifi_p2p_show_pin_message" msgid="4332876077723766909">"PIN:"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблет ће привремено прекинути везу са Wi-Fi-јем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV уређај ће привремено прекинути везу са Wi-Fi мрежом док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
-    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефон ће привремено прекинути везу са Wi-Fi-јем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="tablet" msgid="3372859876274663802">"Таблет ће привремено прекинути везу са WiFi-ем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="tv" msgid="406603193215934517">"Android TV уређај ће привремено прекинути везу са WiFi мрежом док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="wifi_p2p_frequency_conflict_message" product="default" msgid="2723785832319900478">"Телефон ће привремено прекинути везу са WiFi-ем док је повезан са уређајем <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
     <string name="dlg_ok" msgid="3250085870426030310">"Потврди"</string>
     <string name="wifi_cannot_connect_with_randomized_mac_title" msgid="3161171832972320854">"Повезивање на мрежу <xliff:g id="SSID">%1$s</xliff:g> није успело"</string>
     <string name="wifi_cannot_connect_with_randomized_mac_message" msgid="3084495849409387375">"Додирните да бисте променили подешавања приватности и пробали поново"</string>
@@ -79,6 +79,6 @@
     <string name="wifi_eap_error_message_code_32766" msgid="6907401733158262194">"<xliff:g id="SSID">%1$s</xliff:g>: EAP грешка при потврди идентитета 32766"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_title" msgid="3145323037688670043">"Хотспот је искључен"</string>
     <string name="wifi_softap_auto_shutdown_timeout_expired_summary" msgid="5136282560556465701">"Ниједан уређај није повезан. Додирните да бисте изменили."</string>
-    <string name="wifi_sim_required_title" msgid="8362843050699015640">"Wi-Fi веза је прекинута"</string>
+    <string name="wifi_sim_required_title" msgid="8362843050699015640">"WiFi веза је прекинута"</string>
     <string name="wifi_sim_required_message" msgid="6085636103482409595">"Да бисте се повезали на мрежу <xliff:g id="SSID">%1$s</xliff:g>, уметните <xliff:g id="CARRIER_NAME">%2$s</xliff:g> SIM картицу"</string>
 </resources>
diff --git a/service/res/values/config.xml b/service/res/values/config.xml
index cc80f60..0264c3e 100644
--- a/service/res/values/config.xml
+++ b/service/res/values/config.xml
@@ -355,20 +355,19 @@
     config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7-->
     <integer translatable="false" name="config_wifiBssidBlocklistMonitorBaseBlockDurationMs"> 300000 </integer>
 
-    <!-- Base block duration for a failure at low RSSI (less than the sufficient RSSI) used for
-    ASSOCIATION_TIMEOUT, ABNORMAL_DISCONNECT, and NETWORK_VALIDATION failures. The block duration
-    for a BSSID that keeps failing will grow exponentially to the this base duration.
+    <!-- Base duration to block a BSSID after the external connected scorer sets wifi as unusable.
+    The block duration is increased exponentially if the same BSSID is repeated marked as unusable.
     ie. 0.5/1/2/4/8/16/32/64 minutes - capped at 64 minutes because the default for
-    config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7.
-    This value should be configured to be less than config_wifiBssidBlocklistMonitorBaseBlockDurationMs -->
-    <integer translatable="false" name="config_wifiBssidBlocklistMonitorBaseLowRssiBlockDurationMs"> 30000 </integer>
+    config_wifiBssidBlocklistMonitorFailureStreakCap is set to 7. The block duration is reset to
+    the base value 3 hours after the latest connection to this BSSID. -->
+    <integer translatable="false" name="config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs"> 30000 </integer>
 
     <!-- The failure streak is the number of times a BSSID consecutively gets blocked without ever
     successfully connecting in between, and is used to calculate the exponentially growing blocklist time.
     The config_wifiBssidBlocklistMonitorFailureStreakCap controls how many times the block duration
     could exponentially grow when a BSSID keeps failing.
     ie. A value of 0 means BSSIDs are always blocked for the flat base duration defined by
-    config_wifiBssidBlocklistMonitorBaseBlockDurationMs and config_wifiBssidBlocklistMonitorBaseLowRssiBlockDurationMs. -->
+    config_wifiBssidBlocklistMonitorBaseBlockDurationMs. -->
     <integer translatable="false" name="config_wifiBssidBlocklistMonitorFailureStreakCap"> 7 </integer>
 
     <!-- If a non-locally generated disconnect happens within this time window after association,
@@ -462,4 +461,7 @@
 
     <!-- integer indicating additional disconnect delay (in ms) after IMS onLost() indication is received -->
     <integer translatable="false" name="config_wifiDelayDisconnectOnImsLostMs">0</integer>
+
+    <!-- Enable adding minimum confirmation duration when sending network score to connectivity service. -->
+    <bool translatable="false" name="config_wifiMinConfirmationDurationSendNetworkScoreEnabled">false</bool>
 </resources>
diff --git a/service/res/values/overlayable.xml b/service/res/values/overlayable.xml
index a4b7011..60764ba 100644
--- a/service/res/values/overlayable.xml
+++ b/service/res/values/overlayable.xml
@@ -114,7 +114,7 @@
           <item type="integer" name="config_wifiBssidBlocklistMonitorDhcpFailureThreshold" />
           <item type="integer" name="config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold" />
           <item type="integer" name="config_wifiBssidBlocklistMonitorBaseBlockDurationMs" />
-          <item type="integer" name="config_wifiBssidBlocklistMonitorBaseLowRssiBlockDurationMs" />
+          <item type="integer" name="config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs" />
           <item type="integer" name="config_wifiBssidBlocklistMonitorFailureStreakCap" />
           <item type="integer" name="config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs" />
           <item type="bool" name="config_wifiScanHiddenNetworksScanOnlyMode" />
@@ -144,6 +144,7 @@
           <item type="integer" name="config_wifiMovingPnoScanIntervalMillis" />
           <item type="integer" name="config_wifiStationaryPnoScanIntervalMillis" />
           <item type="integer" name="config_wifiDelayDisconnectOnImsLostMs" />
+          <item type="bool" name="config_wifiMinConfirmationDurationSendNetworkScoreEnabled" />
           <!-- Params from config.xml that can be overlayed -->
 
           <!-- Params from strings.xml that can be overlayed -->
diff --git a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
index 8cb2e37..1007391 100644
--- a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
@@ -18,8 +18,10 @@
 
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.times;
 
 import android.content.Context;
+import android.net.wifi.ScanResult;
 import android.util.LocalLog;
 
 import androidx.test.filters.SmallTest;
@@ -32,6 +34,8 @@
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
@@ -47,27 +51,36 @@
     private static final String TEST_BSSID_1 = "0a:08:5c:67:89:00";
     private static final String TEST_BSSID_2 = "0a:08:5c:67:89:01";
     private static final String TEST_BSSID_3 = "0a:08:5c:67:89:02";
+    private static final int TEST_GOOD_RSSI = -50;
+    private static final int TEST_SUFFICIENT_RSSI = -67;
+    private static final int MIN_RSSI_DIFF_TO_UNBLOCK_BSSID = 5;
+    private static final int TEST_FRAMEWORK_BLOCK_REASON =
+            BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE;
     private static final int TEST_L2_FAILURE = BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION;
     private static final int TEST_DHCP_FAILURE = BssidBlocklistMonitor.REASON_DHCP_FAILURE;
     private static final long BASE_BLOCKLIST_DURATION = TimeUnit.MINUTES.toMillis(5); // 5 minutes
-    private static final long BASE_LOW_RSSI_BLOCKLIST_DURATION = TimeUnit.SECONDS.toMillis(30);
+    private static final long BASE_CONNECTED_SCORE_BLOCKLIST_DURATION =
+            TimeUnit.SECONDS.toMillis(30);
     private static final long ABNORMAL_DISCONNECT_TIME_WINDOW_MS = TimeUnit.SECONDS.toMillis(30);
     private static final long ABNORMAL_DISCONNECT_RESET_TIME_MS = TimeUnit.HOURS.toMillis(3);
     private static final int FAILURE_STREAK_CAP = 7;
-    private static final int[] FAILURE_COUNT_DISABLE_THRESHOLD = {
-            1,  //  threshold for REASON_AP_UNABLE_TO_HANDLE_NEW_STA
-            1,  //  threshold for REASON_NETWORK_VALIDATION_FAILURE
-            1,  //  threshold for REASON_WRONG_PASSWORD
-            1,  //  threshold for REASON_EAP_FAILURE
-            3,  //  threshold for REASON_ASSOCIATION_REJECTION
-            3,  //  threshold for REASON_ASSOCIATION_TIMEOUT
-            3,  //  threshold for REASON_AUTHENTICATION_FAILURE
-            3,  //  threshold for REASON_DHCP_FAILURE
-            3   //  threshold for REASON_ABNORMAL_DISCONNECT
-    };
+    private static final Map<Integer, Integer> BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP =
+            Map.ofEntries(
+                    Map.entry(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_WRONG_PASSWORD, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_EAP_FAILURE, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION, 3),
+                    Map.entry(BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, 3),
+                    Map.entry(BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE, 3),
+                    Map.entry(BssidBlocklistMonitor.REASON_DHCP_FAILURE, 3),
+                    Map.entry(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, 3),
+                    Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT, 1),
+                    Map.entry(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE, 1)
+            );
     private static final int NUM_FAILURES_TO_BLOCKLIST =
-            FAILURE_COUNT_DISABLE_THRESHOLD[TEST_L2_FAILURE];
-
+            BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(TEST_L2_FAILURE);
 
     @Mock private Context mContext;
     @Mock private WifiConnectivityHelper mWifiConnectivityHelper;
@@ -75,6 +88,7 @@
     @Mock private Clock mClock;
     @Mock private LocalLog mLocalLog;
     @Mock private WifiScoreCard mWifiScoreCard;
+    @Mock private ScoringParams mScoringParams;
 
     private MockResources mResources;
     private BssidBlocklistMonitor mBssidBlocklistMonitor;
@@ -86,50 +100,60 @@
         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
         when(mWifiConnectivityHelper.getMaxNumBlacklistBssid())
                 .thenReturn(TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS);
+        when(mScoringParams.getSufficientRssi(anyInt())).thenReturn(TEST_SUFFICIENT_RSSI);
         mResources = new MockResources();
         mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorBaseBlockDurationMs,
                 (int) BASE_BLOCKLIST_DURATION);
         mResources.setInteger(
-                R.integer.config_wifiBssidBlocklistMonitorBaseLowRssiBlockDurationMs,
-                (int) BASE_LOW_RSSI_BLOCKLIST_DURATION);
+                R.integer.config_wifiBssidBlocklistMonitorConnectedScoreBaseBlockDurationMs,
+                (int) BASE_CONNECTED_SCORE_BLOCKLIST_DURATION);
         mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorFailureStreakCap,
                 FAILURE_STREAK_CAP);
         mResources.setInteger(R.integer.config_wifiBssidBlocklistAbnormalDisconnectTimeWindowMs,
                 (int) ABNORMAL_DISCONNECT_TIME_WINDOW_MS);
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorApUnableToHandleNewStaThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[0]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA));
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorNetworkValidationFailureThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[1]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE));
         mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorWrongPasswordThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[2]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_WRONG_PASSWORD));
         mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorEapFailureThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[3]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_EAP_FAILURE));
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorAssociationRejectionThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[4]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION));
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorAssociationTimeoutThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[5]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT));
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorAuthenticationFailureThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[6]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE));
         mResources.setInteger(R.integer.config_wifiBssidBlocklistMonitorDhcpFailureThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[7]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_DHCP_FAILURE));
         mResources.setInteger(
                 R.integer.config_wifiBssidBlocklistMonitorAbnormalDisconnectThreshold,
-                FAILURE_COUNT_DISABLE_THRESHOLD[8]);
+                BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.get(
+                        BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT));
 
         when(mContext.getResources()).thenReturn(mResources);
         mBssidBlocklistMonitor = new BssidBlocklistMonitor(mContext, mWifiConnectivityHelper,
-                mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard);
+                mWifiLastResortWatchdog, mClock, mLocalLog, mWifiScoreCard, mScoringParams);
     }
 
     private void verifyAddTestBssidToBlocklist() {
         mBssidBlocklistMonitor.handleBssidConnectionFailure(
                 TEST_BSSID_1, TEST_SSID_1,
-                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI);
         assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
     }
 
@@ -137,12 +161,15 @@
     private void verifyAddMultipleBssidsToBlocklist() {
         when(mClock.getWallClockMillis()).thenReturn(0L);
         mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1,
-                TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+                TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA,
+                TEST_GOOD_RSSI);
         when(mClock.getWallClockMillis()).thenReturn(1L);
         mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_2,
-                TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+                TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA,
+                TEST_GOOD_RSSI);
         mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_3,
-                TEST_SSID_2, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+                TEST_SSID_2, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA,
+                TEST_GOOD_RSSI);
 
         // Verify that we have 3 BSSIDs in the blocklist.
         Set<String> bssidList = mBssidBlocklistMonitor.updateAndGetBssidBlocklist();
@@ -159,18 +186,19 @@
     private void handleBssidConnectionFailureMultipleTimes(String bssid, String ssid, int reason,
             int times) {
         for (int i = 0; i < times; i++) {
-            mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, reason, false);
+            mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid, ssid, reason,
+                    TEST_GOOD_RSSI);
         }
     }
 
     /**
-     * Verify getNumBlockedBssidsForSsid returns the correct number of blocked BSSIDs.
+     * Verify updateAndGetNumBlockedBssidsForSsid returns the correct number of blocked BSSIDs.
      */
     @Test
-    public void testGetNumBlockedBssidsForSsid() {
+    public void testUpdateAndGetNumBlockedBssidsForSsid() {
         verifyAddMultipleBssidsToBlocklist();
-        assertEquals(2, mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(TEST_SSID_1));
-        assertEquals(1, mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(TEST_SSID_2));
+        assertEquals(2, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(TEST_SSID_1));
+        assertEquals(1, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(TEST_SSID_2));
     }
 
     /**
@@ -192,19 +220,31 @@
     }
 
     /**
-     * Verify that a BSSID is blocked for a shorter time if the failure reason is association
-     * timeout and the RSSI is low.
+     * Verify that updateAndGetBssidBlocklist(ssid) updates firmware roaming configuration
+     * if a BSSID that belongs to the ssid is removed from blocklist.
      */
     @Test
-    public void testAssociationTimeoutAtLowRssi() {
-        for (int i = 0; i < NUM_FAILURES_TO_BLOCKLIST; i++) {
-            mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, TEST_SSID_1,
-                    BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, true);
-        }
-        when(mClock.getWallClockMillis()).thenReturn(BASE_LOW_RSSI_BLOCKLIST_DURATION);
-        assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
-        when(mClock.getWallClockMillis()).thenReturn(BASE_LOW_RSSI_BLOCKLIST_DURATION + 1);
-        assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
+    public void testBssidRemovalUpdatesFirmwareConfiguration() {
+        verifyAddTestBssidToBlocklist();
+        when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1);
+        assertEquals(0, mBssidBlocklistMonitor
+                .updateAndGetBssidBlocklistForSsid(TEST_SSID_1).size());
+        verify(mWifiConnectivityHelper).setFirmwareRoamingConfiguration(eq(new ArrayList<>()),
+                eq(new ArrayList<>()));
+    }
+
+    /**
+     * Verify that updateAndGetBssidBlocklist(ssid) does not update firmware roaming configuration
+     * if there are no BSSIDs belonging to the ssid removed from blocklist.
+     */
+    @Test
+    public void testBssidRemovalNotUpdateFirmwareConfiguration() {
+        verifyAddTestBssidToBlocklist();
+        when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1);
+        assertEquals(0, mBssidBlocklistMonitor
+                .updateAndGetBssidBlocklistForSsid(TEST_SSID_2).size());
+        verify(mWifiConnectivityHelper, never()).setFirmwareRoamingConfiguration(
+                eq(new ArrayList<>()), eq(new ArrayList<>()));
     }
 
     /**
@@ -279,7 +319,7 @@
                 .thenReturn(0L);
         when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_TIME_WINDOW_MS + 1);
         assertFalse(mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, TEST_SSID_1,
-                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, false));
+                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI));
         verify(mWifiScoreCard, never()).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
                 BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT);
 
@@ -287,7 +327,7 @@
         // added to blocklist.
         when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_TIME_WINDOW_MS);
         assertTrue(mBssidBlocklistMonitor.handleBssidConnectionFailure(TEST_BSSID_1, TEST_SSID_1,
-                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, false));
+                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI));
         verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
                 BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT);
     }
@@ -301,7 +341,7 @@
         when(mWifiScoreCard.getBssidBlocklistStreak(anyString(), anyString(), anyInt()))
                 .thenReturn(1);
         assertTrue(mBssidBlocklistMonitor.handleBssidConnectionFailure(
-                TEST_BSSID_1, TEST_SSID_1, TEST_L2_FAILURE, false));
+                TEST_BSSID_1, TEST_SSID_1, TEST_L2_FAILURE, TEST_GOOD_RSSI));
         assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
     }
 
@@ -373,6 +413,8 @@
                 ABNORMAL_DISCONNECT_RESET_TIME_MS + 1);
         verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
                 BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT);
+        verify(mWifiScoreCard).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
+                BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE);
     }
 
     /**
@@ -389,6 +431,20 @@
     }
 
     /**
+     * Verify that the streak count for REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE is not reset
+     * if insufficient time has passed.
+     */
+    @Test
+    public void testNetworkConnectionNotResetConnectedScoreStreak() {
+        when(mClock.getWallClockMillis()).thenReturn(ABNORMAL_DISCONNECT_RESET_TIME_MS);
+        mBssidBlocklistMonitor.handleBssidConnectionSuccess(TEST_BSSID_1, TEST_SSID_1);
+        verify(mWifiScoreCard).setBssidConnectionTimestampMs(TEST_SSID_1, TEST_BSSID_1,
+                ABNORMAL_DISCONNECT_RESET_TIME_MS);
+        verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
+                BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE);
+    }
+
+    /**
      * Verify that handleDhcpProvisioningSuccess resets appropriate blocklist streak counts.
      */
     @Test
@@ -433,18 +489,23 @@
      */
     @Test
     public void testIncrementingBlocklistStreakCount() {
-        verifyAddTestBssidToBlocklist();
-        // verify that the blocklist streak is incremented
-        verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
-                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA);
+        for (Map.Entry<Integer, Integer> entry : BLOCK_REASON_TO_DISABLE_THRESHOLD_MAP.entrySet()) {
+            int reason = entry.getKey();
+            int threshold = entry.getValue();
+            when(mClock.getWallClockMillis()).thenReturn(0L);
+            handleBssidConnectionFailureMultipleTimes(TEST_BSSID_1, TEST_SSID_1, reason, threshold);
 
-        // Verify that TEST_BSSID_1 is removed from the blocklist after the timeout duration.
-        when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1);
-        assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
+            // verify that the blocklist streak is incremented
+            verify(mWifiScoreCard).incrementBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1, reason);
 
-        // But the blacklist streak count is not cleared
-        verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
-                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA);
+            // Verify that TEST_BSSID_1 is removed from the blocklist after the timeout duration.
+            when(mClock.getWallClockMillis()).thenReturn(BASE_BLOCKLIST_DURATION + 1);
+            assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
+
+            // But the blocklist streak count is not cleared
+            verify(mWifiScoreCard, never()).resetBssidBlocklistStreak(TEST_SSID_1, TEST_BSSID_1,
+                    reason);
+        }
     }
 
     /**
@@ -542,7 +603,8 @@
         for (int i = 0; i < 10; i++) {
             when(mClock.getWallClockMillis()).thenReturn((long) i);
             mBssidBlocklistMonitor.handleBssidConnectionFailure(bssid + i,
-                    TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+                    TEST_SSID_1, BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA,
+                    TEST_GOOD_RSSI);
 
             // This will build a List of BSSIDs starting from the latest added ones that is at
             // most size |TEST_NUM_MAX_FIRMWARE_SUPPORT_BSSIDS|.
@@ -645,7 +707,8 @@
     public void testBlockBssidForDurationMs() {
         when(mClock.getWallClockMillis()).thenReturn(0L);
         long testDuration = 5500L;
-        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration,
+                TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI);
         assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
 
         // Verify that the BSSID is removed from blocklist by clearBssidBlocklistForSsid
@@ -654,7 +717,8 @@
         assertEquals(1, mBssidBlocklistMonitor.getBssidStatusHistoryLoggerSize());
 
         // Add the BSSID to blocklist again.
-        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, testDuration,
+                TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI);
         assertEquals(1, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
 
         // Verify that the BSSID is removed from blocklist once the specified duration is over.
@@ -671,15 +735,105 @@
         // test invalid BSSID
         when(mClock.getWallClockMillis()).thenReturn(0L);
         long testDuration = 5500L;
-        mBssidBlocklistMonitor.blockBssidForDurationMs(null, TEST_SSID_1, testDuration);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(null, TEST_SSID_1, testDuration,
+                TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI);
         assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
 
         // test invalid SSID
-        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, null, testDuration);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, null, testDuration,
+                TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI);
         assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
 
         // test invalid duration
-        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, -1);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, -1,
+                TEST_FRAMEWORK_BLOCK_REASON, TEST_GOOD_RSSI);
         assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
     }
+
+    private void simulateRssiUpdate(String bssid, int rssi) {
+        ScanDetail scanDetail = mock(ScanDetail.class);
+        ScanResult scanResult = mock(ScanResult.class);
+        scanResult.BSSID = bssid;
+        scanResult.level = rssi;
+        when(scanDetail.getScanResult()).thenReturn(scanResult);
+        List<ScanDetail> scanDetails = new ArrayList<>();
+        scanDetails.add(scanDetail);
+        mBssidBlocklistMonitor.tryEnablingBlockedBssids(scanDetails);
+    }
+
+    /**
+     * Verify that if the RSSI is low when the BSSID is blocked, a RSSI improvement will remove
+     * the BSSID from blocklist.
+     */
+    @Test
+    public void testUnblockBssidAfterRssiImproves() {
+        when(mClock.getWallClockMillis()).thenReturn(0L);
+        // verify TEST_BSSID_1 is blocked
+        mBssidBlocklistMonitor.handleBssidConnectionFailure(
+                TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_EAP_FAILURE,
+                TEST_SUFFICIENT_RSSI - MIN_RSSI_DIFF_TO_UNBLOCK_BSSID);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+
+        // verify the blocklist is not cleared when the rssi improvement is not large enough.
+        simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI - 1);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+
+        // verify TEST_BSSID_1 is removed from the blocklist after RSSI improves
+        simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI);
+        assertEquals(0, mBssidBlocklistMonitor.updateAndGetBssidBlocklist().size());
+    }
+
+    /**
+     * Verify that if the RSSI is already good when the BSSID is blocked, a RSSI improvement will
+     * not remove the BSSID from blocklist.
+     */
+    @Test
+    public void testBssidNotUnblockedIfRssiAlreadyGood() {
+        when(mClock.getWallClockMillis()).thenReturn(0L);
+        // verify TEST_BSSID_1 is blocked
+        mBssidBlocklistMonitor.handleBssidConnectionFailure(
+                TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_EAP_FAILURE,
+                TEST_SUFFICIENT_RSSI);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+
+        // verify TEST_BSSID_1 is not removed from blocklist
+        simulateRssiUpdate(TEST_BSSID_1, TEST_GOOD_RSSI);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+    }
+
+    /**
+     * Verify that the logic to unblock BSSIDs after RSSI improvement does not apply for some
+     * failure reasons.
+     */
+    @Test
+    public void testRssiImprovementNotUnblockBssidForSomeFailureReasons() {
+        when(mClock.getWallClockMillis()).thenReturn(0L);
+        mBssidBlocklistMonitor.handleBssidConnectionFailure(
+                TEST_BSSID_1, TEST_SSID_1, BssidBlocklistMonitor.REASON_WRONG_PASSWORD,
+                TEST_SUFFICIENT_RSSI - MIN_RSSI_DIFF_TO_UNBLOCK_BSSID);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+
+        simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI);
+        assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
+    }
+
+    /**
+     * Verify the failure reasons for all blocked BSSIDs are retrieved.
+     */
+    @Test
+    public void testGetFailureReasonsForSsid() {
+        // Null input should not crash
+        mBssidBlocklistMonitor.getFailureReasonsForSsid(null).size();
+        assertEquals(0, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size());
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, 1000,
+                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI);
+        mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_2, TEST_SSID_1, 1000,
+                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI);
+
+        assertEquals(2, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size());
+        assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1)
+                .contains(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA));
+        assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1)
+                .contains(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT));
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 2372678..d4af7ec 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -1114,6 +1114,23 @@
     }
 
     /**
+     * When the SIM card was removed, if the current wifi connection is using it, the connection
+     * should be disconnected, otherwise, the connection shouldn't be impacted.
+     */
+    @Test
+    public void testResetSimWhenConnectedSimRemovedAfterNetworkRemoval() throws Exception {
+        setupEapSimConnection();
+        doReturn(false).when(mWifiCarrierInfoManager).isSimPresent(eq(DATA_SUBID));
+        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);
+        mCmi.sendMessage(ClientModeImpl.CMD_RESET_SIM_NETWORKS,
+                ClientModeImpl.RESET_SIM_REASON_SIM_REMOVED);
+        mLooper.dispatchAll();
+
+        verify(mSimRequiredNotifier, never()).showSimRequiredNotification(any(), any());
+        assertEquals("ObtainingIpState", getCurrentState().getName());
+    }
+
+    /**
      * When the default data SIM is changed, if the current wifi connection is carrier wifi,
      * the connection should be disconnected.
      */
@@ -1742,10 +1759,10 @@
         // by DHCP failure
         verify(mWifiLastResortWatchdog, times(2)).noteConnectionFailureAndTriggerIfNeeded(
                 sSSID, sBSSID, WifiLastResortWatchdog.FAILURE_CODE_DHCP);
-        verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(sBSSID,
-                sSSID, BssidBlocklistMonitor.REASON_DHCP_FAILURE, false);
-        verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_DHCP_FAILURE, false);
+        verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(eq(sBSSID),
+                eq(sSSID), eq(BssidBlocklistMonitor.REASON_DHCP_FAILURE), anyInt());
+        verify(mBssidBlocklistMonitor, times(2)).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_DHCP_FAILURE), anyInt());
         verify(mBssidBlocklistMonitor, never()).handleDhcpProvisioningSuccess(sBSSID, sSSID);
         verify(mBssidBlocklistMonitor, never()).handleNetworkValidationSuccess(sBSSID, sSSID);
     }
@@ -2364,6 +2381,7 @@
         inOrderMetrics.verify(mWifiMetrics).logStaEvent(StaEvent.TYPE_WIFI_DISABLED);
         assertNull(wifiInfo.getBSSID());
         assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
+        verify(mPasspointManager).clearAnqpRequestsAndFlushCache();
 
         // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated
         mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
@@ -3136,8 +3154,8 @@
         mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
         mLooper.dispatchAll();
 
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT), anyInt());
     }
 
     /**
@@ -3146,6 +3164,7 @@
      */
     @Test
     public void testNotifiesBssidBlocklistMonitorLowRssi() throws Exception {
+        int testLowRssi = -80;
         initializeAndAddNetworkAndVerifySuccess();
         mCmi.sendMessage(ClientModeImpl.CMD_START_CONNECT, FRAMEWORK_NETWORK_ID, 0,
                 ClientModeImpl.SUPPLICANT_BSSID_ANY);
@@ -3154,13 +3173,13 @@
         when(mWifiConfigManager.getScanDetailCacheForNetwork(FRAMEWORK_NETWORK_ID))
                 .thenReturn(mScanDetailCache);
         when(mScanDetailCache.getScanDetail(sBSSID)).thenReturn(
-                getGoogleGuestScanDetail(-80, sBSSID, sFreq));
+                getGoogleGuestScanDetail(testLowRssi, sBSSID, sFreq));
         when(mScanDetailCache.getScanResult(sBSSID)).thenReturn(
-                getGoogleGuestScanDetail(-80, sBSSID, sFreq).getScanResult());
+                getGoogleGuestScanDetail(testLowRssi, sBSSID, sFreq).getScanResult());
         mLooper.dispatchAll();
 
         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, true);
+                BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT, testLowRssi);
     }
 
     /**
@@ -3178,8 +3197,8 @@
         mLooper.dispatchAll();
         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
                 anyString(), anyString(), anyInt());
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA), anyInt());
     }
 
     /**
@@ -3197,8 +3216,8 @@
         mLooper.dispatchAll();
         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
                 anyString(), anyString(), anyInt());
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION), anyInt());
         verify(mWifiMetrics).incrementNumOfCarrierWifiConnectionNonAuthFailure();
     }
 
@@ -3219,8 +3238,8 @@
         mLooper.dispatchAll();
         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
                 anyString(), anyString(), anyInt());
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_WRONG_PASSWORD, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_WRONG_PASSWORD), anyInt());
     }
 
     /**
@@ -3240,8 +3259,8 @@
         mLooper.dispatchAll();
         verify(mWifiLastResortWatchdog, never()).noteConnectionFailureAndTriggerIfNeeded(
                 anyString(), anyString(), anyInt());
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_EAP_FAILURE, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_EAP_FAILURE), anyInt());
     }
 
     /**
@@ -3260,8 +3279,8 @@
         mLooper.dispatchAll();
         verify(mWifiLastResortWatchdog).noteConnectionFailureAndTriggerIfNeeded(
                 anyString(), anyString(), anyInt());
-        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE, false);
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(eq(sBSSID), eq(sSSID),
+                eq(BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE), anyInt());
     }
 
     /**
@@ -3578,7 +3597,7 @@
         verify(mWifiConfigManager).updateNetworkSelectionStatus(
                 FRAMEWORK_NETWORK_ID, DISABLED_NO_INTERNET_TEMPORARY);
         verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(sBSSID, sSSID,
-                BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, true);
+                BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE, RSSI_THRESHOLD_BREACH_MIN);
         verify(mWifiScoreCard).noteValidationFailure(any());
     }
 
@@ -4328,12 +4347,12 @@
     }
 
     /**
-     * Test that handleBssTransitionRequest() blacklist the BSS upon
+     * Test that handleBssTransitionRequest() blocklist the BSS upon
      * receiving BTM request frame that contains MBO-OCE IE with an
      * association retry delay attribute.
      */
     @Test
-    public void testBtmFrameWithMboAssocretryDelayBlackListTheBssid() throws Exception {
+    public void testBtmFrameWithMboAssocretryDelayBlockListTheBssid() throws Exception {
         // Connect to network with |sBSSID|, |sFreq|.
         connect();
 
@@ -4342,14 +4361,37 @@
         btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_REJECT_UNSPECIFIED;
         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
                 | MboOceConstants.BTM_DATA_FLAG_MBO_ASSOC_RETRY_DELAY_INCLUDED;
-        btmFrmData.mBlackListDurationMs = 60000;
+        btmFrmData.mBlockListDurationMs = 60000;
 
         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
         mLooper.dispatchAll();
 
         verify(mWifiMetrics, times(1)).incrementSteeringRequestCountIncludingMboAssocRetryDelay();
-        verify(mBssidBlocklistMonitor).blockBssidForDurationMs(sBSSID, sSSID,
-                btmFrmData.mBlackListDurationMs);
+        verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(sBSSID), eq(sSSID),
+                eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt());
+    }
+
+    /**
+     * Test that handleBssTransitionRequest() blocklist the BSS upon
+     * receiving BTM request frame that contains disassociation imminent bit
+     * set to 1.
+     */
+    @Test
+    public void testBtmFrameWithDisassocImminentBitBlockListTheBssid() throws Exception {
+        // Connect to network with |sBSSID|, |sFreq|.
+        connect();
+
+        MboOceController.BtmFrameData btmFrmData = new MboOceController.BtmFrameData();
+
+        btmFrmData.mStatus = MboOceConstants.BTM_RESPONSE_STATUS_ACCEPT;
+        btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT;
+
+        mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
+        mLooper.dispatchAll();
+
+        verify(mWifiMetrics, never()).incrementSteeringRequestCountIncludingMboAssocRetryDelay();
+        verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(sBSSID), eq(sSSID),
+                eq(MboOceConstants.DEFAULT_BLOCKLIST_DURATION_MS), anyInt(), anyInt());
     }
 
     /**
@@ -4367,13 +4409,13 @@
         btmFrmData.mBssTmDataFlagsMask = MboOceConstants.BTM_DATA_FLAG_DISASSOCIATION_IMMINENT
                 | MboOceConstants.BTM_DATA_FLAG_BSS_TERMINATION_INCLUDED
                 | MboOceConstants.BTM_DATA_FLAG_MBO_CELL_DATA_CONNECTION_PREFERENCE_INCLUDED;
-        btmFrmData.mBlackListDurationMs = 60000;
+        btmFrmData.mBlockListDurationMs = 60000;
 
         mCmi.sendMessage(WifiMonitor.MBO_OCE_BSS_TM_HANDLING_DONE, btmFrmData);
         mLooper.dispatchAll();
 
-        verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(sBSSID, sSSID,
-                btmFrmData.mBlackListDurationMs);
+        verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(eq(sBSSID), eq(sSSID),
+                eq(btmFrmData.mBlockListDurationMs), anyInt(), anyInt());
         verify(mWifiConnectivityManager).forceConnectivityScan(ClientModeImpl.WIFI_WORK_SOURCE);
         verify(mWifiMetrics, times(1)).incrementMboCellularSwitchRequestCount();
         verify(mWifiMetrics, times(1))
@@ -4807,8 +4849,8 @@
      *
      */
     private void setupFilsEnabledApInScanResult() {
-        String caps = "[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP]"
-                + "[RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP][ESS]";
+        String caps = "[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]"
+                + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP][ESS]";
         ScanResult scanResult = new ScanResult(WifiSsid.createFromAsciiEncoded(sFilsSsid),
                 sFilsSsid, sBSSID, 1245, 0, caps, -78, 2412, 1025, 22, 33, 20, 0, 0, true);
         ScanResult.InformationElement ie = createIE(ScanResult.InformationElement.EID_SSID,
@@ -4944,7 +4986,7 @@
 
         verify(mWifiMetrics, times(1)).incrementConnectRequestWithFilsAkmCount();
 
-        mCmi.sendMessage(WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
+        mCmi.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 1, sBSSID);
         mLooper.dispatchAll();
 
         verify(mWifiMetrics, times(1)).incrementL2ConnectionThroughFilsAuthCount();
@@ -5295,4 +5337,28 @@
         assertEquals(mNetwork, mCmi.syncGetCurrentNetwork(mCmiAsyncChannel));
         mLooper.stopAutoDispatch();
     }
+
+    @Test
+    public void clearRequestingPackageNameInWifiInfoOnConnectionFailure() throws Exception {
+        mConnectedNetwork.fromWifiNetworkSpecifier = true;
+        mConnectedNetwork.ephemeral = true;
+        mConnectedNetwork.creatorName = OP_PACKAGE_NAME;
+
+        triggerConnect();
+
+        // association completed
+        mCmi.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
+                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.ASSOCIATED));
+        mLooper.dispatchAll();
+
+        assertTrue(mCmi.getWifiInfo().isEphemeral());
+        assertEquals(OP_PACKAGE_NAME, mCmi.getWifiInfo().getRequestingPackageName());
+
+        // fail the connection.
+        mCmi.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, FRAMEWORK_NETWORK_ID, 0, sBSSID);
+        mLooper.dispatchAll();
+
+        assertFalse(mCmi.getWifiInfo().isEphemeral());
+        assertNull(mCmi.getWifiInfo().getRequestingPackageName());
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
index bb03d42..a570d29 100644
--- a/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/DeviceConfigFacadeTest.java
@@ -205,6 +205,12 @@
                 mDeviceConfigFacade.getStationaryScanRssiValidTimeMs());
         assertEquals(DeviceConfigFacade.DEFAULT_HEALTH_MONITOR_FW_ALERT_VALID_TIME_MS,
                 mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs());
+        assertEquals(DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS,
+                mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs());
+        assertEquals(DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS,
+                mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs());
+        assertEquals(DeviceConfigFacade.DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM,
+                mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm());
     }
 
     /**
@@ -307,6 +313,12 @@
                 anyInt())).thenReturn(3000);
         when(DeviceConfig.getInt(anyString(), eq("health_monitor_fw_alert_valid_time_ms"),
                 anyInt())).thenReturn(1000);
+        when(DeviceConfig.getInt(anyString(), eq("min_confirmation_duration_send_low_score_ms"),
+                anyInt())).thenReturn(4000);
+        when(DeviceConfig.getInt(anyString(), eq("min_confirmation_duration_send_high_score_ms"),
+                anyInt())).thenReturn(1000);
+        when(DeviceConfig.getInt(anyString(), eq("rssi_threshold_not_send_low_score_to_cs_dbm"),
+                anyInt())).thenReturn(-70);
         mOnPropertiesChangedListenerCaptor.getValue().onPropertiesChanged(null);
 
         // Verifying fields are updated to the new values
@@ -363,5 +375,8 @@
         assertEquals(4000, mDeviceConfigFacade.getNonstationaryScanRssiValidTimeMs());
         assertEquals(3000, mDeviceConfigFacade.getStationaryScanRssiValidTimeMs());
         assertEquals(1000, mDeviceConfigFacade.getHealthMonitorFwAlertValidTimeMs());
+        assertEquals(4000, mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs());
+        assertEquals(1000, mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs());
+        assertEquals(-70, mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm());
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java b/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
index d2a3ac0..2639133 100644
--- a/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/EapFailureNotifierTest.java
@@ -21,12 +21,17 @@
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
+import android.app.ActivityManager;
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.net.wifi.WifiConfiguration;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.telephony.SubscriptionManager;
@@ -42,13 +47,18 @@
 import org.mockito.MockitoAnnotations;
 import org.mockito.MockitoSession;
 
+import java.util.Arrays;
+
 /**
  * Unit tests for {@link com.android.server.wifi.EapFailureNotifier}.
  */
 @SmallTest
 public class EapFailureNotifierTest extends WifiBaseTest {
+    private static final String TEST_SETTINGS_PACKAGE = "android";
+
     @Mock WifiContext mContext;
     @Mock Resources mResources;
+    @Mock PackageManager mPackageManager;
     @Mock NotificationManager mNotificationManager;
     @Mock FrameworkFacade mFrameworkFacade;
     @Mock Notification mNotification;
@@ -65,6 +75,7 @@
     private static final String UNDEFINED_ERROR_RESOURCE_NAME = "wifi_eap_error_message_code_12345";
     private MockitoSession mStaticMockSession = null;
 
+
     EapFailureNotifier mEapFailureNotifier;
 
     /**
@@ -73,15 +84,26 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        ResolveInfo settingsResolveInfo = new ResolveInfo();
+        settingsResolveInfo.activityInfo = new ActivityInfo();
+        settingsResolveInfo.activityInfo.packageName = TEST_SETTINGS_PACKAGE;
+        when(mPackageManager.queryIntentActivitiesAsUser(
+                argThat(((intent) -> intent.getAction().equals(Settings.ACTION_WIFI_SETTINGS))),
+                anyInt(), any()))
+                .thenReturn(Arrays.asList(settingsResolveInfo));
+        // static mocking
         mStaticMockSession = mockitoSession()
             .mockStatic(SubscriptionManager.class)
+            .mockStatic(ActivityManager.class, withSettings().lenient())
             .startMocking();
+        when(ActivityManager.getCurrentUser()).thenReturn(UserHandle.USER_SYSTEM);
         when(mContext.getSystemService(NotificationManager.class))
                 .thenReturn(mNotificationManager);
         when(mWifiCarrierInfoManager.getBestMatchSubscriptionId(mWifiConfiguration)).thenReturn(0);
         lenient().when(SubscriptionManager.getResourcesForSubId(eq(mContext), anyInt()))
                 .thenReturn(mResources);
         when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mResources.getIdentifier(eq(DEFINED_ERROR_RESOURCE_NAME), anyString(),
                 anyString())).thenReturn(1);
         when(mResources.getIdentifier(eq(UNDEFINED_ERROR_RESOURCE_NAME), anyString(),
@@ -97,7 +119,10 @@
 
     @After
     public void cleanUp() throws Exception {
-        mStaticMockSession.finishMocking();
+        validateMockitoUsage();
+        if (mStaticMockSession != null) {
+            mStaticMockSession.finishMocking();
+        }
     }
 
     /**
@@ -120,6 +145,7 @@
         ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
         verify(mFrameworkFacade).getActivity(
                 eq(mContext), eq(0), intent.capture(), eq(PendingIntent.FLAG_UPDATE_CURRENT));
+        assertEquals(TEST_SETTINGS_PACKAGE, intent.getValue().getPackage());
         assertEquals(Settings.ACTION_WIFI_SETTINGS, intent.getValue().getAction());
     }
 
@@ -146,6 +172,7 @@
         ArgumentCaptor<Intent> intent = ArgumentCaptor.forClass(Intent.class);
         verify(mFrameworkFacade).getActivity(
                 eq(mContext), eq(0), intent.capture(), eq(PendingIntent.FLAG_UPDATE_CURRENT));
+        assertEquals(TEST_SETTINGS_PACKAGE, intent.getValue().getPackage());
         assertEquals(Settings.ACTION_WIFI_SETTINGS, intent.getValue().getAction());
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java b/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
index ec2142d..77d5c19 100644
--- a/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ImsiPrivacyProtectionExemptionStoreDataTest.java
@@ -17,6 +17,7 @@
 package com.android.server.wifi;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -102,6 +103,17 @@
         assertSerializeDeserialize(imsiPrivacyProtectionExemptionMap);
     }
 
+    @Test
+    public void testDeserializeOnNewDeviceOrNewUser() throws Exception {
+        ArgumentCaptor<Map> deserializedNetworkSuggestionsMap =
+                ArgumentCaptor.forClass(Map.class);
+        mImsiPrivacyProtectionExemptionStoreData.deserializeData(null, 0,
+                WifiConfigStore.ENCRYPT_CREDENTIALS_CONFIG_STORE_DATA_VERSION, null);
+        verify(mDataSource).fromDeserialized(deserializedNetworkSuggestionsMap.capture());
+        assertTrue(deserializedNetworkSuggestionsMap.getValue().isEmpty());
+    }
+
+
     private Map<Integer, Boolean> assertSerializeDeserialize(
             Map<Integer, Boolean> mImsiPrivacyProtectionExemptionMap) throws Exception {
         // Setup the data to serialize.
diff --git a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
index 9c56318..1e06773 100644
--- a/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/NetworkSuggestionNominatorTest.java
@@ -1046,6 +1046,7 @@
                 ArgumentCaptor.forClass(WifiConfiguration.class);
         verify(mWifiConfigManager, times(candidates.length)).addOrUpdateNetwork(
                 wifiConfigurationCaptor.capture(), anyInt(), anyString());
+        verify(mWifiConfigManager, times(candidates.length)).allowAutojoin(anyInt(), anyBoolean());
         for (int i = 0; i < candidates.length; i++) {
             WifiConfiguration addedWifiConfiguration = null;
             for (WifiConfiguration configuration : wifiConfigurationCaptor.getAllValues()) {
diff --git a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java b/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
index b065f82..cc96602 100644
--- a/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ScanRequestProxyTest.java
@@ -22,6 +22,8 @@
 import static com.android.server.wifi.ScanRequestProxy.SCAN_REQUEST_THROTTLE_TIME_WINDOW_FG_APPS_MS;
 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_SCAN_THROTTLE_ENABLED;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.*;
 import static org.mockito.Mockito.*;
 
@@ -1009,6 +1011,19 @@
         mLooper.dispatchAll();
         validateScanResultsAvailableBroadcastSent(true);
         verify(mScanResultsCallback, never()).onScanResultsAvailable();
+    }
 
+    /** Test that modifying the returned scan results list does not change the original. */
+    @Test
+    public void testGetScanResults_modifyReturnedList_doesNotChangeOriginal() {
+        // initialize scan results
+        testStartScanSuccess();
+
+        List<ScanResult> scanResults = mScanRequestProxy.getScanResults();
+        int scanResultsOriginalSize = scanResults.size();
+
+        scanResults.add(new ScanResult());
+
+        assertThat(mScanRequestProxy.getScanResults()).hasSize(scanResultsOriginalSize);
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
index 95f88bb..7e0c20f 100644
--- a/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/SupplicantStaIfaceHalTest.java
@@ -1010,7 +1010,7 @@
                 NativeUtil.decodeSsid(SUPPLICANT_SSID));
 
         wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent(
-                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
+                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), eq(BSSID));
         wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
                 eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
                 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
@@ -1040,9 +1040,11 @@
      * Tests the handling of incorrect network passwords.
      */
     @Test
-    public void testAuthFailurePassword() throws Exception {
+    public void testAuthFailurePasswordOnDisconnect() throws Exception {
         executeAndValidateInitializationSequence();
         assertNotNull(mISupplicantStaIfaceCallback);
+        executeAndValidateConnectSequenceWithKeyMgmt(
+                0, false, WifiConfiguration.KeyMgmt.WPA_PSK, null);
 
         int reasonCode = 3;
         mISupplicantStaIfaceCallback.onDisconnected(
@@ -1061,13 +1063,49 @@
                 SUPPLICANT_NETWORK_ID,
                 NativeUtil.decodeSsid(SUPPLICANT_SSID));
         mISupplicantStaIfaceCallback.onDisconnected(
+                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
+
+        verify(mWifiMonitor).broadcastAuthenticationFailureEvent(
+                eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1));
+    }
+
+    /**
+     * Tests the handling of EAP failure disconnects.
+     */
+    @Test
+    public void testAuthFailureEapOnDisconnect() throws Exception {
+        executeAndValidateInitializationSequence();
+        assertNotNull(mISupplicantStaIfaceCallback);
+        executeAndValidateConnectSequenceWithKeyMgmt(
+                0, false, WifiConfiguration.KeyMgmt.WPA_EAP, null);
+
+        int reasonCode = 3;
+        mISupplicantStaIfaceCallback.onDisconnected(
                 NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
+        verify(mWifiMonitor, times(0))
+                .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt());
+
+        mISupplicantStaIfaceCallback.onDisconnected(
+                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
+        verify(mWifiMonitor, times(0))
+                .broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt());
+
+        mISupplicantStaIfaceCallback.onStateChanged(
+                ISupplicantStaIfaceCallback.State.ASSOCIATED,
+                NativeUtil.macAddressToByteArray(BSSID),
+                SUPPLICANT_NETWORK_ID,
+                NativeUtil.decodeSsid(SUPPLICANT_SSID));
+        // Ensure we don't lose our prev state with this state changed event.
+        mISupplicantStaIfaceCallback.onStateChanged(
+                ISupplicantStaIfaceCallback.State.DISCONNECTED,
+                NativeUtil.macAddressToByteArray(BSSID),
+                SUPPLICANT_NETWORK_ID,
+                NativeUtil.decodeSsid(SUPPLICANT_SSID));
         mISupplicantStaIfaceCallback.onDisconnected(
                 NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
 
-        verify(mWifiMonitor, times(2))
-                .broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME),
-                        eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1));
+        verify(mWifiMonitor).broadcastAuthenticationFailureEvent(
+                eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE), eq(-1));
     }
 
     /**
@@ -2786,7 +2824,7 @@
                 NativeUtil.decodeSsid(SUPPLICANT_SSID), false);
 
         wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent(
-                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
+                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(false), eq(BSSID));
         wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
                 eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
                 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
@@ -2866,8 +2904,8 @@
                 NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
                 NativeUtil.decodeSsid(SUPPLICANT_SSID), true);
 
-        wifiMonitorInOrder.verify(mWifiMonitor).broadcastFilsNetworkConnectionEvent(
-                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
+        wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent(
+                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(true), eq(BSSID));
         wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
                 eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
                 any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
index b6f35c9..e4a918c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigManagerTest.java
@@ -621,7 +621,7 @@
                 return (int) mBssidStatusMap.entrySet().stream()
                         .filter(e -> e.getValue().equals(ssid)).count();
             }
-        }).when(mBssidBlocklistMonitor).getNumBlockedBssidsForSsid(
+        }).when(mBssidBlocklistMonitor).updateAndGetNumBlockedBssidsForSsid(
                 anyString());
         // add bssid to the blocklist
         mBssidStatusMap.put(TEST_BSSID, openNetwork.SSID);
@@ -649,7 +649,8 @@
         assertTrue(oldConfig.trusted);
         assertNull(oldConfig.BSSID);
 
-        assertEquals(0, mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(openNetwork.SSID));
+        assertEquals(0, mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(
+                openNetwork.SSID));
     }
 
     /**
@@ -1375,7 +1376,7 @@
         for (int i = 1; i < MAX_BLOCKED_BSSID_PER_NETWORK + 1; i++) {
             verifyDisableNetwork(result, disableReason);
             int numBssidsInBlocklist = i;
-            when(mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(anyString()))
+            when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString()))
                     .thenReturn(numBssidsInBlocklist);
             timeout = WifiConfigManager.getNetworkSelectionDisableTimeoutMillis(disableReason)
                     * multiplier;
@@ -1386,7 +1387,7 @@
 
         // Verify one last time that the disable duration is capped at some maximum.
         verifyDisableNetwork(result, disableReason);
-        when(mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(anyString()))
+        when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString()))
                 .thenReturn(MAX_BLOCKED_BSSID_PER_NETWORK + 1);
         verifyNetworkIsEnabledAfter(result.getNetworkId(),
                 TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS + timeout);
@@ -1404,7 +1405,7 @@
 
         // Verify that with 0 BSSIDs in blocklist we enable the network immediately
         verifyDisableNetwork(result, disableReason);
-        when(mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(anyString())).thenReturn(0);
+        when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(anyString())).thenReturn(0);
         when(mClock.getElapsedSinceBootMillis())
                 .thenReturn(TEST_ELAPSED_UPDATE_NETWORK_SELECTION_TIME_MILLIS);
         assertTrue(mWifiConfigManager.tryEnableNetwork(result.getNetworkId()));
@@ -2915,6 +2916,7 @@
         Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
         verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
         assertTrue((removedNetworks.size() == 1) && (removedNetworks.contains(user1NetworkId)));
+        verify(mWcmListener).onNetworkRemoved(any());
 
         // Set the expected networks to be |sharedNetwork| and |user2Network|.
         List<WifiConfiguration> expectedNetworks = new ArrayList<WifiConfiguration>() {
@@ -2933,6 +2935,66 @@
         assertTrue(removedNetworks.isEmpty());
     }
 
+    @Test
+    public void testHandleUserSwitchRemovesOldUserEphemeralNetworks() throws Exception {
+        int user1 = TEST_DEFAULT_USER;
+        int user2 = TEST_DEFAULT_USER + 1;
+        setupUserProfiles(user2);
+
+        int appId = 674;
+
+        // Create 2 networks. 1 ephemeral network for user1 and 1 shared.
+        final WifiConfiguration sharedNetwork = WifiConfigurationTestUtil.createPskNetwork();
+
+        // Set up the store data that is loaded initially.
+        List<WifiConfiguration> sharedNetworks = new ArrayList<WifiConfiguration>() {
+            {
+                add(sharedNetwork);
+            }
+        };
+        setupStoreDataForRead(sharedNetworks, Collections.EMPTY_LIST);
+        assertTrue(mWifiConfigManager.loadFromStore());
+        verify(mWifiConfigStore).read();
+
+        WifiConfiguration ephemeralNetwork = WifiConfigurationTestUtil.createEphemeralNetwork();
+        verifyAddEphemeralNetworkToWifiConfigManager(ephemeralNetwork);
+
+        // Fetch the network ID assigned to the user 1 network initially.
+        int ephemeralNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+        List<WifiConfiguration> retrievedNetworks =
+                mWifiConfigManager.getConfiguredNetworksWithPasswords();
+        for (WifiConfiguration network : retrievedNetworks) {
+            if (network.getKey().equals(ephemeralNetwork.getKey())) {
+                ephemeralNetworkId = network.networkId;
+            }
+        }
+
+        // Now switch the user to user 2 and ensure that user 1's private network has been removed.
+        when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true);
+        Set<Integer> removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
+        verify(mWifiConfigStore).switchUserStoresAndRead(any(List.class));
+        assertTrue((removedNetworks.size() == 1));
+        assertTrue(removedNetworks.contains(ephemeralNetworkId));
+        verifyNetworkRemoveBroadcast();
+        verify(mWcmListener).onNetworkRemoved(any());
+
+
+        // Set the expected networks to be |sharedNetwork|.
+        List<WifiConfiguration> expectedNetworks = new ArrayList<WifiConfiguration>() {
+            {
+                add(sharedNetwork);
+            }
+        };
+        WifiConfigurationTestUtil.assertConfigurationsEqualForConfigManagerAddOrUpdate(
+                expectedNetworks, mWifiConfigManager.getConfiguredNetworksWithPasswords());
+
+        // Send another user switch  indication with the same user 2. This should be ignored and
+        // hence should not remove any new networks.
+        when(mUserManager.isUserUnlockingOrUnlocked(UserHandle.of(user2))).thenReturn(true);
+        removedNetworks = mWifiConfigManager.handleUserSwitch(user2);
+        assertTrue(removedNetworks.isEmpty());
+    }
+
     /**
      * Verifies the foreground user switch using {@link WifiConfigManager#handleUserSwitch(int)}
      * and ensures that user switch from a user with no private networks is handled.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
index 8d7f5c6..0dd5b12 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConfigurationUtilTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wifi;
 
+import static android.net.wifi.WifiEnterpriseConfig.OCSP_NONE;
+import static android.net.wifi.WifiEnterpriseConfig.OCSP_REQUIRE_CERT_STATUS;
+
 import static org.junit.Assert.*;
 
 import android.content.pm.UserInfo;
@@ -980,4 +983,82 @@
             return this;
         }
     }
+
+    /**
+     * Verify WifiEnterpriseConfig CA Certificate alias changes are detected.
+     */
+    @Test
+    public void testCaCertificateAliasChangesDetected() {
+        EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password");
+        eapConfig1.enterpriseConfig.setCaCertificateAlias("ALIAS_1");
+
+        EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password");
+        eapConfig2.enterpriseConfig.setCaCertificateAlias("ALIAS_2");
+
+        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig,
+                eapConfig2.enterpriseConfig));
+    }
+
+    /**
+     * Verify WifiEnterpriseConfig Client Certificate alias changes are detected.
+     */
+    @Test
+    public void testClientCertificateAliasChangesDetected() {
+        EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TLS);
+        eapConfig1.enterpriseConfig.setCaCertificateAlias("ALIAS_1");
+        eapConfig1.enterpriseConfig.setClientCertificateAlias("CLIENT_ALIAS_1");
+
+        EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS);
+        eapConfig2.enterpriseConfig.setCaCertificateAlias("ALIAS_1");
+        eapConfig2.enterpriseConfig.setClientCertificateAlias("CLIENT_ALIAS_2");
+
+        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig,
+                eapConfig2.enterpriseConfig));
+    }
+
+    /**
+     * Verify WifiEnterpriseConfig OCSP changes are detected.
+     */
+    @Test
+    public void testOcspChangesDetected() {
+        EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password")
+                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
+        eapConfig1.enterpriseConfig.setOcsp(OCSP_NONE);
+
+        EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password")
+                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
+        eapConfig2.enterpriseConfig.setOcsp(OCSP_REQUIRE_CERT_STATUS);
+
+        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig,
+                eapConfig2.enterpriseConfig));
+    }
+
+    /**
+     * Verify WifiEnterpriseConfig subject match changes are detected.
+     */
+    @Test
+    public void testSubjectMatchChangesDetected() {
+        EnterpriseConfig eapConfig1 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password")
+                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
+        eapConfig1.enterpriseConfig.setAltSubjectMatch("domain1.com");
+
+        EnterpriseConfig eapConfig2 = new EnterpriseConfig(WifiEnterpriseConfig.Eap.TTLS)
+                .setPhase2(WifiEnterpriseConfig.Phase2.MSCHAPV2)
+                .setIdentity("username", "password")
+                .setCaCerts(new X509Certificate[]{FakeKeys.CA_CERT0});
+        eapConfig1.enterpriseConfig.setAltSubjectMatch("domain2.com");
+
+        assertTrue(WifiConfigurationUtil.hasEnterpriseConfigChanged(eapConfig1.enterpriseConfig,
+                eapConfig2.enterpriseConfig));
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
index ba1c4f9..38d2e82 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiConnectivityManagerTest.java
@@ -893,7 +893,7 @@
                 CANDIDATE_SSID);
         // Verify the failed BSSID is added to blocklist
         verify(mBssidBlocklistMonitor).blockBssidForDurationMs(eq(CANDIDATE_BSSID),
-                eq(CANDIDATE_SSID), anyLong());
+                eq(CANDIDATE_SSID), anyLong(), anyInt(), anyInt());
         // Verify another connection starting
         verify(mWifiNS).selectNetwork((List<WifiCandidates.Candidate>)
                 argThat(new WifiCandidatesListSizeMatcher(1)));
@@ -2210,10 +2210,14 @@
     public void verifyBlacklistRefreshedAfterScanResults() {
         when(mWifiConnectivityHelper.isFirmwareRoamingSupported()).thenReturn(true);
 
+        InOrder inOrder = inOrder(mBssidBlocklistMonitor);
         // Force a connectivity scan
-        verify(mBssidBlocklistMonitor, never()).updateAndGetBssidBlocklist();
+        inOrder.verify(mBssidBlocklistMonitor, never())
+                .updateAndGetBssidBlocklistForSsid(anyString());
         mWifiConnectivityManager.forceConnectivityScan(WIFI_WORK_SOURCE);
-        verify(mBssidBlocklistMonitor).updateAndGetBssidBlocklist();
+
+        inOrder.verify(mBssidBlocklistMonitor).tryEnablingBlockedBssids(any());
+        inOrder.verify(mBssidBlocklistMonitor).updateAndGetBssidBlocklistForSsid(anyString());
     }
 
     /**
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java
index 21a00f9..c679954 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiHealthMonitorTest.java
@@ -28,6 +28,7 @@
 import android.app.test.MockAnswerUtil.AnswerWithArguments;
 import android.app.test.TestAlarmManager;
 import android.content.Context;
+import android.content.pm.ModuleInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.net.MacAddress;
@@ -98,6 +99,8 @@
     PackageManager mPackageManager;
     @Mock
     PackageInfo mPackageInfo;
+    @Mock
+    ModuleInfo mModuleInfo;
 
     private final ArrayList<String> mKeys = new ArrayList<>();
     private final ArrayList<WifiScoreCard.BlobListener> mBlobListeners = new ArrayList<>();
@@ -154,8 +157,9 @@
         mDriverVersion = "build 1.1";
         mFirmwareVersion = "HW 1.1";
         when(mPackageInfo.getLongVersionCode()).thenReturn(MODULE_VERSION);
-        when(mContext.getPackageName()).thenReturn("WifiAPK");
         when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenReturn(mPackageInfo);
+        when(mPackageManager.getModuleInfo(anyString(), anyInt())).thenReturn(mModuleInfo);
+        when(mModuleInfo.getPackageName()).thenReturn("WifiAPK");
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
 
         mWifiConfigManager = mockConfigManager();
@@ -323,7 +327,7 @@
         // trigger extractCurrentSoftwareBuildInfo() call to update currSoftwareBuildInfo
         mWifiHealthMonitor.installMemoryStoreSetUpDetectionAlarm(mMemoryStore);
         mWifiHealthMonitor.setWifiEnabled(true);
-        assertEquals(0, mWifiHealthMonitor.getWifiStackVersion());
+        assertEquals(MODULE_VERSION, mWifiHealthMonitor.getWifiStackVersion());
         millisecondsPass(5000);
         mWifiScanner.startScan(mScanSettings, mScanListener);
         mAlarmManager.dispatch(WifiHealthMonitor.POST_BOOT_DETECTION_TIMER_TAG);
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
index 8eef7e7..f6cae66 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiKeyStoreTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wifi;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalMatchers.aryEq;
@@ -223,6 +224,8 @@
      */
     @Test
     public void testConfigureSuiteBRsa3072() throws Exception {
+        when(mWifiEnterpriseConfig.getCaCertificateAliases())
+                .thenReturn(new String[]{USER_CA_CERT_ALIAS});
         when(mWifiEnterpriseConfig.getClientPrivateKey())
                 .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY);
         when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
@@ -249,6 +252,8 @@
      */
     @Test
     public void testConfigureSuiteBEcdsa() throws Exception {
+        when(mWifiEnterpriseConfig.getCaCertificateAliases())
+                .thenReturn(new String[]{USER_CA_CERT_ALIAS});
         when(mWifiEnterpriseConfig.getClientPrivateKey())
                 .thenReturn(FakeKeys.CLIENT_SUITE_B_ECC_KEY);
         when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
@@ -269,4 +274,119 @@
         assertTrue(
                 savedNetwork.allowedSuiteBCiphers.get(WifiConfiguration.SuiteBCipher.ECDHE_ECDSA));
     }
+
+    /**
+     * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when CA and client
+     * certificates are not of the same type.
+     */
+    @Test
+    public void testConfigurationFailureSuiteB() throws Exception {
+        // Create a configuration with RSA client cert and ECDSA CA cert
+        when(mWifiEnterpriseConfig.getClientPrivateKey())
+                .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY);
+        when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_ECDSA_CERT);
+        when(mWifiEnterpriseConfig.getClientCertificateChain())
+                .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+        when(mWifiEnterpriseConfig.getCaCertificates())
+                .thenReturn(new X509Certificate[]{FakeKeys.CA_SUITE_B_ECDSA_CERT});
+        when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn(
+                FakeKeys.CA_SUITE_B_ECDSA_CERT);
+        WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork(
+                WifiConfiguration.SuiteBCipher.ECDHE_ECDSA);
+        savedNetwork.enterpriseConfig = mWifiEnterpriseConfig;
+        assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null));
+    }
+
+    /**
+     * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when CA is RSA but not
+     * with the required security
+     */
+    @Test
+    public void testConfigurationFailureSuiteBNon3072Rsa() throws Exception {
+        // Create a configuration with RSA client cert and weak RSA CA cert
+        when(mWifiEnterpriseConfig.getClientPrivateKey())
+                .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY);
+        when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_CERT0);
+        when(mWifiEnterpriseConfig.getClientCertificateChain())
+                .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+        when(mWifiEnterpriseConfig.getCaCertificates())
+                .thenReturn(new X509Certificate[]{FakeKeys.CA_CERT0});
+        when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn(
+                FakeKeys.CA_CERT0);
+        WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork(
+                WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+        savedNetwork.enterpriseConfig = mWifiEnterpriseConfig;
+        assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null));
+    }
+
+    /**
+     * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when one CA in the list
+     * is RSA but not with the required security
+     */
+    @Test
+    public void testConfigurationFailureSuiteBNon3072RsaInList() throws Exception {
+        // Create a configuration with RSA client cert and weak RSA CA cert
+        when(mWifiEnterpriseConfig.getClientPrivateKey())
+                .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY);
+        when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getClientCertificateChain())
+                .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+        when(mWifiEnterpriseConfig.getCaCertificates())
+                .thenReturn(
+                        new X509Certificate[]{FakeKeys.CA_SUITE_B_RSA3072_CERT, FakeKeys.CA_CERT0});
+        when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn(
+                FakeKeys.CA_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[1]))).thenReturn(
+                FakeKeys.CA_CERT0);
+        when(mWifiEnterpriseConfig.getCaCertificateAliases())
+                .thenReturn(USER_CA_CERT_ALIASES);
+        WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork(
+                WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+        savedNetwork.enterpriseConfig = mWifiEnterpriseConfig;
+        assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null));
+    }
+
+    /**
+     * Test configuring WPA3-Enterprise in 192-bit mode for RSA 3072 fails when one CA in the list
+     * is RSA and the other is ECDSA
+     */
+    @Test
+    public void testConfigurationFailureSuiteBRsaAndEcdsaInList() throws Exception {
+        // Create a configuration with RSA client cert and weak RSA CA cert
+        when(mWifiEnterpriseConfig.getClientPrivateKey())
+                .thenReturn(FakeKeys.CLIENT_SUITE_B_RSA3072_KEY);
+        when(mWifiEnterpriseConfig.getClientCertificate()).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getCaCertificate()).thenReturn(FakeKeys.CA_SUITE_B_RSA3072_CERT);
+        when(mWifiEnterpriseConfig.getClientCertificateChain())
+                .thenReturn(new X509Certificate[]{FakeKeys.CLIENT_SUITE_B_RSA3072_CERT});
+        when(mWifiEnterpriseConfig.getCaCertificates())
+                .thenReturn(
+                        new X509Certificate[]{FakeKeys.CA_SUITE_B_RSA3072_CERT,
+                                FakeKeys.CA_SUITE_B_ECDSA_CERT});
+        when(mKeyStore.getCertificate(eq(USER_CERT_ALIAS))).thenReturn(
+                FakeKeys.CLIENT_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[0]))).thenReturn(
+                FakeKeys.CA_SUITE_B_RSA3072_CERT);
+        when(mKeyStore.getCertificate(eq(USER_CA_CERT_ALIASES[1]))).thenReturn(
+                FakeKeys.CA_SUITE_B_ECDSA_CERT);
+        when(mWifiEnterpriseConfig.getCaCertificateAliases())
+                .thenReturn(USER_CA_CERT_ALIASES);
+        WifiConfiguration savedNetwork = WifiConfigurationTestUtil.createEapSuiteBNetwork(
+                WifiConfiguration.SuiteBCipher.ECDHE_RSA);
+        savedNetwork.enterpriseConfig = mWifiEnterpriseConfig;
+        assertFalse(mWifiKeyStore.updateNetworkKeys(savedNetwork, null));
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index d6b43c6..5439279 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -60,6 +60,7 @@
 import android.net.wifi.SoftApConfiguration;
 import android.net.wifi.SupplicantState;
 import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.net.wifi.WifiEnterpriseConfig;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
@@ -98,6 +99,7 @@
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
 import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
@@ -129,9 +131,11 @@
 import java.util.Arrays;
 import java.util.BitSet;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -586,9 +590,9 @@
         mockScanDetails.add(buildMockScanDetail(false, null, "[WAPI-WAPI-CERT-SMS4-SMS4]", 0));
         // Number of scans of R2 networks must be equal to NUM_HOTSPOT2_R2_NETWORK_SCAN_RESULTS
         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
-                "[WPA-EAP-CCMP+FILS-SHA256-CCMP]", FEATURE_MBO | FEATURE_OCE));
+                "[WPA-EAP-CCMP+EAP-FILS-SHA256-CCMP]", FEATURE_MBO | FEATURE_OCE));
         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R2,
-                "[WPA2-EAP+FT/EAP-CCMP+FILS-SHA256-CCMP]", 0));
+                "[WPA2-EAP+FT/EAP-CCMP+EAP-FILS-SHA256-CCMP]", 0));
         // Number of scans of R1 networks must be equal to NUM_HOTSPOT2_R1_NETWORK_SCAN_RESULTS
         mockScanDetails.add(buildMockScanDetail(false, NetworkDetail.HSRelease.R1,
                 "[WPA-EAP-CCMP]", 0));
@@ -1727,7 +1731,8 @@
         config.allowedKeyManagement = new BitSet();
         when(config.getNetworkSelectionStatus()).thenReturn(
                 mock(WifiConfiguration.NetworkSelectionStatus.class));
-        when(mBssidBlocklistMonitor.getNumBlockedBssidsForSsid(eq(config.SSID))).thenReturn(3);
+        when(mBssidBlocklistMonitor.updateAndGetNumBlockedBssidsForSsid(eq(config.SSID)))
+                .thenReturn(3);
         mWifiMetrics.startConnectionEvent(config, "RED",
                 WifiMetricsProto.ConnectionEvent.ROAM_NONE);
         mWifiMetrics.endConnectionEvent(
@@ -2297,6 +2302,7 @@
         mTestLooper.dispatchAll();
         wifiMetrics.setScreenState(true);
         when(mWifiDataStall.isCellularDataAvailable()).thenReturn(true);
+        wifiMetrics.setAdaptiveConnectivityState(true);
         for (int i = 0; i < mTestStaLogInts.length; i++) {
             int[] lia = mTestStaLogInts[i];
             wifiMetrics.logStaEvent(lia[0], lia[1], lia[2] == 1 ? mTestWifiConfig : null);
@@ -2337,6 +2343,7 @@
                     evs[7] == 1 ? mTestWifiConfig : null, event.configInfo);
             assertEquals(true, event.screenOn);
             assertEquals(true, event.isCellularDataAvailable);
+            assertEquals(true, event.isAdaptiveConnectivityEnabled);
             j++;
         }
         assertEquals(mExpectedValues.length, j);
@@ -2398,9 +2405,8 @@
         int testNetworkId = 0;
         long testStartTimeMillis = 123123L;
         when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
-        WifiConfiguration config = mock(WifiConfiguration.class);
-        when(config.isEphemeral()).thenReturn(true);
-        when(config.isPasspoint()).thenReturn(true);
+        WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
+        config.ephemeral = true;
         when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(config);
 
         mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
@@ -2413,6 +2419,118 @@
         assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
         assertEquals(true, userActionEvents[0].targetNetworkInfo.isEphemeral);
         assertEquals(true, userActionEvents[0].targetNetworkInfo.isPasspoint);
+
+        // Verify that there are no disabled WifiConfiguration and BSSIDs
+        NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+        assertEquals(NetworkDisableReason.REASON_UNKNOWN, networkDisableReason.disableReason);
+        assertEquals(false, networkDisableReason.configTemporarilyDisabled);
+        assertEquals(false, networkDisableReason.configPermanentlyDisabled);
+        assertEquals(0, networkDisableReason.bssidDisableReasons.length);
+    }
+
+    /**
+     * Verify the WifiStatus field in a UserActionEvent is populated correctly.
+     * @throws Exception
+     */
+    @Test
+    public void testLogWifiStatusInUserActionEvent() throws Exception {
+        // setups WifiStatus for information
+        int expectedRssi = -55;
+        int testNetworkId = 1;
+        int expectedTx = 1234;
+        int expectedRx = 2345;
+
+        WifiInfo wifiInfo = mock(WifiInfo.class);
+        when(wifiInfo.getRssi()).thenReturn(expectedRssi);
+        when(wifiInfo.getNetworkId()).thenReturn(testNetworkId);
+        mWifiMetrics.handlePollResult(wifiInfo);
+        mWifiMetrics.incrementThroughputKbpsCount(expectedTx, expectedRx, RSSI_POLL_FREQUENCY);
+        mWifiMetrics.setNominatorForNetwork(testNetworkId,
+                WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
+
+        // generate a user action event and then verify fields
+        int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
+        mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
+        dumpProtoAndDeserialize();
+
+        WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+        assertEquals(1, userActionEvents.length);
+        assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+                userActionEvents[0].eventType);
+        assertEquals(expectedRssi, userActionEvents[0].wifiStatus.lastRssi);
+        assertEquals(expectedTx, userActionEvents[0].wifiStatus.estimatedTxKbps);
+        assertEquals(expectedRx, userActionEvents[0].wifiStatus.estimatedRxKbps);
+        assertTrue(userActionEvents[0].wifiStatus.isStuckDueToUserConnectChoice);
+    }
+
+    /**
+     * verify NetworkDisableReason is populated properly when there exists a disabled
+     * WifiConfiguration and BSSID.
+     */
+    @Test
+    public void testNetworkDisableReasonInUserActionEvent() throws Exception {
+        // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
+        WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
+        NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
+        status.setNetworkSelectionStatus(
+                NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
+        status.setNetworkSelectionDisableReason(
+                NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
+        when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
+
+        // Also setup the same BSSID level failure
+        Set<Integer> testBssidBlocklistReasons = new HashSet<>();
+        testBssidBlocklistReasons.add(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION);
+        when(mBssidBlocklistMonitor.getFailureReasonsForSsid(anyString()))
+                .thenReturn(testBssidBlocklistReasons);
+
+        // Logging the user action event
+        mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+                TEST_NETWORK_ID);
+        dumpProtoAndDeserialize();
+
+        WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+        assertEquals(1, userActionEvents.length);
+        assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+                userActionEvents[0].eventType);
+        NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+        assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
+                networkDisableReason.disableReason);
+        assertEquals(true, networkDisableReason.configTemporarilyDisabled);
+        assertEquals(false, networkDisableReason.configPermanentlyDisabled);
+        assertEquals(1, networkDisableReason.bssidDisableReasons.length);
+        assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
+                networkDisableReason.bssidDisableReasons[0]);
+    }
+
+    /**
+     * verify that auto-join disable overrides any other disable reasons in NetworkDisableReason.
+     */
+    @Test
+    public void testNetworkDisableReasonDisableAutojoinInUserActionEvent() throws Exception {
+        // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
+        WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
+        NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
+        status.setNetworkSelectionStatus(
+                NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
+        status.setNetworkSelectionDisableReason(
+                NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
+        when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
+
+        // Disable autojoin
+        testConfig.allowAutojoin = false;
+
+        // Logging the user action event
+        mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+                TEST_NETWORK_ID);
+        dumpProtoAndDeserialize();
+
+        WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+        NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+        assertEquals(NetworkDisableReason.REASON_AUTO_JOIN_DISABLED,
+                networkDisableReason.disableReason);
+        assertEquals(false, networkDisableReason.configTemporarilyDisabled);
+        assertEquals(true, networkDisableReason.configPermanentlyDisabled);
     }
 
     /**
@@ -2438,6 +2556,35 @@
     }
 
     /**
+     * Test the logging of UserActionEvent for Adaptive Connectivity toggle
+     */
+    @Test
+    public void testLogUserActionEventForAdaptiveConnectivity() throws Exception {
+        long testStartTimeMillis = 123123L;
+        boolean adaptiveConnectivityEnabled = true;
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
+        mWifiMetrics.logUserActionEvent(
+                mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
+                        adaptiveConnectivityEnabled));
+        long testStartTimeMillis2 = 200000L;
+        boolean adaptiveConnectivityEnabled2 = false;
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis2);
+        mWifiMetrics.logUserActionEvent(
+                mWifiMetrics.convertAdaptiveConnectivityStateToUserActionEventType(
+                        adaptiveConnectivityEnabled2));
+        dumpProtoAndDeserialize();
+
+        WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+        assertEquals(2, userActionEvents.length);
+        assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_ON,
+                userActionEvents[0].eventType);
+        assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
+        assertEquals(WifiMetricsProto.UserActionEvent.EVENT_CONFIGURE_ADAPTIVE_CONNECTIVITY_OFF,
+                userActionEvents[1].eventType);
+        assertEquals(testStartTimeMillis2, userActionEvents[1].startTimeMillis);
+    }
+
+    /**
      * Verify that the max length of the UserActionEvent list is limited to MAX_USER_ACTION_EVENTS.
      */
     @Test
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
index 24bb968..c4acd73 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMonitorTest.java
@@ -423,13 +423,14 @@
                 WLAN_IFACE_NAME, WifiMonitor.NETWORK_CONNECTION_EVENT, mHandlerSpy);
         int networkId = NETWORK_ID;
         String bssid = BSSID;
-        mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, bssid);
+        mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, false, bssid);
         mLooper.dispatchAll();
 
         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mHandlerSpy).handleMessage(messageCaptor.capture());
         assertEquals(WifiMonitor.NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what);
         assertEquals(networkId, messageCaptor.getValue().arg1);
+        assertEquals(0, messageCaptor.getValue().arg2);
         assertEquals(bssid, (String) messageCaptor.getValue().obj);
     }
 
@@ -607,17 +608,17 @@
     @Test
     public void testBroadcastFilsNetworkConnectionEvent() {
         mWifiMonitor.registerHandler(
-                WLAN_IFACE_NAME, WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, mHandlerSpy);
+                WLAN_IFACE_NAME, WifiMonitor.NETWORK_CONNECTION_EVENT, mHandlerSpy);
         int networkId = NETWORK_ID;
         String bssid = BSSID;
-        mWifiMonitor.broadcastFilsNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, bssid);
+        mWifiMonitor.broadcastNetworkConnectionEvent(WLAN_IFACE_NAME, networkId, true, bssid);
         mLooper.dispatchAll();
 
         ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
         verify(mHandlerSpy).handleMessage(messageCaptor.capture());
-        assertEquals(WifiMonitor.FILS_NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what);
+        assertEquals(WifiMonitor.NETWORK_CONNECTION_EVENT, messageCaptor.getValue().what);
         assertEquals(networkId, messageCaptor.getValue().arg1);
+        assertEquals(1, messageCaptor.getValue().arg2);
         assertEquals(bssid, (String) messageCaptor.getValue().obj);
     }
-
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
index 5f9e033..f6621a6 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java
@@ -52,6 +52,7 @@
 import android.net.wifi.WifiScanner;
 import android.net.wifi.WifiScanner.ScanListener;
 import android.net.wifi.WifiScanner.ScanSettings;
+import android.net.wifi.WifiSsid;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Message;
@@ -1122,9 +1123,7 @@
         verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
                 eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
 
-        verify(mClientModeImpl).disconnectCommand();
-        verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class),
-                mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt());
+
     }
 
     /**
@@ -1333,6 +1332,134 @@
     }
 
     /**
+     * Verify handling of user selection to trigger connection to a network when the selected bssid
+     * is no longer seen in scan results within the cache expiry duration. Ensure we fill up the
+     * BSSID field.
+     */
+    @Test
+    public void
+            testNetworkSpecifierHandleUserSelectionConnectToNetworkMissingBssidInLatest()
+            throws Exception {
+        WifiScanner.ScanData[] scanDatas1 =
+                ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }});
+        setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK,
+                TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4);
+        // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult.
+        WifiScanner.ScanData[] scanDatas2 =
+                ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }});
+        setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK,
+                TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4);
+
+        // Make a specific AP request.
+        ScanResult matchingScanResult = scanDatas1[0].getResults()[0];
+        PatternMatcher ssidPatternMatch =
+                new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL);
+        Pair<MacAddress, MacAddress> bssidPatternMatch =
+                Pair.create(MacAddress.fromString(matchingScanResult.BSSID),
+                        MacAddress.BROADCAST_ADDRESS);
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
+        attachWifiNetworkSpecifierAndAppInfo(
+                ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1,
+                TEST_PACKAGE_NAME_1);
+        mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0);
+        mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback,
+                TEST_CALLBACK_IDENTIFIER);
+        verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
+                mNetworkRequestUserSelectionCallback.capture());
+        verifyPeriodicScans(
+                0L,
+                new PeriodicScanParams(0, scanDatas1),
+                new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2));
+
+        // Now trigger user selection to the network.
+        mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult);
+        mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\"";
+        INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback =
+                mNetworkRequestUserSelectionCallback.getValue();
+        assertNotNull(networkRequestUserSelectionCallback);
+        sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork);
+        mLooper.dispatchAll();
+
+        // Verify WifiConfiguration params.
+        validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID);
+        verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
+                eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
+
+        verify(mClientModeImpl).disconnectCommand();
+        verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class),
+                mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt());
+    }
+
+    /**
+     * Verify handling of user selection to trigger connection to a network when the selected bssid
+     * is no longer seen in scan results beyond the cache expiry duration. Ensure we don't fill up
+     * the BSSID field.
+     */
+    @Test
+    public void
+            testNetworkSpecifierHandleUserSelectionConnectToNetworkStaleMissingBssidInLatest()
+            throws Exception {
+        WifiScanner.ScanData[] scanDatas1 =
+                ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }});
+        setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK,
+                TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4);
+        // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult.
+        WifiScanner.ScanData[] scanDatas2 =
+                ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }});
+        setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK,
+                TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4);
+
+        // Make a specific AP request.
+        ScanResult matchingScanResult = scanDatas1[0].getResults()[0];
+        PatternMatcher ssidPatternMatch =
+                new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL);
+        Pair<MacAddress, MacAddress> bssidPatternMatch =
+                Pair.create(MacAddress.fromString(matchingScanResult.BSSID),
+                        MacAddress.BROADCAST_ADDRESS);
+        WifiConfiguration wifiConfiguration = new WifiConfiguration();
+        wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
+        wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY;
+        attachWifiNetworkSpecifierAndAppInfo(
+                ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1,
+                TEST_PACKAGE_NAME_1);
+        mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0);
+        mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback,
+                TEST_CALLBACK_IDENTIFIER);
+        verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
+                mNetworkRequestUserSelectionCallback.capture());
+
+        long nowMs = WifiNetworkFactory.CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS + 1;
+        scanDatas2[0].getResults()[0].timestamp = nowMs;
+        scanDatas2[0].getResults()[1].timestamp = nowMs;
+        scanDatas2[0].getResults()[2].timestamp = nowMs;
+        scanDatas2[0].getResults()[3].timestamp = nowMs;
+        verifyPeriodicScans(
+                nowMs,
+                new PeriodicScanParams(0, scanDatas1),
+                new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2));
+
+        // Now trigger user selection to the network.
+        mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult);
+        mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\"";
+        INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback =
+                mNetworkRequestUserSelectionCallback.getValue();
+        assertNotNull(networkRequestUserSelectionCallback);
+        sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork);
+        mLooper.dispatchAll();
+
+        // Verify WifiConfiguration params.
+        validateConnectParams(mSelectedNetwork.SSID, null);
+        verify(mWifiMetrics).setNominatorForNetwork(anyInt(),
+                eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER));
+
+        verify(mClientModeImpl).disconnectCommand();
+        verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class),
+                mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt());
+    }
+
+    /**
      * Verify handling of user selection to reject the request.
      */
     @Test
@@ -2669,13 +2796,33 @@
         verify(mNetworkRequestMatchCallback, atLeastOnce()).onMatch(anyList());
     }
 
+    private void verifyPeriodicScans(long...expectedIntervalsInSeconds) {
+        PeriodicScanParams[] periodicScanParams =
+                new PeriodicScanParams[expectedIntervalsInSeconds.length];
+        for (int i = 0; i < expectedIntervalsInSeconds.length; i++) {
+            periodicScanParams[i] =
+                    new PeriodicScanParams(expectedIntervalsInSeconds[i], mTestScanDatas);
+        }
+        verifyPeriodicScans(0L, periodicScanParams);
+    }
+
+    private static class PeriodicScanParams {
+        public final long expectedIntervalInSeconds;
+        public final WifiScanner.ScanData[] scanDatas;
+
+        PeriodicScanParams(long expectedIntervalInSeconds, WifiScanner.ScanData[] scanDatas) {
+            this.expectedIntervalInSeconds = expectedIntervalInSeconds;
+            this.scanDatas = scanDatas;
+        }
+    }
+
     // Simulates the periodic scans performed to find a matching network.
     // a) Start scan
     // b) Scan results received.
     // c) Set alarm for next scan at the expected interval.
     // d) Alarm fires, go to step a) again and repeat.
-    private void verifyPeriodicScans(long...expectedIntervalsInSeconds) {
-        when(mClock.getElapsedSinceBootMillis()).thenReturn(0L);
+    private void verifyPeriodicScans(long nowMs, PeriodicScanParams... scanParams) {
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(nowMs);
 
         OnAlarmListener alarmListener = null;
         ScanListener scanListener = null;
@@ -2685,9 +2832,9 @@
         // Before we start scans, ensure that we look at the latest cached scan results.
         mInOrder.verify(mWifiScanner).getSingleScanResults();
 
-        for (int i = 0; i < expectedIntervalsInSeconds.length - 1; i++) {
-            long expectedCurrentIntervalInMs = expectedIntervalsInSeconds[i];
-            long expectedNextIntervalInMs = expectedIntervalsInSeconds[i + 1];
+        for (int i = 0; i < scanParams.length - 1; i++) {
+            long expectedCurrentIntervalInMs = scanParams[i].expectedIntervalInSeconds;
+            long expectedNextIntervalInMs = scanParams[i + 1].expectedIntervalInSeconds;
 
             // First scan is immediately fired, so need for the alarm to fire.
             if (expectedCurrentIntervalInMs != 0) {
@@ -2700,10 +2847,10 @@
             assertNotNull(scanListener);
 
             // Now trigger the scan results callback and verify the alarm set for the next scan.
-            scanListener.onResults(mTestScanDatas);
+            scanListener.onResults(scanParams[i].scanDatas);
 
             mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
-                    eq(expectedNextIntervalInMs), any(),
+                    eq(expectedNextIntervalInMs + nowMs), any(),
                     mPeriodicScanListenerArgumentCaptor.capture(), any());
             alarmListener = mPeriodicScanListenerArgumentCaptor.getValue();
             assertNotNull(alarmListener);
@@ -2770,30 +2917,39 @@
         return "";
     }
 
-    // Helper method to setup the scan data for verifying the matching algo.
     private void setupScanData(int scanResultType, String ssid1, String ssid2, String ssid3,
             String ssid4) {
+        setupScanData(mTestScanDatas, scanResultType, ssid1, ssid2, ssid3, ssid4);
+    }
+
+    // Helper method to setup the scan data for verifying the matching algo.
+    private void setupScanData(WifiScanner.ScanData[] testScanDatas, int scanResultType,
+            String ssid1, String ssid2, String ssid3, String ssid4) {
         // 4 scan results,
-        assertEquals(1, mTestScanDatas.length);
-        ScanResult[] scanResults = mTestScanDatas[0].getResults();
+        assertEquals(1, testScanDatas.length);
+        ScanResult[] scanResults = testScanDatas[0].getResults();
         assertEquals(4, scanResults.length);
 
         String caps = getScanResultCapsForType(scanResultType);
 
         // Scan results have increasing RSSI.
         scanResults[0].SSID = ssid1;
+        scanResults[0].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid1);
         scanResults[0].BSSID = TEST_BSSID_1;
         scanResults[0].capabilities = caps;
         scanResults[0].level = -45;
         scanResults[1].SSID = ssid2;
+        scanResults[1].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid2);
         scanResults[1].BSSID = TEST_BSSID_2;
         scanResults[1].capabilities = caps;
         scanResults[1].level = -35;
         scanResults[2].SSID = ssid3;
+        scanResults[2].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid3);
         scanResults[2].BSSID = TEST_BSSID_3;
         scanResults[2].capabilities = caps;
         scanResults[2].level = -25;
         scanResults[3].SSID = ssid4;
+        scanResults[3].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid4);
         scanResults[3].BSSID = TEST_BSSID_4;
         scanResults[3].capabilities = caps;
         scanResults[3].level = -15;
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
index 0bd14a4..1507e9c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
@@ -741,6 +741,56 @@
     }
 
     /**
+     * Wifi network selector stays with current network if current network is not nominated
+     * but has the higher score
+     */
+    @Test
+    public void includeCurrentNetworkWhenCurrentNetworkNotNominated() {
+        String[] ssids = {"\"test1\"", "\"test2\""};
+        String[] bssids = {"6c:f3:7f:ae:8c:f3", "6c:f3:7f:ae:8c:f4"};
+        int[] freqs = {2437, 5120};
+        String[] caps = {"[WPA2-EAP-CCMP][ESS]", "[WPA2-PSK][ESS]"};
+        int[] levels = {mThresholdMinimumRssi2G + 10, mThresholdMinimumRssi2G + 20};
+        int[] securities = {SECURITY_EAP, SECURITY_PSK};
+        // VHT cap IE
+        byte[] iesBytes = {(byte) 0x92, (byte) 0x01, (byte) 0x80, (byte) 0x33, (byte) 0xaa,
+                (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0xaa, (byte) 0xff, (byte) 0x00,
+                (byte) 0x00};
+        byte[][] iesByteStream = {iesBytes, iesBytes};
+        // Make a network selection to connect to test1.
+        ScanDetailsAndWifiConfigs scanDetailsAndConfigs =
+                WifiNetworkSelectorTestUtil.setupScanDetailsAndConfigStore(ssids, bssids,
+                        freqs, caps, levels, securities, mWifiConfigManager, mClock, iesByteStream);
+        List<ScanDetail> scanDetails = scanDetailsAndConfigs.getScanDetails();
+        assertEquals(2, scanDetails.size());
+        HashSet<String> blocklist = new HashSet<String>();
+        List<WifiCandidates.Candidate> candidates = mWifiNetworkSelector.getCandidatesFromScan(
+                scanDetails, blocklist, mWifiInfo, false, true, false);
+        WifiConfiguration candidate = mWifiNetworkSelector.selectNetwork(candidates);
+
+        when(mWifiInfo.getSupplicantState()).thenReturn(SupplicantState.COMPLETED);
+        when(mWifiInfo.getNetworkId()).thenReturn(0); // 0 is current network
+        when(mWifiInfo.getBSSID()).thenReturn(bssids[0]);
+        when(mWifiInfo.is24GHz()).thenReturn(true);
+        when(mWifiInfo.getScore()).thenReturn(ConnectedScore.WIFI_TRANSITION_SCORE);
+        when(mWifiInfo.is5GHz()).thenReturn(false);
+        when(mWifiInfo.getFrequency()).thenReturn(2400);
+        when(mWifiInfo.getRssi()).thenReturn(levels[0]);
+        when(mClock.getElapsedSinceBootMillis()).thenReturn(SystemClock.elapsedRealtime()
+                + WifiNetworkSelector.MINIMUM_NETWORK_SELECTION_INTERVAL_MS + 2000);
+
+        when(mThroughputPredictor.predictThroughput(any(), anyInt(), anyInt(), anyInt(),
+                anyInt(), anyInt(), anyInt(), anyInt(), anyBoolean())).thenReturn(100);
+        // Force to return 2nd network in the network nominator
+        mDummyNominator.setNetworkIndexToReturn(1);
+
+        candidates = mWifiNetworkSelector.getCandidatesFromScan(
+                scanDetails, blocklist, mWifiInfo, true, false, false);
+        assertEquals(2, candidates.size());
+        assertEquals(100, candidates.get(0).getPredictedThroughputMbps());
+    }
+
+    /**
      * If two qualified networks, test1 and test2, are in range when the user selects test2 over
      * test1, WifiNetworkSelector will override the NetworkSelector's choice to connect to test1
      * with test2.
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
index 674ff8c..9ab9f8e 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java
@@ -20,15 +20,15 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.AdditionalAnswers.answerVoid;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.atMost;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
@@ -38,18 +38,21 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
+import android.net.NetworkProvider;
 import android.net.wifi.IScoreUpdateObserver;
 import android.net.wifi.IWifiConnectedNetworkScorer;
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.test.TestLooper;
 
@@ -60,6 +63,7 @@
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -101,6 +105,9 @@
     @Mock WifiNative mWifiNative;
     @Mock BssidBlocklistMonitor mBssidBlocklistMonitor;
     @Mock Network mNetwork;
+    @Mock DeviceConfigFacade mDeviceConfigFacade;
+    @Mock Looper mWifiLooper;
+    @Mock FrameworkFacade mFrameworkFacade;
     private TestLooper mLooper;
 
     public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub {
@@ -123,8 +130,13 @@
     // NetworkAgent is abstract, so a subclass is necessary
     private static class TestNetworkAgent extends NetworkAgent {
         TestNetworkAgent(Context context) {
-            super(new TestLooper().getLooper(), context, "TestNetworkAgent",
-                    mock(NetworkInfo.class), new NetworkCapabilities(), new LinkProperties(), 0);
+            this(context, new TestLooper().getLooper());
+        }
+        private TestNetworkAgent(Context context, Looper looper) {
+            super(context, looper, "TestNetworkAgent", new NetworkCapabilities(),
+                    new LinkProperties(), 0, new NetworkAgentConfig.Builder().build(),
+                    new NetworkProvider(context, looper, "ScoreReportTest agent"));
+            register();
         }
         @Override protected void unwanted() { }
     }
@@ -174,6 +186,9 @@
         when(resources.getInteger(
                 R.integer.config_wifiFrameworkMinPacketPerSecondHighTraffic))
             .thenReturn(100);
+        when(resources.getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled))
+            .thenReturn(false);
     }
 
     /**
@@ -196,9 +211,20 @@
         mClock = new FakeClock();
         mScoringParams = new ScoringParams();
         mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper()));
+        when(mFrameworkFacade.getIntegerSetting(any(Context.class),
+                eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1)))
+                .thenReturn(1);
         mWifiScoreReport = new WifiScoreReport(mScoringParams, mClock, mWifiMetrics, mWifiInfo,
-                mWifiNative, mBssidBlocklistMonitor, mWifiThreadRunner);
+                mWifiNative, mBssidBlocklistMonitor, mWifiThreadRunner,
+                mDeviceConfigFacade, mContext, mWifiLooper, mFrameworkFacade);
         mWifiScoreReport.setNetworkAgent(mNetworkAgent);
+        mWifiScoreReport.initialize();
+        when(mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()).thenReturn(
+                DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS);
+        when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(
+                DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_HIGH_SCORE_MS);
+        when(mDeviceConfigFacade.getRssiThresholdNotSendLowScoreToCsDbm()).thenReturn(
+                DeviceConfigFacade.DEFAULT_RSSI_THRESHOLD_NOT_SEND_LOW_SCORE_TO_CS_DBM);
     }
 
     /**
@@ -761,7 +787,7 @@
     }
 
     /**
-     * Verify BSSID blocklist doesnot happen when score stays below threshold for less than the
+     * Verify BSSID blocklist does not happen when score stays below threshold for less than the
      * minimum duration
      */
     @Test
@@ -781,7 +807,8 @@
         mLooper.dispatchAll();
         mWifiScoreReport.stopConnectedNetworkScorer();
         mLooper.dispatchAll();
-        verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(any(), any(), anyLong());
+        verify(mBssidBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(),
+                anyInt(), anyInt());
     }
 
     /**
@@ -805,11 +832,12 @@
         mLooper.dispatchAll();
         mWifiScoreReport.stopConnectedNetworkScorer();
         mLooper.dispatchAll();
-        verify(mBssidBlocklistMonitor).blockBssidForDurationMs(any(), any(), anyLong());
+        verify(mBssidBlocklistMonitor).handleBssidConnectionFailure(any(), any(),
+                eq(BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE), anyInt());
     }
 
     /**
-     * Verify BSSID blocklist doesnot happen when there is score flip flop
+     * Verify BSSID blocklist does not happen when there is score flip flop
      */
     @Test
     public void bssidBlockListDoesnotHappenWhenExitingIsReset() throws Exception {
@@ -831,6 +859,229 @@
         mLooper.dispatchAll();
         mWifiScoreReport.stopConnectedNetworkScorer();
         mLooper.dispatchAll();
-        verify(mBssidBlocklistMonitor, never()).blockBssidForDurationMs(any(), any(), anyLong());
+        verify(mBssidBlocklistMonitor, never()).handleBssidConnectionFailure(any(), any(),
+                anyInt(), anyInt());
+    }
+
+    /**
+     * Verify that the initial score value in WifiInfo is the max when onStart is called.
+     */
+    @Test
+    public void testOnStartInitialScoreInWifiInfoIsMaxScore() throws Exception {
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, mWifiConnectedNetworkScorer);
+        assertEquals(ConnectedScore.WIFI_MAX_SCORE, mWifiInfo.getScore());
+    }
+
+    /**
+     * Verify confirmation duration is not added when it is not enabled in config overlay by default
+     */
+    @Test
+    public void confirmationDurationIsNotAddedWhenItIsNotEnabledInConfigOverlay() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+
+        mClock.mWallClockMillis = 10;
+        mWifiInfo.setRssi(-65);
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(anyInt());
+    }
+
+    /**
+     * Verify confirmation duration is not added when there is no score breacht
+     */
+    @Test
+    public void confirmationDurationIsNotAddedWhenThereIsNoScoreBreach() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+        when(mContext.getResources().getBoolean(
+            R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true);
+
+        mClock.mWallClockMillis = 10;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 60);
+        mWifiInfo.setRssi(-70);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(60);
+        mClock.mWallClockMillis = 3010;
+        mWifiInfo.setRssi(-65);
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 59);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(59);
+        mClock.mWallClockMillis = 6010;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 58);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(58);
+    }
+
+    /**
+     * Verify confirmation duration and RSSI check is added for reporting low score when it is
+     * enabled in config overlay
+     */
+    @Test
+    public void confirmationDurationAndRssiCheckIsAddedForSendingLowScore() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+        when(mContext.getResources().getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true);
+
+        mClock.mWallClockMillis = 10;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 10
+                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 10
+                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS;
+        mWifiInfo.setRssi(-65);
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(47);
+        mClock.mWallClockMillis = 10
+                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS + 3000;
+        mWifiInfo.setRssi(-68);
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 46);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(46);
+    }
+
+    /**
+     * Verify confirmation duration is not added for reporting high score with default zero value
+     */
+    @Test
+    public void confirmationDurationIsNotAddedForSendingHighScore() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+        when(mContext.getResources().getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true);
+
+        mClock.mWallClockMillis = 10;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 3000;
+        mWifiInfo.setRssi(-70);
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(51);
+        mClock.mWallClockMillis = 6000;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(52);
+    }
+
+    /**
+     * Verify confirmation duration is added for reporting high score with non-zero value
+     */
+    @Test
+    public void confirmationDurationIsAddedForSendingHighScore() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+        when(mContext.getResources().getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true);
+        when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000);
+
+        mClock.mWallClockMillis = 10;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 3000;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 51);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 6999;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 52);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 7000;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 53);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(53);
+    }
+
+    /**
+     * Verify NUD check is not recommended and the score of 51 is sent to connectivity service
+     * when adaptive connectivity is disabled for AOSP scorer.
+     */
+    @Test
+    public void verifyNudCheckAndScoreIfToggleOffForAospScorer() throws Exception {
+        mWifiInfo.setFrequency(5220);
+        mWifiInfo.setRssi(-85);
+        ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class);
+        verify(mFrameworkFacade).registerContentObserver(
+                any(), any(), eq(true), observer.capture());
+        when(mFrameworkFacade.getIntegerSetting(any(Context.class),
+                eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1)))
+                .thenReturn(0);
+        observer.getValue().onChange(true);
+        mWifiScoreReport.calculateAndReportScore();
+        assertFalse(mWifiScoreReport.shouldCheckIpLayer());
+        verify(mNetworkAgent).sendNetworkScore(51);
+    }
+
+    /**
+     * Verify NUD check is not recommended and the score of 51 is sent to connectivity service
+     * when adaptive connectivity is disabled for external Wi-Fi scorer.
+     */
+    @Test
+    public void verifyNudCheckAndScoreIfToggleOffForExternalScorer() throws Exception {
+        WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl();
+        // Register Client for verification.
+        mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl);
+        when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID);
+        mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID);
+        mClock.mStepMillis = 0;
+        when(mContext.getResources().getBoolean(
+                R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true);
+        when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000);
+
+        ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class);
+        verify(mFrameworkFacade).registerContentObserver(
+                any(), any(), eq(true), observer.capture());
+        when(mFrameworkFacade.getIntegerSetting(any(Context.class),
+                eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1)))
+                .thenReturn(0);
+        observer.getValue().onChange(true);
+
+        mClock.mWallClockMillis = 10;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        assertFalse(mWifiScoreReport.shouldCheckIpLayer());
+
+        mClock.mWallClockMillis = 10
+                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent, never()).sendNetworkScore(anyInt());
+        mClock.mWallClockMillis = 10
+                + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS;
+        scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47);
+        mLooper.dispatchAll();
+        verify(mNetworkAgent).sendNetworkScore(51);
     }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 6d1ae29..22561a1 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -571,7 +571,8 @@
         assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
         inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
         inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(true));
-        inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF);
+        inorder.verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_TOGGLE_WIFI_OFF),
+                anyInt());
         inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(false));
     }
 
@@ -3621,7 +3622,8 @@
                 mock(IActionListener.class), 0);
         verify(mClientModeImpl).connect(any(WifiConfiguration.class), anyInt(),
                 any(Binder.class), any(IActionListener.class), anyInt(), anyInt());
-        verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_MANUAL_CONNECT), anyInt());
+        verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK),
+                anyInt());
     }
 
     /**
@@ -3632,8 +3634,11 @@
     public void testSaveNetworkWithPrivilegedPermission() throws Exception {
         when(mContext.checkPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
             anyInt(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
+        when(mWifiPermissionsUtil.checkNetworkSettingsPermission(anyInt())).thenReturn(true);
         mWifiServiceImpl.save(mock(WifiConfiguration.class), mock(Binder.class),
                 mock(IActionListener.class), 0);
+        verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK),
+                anyInt());
         verify(mClientModeImpl).save(any(WifiConfiguration.class),
                 any(Binder.class), any(IActionListener.class), anyInt(), anyInt());
     }
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java b/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java
index 555e891..351bb98 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/TestUtils.java
@@ -49,7 +49,7 @@
 
         public boolean enableAndConfigure(short transactionId, ConfigRequest configRequest,
                 boolean notifyIdentityChange, boolean initialConfiguration, boolean isInteractive,
-                boolean isIdle) {
+                boolean isIdle, boolean rangingEnabled) {
             addTransactionId(transactionId);
             return true;
         }
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
index f496b1c..a21442f 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareDataPathStateManagerTest.java
@@ -1846,7 +1846,7 @@
 
         if (startUpSequence) {
             inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                    eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                    eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
             mDut.onConfigSuccessResponse(transactionId.getValue());
             mMockLooper.dispatchAll();
         }
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java
index 0a30228..08eae1d 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareNativeApiTest.java
@@ -595,7 +595,7 @@
         mIsInterface12 = isHal12;
 
         mDut.enableAndConfigure(transactionId, configRequest, notifyIdentityChange,
-                initialConfiguration, isInteractive, isIdle);
+                initialConfiguration, isInteractive, isIdle, false);
 
         ArgumentCaptor<NanEnableRequest> enableReqCaptor = ArgumentCaptor.forClass(
                 NanEnableRequest.class);
diff --git a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
index f5da0b2..7292fca 100644
--- a/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/aware/WifiAwareStateManagerTest.java
@@ -268,7 +268,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback1).onConnectSuccess(clientId1);
@@ -369,7 +369,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -466,7 +466,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -512,7 +512,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -540,7 +540,7 @@
         InOrder inOrder = inOrder(mMockContext, mMockNative, mockCallback);
 
         when(mMockNative.enableAndConfigure(anyShort(), any(), anyBoolean(),
-                anyBoolean(), eq(true), eq(false))).thenReturn(false);
+                anyBoolean(), eq(true), eq(false), eq(false))).thenReturn(false);
 
         // (1) check initial state
         mDut.enableUsage();
@@ -555,7 +555,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         inOrder.verify(mockCallback).onConnectFail(NanStatusType.INTERNAL_FAILURE);
 
         validateInternalClientInfoCleanedUp(clientId);
@@ -601,7 +601,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         short transactionId = transactionIdCapture.getValue();
         mDut.onConfigSuccessResponse(transactionId);
         mMockLooper.dispatchAll();
@@ -611,7 +611,7 @@
                 configRequest, true);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionIdCapture.capture(),
-                eq(configRequest), eq(true), eq(false), eq(true), eq(false));
+                eq(configRequest), eq(true), eq(false), eq(true), eq(false), eq(false));
         transactionId = transactionIdCapture.getValue();
         mDut.onConfigSuccessResponse(transactionId);
         mMockLooper.dispatchAll();
@@ -689,7 +689,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -755,7 +755,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -828,7 +828,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -912,7 +912,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -931,6 +931,12 @@
         inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(false),
                 eq(-1), eq(-1), any());
         inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, true);
+        mMockLooper.dispatchAll();
+        // Verify reconfigure aware to enable ranging.
+        inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
+                eq(false), eq(false), eq(true), eq(false), eq(true));
+        mDut.onConfigSuccessResponse(transactionId.getValue());
+        mMockLooper.dispatchAll();
 
         // (3) update publish
         mDut.updatePublish(clientId, sessionId.getValue(), publishConfig);
@@ -979,6 +985,12 @@
         inOrder.verify(mockSessionCallback).onSessionConfigFail(NanStatusType.INVALID_SESSION_ID);
         inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid,
                 NanStatusType.INVALID_SESSION_ID, true);
+        // Verify reconfigure aware to disable ranging.
+        mMockLooper.dispatchAll();
+        inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
+                eq(false), eq(false), eq(true), eq(false), eq(false));
+        mDut.onConfigSuccessResponse(transactionId.getValue());
+        mMockLooper.dispatchAll();
 
         // (9) try updating again - do nothing/get nothing
         mDut.updatePublish(clientId, sessionId.getValue(), publishConfig);
@@ -1024,7 +1036,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1092,7 +1104,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1166,7 +1178,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1250,7 +1262,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1269,6 +1281,12 @@
         inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true),
                 eq(-1), eq(rangeMax), any());
         inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false);
+        // Verify reconfigure aware to enable ranging.
+        mMockLooper.dispatchAll();
+        inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
+                eq(false), eq(false), eq(true), eq(false), eq(true));
+        mDut.onConfigSuccessResponse(transactionId.getValue());
+        mMockLooper.dispatchAll();
 
         // (3) update subscribe
         mDut.updateSubscribe(clientId, sessionId.getValue(), subscribeConfig);
@@ -1343,7 +1361,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1426,7 +1444,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1443,6 +1461,13 @@
         inOrderM.verify(mAwareMetricsMock).recordDiscoverySessionWithRanging(eq(uid), eq(true),
                 eq(rangeMin), eq(rangeMax), any());
         inOrderM.verify(mAwareMetricsMock).recordDiscoveryStatus(uid, NanStatusType.SUCCESS, false);
+        // Verify reconfigure aware to enable ranging.
+        mMockLooper.dispatchAll();
+        inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
+                eq(false), eq(false), eq(true), eq(false), eq(true));
+        mDut.onConfigSuccessResponse(transactionId.getValue());
+        mMockLooper.dispatchAll();
+
 
         // (2) 2 matches : with and w/o range
         mDut.onMatchNotification(subscribeId, requestorId, peerMac, peerSsi.getBytes(),
@@ -1554,7 +1579,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1658,7 +1683,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1752,7 +1777,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1823,7 +1848,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -1951,7 +1976,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2040,7 +2065,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2130,7 +2155,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2244,7 +2269,7 @@
                 configRequest1, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest1), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest1), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId1);
@@ -2379,7 +2404,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2513,7 +2538,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2746,7 +2771,7 @@
                 configRequest1, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                crCapture.capture(), eq(false), eq(true), eq(true), eq(false));
+                crCapture.capture(), eq(false), eq(true), eq(true), eq(false), eq(false));
         collector.checkThat("merge: stage 1", crCapture.getValue(), equalTo(configRequest1));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
@@ -2764,7 +2789,7 @@
                 configRequest3, true);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                crCapture.capture(), eq(true), eq(false), eq(true), eq(false));
+                crCapture.capture(), eq(true), eq(false), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback3).onConnectSuccess(clientId3);
@@ -2786,7 +2811,7 @@
         mMockLooper.dispatchAll();
         validateInternalClientInfoCleanedUp(clientId3);
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                crCapture.capture(), eq(false), eq(false), eq(true), eq(false));
+                crCapture.capture(), eq(false), eq(false), eq(true), eq(false), eq(false));
 
         collector.checkThat("configRequest1", configRequest1, equalTo(crCapture.getValue()));
 
@@ -2837,7 +2862,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                any(ConfigRequest.class), eq(false), eq(true), eq(true), eq(false));
+                any(ConfigRequest.class), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2855,7 +2880,7 @@
                 configRequest, true);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                any(ConfigRequest.class), eq(true), eq(false), eq(true), eq(false));
+                any(ConfigRequest.class), eq(true), eq(false), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2918,7 +2943,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -2995,7 +3020,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3041,7 +3066,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
 
         verifyNoMoreInteractions(mMockNative, mockCallback, mockSessionCallback);
     }
@@ -3077,7 +3102,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         short transactionIdConfig = transactionId.getValue();
         mDut.onConfigSuccessResponse(transactionIdConfig);
         mMockLooper.dispatchAll();
@@ -3135,7 +3160,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(), eq(configRequest),
-                eq(false), eq(true), eq(true), eq(false));
+                eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3192,7 +3217,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3247,7 +3272,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3303,7 +3328,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3312,7 +3337,7 @@
         simulatePowerStateChangeInteractive(false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(false), eq(false), eq(false));
+                eq(configRequest), eq(false), eq(false), eq(false), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
 
@@ -3320,7 +3345,7 @@
         simulatePowerStateChangeDoze(true);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(false), eq(false), eq(true));
+                eq(configRequest), eq(false), eq(false), eq(false), eq(true), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
 
@@ -3328,7 +3353,7 @@
         simulatePowerStateChangeInteractive(true); // effectively treated as no-doze
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(false), eq(true), eq(true));
+                eq(configRequest), eq(false), eq(false), eq(true), eq(true), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
 
@@ -3371,7 +3396,7 @@
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNativeManager).tryToGetAware();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3448,7 +3473,7 @@
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNativeManager).tryToGetAware();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3521,7 +3546,7 @@
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNativeManager).tryToGetAware();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3591,7 +3616,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
@@ -3607,7 +3632,7 @@
                 configRequest, false);
         mMockLooper.dispatchAll();
         inOrder.verify(mMockNative).enableAndConfigure(transactionId.capture(),
-                eq(configRequest), eq(false), eq(true), eq(true), eq(false));
+                eq(configRequest), eq(false), eq(true), eq(true), eq(false), eq(false));
         mDut.onConfigSuccessResponse(transactionId.getValue());
         mMockLooper.dispatchAll();
         inOrder.verify(mockCallback).onConnectSuccess(clientId);
diff --git a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
index dbc38d4..9caf85f 100644
--- a/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/hotspot2/PasspointManagerTest.java
@@ -20,6 +20,7 @@
 import static android.app.AppOpsManager.OPSTR_CHANGE_WIFI_STATE;
 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
+import static android.net.wifi.WifiInfo.DEFAULT_MAC_ADDRESS;
 
 import static com.android.server.wifi.WifiConfigurationTestUtil.SECURITY_EAP;
 
@@ -50,6 +51,7 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.Intent;
+import android.net.MacAddress;
 import android.net.Uri;
 import android.net.wifi.EAPConstants;
 import android.net.wifi.ScanResult;
@@ -78,6 +80,7 @@
 import com.android.server.wifi.Clock;
 import com.android.server.wifi.FakeKeys;
 import com.android.server.wifi.FrameworkFacade;
+import com.android.server.wifi.MacAddressUtil;
 import com.android.server.wifi.NetworkUpdateResult;
 import com.android.server.wifi.WifiBaseTest;
 import com.android.server.wifi.WifiCarrierInfoManager;
@@ -188,6 +191,7 @@
     @Mock TelephonyManager mTelephonyManager;
     @Mock SubscriptionManager mSubscriptionManager;
     @Mock WifiNetworkSuggestionsManager mWifiNetworkSuggestionsManager;
+    @Mock MacAddressUtil mMacAddressUtil;
 
     Handler mHandler;
     TestLooper mLooper;
@@ -223,7 +227,7 @@
         mHandler = new Handler(mLooper.getLooper());
         mManager = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, mObjectFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil);
         ArgumentCaptor<PasspointEventHandler.Callbacks> callbacks =
                 ArgumentCaptor.forClass(PasspointEventHandler.Callbacks.class);
         verify(mObjectFactory).makePasspointEventHandler(any(WifiNative.class),
@@ -749,7 +753,7 @@
                 .thenReturn(true);
         PasspointManager ut = new PasspointManager(mContext, mWifiInjector, mHandler, mWifiNative,
                 mWifiKeyStore, mClock, spyFactory, mWifiConfigManager,
-                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager);
+                mWifiConfigStore, mWifiMetrics, mWifiCarrierInfoManager, mMacAddressUtil);
 
         assertTrue(ut.addOrUpdateProvider(config, TEST_CREATOR_UID, TEST_PACKAGE,
                 true, true));
@@ -1230,6 +1234,39 @@
     }
 
     /**
+     * Verify that a {@link WifiConfiguration} will be returned with the correct value for the
+     * randomized MAC address.
+     */
+    @Test
+    public void getWifiConfigsForPasspointProfilesWithoutEnhancedMacRandomization() {
+        MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab");
+        when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress);
+        when(mWifiConfigManager.shouldUseAggressiveRandomization(any())).thenReturn(false);
+        PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
+                TEST_PACKAGE, false, null);
+        WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles(
+                Collections.singletonList(provider.getConfig().getUniqueId())).get(0);
+        assertEquals(config.getRandomizedMacAddress(), randomizedMacAddress);
+    }
+
+    /**
+     * Verify that a {@link WifiConfiguration} will be returned with DEFAULT_MAC_ADDRESS for the
+     * randomized MAC address if enhanced mac randomization is enabled. This value will display in
+     * the wifi picker's network details page as "Not available" if the network is disconnected.
+     */
+    @Test
+    public void getWifiConfigsForPasspointProfilesWithEnhancedMacRandomization() {
+        MacAddress randomizedMacAddress = MacAddress.fromString("01:23:45:67:89:ab");
+        when(mMacAddressUtil.calculatePersistentMac(any(), any())).thenReturn(randomizedMacAddress);
+        when(mWifiConfigManager.shouldUseAggressiveRandomization(any())).thenReturn(true);
+        PasspointProvider provider = addTestProvider(TEST_FQDN, TEST_FRIENDLY_NAME,
+                TEST_PACKAGE, false, null);
+        WifiConfiguration config = mManager.getWifiConfigsForPasspointProfiles(
+                Collections.singletonList(provider.getConfig().getUniqueId())).get(0);
+        assertEquals(config.getRandomizedMacAddress(), MacAddress.fromString(DEFAULT_MAC_ADDRESS));
+    }
+
+    /**
      * Verify that an empty map will be returned when trying to get all matching FQDN for a {@code
      * null} {@link ScanResult}.
      */
diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
index 6a7f203..b4943d7 100644
--- a/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/p2p/SupplicantP2pIfaceHalTest.java
@@ -2882,6 +2882,8 @@
         config.wps.setup = wpsProvMethod;
         config.wps.pin = pin;
 
+        config.groupOwnerIntent = WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT;
+
         return config;
     }
 
diff --git a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
index cae812d..171dc9b 100644
--- a/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/p2p/WifiP2pServiceImplTest.java
@@ -56,6 +56,8 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.TetheringManager;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.net.wifi.WpsInfo;
 import android.net.wifi.p2p.WifiP2pConfig;
@@ -65,6 +67,7 @@
 import android.net.wifi.p2p.WifiP2pGroupList;
 import android.net.wifi.p2p.WifiP2pInfo;
 import android.net.wifi.p2p.WifiP2pManager;
+import android.net.wifi.p2p.WifiP2pProvDiscEvent;
 import android.net.wifi.p2p.WifiP2pWfdInfo;
 import android.net.wifi.p2p.nsd.WifiP2pServiceInfo;
 import android.net.wifi.p2p.nsd.WifiP2pServiceRequest;
@@ -167,6 +170,8 @@
     @Mock WifiP2pServiceRequest mTestWifiP2pServiceRequest;
     @Mock UserManager mUserManager;
     @Mock WifiP2pMetrics mWifiP2pMetrics;
+    @Mock WifiManager mWifiManager;
+    @Mock WifiInfo mWifiInfo;
     @Spy FakeWifiLog mLog;
     @Spy MockWifiP2pMonitor mWifiMonitor;
 
@@ -626,6 +631,25 @@
     }
 
     /**
+     * Send simple API msg.
+     *
+     * Mock the API msg with objects.
+     *
+     * @param replyMessenger for checking replied message.
+     */
+    private void sendSimpleMsg(Messenger replyMessenger,
+            int what, Object obj) throws Exception {
+        Message msg = Message.obtain();
+        msg.what = what;
+        msg.obj = obj;
+        if (replyMessenger != null) {
+            msg.replyTo = replyMessenger;
+        }
+        mP2pStateMachineMessenger.send(Message.obtain(msg));
+        mLooper.dispatchAll();
+    }
+
+    /**
      * force P2p State enter InactiveState to start others unit test
      *
      * @param clientBinder client binder to use for p2p channel init
@@ -747,6 +771,8 @@
 
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getResources()).thenReturn(mResources);
+        when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+        when(mWifiManager.getConnectionInfo()).thenReturn(mWifiInfo);
         when(mWifiSettingsConfigStore.get(eq(WIFI_P2P_DEVICE_NAME))).thenReturn(thisDeviceName);
         when(mWifiSettingsConfigStore.get(eq(WIFI_P2P_PENDING_FACTORY_RESET))).thenReturn(false);
         when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
@@ -772,6 +798,8 @@
         when(mWifiPermissionsUtil.checkNetworkStackPermission(anyInt())).thenReturn(true);
         when(mWifiPermissionsUtil.checkReadWifiCredentialPermission(anyInt())).thenReturn(true);
         when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
+        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
+                anyBoolean())).thenReturn(true);
         when(mWifiNative.setupInterface(any(), any())).thenReturn(IFACE_NAME_P2P);
         when(mWifiNative.p2pGetDeviceAddress()).thenReturn(thisDeviceMac);
         doAnswer(new AnswerWithArguments() {
@@ -982,8 +1010,6 @@
         forceP2pEnabled(mClient1);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString());
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pServiceAdd(any())).thenReturn(true);
         sendAddLocalServiceMsg(mClientMessenger);
         verify(mWifiNative).p2pServiceAdd(any());
@@ -1000,8 +1026,6 @@
         forceP2pEnabled(mClient1);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         doNothing().when(mWifiPermissionsUtil).checkPackage(anyInt(), anyString());
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pServiceAdd(any())).thenReturn(false);
         sendAddLocalServiceMsg(mClientMessenger);
         verify(mWifiNative).p2pServiceAdd(any());
@@ -1062,8 +1086,6 @@
     @Test
     public void testConnectWithConfigValidAsGroupSuccess() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(true);
         sendConnectMsgWithConfigValidAsGroup(mClientMessenger);
@@ -1079,8 +1101,6 @@
     @Test
     public void testConnectWithConfigValidAsGroupFailureWhenNativeCallFailure() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(false);
         sendConnectMsgWithConfigValidAsGroup(mClientMessenger);
@@ -1147,8 +1167,6 @@
     @Test
     public void testCreateGroupWithConfigValidAsGroupSuccess() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(true);
         sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger);
@@ -1165,8 +1183,6 @@
     public void testCreateGroupWithConfigValidAsGroupFailureWhenNativeCallFailure()
             throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         when(mWifiNative.p2pGroupAdd(any(), eq(false))).thenReturn(false);
         sendCreateGroupMsgWithConfigValidAsGroup(mClientMessenger);
@@ -1247,8 +1263,6 @@
     @Test
     public void testDiscoverPeersSuccess() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pFind(anyInt())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendDiscoverPeersMsg(mClientMessenger);
@@ -1264,8 +1278,6 @@
     @Test
     public void testDiscoverPeersFailureWhenNativeCallFailure() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pFind(anyInt())).thenReturn(false);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendDiscoverPeersMsg(mClientMessenger);
@@ -1364,8 +1376,6 @@
                 .thenReturn("mServiceDiscReqId");
         when(mWifiNative.p2pFind(anyInt())).thenReturn(true);
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendAddServiceRequestMsg(mClientMessenger);
         sendDiscoverServiceMsg(mClientMessenger);
@@ -1383,8 +1393,6 @@
     public void testDiscoverServicesFailureWhenAddServiceRequestFailure() throws Exception {
         when(mWifiNative.p2pServDiscReq(anyString(), anyString())).thenReturn(null);
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendAddServiceRequestMsg(mClientMessenger);
         sendDiscoverServiceMsg(mClientMessenger);
@@ -1404,8 +1412,6 @@
                 .thenReturn("mServiceDiscReqId");
         when(mWifiNative.p2pFind(anyInt())).thenReturn(false);
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendAddServiceRequestMsg(mClientMessenger);
         sendDiscoverServiceMsg(mClientMessenger);
@@ -1504,8 +1510,6 @@
     public void testRequestPeersSuccess() throws Exception {
         forceP2pEnabled(mClient1);
         mockPeersList();
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendRequestPeersMsg(mClientMessenger);
         verify(mClientHandler).sendMessage(mMessageCaptor.capture());
@@ -1581,8 +1585,6 @@
         sendGroupStartedMsg(mTestWifiP2pGroup);
         simulateTetherReady();
         when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(false);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendRequestGroupInfoMsg(mClientMessenger);
         verify(mClientHandler).sendMessage(mMessageCaptor.capture());
@@ -1606,8 +1608,6 @@
         sendGroupStartedMsg(mTestWifiP2pGroup);
         simulateTetherReady();
         when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendRequestGroupInfoMsg(mClientMessenger);
         verify(mClientHandler).sendMessage(mMessageCaptor.capture());
@@ -1791,8 +1791,6 @@
     @Test
     public void testPeerScanMetricWhenSendDiscoverPeers() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pFind(anyInt())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendDiscoverPeersMsg(mClientMessenger);
@@ -1811,8 +1809,6 @@
                 .thenReturn("mServiceDiscReqId");
         when(mWifiNative.p2pFind(anyInt())).thenReturn(true);
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendAddServiceRequestMsg(mClientMessenger);
         sendDiscoverServiceMsg(mClientMessenger);
@@ -1920,8 +1916,6 @@
     @Test
     public void testStartFreshConnectionEventWhenSendConnect() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
         mockPeersList();
@@ -1943,8 +1937,6 @@
     @Test
     public void testStartReinvokeConnectionEventWhenSendConnect() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyInt()))
                 .thenReturn(true);
         when(mTestWifiP2pDevice.isGroupOwner()).thenReturn(true);
@@ -1976,8 +1968,6 @@
     public void testStartReinvokeConnectionEventWhenCreateGroup()
             throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
         sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_PERSISTENT, null);
@@ -1996,8 +1986,6 @@
     @Test
     public void testStartLocalConnectionWhenCreateGroup() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
         // permissions for factory reset
@@ -2028,8 +2016,6 @@
     @Test
     public void testStartLocalConnectionEventWhenCreateTemporaryGroup() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
         sendCreateGroupMsg(mClientMessenger, WifiP2pGroup.NETWORK_ID_TEMPORARY, null);
@@ -2049,8 +2035,6 @@
     public void testStartFastConnectionEventWhenSendConnectWithConfig()
             throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(any(), eq(true))).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2075,8 +2059,6 @@
     public void testStartFastConnectionEventWhenCreateGroupWithConfig()
             throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
         sendCreateGroupMsg(mClientMessenger, 0, mTestWifiP2pFastConnectionConfig);
@@ -2118,8 +2100,6 @@
     @Test
     public void testEndConnectionEventWhenTimeout() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2140,8 +2120,6 @@
     @Test
     public void testEndConnectionEventWhenCancel() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2161,8 +2139,6 @@
     @Test
     public void testEndConnectionEventWhenProvDiscFailure() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2182,8 +2158,6 @@
     @Test
     public void testEndConnectionEventWhenGroupRemoval() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2203,8 +2177,6 @@
     @Test
     public void testEndConnectionEventWhenInvitationFailure() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pGroupAdd(anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
 
@@ -2244,8 +2216,6 @@
     @Test
     public void testRequestDeviceInfoSuccessWhenP2pEnabled() throws Exception {
         forceP2pEnabled(mClient1);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO);
         verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"),
@@ -2263,8 +2233,6 @@
      */
     @Test
     public void testRequestDeviceInfoReturnEmptyWifiP2pDeviceWhenP2pDisabled() throws Exception {
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO);
         verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"),
@@ -2284,8 +2252,6 @@
     public void testRequestDeviceInfoReturnsActualMacForNetworkSettingsApp() throws Exception {
         forceP2pEnabled(mClient1);
         when(mWifiPermissionsUtil.checkLocalMacAddressPermission(anyInt())).thenReturn(true);
-        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(anyString(), anyString(), anyInt(),
-                anyBoolean())).thenReturn(true);
         sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
         sendSimpleMsg(mClientMessenger, WifiP2pManager.REQUEST_DEVICE_INFO);
         verify(mWifiPermissionsUtil).checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"),
@@ -3578,6 +3544,8 @@
     @Test
     public void testRequestDiscoveryStateWhenStarted() throws Exception {
         forceP2pEnabled(mClient1);
+        when(mWifiPermissionsUtil.checkCanAccessWifiDirect(any(), any(),
+                anyInt(), anyBoolean())).thenReturn(false);
         when(mWifiPermissionsUtil.checkCanAccessWifiDirect(eq("testPkg1"), eq("testFeature"),
                 anyInt(), anyBoolean())).thenReturn(true);
         when(mWifiNative.p2pFind(anyInt())).thenReturn(true);
@@ -4002,4 +3970,108 @@
         Message message = mMessageCaptor.getValue();
         assertEquals(WifiP2pManager.CONNECT_FAILED, message.what);
     }
+
+    /**
+     * Verify the group owner intent value is selected correctly when no STA connection.
+     */
+    @Test
+    public void testGroupOwnerIntentSelectionWithoutStaConnection() throws Exception {
+        when(mWifiInfo.getNetworkId()).thenReturn(WifiConfiguration.INVALID_NETWORK_ID);
+        when(mWifiInfo.getFrequency()).thenReturn(2412);
+        forceP2pEnabled(mClient1);
+        sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
+
+        mockEnterProvisionDiscoveryState();
+
+        WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent();
+        pdEvent.device = mTestWifiP2pDevice;
+        sendSimpleMsg(null,
+                WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT,
+                pdEvent);
+
+        ArgumentCaptor<WifiP2pConfig> configCaptor =
+                ArgumentCaptor.forClass(WifiP2pConfig.class);
+        verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean());
+        WifiP2pConfig config = configCaptor.getValue();
+        assertEquals(WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT + 1,
+                config.groupOwnerIntent);
+    }
+
+    /**
+     * Verify the group owner intent value is selected correctly when 2.4GHz STA connection.
+     */
+    @Test
+    public void testGroupOwnerIntentSelectionWith24GStaConnection() throws Exception {
+        when(mWifiInfo.getNetworkId()).thenReturn(1);
+        when(mWifiInfo.getFrequency()).thenReturn(2412);
+        forceP2pEnabled(mClient1);
+        sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
+
+        mockEnterProvisionDiscoveryState();
+
+        WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent();
+        pdEvent.device = mTestWifiP2pDevice;
+        sendSimpleMsg(null,
+                WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT,
+                pdEvent);
+
+        ArgumentCaptor<WifiP2pConfig> configCaptor =
+                ArgumentCaptor.forClass(WifiP2pConfig.class);
+        verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean());
+        WifiP2pConfig config = configCaptor.getValue();
+        assertEquals(WifiP2pConfig.GROUP_OWNER_INTENT_MIN,
+                config.groupOwnerIntent);
+    }
+
+    /**
+     * Verify the group owner intent value is selected correctly when 5GHz STA connection.
+     */
+    @Test
+    public void testGroupOwnerIntentSelectionWith5GHzStaConnection() throws Exception {
+        when(mWifiInfo.getNetworkId()).thenReturn(1);
+        when(mWifiInfo.getFrequency()).thenReturn(5200);
+        forceP2pEnabled(mClient1);
+        sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
+
+        mockEnterProvisionDiscoveryState();
+
+        WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent();
+        pdEvent.device = mTestWifiP2pDevice;
+        sendSimpleMsg(null,
+                WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT,
+                pdEvent);
+
+        ArgumentCaptor<WifiP2pConfig> configCaptor =
+                ArgumentCaptor.forClass(WifiP2pConfig.class);
+        verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean());
+        WifiP2pConfig config = configCaptor.getValue();
+        assertEquals(WifiP2pConfig.GROUP_OWNER_INTENT_MAX - 1,
+                config.groupOwnerIntent);
+    }
+
+    /**
+     * Verify the group owner intent value is selected correctly when 6GHz STA connection.
+     */
+    @Test
+    public void testGroupOwnerIntentSelectionWith6GHzStaConnection() throws Exception {
+        when(mWifiInfo.getNetworkId()).thenReturn(1);
+        when(mWifiInfo.getFrequency()).thenReturn(6000);
+        forceP2pEnabled(mClient1);
+        sendChannelInfoUpdateMsg("testPkg1", "testFeature", mClient1, mClientMessenger);
+
+        mockEnterProvisionDiscoveryState();
+
+        WifiP2pProvDiscEvent pdEvent = new WifiP2pProvDiscEvent();
+        pdEvent.device = mTestWifiP2pDevice;
+        sendSimpleMsg(null,
+                WifiP2pMonitor.P2P_PROV_DISC_PBC_RSP_EVENT,
+                pdEvent);
+
+        ArgumentCaptor<WifiP2pConfig> configCaptor =
+                ArgumentCaptor.forClass(WifiP2pConfig.class);
+        verify(mWifiNative).p2pConnect(configCaptor.capture(), anyBoolean());
+        WifiP2pConfig config = configCaptor.getValue();
+        assertEquals(WifiP2pServiceImpl.DEFAULT_GROUP_OWNER_INTENT,
+                config.groupOwnerIntent);
+    }
 }
diff --git a/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
index 16c9157..df85aa9 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/ApConfigUtilTest.java
@@ -112,9 +112,9 @@
             5845, SoftApConfiguration.BAND_5GHZ, 169,
             5865, SoftApConfiguration.BAND_5GHZ, 173,
             /* Now some 6GHz channels */
-            5945, SoftApConfiguration.BAND_6GHZ, 1,
-            5960, SoftApConfiguration.BAND_6GHZ, 4,
-            6100, SoftApConfiguration.BAND_6GHZ, 32
+            5955, SoftApConfiguration.BAND_6GHZ, 1,
+            5970, SoftApConfiguration.BAND_6GHZ, 4,
+            6110, SoftApConfiguration.BAND_6GHZ, 32
     };
 
     private static final int[] EMPTY_CHANNEL_LIST = {};
diff --git a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
index 77c99a9..3d54e69 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/InformationElementUtilTest.java
@@ -663,8 +663,8 @@
         capabilities.from(ies, beaconCap, true);
         String result = capabilities.generateCapabilitiesString();
 
-        assertEquals("[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP][RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP]",
-                result);
+        assertEquals("[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]"
+                + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]", result);
     }
 
     /**
@@ -704,8 +704,8 @@
         capabilities.from(ies, beaconCap, true);
         String result = capabilities.generateCapabilitiesString();
 
-        assertEquals("[WPA2-EAP+EAP-SHA256+FILS-SHA384-CCMP][RSN-EAP+EAP-SHA256+FILS-SHA384-CCMP]",
-                result);
+        assertEquals("[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA384-CCMP]"
+                + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA384-CCMP]", result);
     }
 
     /**
@@ -1367,7 +1367,7 @@
         assertTrue(heOperation.is6GhzInfoPresent());
         assertFalse(heOperation.isVhtInfoPresent());
         assertEquals(ScanResult.CHANNEL_WIDTH_80MHZ, heOperation.getChannelWidth());
-        assertEquals(6040, heOperation.getCenterFreq0());
+        assertEquals(6050, heOperation.getCenterFreq0());
         assertEquals(0, heOperation.getCenterFreq1());
     }
 
@@ -1412,8 +1412,8 @@
         assertTrue(heOperation.is6GhzInfoPresent());
         assertFalse(heOperation.isVhtInfoPresent());
         assertEquals(ScanResult.CHANNEL_WIDTH_160MHZ, heOperation.getChannelWidth());
-        assertEquals(6040, heOperation.getCenterFreq0());
-        assertEquals(6080, heOperation.getCenterFreq1());
+        assertEquals(6050, heOperation.getCenterFreq0());
+        assertEquals(6090, heOperation.getCenterFreq1());
     }
 
     /**
diff --git a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
index e58d083..00e3a0b 100644
--- a/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/util/ScanResultUtilTest.java
@@ -211,8 +211,8 @@
     @Test
     public void testFilsSha256AkmSupportedNetwork() {
         final String ssid = "FILS-AP";
-        String caps = "[WPA2-EAP+EAP-SHA256+FILS-SHA256-CCMP]"
-                + "[RSN-EAP+EAP-SHA256+FILS-SHA256-CCMP][ESS]";
+        String caps = "[WPA2-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP]"
+                + "[RSN-EAP+EAP-SHA256+EAP-FILS-SHA256-CCMP][ESS]";
 
         ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
                 "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,
@@ -231,8 +231,8 @@
     @Test
     public void testFilsSha384AkmSupportedNetwork() {
         final String ssid = "FILS-AP";
-        String caps = "[WPA2-EAP+EAP-SHA384+FILS-SHA384-CCMP]"
-                + "[RSN-EAP+EAP-SHA384+FILS-SHA384-CCMP][ESS]";
+        String caps = "[WPA2-EAP+EAP-SHA384+EAP-FILS-SHA384-CCMP]"
+                + "[RSN-EAP+EAP-SHA384+EAP-FILS-SHA384-CCMP][ESS]";
 
         ScanResult input = new ScanResult(WifiSsid.createFromAsciiEncoded(ssid), ssid,
                 "ab:cd:01:ef:45:89", 1245, 0, caps, -78, 2450, 1025, 22, 33, 20, 0,